From: NeilBrown Date: Thu, 9 Dec 2010 00:51:13 +0000 (+1100) Subject: Grow: warn if growing an array will make it degraded. X-Git-Tag: mdadm-3.2~188 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=691a36b76f871a63a327641589f41e968b05afa9;p=thirdparty%2Fmdadm.git Grow: warn if growing an array will make it degraded. Growing an array when there aren't enough spares can make the array degraded. This works but might not be what is wanted. So warn the user in this case and require a --force to go ahead with the reshape. Signed-off-by: NeilBrown --- diff --git a/Grow.c b/Grow.c index cf09a604..222d755c 100644 --- a/Grow.c +++ b/Grow.c @@ -996,7 +996,8 @@ unsigned long compute_backup_blocks(int nchunk, int ochunk, int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, long long size, - int level, char *layout_str, int chunksize, int raid_disks) + int level, char *layout_str, int chunksize, int raid_disks, + int force) { /* Make some changes in the shape of an array. * The kernel must support the change. @@ -1128,6 +1129,19 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, if (mdmon_running(container_dev)) st->update_tail = &st->updates; + } + + if (raid_disks > array.raid_disks && + array.spare_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); + return 1; } sra = sysfs_read(fd, 0, GET_LEVEL | GET_DISKS | GET_DEVS | GET_STATE); @@ -1309,6 +1323,36 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, rv = 1;/* not possible */ goto release; } + if (!force) { + /* Need to check there are enough spares */ + int spares_needed = 0; + switch (array.level * 16 + level) { + case 0x05: + spares_needed = 1; break; + case 0x06: + spares_needed = 2; break; + case 0x15: + spares_needed = 1; break; + case 0x16: + spares_needed = 2; break; + case 0x56: + spares_needed = 1; break; + } + if (raid_disks > array.raid_disks) + spares_needed += raid_disks-array.raid_disks; + if (spares_needed > array.spare_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", + array.spare_disks); + rv = 1; + goto release; + } + } err = sysfs_set_str(sra, NULL, "level", c); if (err) { err = errno; diff --git a/mdadm.c b/mdadm.c index 187ad891..dd5311d5 100644 --- a/mdadm.c +++ b/mdadm.c @@ -1610,7 +1610,8 @@ int main(int argc, char *argv[]) } else if (size >= 0 || raiddisks != 0 || layout_str != NULL || chunk != 0 || level != UnSet) { rv = Grow_reshape(devlist->devname, mdfd, quiet, backup_file, - size, level, layout_str, chunk, raiddisks); + size, level, layout_str, chunk, raiddisks, + force); } else if (array_size < 0) fprintf(stderr, Name ": no changes to --grow\n"); break; diff --git a/mdadm.h b/mdadm.h index 175d228b..8e2c2314 100644 --- a/mdadm.h +++ b/mdadm.h @@ -965,7 +965,8 @@ extern int Grow_Add_device(char *devname, int fd, char *newdev); extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force); extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, long long size, - int level, char *layout_str, int chunksize, int raid_disks); + int level, char *layout_str, int chunksize, int raid_disks, + int force); extern int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt, char *backup_file, int verbose); extern int Grow_continue(int mdfd, struct supertype *st,