mpb = super->anchor;
- if (strcmp(update, "uuid") == 0 && uuid_set && !info->update_private)
- rv = -1;
- else if (strcmp(update, "uuid") == 0 && uuid_set && info->update_private) {
- mpb->orig_family_num = *((__u32 *) info->update_private);
- rv = 0;
- } else if (strcmp(update, "uuid") == 0) {
- __u32 *new_family = malloc(sizeof(*new_family));
-
- /* update orig_family_number with the incoming random
- * data, report the new effective uuid, and store the
- * new orig_family_num for future updates.
+ if (strcmp(update, "uuid") == 0) {
+ /* We take this to mean that the family_num should be updated.
+ * However that is much smaller than the uuid so we cannot really
+ * allow an explicit uuid to be given. And it is hard to reliably
+ * know if one was.
+ * So if !uuid_set we know the current uuid is random and just used
+ * the first 'int' and copy it to the other 3 positions.
+ * Otherwise we require the 4 'int's to be the same as would be the
+ * case if we are using a random uuid. So an explicit uuid will be
+ * accepted as long as all for ints are the same... which shouldn't hurt
*/
- if (new_family) {
- memcpy(&mpb->orig_family_num, info->uuid, sizeof(__u32));
- uuid_from_super_imsm(st, info->uuid);
- *new_family = mpb->orig_family_num;
- info->update_private = new_family;
+ if (!uuid_set) {
+ info->uuid[1] = info->uuid[2] = info->uuid[3] = info->uuid[0];
rv = 0;
+ } else {
+ if (info->uuid[0] != info->uuid[1] ||
+ info->uuid[1] != info->uuid[2] ||
+ info->uuid[2] != info->uuid[3])
+ rv = -1;
+ else
+ rv = 0;
}
+ if (rv == 0)
+ mpb->orig_family_num = info->uuid[0];
} else if (strcmp(update, "assemble") == 0)
rv = 0;
else
rv = readlink(path, dname, sizeof(dname)-1);
if (rv <= 0)
return;
-
+
dname[rv] = '\0';
nm = strrchr(dname, '/');
if (nm) {
return champion;
}
+
+static int
+get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd);
+
+static int get_super_block(struct intel_super **super_list, int devnum, char *devname,
+ int major, int minor, int keep_fd);
+
static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
- char *devname)
+ char *devname, int keep_fd)
{
- struct mdinfo *sra;
struct intel_super *super_list = NULL;
struct intel_super *super = NULL;
- int devnum = fd2devnum(fd);
- struct mdinfo *sd;
- int retry;
int err = 0;
- int i;
+ int i = 0;
- /* check if 'fd' an opened container */
- sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
- if (!sra)
+ if (fd >= 0)
+ /* 'fd' is an opened container */
+ err = get_sra_super_block(fd, &super_list, devname, &i, keep_fd);
+ else
return 1;
-
- if (sra->array.major_version != -1 ||
- sra->array.minor_version != -2 ||
- strcmp(sra->text_version, "imsm") != 0) {
- err = 1;
+ if (err)
goto error;
- }
- /* load all mpbs */
- for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) {
- struct intel_super *s = alloc_super();
- char nm[32];
- int dfd;
- int rv;
-
- err = 1;
- if (!s)
- goto error;
- s->next = super_list;
- super_list = s;
-
- err = 2;
- sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
- dfd = dev_open(nm, O_RDWR);
- if (dfd < 0)
- goto error;
-
- rv = find_intel_hba_capability(dfd, s, devname);
- /* no orom/efi or non-intel hba of the disk */
- if (rv != 0)
- goto error;
-
- err = load_and_parse_mpb(dfd, s, NULL, 1);
-
- /* retry the load if we might have raced against mdmon */
- if (err == 3 && mdmon_running(devnum))
- for (retry = 0; retry < 3; retry++) {
- usleep(3000);
- err = load_and_parse_mpb(dfd, s, NULL, 1);
- if (err != 3)
- break;
- }
- if (err)
- goto error;
- }
-
/* all mpbs enter, maybe one leaves */
super = imsm_thunderdome(&super_list, i);
if (!super) {
super_list = super_list->next;
free_imsm(s);
}
- sysfs_free(sra);
+
if (err)
return err;
*sbp = super;
- st->container_dev = devnum;
+ if (fd >= 0)
+ st->container_dev = fd2devnum(fd);
+ else
+ st->container_dev = NoMdDev;
if (err == 0 && st->ss == NULL) {
st->ss = &super_imsm;
st->minor_version = 0;
return 0;
}
+
+
+
+static int get_super_block(struct intel_super **super_list, int devnum, char *devname,
+ int major, int minor, int keep_fd)
+{
+ struct intel_super*s = NULL;
+ char nm[32];
+ int dfd = -1;
+ int rv;
+ int err = 0;
+ int retry;
+
+ s = alloc_super();
+ if (!s) {
+ err = 1;
+ goto error;
+ }
+
+ sprintf(nm, "%d:%d", major, minor);
+ dfd = dev_open(nm, O_RDWR);
+ if (dfd < 0) {
+ err = 2;
+ goto error;
+ }
+
+ rv = find_intel_hba_capability(dfd, s, devname);
+ /* no orom/efi or non-intel hba of the disk */
+ if (rv != 0) {
+ err = 4;
+ goto error;
+ }
+
+ err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
+
+ /* retry the load if we might have raced against mdmon */
+ if (err == 3 && (devnum != -1) && mdmon_running(devnum))
+ for (retry = 0; retry < 3; retry++) {
+ usleep(3000);
+ err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
+ if (err != 3)
+ break;
+ }
+ error:
+ if (!err) {
+ s->next = *super_list;
+ *super_list = s;
+ } else {
+ if (s)
+ free(s);
+ if (dfd)
+ close(dfd);
+ }
+ if ((dfd >= 0) && (!keep_fd))
+ close(dfd);
+ return err;
+
+}
+
+static int
+get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd)
+{
+ struct mdinfo *sra;
+ int devnum;
+ struct mdinfo *sd;
+ int err = 0;
+ int i = 0;
+ sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
+ if (!sra)
+ return 1;
+
+ if (sra->array.major_version != -1 ||
+ sra->array.minor_version != -2 ||
+ strcmp(sra->text_version, "imsm") != 0) {
+ err = 1;
+ goto error;
+ }
+ /* load all mpbs */
+ devnum = fd2devnum(fd);
+ for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) {
+ if (get_super_block(super_list, devnum, devname,
+ sd->disk.major, sd->disk.minor, keep_fd) != 0) {
+ err = 7;
+ goto error;
+ }
+ }
+ error:
+ sysfs_free(sra);
+ *max = i;
+ return err;
+}
+
static int load_container_imsm(struct supertype *st, int fd, char *devname)
{
- return load_super_imsm_all(st, fd, &st->sb, devname);
+ return load_super_imsm_all(st, fd, &st->sb, devname, 1);
}
#endif
mpb = super->anchor;
- if (mpb->num_raid_devs > 0 && mpb->num_disks != raiddisks) {
- fprintf(stderr, Name ": the option-rom requires all "
- "member disks to be a member of all volumes.\n");
- return 0;
- }
-
if (!validate_geometry_imsm_orom(super, level, layout, raiddisks, chunk, verbose)) {
fprintf(stderr, Name ": RAID gemetry validation failed. "
"Cannot proceed with the action(s).\n");
fprintf(stderr, Name ": The option-rom requires all member"
" disks to be a member of all volumes\n");
return 0;
+ } else if (super->orom && mpb->num_raid_devs > 0 &&
+ mpb->num_disks != raiddisks) {
+ fprintf(stderr, Name ": The option-rom requires all member"
+ " disks to be a member of all volumes\n");
+ return 0;
}
/* retrieve the largest free space block */
}
if (maxsize < size || maxsize == 0) {
- if (verbose)
- fprintf(stderr, Name ": not enough space after merge (%llu < %llu)\n",
- maxsize, size);
+ if (verbose) {
+ if (maxsize == 0)
+ fprintf(stderr, Name ": no free space"
+ " left on device. Aborting...\n");
+ else
+ fprintf(stderr, Name ": not enough space"
+ " to create volume of given size"
+ " (%llu < %llu). Aborting...\n",
+ maxsize, size);
+ }
return 0;
}
dev, freesize,
verbose);
}
-
+
if (!dev) {
if (st->sb) {
if (!validate_geometry_imsm_orom(st->sb, level, layout,
*/
struct intel_super *super;
- if (load_super_imsm_all(st, cfd, (void **) &super, NULL) == 0) {
+ if (load_super_imsm_all(st, cfd, (void **) &super, NULL, 1) == 0) {
st->sb = super;
st->container_dev = fd2devnum(cfd);
close(cfd);
{
struct intel_super *super = c->sb;
struct imsm_super *mpb = super->anchor;
-
+
if (atoi(inst) >= mpb->num_raid_devs) {
fprintf(stderr, "%s: subarry index %d, out of range\n",
__func__, atoi(inst));
int change = -1;
int check_devs = 0;
int chunk;
- int devNumChange=0;
- int layout = -1;
+ /* number of added/removed disks in operation result */
+ int devNumChange = 0;
+ /* imsm compatible layout value for array geometry verification */
+ int imsm_layout = -1;
getinfo_super_imsm_volume(st, &info, NULL);
if ((geo->level != info.array.level) &&
change = -1;
goto analyse_change_exit;
}
- layout = geo->layout;
+ imsm_layout = geo->layout;
check_devs = 1;
devNumChange = 1; /* parity disk added */
} else if (geo->level == 10) {
change = CH_TAKEOVER;
check_devs = 1;
devNumChange = 2; /* two mirrors added */
- layout = 0x102; /* imsm supported layout */
+ imsm_layout = 0x102; /* imsm supported layout */
}
break;
case 1:
change = CH_TAKEOVER;
check_devs = 1;
devNumChange = -(geo->raid_disks/2);
- layout = 0; /* imsm raid0 layout */
+ imsm_layout = 0; /* imsm raid0 layout */
}
break;
}
change = -1;
goto analyse_change_exit;
}
- } else
+ } else {
geo->layout = info.array.layout;
+ if (imsm_layout == -1)
+ imsm_layout = info.array.layout;
+ }
if ((geo->chunksize > 0) && (geo->chunksize != UnSet)
&& (geo->chunksize != info.array.chunk_size))
chunk = geo->chunksize / 1024;
if (!validate_geometry_imsm(st,
geo->level,
- layout,
+ imsm_layout,
geo->raid_disks + devNumChange,
&chunk,
geo->size,