summaryrefslogtreecommitdiff
path: root/usr/src/cmd/raidctl/raidctl.c
diff options
context:
space:
mode:
authorjesseb <none@none>2005-09-01 20:01:56 -0700
committerjesseb <none@none>2005-09-01 20:01:56 -0700
commit0541156464ba74bca005fda4b225d3bbe53f7a0c (patch)
tree257068e59870bb2b578ad3dd2d45f86280b38d9e /usr/src/cmd/raidctl/raidctl.c
parent2c75e67e98ffd095634e492eb347bac08db7c288 (diff)
downloadillumos-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.c494
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);