X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;ds=sidebyside;f=Grow.c;h=8aa0a1392241a6afd052d3cd42a7d3b4108422dd;hb=72d566f68d495261608a900b2d8cb8d037cd9178;hp=c1bc1cac9c6dc3a5251a41d64a5c95a4ba6bf6c2;hpb=3c20f9899bc95b35f5b9544c6741b4fccd616326;p=thirdparty%2Fmdadm.git diff --git a/Grow.c b/Grow.c index c1bc1cac..8aa0a139 100644 --- a/Grow.c +++ b/Grow.c @@ -49,12 +49,8 @@ int restore_backup(struct supertype *st, int disk_count = next_spare + working_disks; dprintf("Called restore_backup()\n"); - fdlist = malloc(sizeof(int) * disk_count); - if (fdlist == NULL) { - fprintf(stderr, - Name ": cannot allocate memory for disk list\n"); - return 1; - } + fdlist = xmalloc(sizeof(int) * disk_count); + for (i = 0; i < next_spare; i++) fdlist[i] = -1; for (dev = content->devs; dev; dev = dev->next) { @@ -84,10 +80,10 @@ int restore_backup(struct supertype *st, } free(fdlist); if (err) { - fprintf(stderr, Name ": Failed to restore critical" - " section for reshape - sorry.\n"); + pr_err("Failed to restore critical" + " section for reshape - sorry.\n"); if (!backup_file) - fprintf(stderr, Name ": Possibly you need" + pr_err("Possibly you need" " to specify a --backup-file\n"); return 1; } @@ -115,23 +111,23 @@ int Grow_Add_device(char *devname, int fd, char *newdev) char *subarray = NULL; if (ioctl(fd, GET_ARRAY_INFO, &info.array) < 0) { - fprintf(stderr, Name ": cannot get array info for %s\n", devname); + pr_err("cannot get array info for %s\n", devname); return 1; } if (info.array.level != -1) { - fprintf(stderr, Name ": can only add devices to linear arrays\n"); + pr_err("can only add devices to linear arrays\n"); return 1; } st = super_by_fd(fd, &subarray); if (!st) { - fprintf(stderr, Name ": cannot handle arrays with superblock version %d\n", info.array.major_version); + pr_err("cannot handle arrays with superblock version %d\n", info.array.major_version); return 1; } if (subarray) { - fprintf(stderr, Name ": Cannot grow linear sub-arrays yet\n"); + pr_err("Cannot grow linear sub-arrays yet\n"); free(subarray); free(st); return 1; @@ -139,13 +135,13 @@ int Grow_Add_device(char *devname, int fd, char *newdev) nfd = open(newdev, O_RDWR|O_EXCL|O_DIRECT); if (nfd < 0) { - fprintf(stderr, Name ": cannot open %s\n", newdev); + pr_err("cannot open %s\n", newdev); free(st); return 1; } fstat(nfd, &stb); if ((stb.st_mode & S_IFMT) != S_IFBLK) { - fprintf(stderr, Name ": %s is not a block device!\n", newdev); + pr_err("%s is not a block device!\n", newdev); close(nfd); free(st); return 1; @@ -159,7 +155,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) disk.number = d; if (ioctl(fd, GET_DISK_INFO, &disk) < 0) { - fprintf(stderr, Name ": cannot get device detail for device %d\n", + pr_err("cannot get device detail for device %d\n", d); close(nfd); free(st); @@ -167,7 +163,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) } dv = map_dev(disk.major, disk.minor, 1); if (!dv) { - fprintf(stderr, Name ": cannot find device file for device %d\n", + pr_err("cannot find device file for device %d\n", d); close(nfd); free(st); @@ -175,14 +171,14 @@ int Grow_Add_device(char *devname, int fd, char *newdev) } fd2 = dev_open(dv, O_RDWR); if (fd2 < 0) { - fprintf(stderr, Name ": cannot open device file %s\n", dv); + pr_err("cannot open device file %s\n", dv); close(nfd); free(st); return 1; } if (st->ss->load_super(st, fd2, NULL)) { - fprintf(stderr, Name ": cannot find super block on %s\n", dv); + pr_err("cannot find super block on %s\n", dv); close(nfd); close(fd2); free(st); @@ -203,7 +199,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) 0, 0, NULL); if (st->ss->store_super(st, nfd)) { - fprintf(stderr, Name ": Cannot store new superblock on %s\n", + pr_err("Cannot store new superblock on %s\n", newdev); close(nfd); return 1; @@ -211,7 +207,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) close(nfd); if (ioctl(fd, ADD_NEW_DISK, &info.disk) != 0) { - fprintf(stderr, Name ": Cannot add new disk to this array\n"); + pr_err("Cannot add new disk to this array\n"); return 1; } /* Well, that seems to have worked. @@ -219,7 +215,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) */ if (ioctl(fd, GET_ARRAY_INFO, &info.array) < 0) { - fprintf(stderr, Name ": cannot get array info for %s\n", devname); + pr_err("cannot get array info for %s\n", devname); return 1; } @@ -230,23 +226,23 @@ int Grow_Add_device(char *devname, int fd, char *newdev) disk.number = d; if (ioctl(fd, GET_DISK_INFO, &disk) < 0) { - fprintf(stderr, Name ": cannot get device detail for device %d\n", + pr_err("cannot get device detail for device %d\n", d); return 1; } dv = map_dev(disk.major, disk.minor, 1); if (!dv) { - fprintf(stderr, Name ": cannot find device file for device %d\n", + pr_err("cannot find device file for device %d\n", d); return 1; } fd2 = dev_open(dv, O_RDWR); if (fd2 < 0) { - fprintf(stderr, Name ": cannot open device file %s\n", dv); + pr_err("cannot open device file %s\n", dv); return 1; } if (st->ss->load_super(st, fd2, NULL)) { - fprintf(stderr, Name ": cannot find super block on %s\n", dv); + pr_err("cannot find super block on %s\n", dv); close(fd); return 1; } @@ -259,7 +255,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) 0, 0, NULL); if (st->ss->store_super(st, fd2)) { - fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv); + pr_err("Cannot store new superblock on %s\n", dv); close(fd2); return 1; } @@ -290,7 +286,7 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int if (vers < 9003) { major = BITMAP_MAJOR_HOSTENDIAN; - fprintf(stderr, Name ": Warning - bitmaps created on this kernel" + pr_err("Warning - bitmaps created on this kernel" " are not portable\n" " between different architectures. Consider upgrading" " the Linux kernel.\n"); @@ -298,48 +294,48 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int if (ioctl(fd, GET_BITMAP_FILE, &bmf) != 0) { if (errno == ENOMEM) - fprintf(stderr, Name ": Memory allocation failure.\n"); + pr_err("Memory allocation failure.\n"); else - fprintf(stderr, Name ": bitmaps not supported by this kernel.\n"); + pr_err("bitmaps not supported by this kernel.\n"); return 1; } if (bmf.pathname[0]) { if (strcmp(file,"none")==0) { if (ioctl(fd, SET_BITMAP_FILE, -1)!= 0) { - fprintf(stderr, Name ": failed to remove bitmap %s\n", + pr_err("failed to remove bitmap %s\n", bmf.pathname); return 1; } return 0; } - fprintf(stderr, Name ": %s already has a bitmap (%s)\n", + pr_err("%s already has a bitmap (%s)\n", devname, bmf.pathname); return 1; } if (ioctl(fd, GET_ARRAY_INFO, &array) != 0) { - fprintf(stderr, Name ": cannot get array status for %s\n", devname); + pr_err("cannot get array status for %s\n", devname); return 1; } if (array.state & (1<ss->add_internal_bitmap == NULL) { - fprintf(stderr, Name ": Internal bitmaps not supported " + pr_err("Internal bitmaps not supported " "with %s metadata\n", st->ss->name); return 1; } @@ -412,8 +408,8 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int ) st->ss->write_bitmap(st, fd2); else { - fprintf(stderr, Name ": failed " - "to create internal bitmap - chunksize problem.\n"); + pr_err("failed " + "to create internal bitmap - chunksize problem.\n"); close(fd2); return 1; } @@ -424,18 +420,17 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int if (offset_setable) { st->ss->getinfo_super(st, mdi, NULL); sysfs_init(mdi, fd, -1); - rv = sysfs_set_num(mdi, NULL, "bitmap/location", - mdi->bitmap_offset); + rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location", + mdi->bitmap_offset); } else { array.state |= (1<ss->external) return 0; if (!st->ss->reshape_super || !st->ss->manage_reshape) { - fprintf(stderr, Name ": %s metadata does not support reshape\n", + pr_err("%s metadata does not support reshape\n", st->ss->name); return 1; } return st->ss->reshape_super(st, size, level, layout, chunksize, raid_disks, delta_disks, backup_file, dev, - verbose); + direction, verbose); } static void sync_metadata(struct supertype *st) @@ -863,9 +855,8 @@ int reshape_prepare_fdlist(char *devname, = dev_open(dn, O_RDONLY); offsets[sd->disk.raid_disk] = sd->data_offset*512; if (fdlist[sd->disk.raid_disk] < 0) { - fprintf(stderr, - Name ": %s: cannot open component %s\n", - devname, dn ? dn : "-unknown-"); + pr_err("%s: cannot open component %s\n", + devname, dn ? dn : "-unknown-"); d = -1; goto release; } @@ -876,7 +867,7 @@ int reshape_prepare_fdlist(char *devname, fdlist[d] = dev_open(dn, O_RDWR); offsets[d] = (sd->data_offset + sra->component_size - blocks - 8)*512; if (fdlist[d] < 0) { - fprintf(stderr, Name ": %s: cannot open component %s\n", + pr_err("%s: cannot open component %s\n", devname, dn ? dn : "-unknown-"); d = -1; goto release; @@ -907,7 +898,7 @@ int reshape_open_backup_file(char *backup_file, S_IRUSR | S_IWUSR); *offsets = 8 * 512; if (*fdlist < 0) { - fprintf(stderr, Name ": %s: cannot create backup file %s: %s\n", + pr_err("%s: cannot create backup file %s: %s\n", devname, backup_file, strerror(errno)); return 0; } @@ -920,7 +911,7 @@ int reshape_open_backup_file(char *backup_file, dev = stb.st_dev; fstat(fd, &stb); if (stb.st_rdev == dev) { - fprintf(stderr, Name ": backup file must NOT be" + pr_err("backup file must NOT be" " on the array being reshaped.\n"); close(*fdlist); return 0; @@ -929,14 +920,14 @@ int reshape_open_backup_file(char *backup_file, memset(buf, 0, 512); for (i=0; i < blocks + 8 ; i++) { if (write(*fdlist, buf, 512) != 512) { - fprintf(stderr, Name ": %s: cannot create" + pr_err("%s: cannot create" " backup file %s: %s\n", devname, backup_file, strerror(errno)); return 0; } } if (fsync(*fdlist) != 0) { - fprintf(stderr, Name ": %s: cannot create backup file %s: %s\n", + pr_err("%s: cannot create backup file %s: %s\n", devname, backup_file, strerror(errno)); return 0; } @@ -1023,6 +1014,10 @@ char *analyse_change(struct mdinfo *info, struct reshape *re) * raid5 with 2 disks, or * raid0 with 1 disk */ + if (info->new_level > 1 && + (info->component_size & 7)) + return "Cannot convert RAID1 of this size - " + "reduce size to multiple of 4K first."; if (info->new_level == 0) { if (info->delta_disks != UnSet && info->delta_disks != 0) @@ -1275,7 +1270,7 @@ char *analyse_change(struct mdinfo *info, struct reshape *re) break; case 5: - /* We get to RAID5 for RAID5 or RAID6 */ + /* We get to RAID5 from RAID5 or RAID6 */ if (re->level != 5 && re->level != 6) return "Cannot convert to RAID5 from this level"; @@ -1297,11 +1292,27 @@ char *analyse_change(struct mdinfo *info, struct reshape *re) char layout[40]; char *ls = map_num(r5layout, info->new_layout); int l; - strcat(strcpy(layout, ls), "-6"); - l = map_name(r6layout, layout); - if (l == UnSet) - return "Cannot find RAID6 layout" - " to convert to"; + if (ls) { + /* Current RAID6 layout has a RAID5 + * equivalent - good + */ + strcat(strcpy(layout, ls), "-6"); + l = map_name(r6layout, layout); + if (l == UnSet) + return "Cannot find RAID6 layout" + " to convert to"; + } else { + /* Current RAID6 has no equivalent. + * If it is already a '-6' layout we + * can leave it unchanged, else we must + * fail + */ + ls = map_num(r6layout, info->new_layout); + if (!ls || + strcmp(ls+strlen(ls)-2, "-6") != 0) + return "Please specify new layout"; + l = info->new_layout; + } re->after.layout = l; } } @@ -1366,6 +1377,44 @@ char *analyse_change(struct mdinfo *info, struct reshape *re) return NULL; } +static int set_array_size(struct supertype *st, struct mdinfo *sra, + char *text_version) +{ + struct mdinfo *info; + char *subarray; + int ret_val = -1; + + if ((st == NULL) || (sra == NULL)) + return ret_val; + + if (text_version == NULL) + text_version = sra->text_version; + subarray = strchr(text_version+1, '/')+1; + info = st->ss->container_content(st, subarray); + if (info) { + unsigned long long current_size = 0; + unsigned long long new_size = + info->custom_array_size/2; + + if (sysfs_get_ll(sra, NULL, "array_size", ¤t_size) == 0 && + new_size > current_size) { + if (sysfs_set_num(sra, NULL, "array_size", new_size) + < 0) + dprintf("Error: Cannot set array size"); + else { + ret_val = 0; + dprintf("Array size changed"); + } + dprintf(" from %llu to %llu.\n", + current_size, new_size); + } + sysfs_free(info); + } else + dprintf("Error: set_array_size(): info pointer in NULL\n"); + + return ret_val; +} + static int reshape_array(char *container, int fd, char *devname, struct supertype *st, struct mdinfo *info, int force, struct mddev_dev *devlist, @@ -1420,14 +1469,14 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, struct mdinfo *sra; if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) { - fprintf(stderr, Name ": %s is not an active md array - aborting\n", + pr_err("%s is not an active md array - aborting\n", devname); return 1; } if (size >= 0 && (chunksize || level!= UnSet || layout_str || raid_disks)) { - fprintf(stderr, Name ": cannot change component size at the same time " + pr_err("cannot change component size at the same time " "as other changes.\n" " Change size first, then check data is intact before " "making other changes.\n"); @@ -1437,18 +1486,18 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, if (raid_disks && raid_disks < array.raid_disks && array.level > 1 && get_linux_version() < 2006032 && !check_env("MDADM_FORCE_FEWER")) { - fprintf(stderr, Name ": reducing the number of devices is not safe before Linux 2.6.32\n" + pr_err("reducing the number of devices is not safe before Linux 2.6.32\n" " Please use a newer kernel\n"); return 1; } st = super_by_fd(fd, &subarray); if (!st) { - fprintf(stderr, Name ": Unable to determine metadata format for %s\n", devname); + pr_err("Unable to determine metadata format for %s\n", devname); return 1; } if (raid_disks > st->max_devs) { - fprintf(stderr, Name ": Cannot increase raid-disks on this array" + pr_err("Cannot increase raid-disks on this array" " beyond %d\n", st->max_devs); return 1; } @@ -1471,7 +1520,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, fd = cfd; } if (cfd < 0) { - fprintf(stderr, Name ": Unable to open container for %s\n", + pr_err("Unable to open container for %s\n", devname); free(subarray); return 1; @@ -1483,7 +1532,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, rv = st->ss->load_container(st, cfd, NULL); if (rv) { - fprintf(stderr, Name ": Cannot read superblock for %s\n", + pr_err("Cannot read superblock for %s\n", devname); free(subarray); return 1; @@ -1507,11 +1556,10 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, & (1< array.raid_disks && array.spare_disks +added_disks < (raid_disks - array.raid_disks) && !force) { - fprintf(stderr, - Name ": Need %d spare%s to avoid degraded array," - " and only have %d.\n" - " Use --force to over-ride this check.\n", - raid_disks - array.raid_disks, - raid_disks - array.raid_disks == 1 ? "" : "s", - array.spare_disks + added_disks); + pr_err("Need %d spare%s to avoid degraded array," + " and only have %d.\n" + " Use --force to over-ride this check.\n", + raid_disks - array.raid_disks, + raid_disks - array.raid_disks == 1 ? "" : "s", + array.spare_disks + added_disks); return 1; } @@ -1547,7 +1594,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, sra->array.level = LEVEL_CONTAINER; } } else { - fprintf(stderr, Name ": failed to read sysfs parameters for %s\n", + pr_err("failed to read sysfs parameters for %s\n", devname); return 1; } @@ -1557,7 +1604,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, sysfs_free(sra); return 1; } else if (frozen < 0) { - fprintf(stderr, Name ": %s is performing resync/recovery and cannot" + pr_err("%s is performing resync/recovery and cannot" " be reshaped\n", devname); sysfs_free(sra); return 1; @@ -1568,16 +1615,38 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, long long orig_size = get_component_size(fd)/2; long long min_csize; struct mdinfo *mdi; + int raid0_takeover = 0; if (orig_size == 0) orig_size = array.size; if (reshape_super(st, size, UnSet, UnSet, 0, 0, UnSet, NULL, - devname, !quiet)) { + devname, APPLY_METADATA_CHANGES, !quiet)) { rv = 1; goto release; } sync_metadata(st); + if (st->ss->external) { + /* metadata can have size limitation + * update size value according to metadata information + */ + struct mdinfo *sizeinfo = + st->ss->container_content(st, subarray); + if (sizeinfo) { + unsigned long long new_size = + sizeinfo->custom_array_size/2; + int data_disks = get_data_disks( + sizeinfo->array.level, + sizeinfo->array.layout, + sizeinfo->array.raid_disks); + new_size /= data_disks; + dprintf("Metadata size correction from %llu to " + "%llu (%llu)\n", orig_size, new_size, + new_size * data_disks); + size = new_size; + sysfs_free(sizeinfo); + } + } /* Update the size of each member device in case * they have been resized. This will never reduce @@ -1585,9 +1654,14 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, * understands '0' to mean 'max'. */ min_csize = 0; + rv = 0; for (mdi = sra->devs; mdi; mdi = mdi->next) { - if (sysfs_set_num(sra, mdi, "size", size) < 0) + if (sysfs_set_num(sra, mdi, "size", size) < 0) { + /* Probably kernel refusing to let us + * reduce the size - not an error. + */ break; + } if (array.not_persistent == 0 && array.major_version == 0 && get_linux_version() < 3001000) { @@ -1602,20 +1676,46 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, } } } + if (rv) { + pr_err("Cannot set size on " + "array members.\n"); + goto size_change_error; + } if (min_csize && size > min_csize) { - fprintf(stderr, Name ": Cannot safely make this array " + pr_err("Cannot safely make this array " "use more than 2TB per device on this kernel.\n"); rv = 1; - goto release; + goto size_change_error; } if (min_csize && size == 0) { /* Don't let the kernel choose a size - it will get * it wrong */ - fprintf(stderr, Name ": Limited v0.90 array to " - "2TB per device\n"); + pr_err("Limited v0.90 array to " + "2TB per device\n"); size = min_csize; } + if (st->ss->external) { + if (sra->array.level == 0) { + rv = sysfs_set_str(sra, NULL, "level", + "raid5"); + if (!rv) { + raid0_takeover = 1; + /* get array parametes after takeover + * to chane one parameter at time only + */ + rv = ioctl(fd, GET_ARRAY_INFO, &array); + } + } + /* make sure mdmon is + * aware of the new level */ + if (!mdmon_running(st->container_dev)) + start_mdmon(st->container_dev); + ping_monitor(container); + if (mdmon_running(st->container_dev) && + st->update_tail == NULL) + st->update_tail = &st->updates; + } array.size = size; if (array.size != size) { @@ -1627,20 +1727,41 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, "component_size", size); else rv = -1; - } else + } else { rv = ioctl(fd, SET_ARRAY_INFO, &array); + + /* manage array size when it is managed externally + */ + if ((rv == 0) && st->ss->external) + rv = set_array_size(st, sra, sra->text_version); + } + + if (raid0_takeover) { + /* do not recync non-existing parity, + * we will drop it anyway + */ + sysfs_set_str(sra, NULL, "sync_action", "frozen"); + /* go back to raid0, drop parity disk + */ + sysfs_set_str(sra, NULL, "level", "raid0"); + ioctl(fd, GET_ARRAY_INFO, &array); + } + +size_change_error: if (rv != 0) { int err = errno; /* restore metadata */ if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0, - UnSet, NULL, devname, !quiet) == 0) + UnSet, NULL, devname, + ROLLBACK_METADATA_CHANGES, + !quiet) == 0) sync_metadata(st); - fprintf(stderr, Name ": Cannot set device size for %s: %s\n", + pr_err("Cannot set device size for %s: %s\n", devname, strerror(err)); if (err == EBUSY && (array.state & (1<= 16) { - fprintf(stderr, Name - ": %s has a non-standard layout. If you" - " wish to preserve this\n" - " during the reshape, please specify" - " --layout=preserve\n" - " If you want to change it, specify a" - " layout or use --layout=normalise\n", - devname); + pr_err("%s has a non-standard layout. If you" + " wish to preserve this\n", devname); + cont_err("during the reshape, please specify" + " --layout=preserve\n"); + cont_err("If you want to change it, specify a" + " layout or use --layout=normalise\n"); rv = 1; goto release; } @@ -1753,9 +1872,35 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, *h = 0; info.new_layout = map_name(r6layout, l); } + } else { + pr_err("%s is only meaningful when reshaping" + " a RAID6 array.\n", layout_str); + rv = 1; + goto release; } } else if (strcmp(layout_str, "preserve") == 0) { - info.new_layout = UnSet; + /* This means that a non-standard RAID6 layout + * is OK. + * In particular: + * - When reshape a RAID6 (e.g. adding a device) + * which is in a non-standard layout, it is OK + * to preserve that layout. + * - When converting a RAID5 to RAID6, leave it in + * the XXX-6 layout, don't re-layout. + */ + if (info.array.level == 6 && info.new_level == UnSet) + info.new_layout = info.array.layout; + else if (info.array.level == 5 && info.new_level == 6) { + char l[40]; + strcpy(l, map_num(r5layout, info.array.layout)); + strcat(l, "-6"); + info.new_layout = map_name(r6layout, l); + } else { + pr_err("%s in only meaningful when reshaping" + " to RAID6\n", layout_str); + rv = 1; + goto release; + } } else { int l = info.new_level; if (l == UnSet) @@ -1774,13 +1919,13 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, info.new_layout = parse_layout_faulty(layout_str); break; default: - fprintf(stderr, Name ": layout not meaningful" + pr_err("layout not meaningful" " with this level\n"); rv = 1; goto release; } if (info.new_layout == UnSet) { - fprintf(stderr, Name ": layout %s not understood" + pr_err("layout %s not understood" " for this level\n", layout_str); rv = 1; @@ -1790,15 +1935,15 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, if (array.level == LEVEL_FAULTY) { if (level != UnSet && level != array.level) { - fprintf(stderr, Name ": cannot change level of Faulty device\n"); + pr_err("cannot change level of Faulty device\n"); rv =1 ; } if (chunksize) { - fprintf(stderr, Name ": cannot set chunksize of Faulty device\n"); + pr_err("cannot set chunksize of Faulty device\n"); rv =1 ; } if (raid_disks && raid_disks != 1) { - fprintf(stderr, Name ": cannot set raid_disks of Faulty device\n"); + pr_err("cannot set raid_disks of Faulty device\n"); rv =1 ; } if (layout_str) { @@ -1808,7 +1953,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, } array.layout = info.new_layout; if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) { - fprintf(stderr, Name ": failed to set new layout\n"); + pr_err("failed to set new layout\n"); rv = 1; } else if (!quiet) printf("layout for %s set to %d\n", @@ -1843,10 +1988,11 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, /* Impose these changes on a single array. First * check that the metadata is OK with the change. */ - if (reshape_super(st, info.component_size, info.new_level, + if (reshape_super(st, -1, info.new_level, info.new_layout, info.new_chunk, info.array.raid_disks, info.delta_disks, - backup_file, devname, quiet)) { + backup_file, devname, APPLY_METADATA_CHANGES, + quiet)) { rv = 1; goto release; } @@ -1862,6 +2008,63 @@ release: return rv; } +/* verify_reshape_position() + * Function checks if reshape position in metadata is not farther + * than position in md. + * Return value: + * 0 : not valid sysfs entry + * it can be caused by not started reshape, it should be started + * by reshape array or raid0 array is before takeover + * -1 : error, reshape position is obviously wrong + * 1 : success, reshape progress correct or updated +*/ +static int verify_reshape_position(struct mdinfo *info, int level) +{ + int ret_val = 0; + char buf[40]; + int rv; + + /* read sync_max, failure can mean raid0 array */ + rv = sysfs_get_str(info, NULL, "sync_max", buf, 40); + + if (rv > 0) { + char *ep; + unsigned long long position = strtoull(buf, &ep, 0); + + dprintf(Name": Read sync_max sysfs entry is: %s\n", buf); + if (!(ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' '))) { + position *= get_data_disks(level, + info->new_layout, + info->array.raid_disks); + if (info->reshape_progress < position) { + dprintf("Corrected reshape progress (%llu) to " + "md position (%llu)\n", + info->reshape_progress, position); + info->reshape_progress = position; + ret_val = 1; + } else if (info->reshape_progress > position) { + pr_err("Fatal error: array " + "reshape was not properly frozen " + "(expected reshape position is %llu, " + "but reshape progress is %llu.\n", + position, info->reshape_progress); + ret_val = -1; + } else { + dprintf("Reshape position in md and metadata " + "are the same;"); + ret_val = 1; + } + } + } else if (rv == 0) { + /* for valid sysfs entry, 0-length content + * should be indicated as error + */ + ret_val = -1; + } + + return ret_val; +} + static int reshape_array(char *container, int fd, char *devname, struct supertype *st, struct mdinfo *info, int force, struct mddev_dev *devlist, @@ -1918,7 +2121,7 @@ static int reshape_array(char *container, int fd, char *devname, } else msg = analyse_change(info, &reshape); if (msg) { - fprintf(stderr, Name ": %s\n", msg); + pr_err("%s\n", msg); goto release; } if (restart && @@ -1926,11 +2129,23 @@ static int reshape_array(char *container, int fd, char *devname, reshape.before.layout != info->array.layout || reshape.before.data_disks + reshape.parity != info->array.raid_disks - max(0, info->delta_disks))) { - fprintf(stderr, Name ": reshape info is not in native format -" + pr_err("reshape info is not in native format -" " cannot continue.\n"); goto release; } + if (st->ss->external && restart && (info->reshape_progress == 0)) { + /* When reshape is restarted from '0', very begin of array + * it is possible that for external metadata reshape and array + * configuration doesn't happen. + * Check if md has the same opinion, and reshape is restarted + * from 0. If so, this is regular reshape start after reshape + * switch in metadata to next array only. + */ + if ((verify_reshape_position(info, reshape.level) >= 0) && + (info->reshape_progress == 0)) + restart = 0; + } if (restart) { /* reshape already started. just skip to monitoring the reshape */ if (reshape.backup_blocks == 0) @@ -1954,13 +2169,12 @@ static int reshape_array(char *container, int fd, char *devname, if (!force && info->new_level > 1 && info->array.level > 1 && spares_needed > info->array.spare_disks + added_disks) { - fprintf(stderr, - Name ": Need %d spare%s to avoid degraded array," - " and only have %d.\n" - " Use --force to over-ride this check.\n", - spares_needed, - spares_needed == 1 ? "" : "s", - info->array.spare_disks + added_disks); + pr_err("Need %d spare%s to avoid degraded array," + " and only have %d.\n" + " Use --force to over-ride this check.\n", + spares_needed, + spares_needed == 1 ? "" : "s", + info->array.spare_disks + added_disks); goto release; } /* Check we have enough spares to not fail */ @@ -1969,12 +2183,11 @@ static int reshape_array(char *container, int fd, char *devname, - array.raid_disks; if ((info->new_level > 1 || info->new_level == 0) && spares_needed > info->array.spare_disks +added_disks) { - fprintf(stderr, - Name ": Need %d spare%s to create working array," - " and only have %d.\n", - spares_needed, - spares_needed == 1 ? "" : "s", - info->array.spare_disks + added_disks); + pr_err("Need %d spare%s to create working array," + " and only have %d.\n", + spares_needed, + spares_needed == 1 ? "" : "s", + info->array.spare_disks + added_disks); goto release; } @@ -1987,22 +2200,25 @@ static int reshape_array(char *container, int fd, char *devname, err = sysfs_set_str(info, NULL, "level", c); if (err) { err = errno; - fprintf(stderr, Name ": %s: could not set level to %s\n", + pr_err("%s: could not set level to %s\n", devname, c); if (err == EBUSY && (info->array.state & (1< 0 && st->ss->external) { /* make sure mdmon is aware of the new level */ + if (mdmon_running(st->container_dev)) + flush_mdmon(container); + if (!mdmon_running(st->container_dev)) start_mdmon(st->container_dev); ping_monitor(container); @@ -2068,7 +2284,7 @@ static int reshape_array(char *container, int fd, char *devname, info->new_layout != array.layout) { array.layout = info->new_layout; if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) { - fprintf(stderr, Name ": failed to set new layout\n"); + pr_err("failed to set new layout\n"); goto release; } else if (!quiet) printf("layout for %s set to %d\n", @@ -2079,7 +2295,7 @@ static int reshape_array(char *container, int fd, char *devname, array.raid_disks != (info->array.raid_disks + info->delta_disks)) { array.raid_disks += info->delta_disks; if (ioctl(fd, SET_ARRAY_INFO, &array) != 0) { - fprintf(stderr, Name ": failed to set raid disks\n"); + pr_err("failed to set raid disks\n"); goto release; } else if (!quiet) { printf("raid_disks for %s set to %d\n", @@ -2090,7 +2306,7 @@ static int reshape_array(char *container, int fd, char *devname, info->new_chunk != array.chunk_size) { if (sysfs_set_num(info, NULL, "chunk_size", info->new_chunk) != 0) { - fprintf(stderr, Name ": failed to set chunk size\n"); + pr_err("failed to set chunk size\n"); goto release; } else if (!quiet) printf("chunk size for %s set to %d\n", @@ -2137,11 +2353,10 @@ started: /* Check that we can hold all the data */ get_dev_size(fd, NULL, &array_size); if (reshape.new_size < (array_size/512)) { - fprintf(stderr, - Name ": this change will reduce the size of the array.\n" - " use --grow --array-size first to truncate array.\n" - " e.g. mdadm --grow %s --array-size %llu\n", - devname, reshape.new_size/2); + pr_err("this change will reduce the size of the array.\n" + " use --grow --array-size first to truncate array.\n" + " e.g. mdadm --grow %s --array-size %llu\n", + devname, reshape.new_size/2); goto release; } @@ -2149,7 +2364,7 @@ started: GET_COMPONENT|GET_DEVS|GET_OFFSET|GET_STATE|GET_CHUNK| GET_CACHE); if (!sra) { - fprintf(stderr, Name ": %s: Cannot get array details from sysfs\n", + pr_err("%s: Cannot get array details from sysfs\n", devname); goto release; } @@ -2168,11 +2383,11 @@ started: blocks < 16*1024*2) blocks *= 2; } else - fprintf(stderr, Name ": Need to backup %luK of critical " + pr_err("Need to backup %luK of critical " "section..\n", blocks/2); if (blocks >= sra->component_size/2) { - fprintf(stderr, Name ": %s: Something wrong" + pr_err("%s: Something wrong" " - reshape aborted\n", devname); goto release; @@ -2183,12 +2398,8 @@ started: nrdisks = max(reshape.before.data_disks, reshape.after.data_disks) + reshape.parity + sra->array.spare_disks; - fdlist = malloc((1+nrdisks) * sizeof(int)); - offsets = malloc((1+nrdisks) * sizeof(offsets[0])); - if (!fdlist || !offsets) { - fprintf(stderr, Name ": malloc failed: grow aborted\n"); - goto release; - } + fdlist = xcalloc((1+nrdisks), sizeof(int)); + offsets = xcalloc((1+nrdisks), sizeof(offsets[0])); odisks = reshape.before.data_disks + reshape.parity; d = reshape_prepare_fdlist(devname, sra, odisks, @@ -2202,11 +2413,11 @@ started: if (backup_file == NULL) { if (reshape.after.data_disks <= reshape.before.data_disks) { - fprintf(stderr, Name ": %s: Cannot grow - " + pr_err("%s: Cannot grow - " "need backup-file\n", devname); goto release; } else if (sra->array.spare_disks == 0) { - fprintf(stderr, Name ": %s: Cannot grow - " + pr_err("%s: Cannot grow - " "need a spare or backup-file to backup " "critical section\n", devname); goto release; @@ -2248,9 +2459,16 @@ started: sra->new_chunk = info->new_chunk; - if (restart) + if (restart) { + /* for external metadata checkpoint saved by mdmon can be lost + * or missed /due to e.g. crash/. Check if md is not during + * restart farther than metadata points to. + * If so, this means metadata information is obsolete. + */ + if (st->ss->external) + verify_reshape_position(info, reshape.level); sra->reshape_progress = info->reshape_progress; - else { + } else { sra->reshape_progress = 0; if (reshape.after.data_disks < reshape.before.data_disks) /* start from the end of the new array */ @@ -2268,15 +2486,13 @@ started: ioctl(fd, SET_ARRAY_INFO, &array) != 0) { int err = errno; - fprintf(stderr, - Name ": Cannot set device shape for %s: %s\n", - devname, strerror(errno)); + pr_err("Cannot set device shape for %s: %s\n", + devname, strerror(errno)); if (err == EBUSY && (array.state & (1<reshape_progress); return 1; } @@ -2334,7 +2548,7 @@ started: */ switch(forked ? 0 : fork()) { case -1: - fprintf(stderr, Name ": Cannot run child to monitor reshape: %s\n", + pr_err("Cannot run child to monitor reshape: %s\n", strerror(errno)); abort_reshape(sra); goto release; @@ -2396,8 +2610,7 @@ started: /* Re-load the metadata as much could have changed */ int cfd = open_dev(st->container_dev); if (cfd >= 0) { - ping_manager(container); - ping_monitor(container); + flush_mdmon(container); st->ss->free_super(st); st->ss->load_container(st, cfd, container); close(cfd); @@ -2409,35 +2622,8 @@ started: */ if (reshape.before.data_disks != reshape.after.data_disks && - info->custom_array_size) { - struct mdinfo *info2; - char *subarray = strchr(info->text_version+1, '/')+1; - - info2 = st->ss->container_content(st, subarray); - if (info2) { - unsigned long long current_size = 0; - unsigned long long new_size = - info2->custom_array_size/2; - - if (sysfs_get_ll(sra, - NULL, - "array_size", - ¤t_size) == 0 && - new_size > current_size) { - if (sysfs_set_num(sra, NULL, - "array_size", new_size) - < 0) - dprintf("Error: Cannot" - " set array size"); - else - dprintf("Array size " - "changed"); - dprintf(" from %llu to %llu.\n", - current_size, new_size); - } - sysfs_free(info2); - } - } + info->custom_array_size) + set_array_size(st, info, info->text_version); if (info->new_level != reshape.level) { @@ -2445,9 +2631,8 @@ started: if (c) { err = sysfs_set_str(sra, NULL, "level", c); if (err) - fprintf(stderr, Name\ - ": %s: could not set level " - "to %s\n", devname, c); + pr_err("%s: could not set level " + "to %s\n", devname, c); } if (info->new_level == 0) st->update_tail = NULL; @@ -2465,7 +2650,7 @@ release: if (orig_level != UnSet && sra) { c = map_num(pers, orig_level); if (c && sysfs_set_str(sra, NULL, "level", c) == 0) - fprintf(stderr, Name ": aborting level change\n"); + pr_err("aborting level change\n"); } sysfs_free(sra); if (!forked) @@ -2494,7 +2679,8 @@ int reshape_container(char *container, char *devname, reshape_super(st, -1, info->new_level, info->new_layout, info->new_chunk, info->array.raid_disks, info->delta_disks, - backup_file, devname, quiet)) { + backup_file, devname, APPLY_METADATA_CHANGES, + quiet)) { unfreeze(st); return 1; } @@ -2556,6 +2742,13 @@ int reshape_container(char *container, char *devname, devname2devnum(container)); if (!mdstat) continue; + if (mdstat->active == 0) { + pr_err("Skipping inactive " + "array md%i.\n", mdstat->devnum); + free_mdstat(mdstat); + mdstat = NULL; + continue; + } break; } if (!content) @@ -2594,6 +2787,9 @@ int reshape_container(char *container, char *devname, sysfs_init(content, fd, mdstat->devnum); + if (mdmon_running(devname2devnum(container))) + flush_mdmon(container); + rv = reshape_array(container, fd, adev, st, content, force, NULL, backup_file, quiet, 1, restart, @@ -2608,6 +2804,9 @@ int reshape_container(char *container, char *devname, restart = 0; if (rv) break; + + if (mdmon_running(devname2devnum(container))) + flush_mdmon(container); } if (!rv) unfreeze(st); @@ -3209,8 +3408,8 @@ static void validate(int afd, int bfd, unsigned long long offset) free(abuf); free(bbuf); abuflen = len; - abuf = malloc(abuflen); - bbuf = malloc(abuflen); + abuf = xmalloc(abuflen); + bbuf = xmalloc(abuflen); } lseek64(bfd, offset+__le64_to_cpu(bsb2.devstart2)*512, 0); @@ -3272,7 +3471,7 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape, break; } if (!sd) { - fprintf(stderr, Name ": Cannot find a superblock\n"); + pr_err("Cannot find a superblock\n"); return 0; } @@ -3467,7 +3666,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt if (i == old_disks-1) { fd = open(backup_file, O_RDONLY); if (fd<0) { - fprintf(stderr, Name ": backup file %s inaccessible: %s\n", + pr_err("backup file %s inaccessible: %s\n", backup_file, strerror(errno)); continue; } @@ -3485,7 +3684,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt if (lseek64(fd, (dinfo.data_offset + dinfo.component_size - 8) <<9, 0) < 0) { - fprintf(stderr, Name ": Cannot seek on device %d\n", i); + pr_err("Cannot seek on device %d\n", i); continue; /* Cannot seek */ } sprintf(namebuf, "device-%d", i); @@ -3493,29 +3692,29 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt } if (read(fd, &bsb, sizeof(bsb)) != sizeof(bsb)) { if (verbose) - fprintf(stderr, Name ": Cannot read from %s\n", devname); + pr_err("Cannot read from %s\n", devname); continue; /* Cannot read */ } if (memcmp(bsb.magic, "md_backup_data-1", 16) != 0 && memcmp(bsb.magic, "md_backup_data-2", 16) != 0) { if (verbose) - fprintf(stderr, Name ": No backup metadata on %s\n", devname); + pr_err("No backup metadata on %s\n", devname); continue; } if (bsb.sb_csum != bsb_csum((char*)&bsb, ((char*)&bsb.sb_csum)-((char*)&bsb))) { if (verbose) - fprintf(stderr, Name ": Bad backup-metadata checksum on %s\n", devname); + pr_err("Bad backup-metadata checksum on %s\n", devname); continue; /* bad checksum */ } if (memcmp(bsb.magic, "md_backup_data-2", 16) == 0 && bsb.sb_csum2 != bsb_csum((char*)&bsb, ((char*)&bsb.sb_csum2)-((char*)&bsb))) { if (verbose) - fprintf(stderr, Name ": Bad backup-metadata checksum2 on %s\n", devname); + pr_err("Bad backup-metadata checksum2 on %s\n", devname); continue; /* Bad second checksum */ } if (memcmp(bsb.set_uuid,info->uuid, 16) != 0) { if (verbose) - fprintf(stderr, Name ": Wrong uuid on backup-metadata on %s\n", devname); + pr_err("Wrong uuid on backup-metadata on %s\n", devname); continue; /* Wrong uuid */ } @@ -3526,13 +3725,13 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt if (info->array.utime > (int)__le64_to_cpu(bsb.mtime) + 2*60*60 || info->array.utime < (int)__le64_to_cpu(bsb.mtime) - 10*60) { if (check_env("MDADM_GROW_ALLOW_OLD")) { - fprintf(stderr, Name ": accepting backup with timestamp %lu " + pr_err("accepting backup with timestamp %lu " "for array with timestamp %lu\n", (unsigned long)__le64_to_cpu(bsb.mtime), (unsigned long)info->array.utime); } else { if (verbose) - fprintf(stderr, Name ": too-old timestamp on " + pr_err("too-old timestamp on " "backup-metadata on %s\n", devname); continue; /* time stamp is too bad */ } @@ -3548,8 +3747,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt < info->reshape_progress) { nonew: if (verbose) - fprintf(stderr, Name - ": backup-metadata found on %s but is not needed\n", devname); + pr_err("backup-metadata found on %s but is not needed\n", devname); continue; /* No new data here */ } } else { @@ -3583,9 +3781,8 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt if (lseek64(fd, __le64_to_cpu(bsb.devstart)*512, 0)< 0) { second_fail: if (verbose) - fprintf(stderr, Name - ": Failed to verify secondary backup-metadata block on %s\n", - devname); + pr_err("Failed to verify secondary backup-metadata block on %s\n", + devname); continue; /* Cannot seek */ } /* There should be a duplicate backup superblock 4k before here */ @@ -3600,7 +3797,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt goto second_fail; /* Cannot find leading superblock */ /* Now need the data offsets for all devices. */ - offsets = malloc(sizeof(*offsets)*info->array.raid_disks); + offsets = xmalloc(sizeof(*offsets)*info->array.raid_disks); for(j=0; jarray.raid_disks; j++) { if (fdlist[j] < 0) continue; @@ -3623,7 +3820,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt __le64_to_cpu(bsb.length)*512, NULL)) { /* didn't succeed, so giveup */ if (verbose) - fprintf(stderr, Name ": Error restoring backup from %s\n", + pr_err("Error restoring backup from %s\n", devname); free(offsets); return 1; @@ -3641,7 +3838,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt __le64_to_cpu(bsb.length2)*512, NULL)) { /* didn't succeed, so giveup */ if (verbose) - fprintf(stderr, Name ": Error restoring second backup from %s\n", + pr_err("Error restoring second backup from %s\n", devname); free(offsets); return 1; @@ -3740,7 +3937,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt } /* needed to recover critical section! */ if (verbose) - fprintf(stderr, Name ": Failed to find backup of critical section\n"); + pr_err("Failed to find backup of critical section\n"); return 1; } @@ -3757,24 +3954,21 @@ int Grow_continue_command(char *devname, int fd, char buf[40]; int cfd = -1; int fd2 = -1; - char *ep; - unsigned long long position; dprintf("Grow continue from command line called for %s\n", devname); st = super_by_fd(fd, &subarray); if (!st || !st->ss) { - fprintf(stderr, - Name ": Unable to determine metadata format for %s\n", - devname); + pr_err("Unable to determine metadata format for %s\n", + devname); return 1; } dprintf("Grow continue is run for "); if (st->ss->external == 0) { dprintf("native array (%s)\n", devname); if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) { - fprintf(stderr, Name ": %s is not an active md array -" + pr_err("%s is not an active md array -" " aborting\n", devname); ret_val = 1; goto Grow_continue_command_exit; @@ -3796,7 +3990,7 @@ int Grow_continue_command(char *devname, int fd, fd = cfd; } if (cfd < 0) { - fprintf(stderr, Name ": Unable to open container " + pr_err("Unable to open container " "for %s\n", devname); ret_val = 1; goto Grow_continue_command_exit; @@ -3807,9 +4001,8 @@ int Grow_continue_command(char *devname, int fd, */ ret_val = st->ss->load_container(st, cfd, NULL); if (ret_val) { - fprintf(stderr, - Name ": Cannot read superblock for %s\n", - devname); + pr_err("Cannot read superblock for %s\n", + devname); ret_val = 1; goto Grow_continue_command_exit; } @@ -3835,11 +4028,10 @@ int Grow_continue_command(char *devname, int fd, allow_reshape = 0; if (!allow_reshape) { - fprintf(stderr, Name - ": cannot continue reshape of an array" - " in container with unsupported" - " metadata: %s(%s)\n", - devname, buf); + pr_err("cannot continue reshape of an array" + " in container with unsupported" + " metadata: %s(%s)\n", + devname, buf); ret_val = 1; goto Grow_continue_command_exit; } @@ -3848,18 +4040,24 @@ int Grow_continue_command(char *devname, int fd, mdstat = mdstat_by_subdev(array, container_dev); if (!mdstat) continue; + if (mdstat->active == 0) { + pr_err("Skipping inactive " + "array md%i.\n", mdstat->devnum); + free_mdstat(mdstat); + mdstat = NULL; + continue; + } break; } if (!content) { - fprintf(stderr, - Name ": Unable to determine reshaped " - "array for %s\n", devname); + pr_err("Unable to determine reshaped " + "array for %s\n", devname); ret_val = 1; goto Grow_continue_command_exit; } fd2 = open_dev(mdstat->devnum); if (fd2 < 0) { - fprintf(stderr, Name ": cannot open (md%i)\n", + pr_err("cannot open (md%i)\n", mdstat->devnum); ret_val = 1; goto Grow_continue_command_exit; @@ -3876,7 +4074,7 @@ int Grow_continue_command(char *devname, int fd, if (mdmon_running(container_dev)) st->update_tail = &st->updates; else { - fprintf(stderr, Name ": No mdmon found. " + pr_err("No mdmon found. " "Grow cannot continue.\n"); ret_val = 1; goto Grow_continue_command_exit; @@ -3886,28 +4084,8 @@ int Grow_continue_command(char *devname, int fd, /* verify that array under reshape is started from * correct position */ - ret_val = sysfs_get_str(content, NULL, "sync_max", buf, 40); - if (ret_val <= 0) { - fprintf(stderr, Name - ": cannot open verify reshape progress for %s (%i)\n", - content->sys_name, ret_val); - ret_val = 1; - goto Grow_continue_command_exit; - } - dprintf(Name ": Read sync_max sysfs entry is: %s\n", buf); - position = strtoull(buf, &ep, 0); - if (ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' ')) { - fprintf(stderr, Name ": Fatal error: array reshape was" - " not properly frozen\n"); - ret_val = 1; - goto Grow_continue_command_exit; - } - position *= get_data_disks(map_name(pers, mdstat->level), - content->new_layout, - content->array.raid_disks); - if (position != content->reshape_progress) { - fprintf(stderr, Name ": Fatal error: array reshape was" - " not properly frozen.\n"); + if (verify_reshape_position(content, + map_name(pers, mdstat->level)) < 0) { ret_val = 1; goto Grow_continue_command_exit; }