* (for recovered migrations) */
} __attribute__ ((__packed__));
+struct md_list {
+ /* usage marker:
+ * 1: load metadata
+ * 2: metadata does not match
+ * 4: already checked
+ */
+ int used;
+ char *devname;
+ int found;
+ int container;
+ dev_t st_rdev;
+ struct md_list *next;
+};
+
+#define pr_vrb(fmt, arg...) (void) (verbose && fprintf(stderr, Name fmt, ##arg))
+
static __u8 migr_type(struct imsm_dev *dev)
{
if (dev->vol.migr_type == MIGR_VERIFY &&
* Returns:
* 0 : success
* -1 : fail
+ * -2 : no migration in progress
******************************************************************************/
static int load_imsm_migr_rec(struct intel_super *super, struct mdinfo *info)
{
/* nothing to load,no migration in progress?
*/
if (dev == NULL)
- return 0;
+ return -2;
map = get_imsm_map(dev, MAP_0);
if (info) {
enough = 0;
else /* we're normal, or already degraded */
enough = 1;
-
+ if (is_gen_migration(dev) && missing) {
+ /* during general migration we need all disks
+ * that process is running on.
+ * No new missing disk is allowed.
+ */
+ max_enough = -1;
+ enough = -1;
+ /* no more checks necessary
+ */
+ break;
+ }
/* in the missing/failed disk case check to see
* if at least one array is runnable
*/
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) {
len_migr = sizeof_imsm_dev(dev_iter, 1);
if (len_migr > len)
space_needed += len_migr - len;
-
+
dv = malloc(sizeof(*dv));
if (!dv)
return 1;
super->buf = buf;
super->len = len;
}
-
+
return 0;
}
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
+get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list,
+ int *max, int keep_fd);
+
+
static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
- char *devname)
+ char *devname, struct md_list *devlist,
+ 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)
- return 1;
-
- if (sra->array.major_version != -1 ||
- sra->array.minor_version != -2 ||
- strcmp(sra->text_version, "imsm") != 0) {
- err = 1;
+ if (fd >= 0)
+ /* 'fd' is an opened container */
+ err = get_sra_super_block(fd, &super_list, devname, &i, keep_fd);
+ else
+ /* get super block from devlist devices */
+ err = get_devlist_super_block(devlist, &super_list, &i, keep_fd);
+ 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) {
/* load migration record */
err = load_imsm_migr_rec(super, NULL);
- if (err) {
+ if (err == -1) {
+ /* migration is in progress,
+ * but migr_rec cannot be loaded,
+ */
err = 4;
goto error;
}
/* Check migration compatibility */
- if (check_mpb_migr_compatibility(super) != 0) {
+ if ((err == 0) && (check_mpb_migr_compatibility(super) != 0)) {
fprintf(stderr, Name ": Unsupported migration detected");
if (devname)
fprintf(stderr, " on %s\n", devname);
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_devlist_super_block(struct md_list *devlist, struct intel_super **super_list,
+ int *max, int keep_fd)
+{
+ struct md_list *tmpdev;
+ int err = 0;
+ int i = 0;
+
+ for (i = 0, tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) {
+ if (tmpdev->used != 1)
+ continue;
+ if (tmpdev->container == 1) {
+ int lmax = 0;
+ int fd = dev_open(tmpdev->devname, O_RDONLY|O_EXCL);
+ if (fd < 0) {
+ fprintf(stderr, Name ": cannot open device %s: %s\n",
+ tmpdev->devname, strerror(errno));
+ err = 8;
+ goto error;
+ }
+ err = get_sra_super_block(fd, super_list,
+ tmpdev->devname, &lmax,
+ keep_fd);
+ i += lmax;
+ close(fd);
+ if (err) {
+ err = 7;
+ goto error;
+ }
+ } else {
+ int major = major(tmpdev->st_rdev);
+ int minor = minor(tmpdev->st_rdev);
+ err = get_super_block(super_list,
+ -1,
+ tmpdev->devname,
+ major, minor,
+ keep_fd);
+ i++;
+ if (err) {
+ err = 6;
+ goto error;
+ }
+ }
+ }
+ error:
+ *max = i;
+ return err;
+}
+
+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, NULL, 1);
}
#endif
if (d->index < 0 || is_failed(&d->disk))
continue;
if (store_imsm_mpb(d->fd, mpb))
- fprintf(stderr, "%s: failed for device %d:%d %s\n",
- __func__, d->major, d->minor, strerror(errno));
+ fprintf(stderr, "%s: failed for device %d:%d (fd: %d)%s\n",
+ __func__, d->major, d->minor, d->fd, strerror(errno));
+
if (clear_migration_record) {
unsigned long long dsize;
return 0;
}
+
+static int
+active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
+ int dpa, int verbose)
+{
+ struct mdstat_ent *mdstat = mdstat_read(0, 0);
+ struct mdstat_ent *memb = NULL;
+ int count = 0;
+ int num = 0;
+ struct md_list *dv = NULL;
+ int found;
+
+ for (memb = mdstat ; memb ; memb = memb->next) {
+ if (memb->metadata_version &&
+ (strncmp(memb->metadata_version, "external:", 9) == 0) &&
+ (strcmp(&memb->metadata_version[9], name) == 0) &&
+ !is_subarray(memb->metadata_version+9) &&
+ memb->members) {
+ struct dev_member *dev = memb->members;
+ int fd = -1;
+ while(dev && (fd < 0)) {
+ char *path = malloc(strlen(dev->name) + strlen("/dev/") + 1);
+ if (path) {
+ num = sprintf(path, "%s%s", "/dev/", dev->name);
+ if (num > 0)
+ fd = open(path, O_RDONLY, 0);
+ if ((num <= 0) || (fd < 0)) {
+ pr_vrb(": Cannot open %s: %s\n",
+ dev->name, strerror(errno));
+ }
+ free(path);
+ }
+ dev = dev->next;
+ }
+ found = 0;
+ if ((fd >= 0) && disk_attached_to_hba(fd, hba)) {
+ struct mdstat_ent *vol;
+ for (vol = mdstat ; vol ; vol = vol->next) {
+ if ((vol->active > 0) &&
+ vol->metadata_version &&
+ is_container_member(vol, memb->dev)) {
+ found++;
+ count++;
+ }
+ }
+ if (*devlist && (found < dpa)) {
+ dv = calloc(1, sizeof(*dv));
+ if (dv == NULL)
+ fprintf(stderr, Name ": calloc failed\n");
+ else {
+ dv->devname = malloc(strlen(memb->dev) + strlen("/dev/") + 1);
+ if (dv->devname != NULL) {
+ sprintf(dv->devname, "%s%s", "/dev/", memb->dev);
+ dv->found = found;
+ dv->used = 0;
+ dv->next = *devlist;
+ *devlist = dv;
+ } else
+ free(dv);
+ }
+ }
+ }
+ if (fd >= 0)
+ close(fd);
+ }
+ }
+ free_mdstat(mdstat);
+ return count;
+}
+
+#ifdef DEBUG_LOOP
+static struct md_list*
+get_loop_devices(void)
+{
+ int i;
+ struct md_list *devlist = NULL;
+ struct md_list *dv = NULL;
+
+ for(i = 0; i < 12; i++) {
+ dv = calloc(1, sizeof(*dv));
+ if (dv == NULL) {
+ fprintf(stderr, Name ": calloc failed\n");
+ break;
+ }
+ dv->devname = malloc(40);
+ if (dv->devname == NULL) {
+ fprintf(stderr, Name ": malloc failed\n");
+ free(dv);
+ break;
+ }
+ sprintf(dv->devname, "/dev/loop%d", i);
+ dv->next = devlist;
+ devlist = dv;
+ }
+ return devlist;
+}
+#endif
+
+static struct md_list*
+get_devices(const char *hba_path)
+{
+ struct md_list *devlist = NULL;
+ struct md_list *dv = NULL;
+ struct dirent *ent;
+ DIR *dir;
+ int err = 0;
+
+#if DEBUG_LOOP
+ devlist = get_loop_devices();
+ return devlist;
+#endif
+ /* scroll through /sys/dev/block looking for devices attached to
+ * this hba
+ */
+ dir = opendir("/sys/dev/block");
+ for (ent = dir ? readdir(dir) : NULL; ent; ent = readdir(dir)) {
+ int fd;
+ char buf[1024];
+ int major, minor;
+ char *path = NULL;
+ if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2)
+ continue;
+ path = devt_to_devpath(makedev(major, minor));
+ if (!path)
+ continue;
+ if (!path_attached_to_hba(path, hba_path)) {
+ free(path);
+ path = NULL;
+ continue;
+ }
+ free(path);
+ path = NULL;
+ fd = dev_open(ent->d_name, O_RDONLY);
+ if (fd >= 0) {
+ fd2devname(fd, buf);
+ close(fd);
+ } else {
+ fprintf(stderr, Name ": cannot open device: %s\n",
+ ent->d_name);
+ continue;
+ }
+
+
+ dv = calloc(1, sizeof(*dv));
+ if (dv == NULL) {
+ fprintf(stderr, Name ": malloc failed\n");
+ err = 1;
+ break;
+ }
+ dv->devname = strdup(buf);
+ if (dv->devname == NULL) {
+ fprintf(stderr, Name ": malloc failed\n");
+ err = 1;
+ free(dv);
+ break;
+ }
+ dv->next = devlist;
+ devlist = dv;
+ }
+ if (err) {
+ while(devlist) {
+ dv = devlist;
+ devlist = devlist->next;
+ free(dv->devname);
+ free(dv);
+ }
+ }
+ return devlist;
+}
+
+static int
+count_volumes_list(struct md_list *devlist, char *homehost,
+ int verbose, int *found)
+{
+ struct md_list *tmpdev;
+ int count = 0;
+ struct supertype *st = NULL;
+
+ /* first walk the list of devices to find a consistent set
+ * that match the criterea, if that is possible.
+ * We flag the ones we like with 'used'.
+ */
+ *found = 0;
+ st = match_metadata_desc_imsm("imsm");
+ if (st == NULL) {
+ pr_vrb(": cannot allocate memory for imsm supertype\n");
+ return 0;
+ }
+
+ for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) {
+ char *devname = tmpdev->devname;
+ struct stat stb;
+ struct supertype *tst;
+ int dfd;
+ if (tmpdev->used > 1)
+ continue;
+ tst = dup_super(st);
+ if (tst == NULL) {
+ pr_vrb(": cannot allocate memory for imsm supertype\n");
+ goto err_1;
+ }
+ tmpdev->container = 0;
+ dfd = dev_open(devname, O_RDONLY|O_EXCL);
+ if (dfd < 0) {
+ dprintf(": cannot open device %s: %s\n",
+ devname, strerror(errno));
+ tmpdev->used = 2;
+ } else if (fstat(dfd, &stb)< 0) {
+ /* Impossible! */
+ dprintf(": fstat failed for %s: %s\n",
+ devname, strerror(errno));
+ tmpdev->used = 2;
+ } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
+ dprintf(": %s is not a block device.\n",
+ devname);
+ tmpdev->used = 2;
+ } else if (must_be_container(dfd)) {
+ struct supertype *cst;
+ cst = super_by_fd(dfd, NULL);
+ if (cst == NULL) {
+ dprintf(": cannot recognize container type %s\n",
+ devname);
+ tmpdev->used = 2;
+ } else if (tst->ss != st->ss) {
+ dprintf(": non-imsm container - ignore it: %s\n",
+ devname);
+ tmpdev->used = 2;
+ } else if (!tst->ss->load_container ||
+ tst->ss->load_container(tst, dfd, NULL))
+ tmpdev->used = 2;
+ else {
+ tmpdev->container = 1;
+ }
+ if (cst)
+ cst->ss->free_super(cst);
+ } else {
+ tmpdev->st_rdev = stb.st_rdev;
+ if (tst->ss->load_super(tst,dfd, NULL)) {
+ dprintf(": no RAID superblock on %s\n",
+ devname);
+ tmpdev->used = 2;
+ } else if (tst->ss->compare_super == NULL) {
+ dprintf(": Cannot assemble %s metadata on %s\n",
+ tst->ss->name, devname);
+ tmpdev->used = 2;
+ }
+ }
+ if (dfd >= 0)
+ close(dfd);
+ if (tmpdev->used == 2 || tmpdev->used == 4) {
+ /* Ignore unrecognised devices during auto-assembly */
+ goto loop;
+ }
+ else {
+ struct mdinfo info;
+ tst->ss->getinfo_super(tst, &info, NULL);
+
+ if (st->minor_version == -1)
+ st->minor_version = tst->minor_version;
+
+ if (memcmp(info.uuid, uuid_zero,
+ sizeof(int[4])) == 0) {
+ /* this is a floating spare. It cannot define
+ * an array unless there are no more arrays of
+ * this type to be found. It can be included
+ * in an array of this type though.
+ */
+ tmpdev->used = 3;
+ goto loop;
+ }
+
+ if (st->ss != tst->ss ||
+ st->minor_version != tst->minor_version ||
+ st->ss->compare_super(st, tst) != 0) {
+ /* Some mismatch. If exactly one array matches this host,
+ * we can resolve on that one.
+ * Or, if we are auto assembling, we just ignore the second
+ * for now.
+ */
+ dprintf(": superblock on %s doesn't match others - assembly aborted\n",
+ devname);
+ goto loop;
+ }
+ tmpdev->used = 1;
+ *found = 1;
+ dprintf("found: devname: %s\n", devname);
+ }
+ loop:
+ if (tst)
+ tst->ss->free_super(tst);
+ }
+ if (*found != 0) {
+ int err;
+ if ((err = load_super_imsm_all(st, -1, &st->sb, NULL, devlist, 0)) == 0) {
+ struct mdinfo *iter, *head = st->ss->container_content(st, NULL);
+ for (iter = head; iter; iter = iter->next) {
+ dprintf("content->text_version: %s vol\n",
+ iter->text_version);
+ if (iter->array.state & (1<<MD_SB_BLOCK_VOLUME)) {
+ /* do not assemble arrays with unsupported
+ configurations */
+ dprintf(": Cannot activate member %s.\n",
+ iter->text_version);
+ } else
+ count++;
+ }
+ sysfs_free(head);
+
+ } else {
+ dprintf(" no valid super block on device list: err: %d %p\n",
+ err, st->sb);
+ }
+ } else {
+ dprintf(" no more devices to examin\n");
+ }
+
+ for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) {
+ if ((tmpdev->used == 1) && (tmpdev->found)) {
+ if (count) {
+ if (count < tmpdev->found)
+ count = 0;
+ else
+ count -= tmpdev->found;
+ }
+ }
+ if (tmpdev->used == 1)
+ tmpdev->used = 4;
+ }
+ err_1:
+ if (st)
+ st->ss->free_super(st);
+ return count;
+}
+
+
+static int
+count_volumes(char *hba, int dpa, int verbose)
+{
+ struct md_list *devlist = NULL;
+ int count = 0;
+ int found = 0;;
+
+ devlist = get_devices(hba);
+ /* if no intel devices return zero volumes */
+ if (devlist == NULL)
+ return 0;
+
+ count = active_arrays_by_format("imsm", hba, &devlist, dpa, verbose);
+ dprintf(" path: %s active arrays: %d\n", hba, count);
+ if (devlist == NULL)
+ return 0;
+ do {
+ found = 0;
+ count += count_volumes_list(devlist,
+ NULL,
+ verbose,
+ &found);
+ dprintf("found %d count: %d\n", found, count);
+ } while (found);
+
+ dprintf("path: %s total number of volumes: %d\n", hba, count);
+
+ while(devlist) {
+ struct md_list *dv = devlist;
+ devlist = devlist->next;
+ free(dv->devname);
+ free(dv);
+ }
+ return count;
+}
+
static int imsm_default_chunk(const struct imsm_orom *orom)
{
/* up to 512 if the plaform supports it, otherwise the platform max.
return min(512, (1 << fs));
}
-#define pr_vrb(fmt, arg...) (void) (verbose && fprintf(stderr, Name fmt, ##arg))
static int
validate_geometry_imsm_orom(struct intel_super *super, int level, int layout,
int raiddisks, int *chunk, int verbose)
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;
}
*freesize = maxsize;
+ if (super->orom) {
+ int count = count_volumes(super->hba->path,
+ super->orom->dpa, verbose);
+ if (super->orom->vphba <= count) {
+ pr_vrb(": platform does not support more then %d raid volumes.\n",
+ super->orom->vphba);
+ return 0;
+ }
+ }
return 1;
}
size /= 2 * chunk;
size *= 2 * chunk;
}
+ maxsize = size;
+ }
+ if (!check_env("IMSM_NO_PLATFORM") &&
+ mpb->num_raid_devs > 0 && size && size != maxsize) {
+ fprintf(stderr, Name ": attempting to create a second "
+ "volume with size less then remaining space. "
+ "Aborting...\n");
+ return 0;
}
-
cnt = 0;
for (dl = super->disks; dl; dl = dl->next)
if (dl->e)
dev, freesize,
verbose);
}
-
+
if (!dev) {
if (st->sb) {
+ struct intel_super *super = st->sb;
if (!validate_geometry_imsm_orom(st->sb, level, layout,
raiddisks, chunk,
verbose))
* created. add_to_super and getinfo_super
* detect when autolayout is in progress.
*/
+ /* assuming that freesize is always given when array is
+ created */
+ if (super->orom && freesize) {
+ int count;
+ count = count_volumes(super->hba->path,
+ super->orom->dpa, verbose);
+ if (super->orom->vphba <= count) {
+ pr_vrb(": platform does not support more"
+ "then %d raid volumes.\n",
+ super->orom->vphba);
+ return 0;
+ }
+ }
if (freesize)
return reserve_space(st, raiddisks, size,
chunk?*chunk:0, freesize);
*/
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, NULL, 1) == 0) {
st->sb = super;
st->container_dev = fd2devnum(cfd);
close(cfd);
struct imsm_map *map;
struct imsm_map *map2;
struct mdinfo *this;
- int slot, chunk;
+ int slot;
+#ifndef MDASSEMBLE
+ int chunk;
+#endif
char *ep;
if (subarray &&
* OROM/EFI
*/
- chunk = __le16_to_cpu(map->blocks_per_strip) >> 1;
this = malloc(sizeof(*this));
if (!this) {
fprintf(stderr, Name ": failed to allocate %zu bytes\n",
getinfo_super_imsm_volume(st, this, NULL);
this->next = rest;
#ifndef MDASSEMBLE
+ chunk = __le16_to_cpu(map->blocks_per_strip) >> 1;
/* mdadm does not support all metadata features- set the bit in all arrays state */
if (!validate_geometry_imsm_orom(super,
get_imsm_raid_level(map), /* RAID level */
{
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));
}
return NULL;
}
-
+
mu->space = NULL;
mu->space_list = NULL;
mu->len = sizeof(struct imsm_update_activate_spare) * num_spares;
}
static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
- struct intel_super *super,
+ struct intel_super *super,
struct active_array *active_array)
{
struct imsm_super *mpb = super->anchor;
struct imsm_dev *dev)
{
switch (level) {
+ case 1:
case 10:{
int ret_val = 0;
struct imsm_map *map;
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,