diff options
| author | jesseb <none@none> | 2005-09-01 20:01:56 -0700 |
|---|---|---|
| committer | jesseb <none@none> | 2005-09-01 20:01:56 -0700 |
| commit | 0541156464ba74bca005fda4b225d3bbe53f7a0c (patch) | |
| tree | 257068e59870bb2b578ad3dd2d45f86280b38d9e /usr/src/cmd/raidctl/raidctl.c | |
| parent | 2c75e67e98ffd095634e492eb347bac08db7c288 (diff) | |
| download | illumos-joyent-0541156464ba74bca005fda4b225d3bbe53f7a0c.tar.gz | |
PSARC 2005/097 Solaris support for LSISAS1064 on Ontario
6228874 Raidctl should enable RAID0
Diffstat (limited to 'usr/src/cmd/raidctl/raidctl.c')
| -rw-r--r-- | usr/src/cmd/raidctl/raidctl.c | 494 |
1 files changed, 345 insertions, 149 deletions
diff --git a/usr/src/cmd/raidctl/raidctl.c b/usr/src/cmd/raidctl/raidctl.c index 8ebd74d218..5c794e1019 100644 --- a/usr/src/cmd/raidctl/raidctl.c +++ b/usr/src/cmd/raidctl/raidctl.c @@ -26,7 +26,6 @@ #pragma ident "%Z%%M% %I% %E% SMI" - #include <ctype.h> #include <dirent.h> #include <errno.h> @@ -90,6 +89,10 @@ static int ctrl_nums = 0; #define DO_HW_RAID_DELETE 2 #define DO_HW_RAID_FLASH 3 +/* values to use for raid level in raidctl */ +#define RAID_STRIPE 0 +#define RAID_MIRROR 1 + /* * Error return codes */ @@ -124,6 +127,11 @@ static int ctrl_nums = 0; #define FW_ROM_OFFSET_VERSION 0x24 /* (U16) */ #define FW_ROM_OFFSET_VERSION_NAME 0x44 /* (32 U8) */ +/* ID's for supported chips */ +#define LSI_1030 0x30 +#define LSI_1064 0x50 +#define LSI_1064E 0x56 + /* Key to search for when looking for fcode version */ #define FCODE_VERS_KEY1 0x12 #define FCODE_VERS_KEY2 0x7 @@ -132,8 +140,11 @@ static int ctrl_nums = 0; /* get a word from a buffer (works with non-word aligned offsets) */ #define gw(x) (((x)[0]) + (((x)[1]) << 8)) -/* Number of disks currently supported */ -#define N_DISKS 2 +/* Number of disks currently supported, per RAID volume */ +#define N_DISKS 8 + +/* Number of RAID volumes currently supported, per HBA */ +#define N_RAIDVOLS 2 /* * Function and strings to properly localize our prompt. @@ -145,7 +156,7 @@ static char yeschr[SCHAR_MAX + 2]; static char nochr[SCHAR_MAX +2]; typedef struct raidlist { - raid_config_t raid_config; + raid_config_t raid_config[N_RAIDVOLS]; int controller; char devctl[MAXPATHLEN]; struct raidlist *next; @@ -153,14 +164,35 @@ typedef struct raidlist { static raidlist_t *raids; +/* + * usage: raidctl + * usage: raidctl -c primary secondary + * usage: raidctl -c -r 1 primary secondary + * usage: raidctl -c -r 0 disk1 disk2 [disk3] ... + * usage: raidctl -d volume + * usage: raidctl [-f] -F image_file controller + * usage: raidctl -l [controller...] + * example: + * raidctl -c c1t1d0 c1t2d0 + * raidctl -c -r 0 c1t1d0 c1t2d0 c1t3d0 c1t4d0 + * raidctl -d c1t1d0 + * raidctl -F image 1 + */ static void usage(char *prog_name) { (void) fprintf(stderr, gettext("usage: %s\n"), prog_name); - (void) fprintf(stderr, gettext("usage: %s -c disk1 disk2\n"), - prog_name); - (void) fprintf(stderr, gettext("usage: %s -d disk1\n"), prog_name); + (void) fprintf(stderr, gettext("usage: %s -c primary secondary\n"), + prog_name); + + (void) fprintf(stderr, gettext("usage: %s -c -r 1 primary secondary\n"), + prog_name); + + (void) fprintf(stderr, gettext("usage: %s -c -r 0 disk1 disk2 " + "[disk3] ...\n"), prog_name); + + (void) fprintf(stderr, gettext("usage: %s -d volume\n"), prog_name); (void) fprintf(stderr, gettext("usage: %s [-f] -F image_file controller \n"), @@ -171,6 +203,8 @@ usage(char *prog_name) (void) fprintf(stderr, gettext("example:\n")); (void) fprintf(stderr, "%s -c c1t1d0 c1t2d0\n", prog_name); + (void) fprintf(stderr, "%s -c -r 0 c1t1d0 c1t2d0 " + "c1t3d0 c1t4d0\n", prog_name); (void) fprintf(stderr, "%s -d c1t1d0\n", prog_name); (void) fprintf(stderr, "%s -F image 1\n", prog_name); @@ -250,7 +284,9 @@ get_devctl(char *disk, char *b) (void) snprintf(devctl_buf, MAXPATHLEN, "%s%s:devctl", devctl_buf, devname); + (void) strlcpy(b, devctl_buf, MAXPATHLEN); + return (0); } @@ -312,12 +348,11 @@ print_no_raids() static void add_raid_to_raidlist(char *ctrl_name, int controller) { - raid_config_t config; + raid_config_t config[N_RAIDVOLS]; raidlist_t *curr; char buf[MAXPATHLEN] = {0}; char buf1[MAXPATHLEN] = {0}; - int fd; - int i; + int fd, i, n; if (readlink(ctrl_name, buf, sizeof (buf)) < 0) return; @@ -330,16 +365,14 @@ add_raid_to_raidlist(char *ctrl_name, int controller) * listed as part of the command line input. */ if (info_ctrl != NULL) { - int found = 0; for (i = 0; i < ctrl_nums; i++) { if (info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) continue; - if (controller == info_ctrl[i][INFO_CTRL]) { - found = 1; + if (controller == info_ctrl[i][INFO_CTRL]) break; - } } - if (!found) + /* return if we didn't find a controller */ + if (i == ctrl_nums) return; } @@ -357,14 +390,23 @@ add_raid_to_raidlist(char *ctrl_name, int controller) /* Fail silently */ return; } + (void) close(fd); - if (config.ndisks == 0) { + /* check if there are any raid volumes on this hba */ + for (n = 0; n < N_RAIDVOLS; n++) { + if (config[n].ndisks != 0) + break; + } + + if (n == N_RAIDVOLS) { + /* no raid volumes were found */ if (info_ctrl != NULL) info_ctrl[i][INFO_STATUS] = RAID_NOT_FOUND; return; } + /* we've at least one raid volume on this hba */ if (info_ctrl != NULL) info_ctrl[i][INFO_STATUS] = RAID_FOUND; @@ -389,15 +431,17 @@ add_raid_to_raidlist(char *ctrl_name, int controller) (void) strlcpy(curr->devctl, buf1, sizeof (curr->devctl)); (void) fflush(stdout); - (void) memcpy(&curr->raid_config, &config, sizeof (raid_config_t)); + + (void) memcpy(&curr->raid_config, &config, + (sizeof (raid_config_t) * N_RAIDVOLS)); } static void print_header() { - (void) printf(gettext("RAID\t\tRAID\t\tRAID\t\tDisk")); + (void) printf(gettext("RAID\tVolume\tRAID\t\tRAID\t\tDisk")); (void) printf("\n"); - (void) printf(gettext("Volume\t\tStatus\t\tDisk\t\tStatus")); + (void) printf(gettext("Volume\tType\tStatus\t\tDisk\t\tStatus")); (void) printf("\n"); (void) printf("------------------------------------------------------"); (void) printf("\n"); @@ -407,9 +451,16 @@ static void print_raidconfig(int c, raid_config_t config) { int i; + char voltype[8]; + + /* print RAID volume target ID and volume type */ + if (config.raid_level == RAID_STRIPE) { + (void) snprintf(voltype, sizeof (voltype), "IS"); + } else if (config.raid_level == RAID_MIRROR) { + (void) snprintf(voltype, sizeof (voltype), "IM"); + } - /* Get RAID Volume */ - (void) printf("c%dt%dd0\t\t", c, config.targetid); + (void) printf("c%dt%dd0\t%s\t", c, config.targetid, voltype); /* Get RAID Info */ if (config.flags & RAID_FLAG_RESYNCING && @@ -453,8 +504,15 @@ static void print_disklist() { raidlist_t *curr = raids; + int i; + while (curr != NULL) { - print_raidconfig(curr->controller, curr->raid_config); + for (i = 0; i < N_RAIDVOLS; i++) { + if (curr->raid_config[i].ndisks != 0) { + print_raidconfig(curr->controller, + curr->raid_config[i]); + } + } curr = curr->next; } } @@ -557,6 +615,34 @@ do_info() } static int +disk_in_raid(int c, int t) +{ + raidlist_t *curr; + raid_config_t raid; + int i, j, n; + + do_search(); + curr = raids; + + while (curr != NULL) { + if (curr->controller == c) { + for (i = 0; i < N_RAIDVOLS; i++) { + raid = curr->raid_config[i]; + if ((n = raid.ndisks) != 0) { + for (j = 0; j < n; j++) { + if (raid.disk[j] == t) { + return (1); + } + } + } + } + } + curr = curr->next; + } + return (0); +} + +static int disk_there(int c, int t) { char disk[100]; @@ -598,9 +684,10 @@ disk_mounted(char *d) struct mnttab mt; FILE *f = fopen("/etc/mnttab", "r"); - while (getmntent(f, &mt) != EOF) + while (getmntent(f, &mt) != EOF) { if (strstr(mt.mnt_special, d) != NULL) return (1); + } return (0); } @@ -609,17 +696,18 @@ disk_big_enough(char **d, diskaddr_t *cap, int *errcond) { struct dk_minfo minfo; char disk[N_DISKS][MAXPATHLEN]; - diskaddr_t disk_lbsize[N_DISKS]; + uint_t disk_lbsize[N_DISKS]; diskaddr_t disk_capacity[N_DISKS]; int i, fd; for (i = 0; i < N_DISKS; i++) { + if (d[i] == NULL) + break; + (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); - fd = open(disk[i], O_RDWR | O_NDELAY); - if (fd == -1) { + fd = open(disk[i], O_RDWR | O_NDELAY); + if (fd == -1) return (FAILURE); - } - if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == -1) { (void) close(fd); return (FAILURE); @@ -627,22 +715,25 @@ disk_big_enough(char **d, diskaddr_t *cap, int *errcond) disk_lbsize[i] = minfo.dki_lbsize; disk_capacity[i] = minfo.dki_capacity; - (void) close(fd); - } - /* lbsize must be the same on both disks */ - if (disk_lbsize[0] != disk_lbsize[1]) { - *errcond = 2; - return (INVALID_ARG); - } + /* lbsize must be the same on all disks */ + if (disk_lbsize[0] != disk_lbsize[i]) { + *errcond = 2; + return (INVALID_ARG); + } - /* secondary size is not greater than or equal to primary size */ - if (disk_capacity[0] > disk_capacity[1]) { - *errcond = 1; - return (INVALID_ARG); + /* ensure drive capacity is greater than or equal to first */ + if (disk_capacity[0] > disk_capacity[i]) { + *errcond = 1; + return (INVALID_ARG); + } + (void) close(fd); } - /* Secondary disk is big enough */ + /* + * setting capacity as the dk_minfo.dki_capacity of d[0] + * this is the number of dki_lbsize blocks on disk + */ *cap = disk_capacity[0]; return (SUCCESS); } @@ -687,69 +778,102 @@ do_config_change_state(cfga_cmd_t cmd, int d, int c) } static int -do_create(char **d) +do_create(char **d, int rlevel) { - raid_config_t config; + raid_config_t config[N_RAIDVOLS]; + raid_config_t newvol; char disk[N_DISKS][MAXPATHLEN] = {0}; + int map[N_DISKS]; char channel1[MAXPATHLEN]; char channel2[MAXPATHLEN]; diskaddr_t capacity; - int fd, fd2, size, errcond, disk_here = 1; + int fd, fd2, size, errcond; int c[N_DISKS]; int t[N_DISKS]; char *tmp; - int i; + int loc, i; + int ndisks = 0; + ushort_t devid; (void) chdir(DEVDIR); + /* initialize target map */ + for (i = 0; i < N_DISKS; i++) + map[i] = -1; + for (i = 0; i < N_DISKS; i++) { + if (d[i] == NULL) + break; + if ((sscanf(d[i], "c%dt%dd0", &c[i], &t[i])) != 2 || t[i] < 0) { (void) fprintf(stderr, gettext("Invalid disk format.\n")); return (INVALID_ARG); } - (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); - } - /* Must be on same controller */ - if (c[0] != c[1]) { - (void) fprintf(stderr, - gettext("Disks must be on the same controller.\n")); - return (INVALID_ARG); - } + /* ensure that all disks are on the same controller, */ + if (c[i] != c[0]) { + (void) fprintf(stderr, gettext("Disks must be " + "on the same controller.\n")); + return (INVALID_ARG); + } - /* primary disk target must be lower than secondary disk target */ - if (t[0] > t[1]) { - (void) fprintf(stderr, gettext("Primary target ID " - "must be less than secondary target ID.\n")); - return (INVALID_ARG); - } + /* that all disks are online, */ + if (disk_there(c[0], t[i])) { + (void) printf(gettext("Disk 'c%dt%dd0' is not " + "present.\n"), c[0], t[i]); + (void) printf(gettext("Cannot create RAID volume.\n")); + return (INVALID_ARG); + } - /* disks must not be the same */ - if (t[0] == t[1]) { - (void) fprintf(stderr, gettext("Disks must be different.\n")); - return (INVALID_ARG); - } + /* that there are no duplicate disks, */ + loc = t[i]; + if (map[loc] == -1) { + map[loc] = t[i]; + } else { + (void) fprintf(stderr, + gettext("Disks must be different.\n")); + return (INVALID_ARG); + } - /* disks must be present */ - if (disk_there(c[0], t[0])) { - (void) printf(gettext("Disk 'c%dt%dd0' is not present.\n"), - c[0], t[0]); - disk_here = 0; - } - if (disk_there(c[1], t[1])) { - (void) printf(gettext("Disk 'c%dt%dd0' is not present.\n"), - c[0], t[1]); - disk_here = 0; - } + /* that no disk is already in use by another volume, */ + if (disk_in_raid(c[0], t[i])) { + (void) fprintf(stderr, gettext("Disk %s is already in " + "a RAID volume.\n"), d[i]); + return (INVALID_ARG); + } - if (!disk_here) { - (void) printf(gettext("Cannot create RAID volume.\n")); - return (INVALID_ARG); + /* that no target's id is lower than the raidtarg, */ + if (t[0] > t[i]) { + (void) fprintf(stderr, gettext("First target ID must " + "be less than other member target IDs.\n")); + return (INVALID_ARG); + } + + /* and that no disk other than a mirror primary is mounted */ + if (disk_mounted(d[i])) { + /* data on all stripe disks will be destroyed */ + if ((rlevel == RAID_STRIPE) && (i != 0)) { + (void) fprintf(stderr, gettext("Cannot " + "create RAID0 volume, secondary disk " + "\"%s\" is mounted.\n"), d[i]); + return (INVALID_ARG); + } + /* data on mirror's secondary will be destroyed */ + if (i != 0) { + (void) fprintf(stderr, gettext("Cannot " + "create RAID mirror, secondary " + "disk \"%s\" is mounted.\n"), d[i]); + return (INVALID_ARG); + } + } + + (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); + ndisks++; } - /* secondary disk's size must be greater or equal to primary disk's */ + /* validate the drive capacities */ switch (disk_big_enough(d, &capacity, &errcond)) { case FAILURE: return (FAILURE); @@ -766,14 +890,14 @@ do_create(char **d) return (INVALID_ARG); } - /* secondary disk must not be mounted */ - if (disk_mounted(d[1])) { - (void) fprintf(stderr, gettext("Cannot create RAID volume when " - "secondary disk \"%s\" is mounted.\n"), d[1]); - return (INVALID_ARG); - } + /* + * capacity is now set to the number of blocks on a disk, which is + * the total capacity of a mirror. the capacity of a stripe is the + * cumulative amount of blocks on all disks + */ + if (rlevel == RAID_STRIPE) + capacity *= ndisks; - /* Only one RAID can exist per controller */ if (get_devctl(disk[0], channel1)) return (FAILURE); @@ -783,20 +907,53 @@ do_create(char **d) return (FAILURE); } + /* get the current configuration */ if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { raidctl_error("RAID_GETCONFIG"); - goto fail1; + goto fail; } - if (config.ndisks != 0) { - (void) printf(gettext("RAID Volume already exists on this " - "controller 'c%dt%dd0'\n"), c[0], config.targetid); - goto fail1; + /* + * current support for both LSI1030 and LSI1064 HBAs + * get the devid of the HBA so we can determine capabilities + */ + if (ioctl(fd, RAID_GETDEVID, &devid) < 0) { + raidctl_error("RAID_GETDEVID"); + goto fail; } + if ((devid == LSI_1064) || (devid == LSI_1064E)) { + /* + * 2 raid volumes supported, single channel + */ + for (i = 0; i < N_RAIDVOLS; i++) { + if (config[i].ndisks == 0) + goto no_secondary_channel; + } + + (void) printf(gettext("HBA supports a maximum of 2 " + "RAID Volumes, HBA is full\n")); + goto fail; + } + + /* + * LSI1030, support for single IM volume + */ + if (rlevel != RAID_MIRROR) { + (void) printf(gettext("HBA only supports RAID " + "level 1 (mirrored) volumes\n")); + goto fail; + } + + if (config[0].ndisks != 0) { + (void) printf(gettext("RAID Volume already exists " + "on this controller 'c%dt%dd0'\n"), + c[0], config[0].targetid); + goto fail; + } /* * Make sure there isn't a raid created on this controller's - * other channel + * other channel, if it has multiple channels */ (void) strlcpy(channel2, channel1, sizeof (channel2)); tmp = strrchr(channel2, ':'); @@ -805,19 +962,19 @@ do_create(char **d) /* * Format the channel string for the other channel so we can - * see if a raid exists on it. In this case if we are being asked - * to create a raid on channel 2 (indicated by the 1,1 at the end - * of the string) we want to check channel 1) otherwise we will - * check channel 2. + * see if a raid exists on it. In this case if we are being + * asked to create a raid on channel 2 (indicated by the 1,1 + * at the end of the string) we want to check channel 1), + * otherwise we will check channel 2. */ if (channel2[size - 2] == ',') { channel2[size - 1] = 0; channel2[size - 2] = 0; - (void) snprintf(channel2, sizeof (channel2), "%s:devctl", - channel2); + (void) snprintf(channel2, sizeof (channel2), + "%s:devctl", channel2); } else { - (void) snprintf(channel2, sizeof (channel2), "%s,1:devctl", - channel2); + (void) snprintf(channel2, sizeof (channel2), + "%s,1:devctl", channel2); } fd2 = open(channel2, O_RDONLY); @@ -825,42 +982,49 @@ do_create(char **d) if (errno == ENOENT) goto no_secondary_channel; perror(channel2); - goto fail1; + goto fail; } if (ioctl(fd2, RAID_GETCONFIG, &config) < 0) { - goto fail2; + goto fail; } - if (config.ndisks != 0) { + if (config[0].ndisks != 0) { int cx; cx = get_controller(channel2); - (void) printf(gettext("RAID Volume already exists on this " - "controller 'c%dt%dd0'\n"), cx, config.targetid); - goto fail2; + (void) printf(gettext("RAID Volume already exists " + "on this controller 'c%dt%dd0'\n"), cx, + config[0].targetid); + goto fail; } no_secondary_channel: - /* No other RAID volumes exist, so we may continue */ - config.raid_capacity = capacity; - config.raid_level = 1; /* RAID 1: Mirror */ - config.targetid = t[0]; /* Assume identity of first disk */ - config.disk[0] = t[0]; /* Primary Disk */ - config.disk[1] = t[1]; /* Secondary Disk */ - - /* Make secondary disk inaccessible to the system */ - if (do_config_change_state(CFGA_CMD_UNCONFIGURE, - config.disk[1], c[0])) { - perror("config_change_state"); - goto fail2; + /* all checks complete, fill in the config */ + newvol.targetid = t[0]; + newvol.disk[0] = t[0]; + newvol.raid_level = rlevel; + newvol.ndisks = ndisks; + newvol.raid_capacity = capacity; + + /* populate config.disk, and unconfigure all disks, except targetid */ + for (i = 1; i < ndisks; i++) { + if (do_config_change_state(CFGA_CMD_UNCONFIGURE, + t[i], c[0])) { + perror("config_change_state"); + goto fail; + } + newvol.disk[i] = t[i]; } - if (ioctl(fd, RAID_CREATE, &config)) { - (void) do_config_change_state(CFGA_CMD_CONFIGURE, - config.disk[1], c[0]); + if (ioctl(fd, RAID_CREATE, &newvol)) { + /* reconfigure all disks, except targetid */ + for (i = 1; i < ndisks; i++) { + (void) do_config_change_state(CFGA_CMD_CONFIGURE, + newvol.disk[i], c[0]); + } raidctl_error("RAID_CREATE"); - goto fail2; + goto fail; } (void) printf(gettext("Volume 'c%dt%dd0' created\n"), c[0], t[0]); @@ -868,22 +1032,23 @@ no_secondary_channel: (void) close(fd2); return (SUCCESS); -fail2: - (void) close(fd2); -fail1: +fail: (void) close(fd); + (void) close(fd2); return (FAILURE); } static int do_delete(char *d) { - raid_config_t config; + raid_config_t config[N_RAIDVOLS]; char disk1[MAXPATHLEN]; char buf[MAXPATHLEN]; int fd; int target; int ctrl; + int i, j; + int wrong_targ = 0; uint8_t t; (void) chdir(DEVDIR); @@ -897,6 +1062,7 @@ do_delete(char *d) (void) snprintf(disk1, sizeof (disk1), DEVDIR"/%ss2", d); if (get_devctl(disk1, buf) != 0) { + (void) fprintf(stderr, gettext("Not a volume '%s'\n"), d); return (FAILURE); } @@ -911,13 +1077,27 @@ do_delete(char *d) goto fail; } - if (config.ndisks == 0) { - (void) fprintf(stderr, gettext("No RAID Volume exists on " + for (i = 0; i < N_RAIDVOLS; i++) { + if (config[i].ndisks != 0) { + /* there is a RAID volume in this slot */ + if (config[i].targetid != t) { + wrong_targ++; + continue; + } + /* and it's our target */ + break; + } + } + + if (i == N_RAIDVOLS) { + /* we found no RAID volumes */ + (void) fprintf(stderr, gettext("No RAID volumes exist on " "controller '%d'\n"), ctrl); goto fail; } - if (config.targetid != t) { + if (wrong_targ == N_RAIDVOLS) { + /* we found RAID volumes, but none matched */ (void) fprintf(stderr, gettext("RAID volume 'c%dt%dd0' does not exist\n"), ctrl, t); @@ -929,11 +1109,11 @@ do_delete(char *d) goto fail; } - /* - * Make secondary disk accessible to the system. - * Ignore return value from do_config_change_state. - */ - (void) do_config_change_state(CFGA_CMD_CONFIGURE, config.disk[1], ctrl); + /* reconfigure all disks, except targetid */ + for (j = 1; j < config[i].ndisks; j++) { + (void) do_config_change_state(CFGA_CMD_CONFIGURE, + config[i].disk[j], ctrl); + } (void) fprintf(stderr, gettext("Volume 'c%dt%dd0' deleted.\n"), ctrl, target); @@ -1348,9 +1528,10 @@ main(int argc, char **argv) int i, c; int findex = DO_HW_RAID_INFO; int controller; - char *disks[N_DISKS]; + char *disks[N_DISKS] = {0}; char *darg; char *farg; + char *rarg; char *progname; int l_flag = 0; @@ -1358,7 +1539,9 @@ main(int argc, char **argv) int d_flag = 0; int f_flag = 0; int F_flag = 0; + int r_flag = 0; int no_flags = 1; + int r = RAID_MIRROR; /* default raid level is 1 */ char *current_dir; (void) setlocale(LC_ALL, ""); @@ -1379,17 +1562,22 @@ main(int argc, char **argv) (void) strncpy(yeschr, nl_langinfo(YESSTR), SCHAR_MAX + 1); (void) strncpy(nochr, nl_langinfo(NOSTR), SCHAR_MAX + 1); - while ((c = getopt(argc, argv, "clfd:F:")) != EOF) { + while ((c = getopt(argc, argv, "cr:lfd:F:")) != EOF) { switch (c) { case 'c': - if (f_flag || argc != 4) { + if (f_flag || argc < 4) usage(progname); - } - findex = DO_HW_RAID_CREATE; c_flag = 1; no_flags = 0; break; + case 'r': + rarg = optarg; + r = atoi(rarg); + if ((r != RAID_STRIPE) && (r != RAID_MIRROR)) + usage(progname); + r_flag = 1; + break; case 'd': darg = optarg; d_flag = 1; @@ -1411,7 +1599,8 @@ main(int argc, char **argv) f_flag = 1; no_flags = 0; break; - case '?': default: + case '?': + default: usage(progname); } } @@ -1422,9 +1611,11 @@ main(int argc, char **argv) /* compatibility rules */ if (c_flag && d_flag) usage(progname); - if (l_flag && (d_flag || c_flag || f_flag || F_flag)) + if (r_flag && !(c_flag)) + usage(progname); + if (l_flag && (d_flag || c_flag || f_flag || F_flag || r_flag)) usage(progname); - if (F_flag && (d_flag || c_flag || l_flag)) + if (F_flag && (d_flag || c_flag || l_flag || r_flag)) usage(progname); switch (findex) { @@ -1470,11 +1661,22 @@ main(int argc, char **argv) break; case DO_HW_RAID_CREATE: for (i = 0; i < N_DISKS; i++) { - disks[i] = argv[argc - 2 + i]; + int p = 2 + (r_flag * 2) + i; + + if (p == argc) + break; + + disks[i] = argv[p]; + if (!canonical_name(disks[i])) usage(progname); + + /* no more than 2 disks for raid level 1 */ + if ((r == RAID_MIRROR) && (i > 1)) + usage(progname); } - rv = do_create(disks); + + rv = do_create(disks, r); break; case DO_HW_RAID_DELETE: if (!canonical_name(darg)) @@ -1483,12 +1685,6 @@ main(int argc, char **argv) rv = do_delete(darg); break; case DO_HW_RAID_FLASH: - /* - * "raidctl" makes argc == 1 - * "-F" makes argc == 2 - * "filename" makes argc == 3 - * "-f" makes argc == 4 if added. - */ ctrl_nums = argc - f_flag - 3; if (ctrl_nums == 0) usage(progname); |
