From e2e53a2da5d9fe743fca0c995b5b720a058c5bab Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 10 Mar 2011 15:05:23 +1100 Subject: [PATCH] Grow: support reshape of RAID0 arrays. This is done via conversion to RAID4 and back. To grow the array, extra devices will be needed which cannot already be present as spares - so allow a list of new devices to be included in grow request which changed the number of devices. Signed-off-by: NeilBrown --- Grow.c | 47 ++++++++++++++++++++++++++++++++++------------- mdadm.c | 19 ++++++++++++------- mdadm.h | 1 + 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/Grow.c b/Grow.c index 812c1da..2a41428 100644 --- a/Grow.c +++ b/Grow.c @@ -1273,7 +1273,8 @@ char *analyse_change(struct mdinfo *info, struct reshape *re) static int reshape_array(char *container, int fd, char *devname, struct supertype *st, struct mdinfo *info, - int force, char *backup_file, int quiet, int forked, + int force, struct mddev_dev *devlist, + char *backup_file, int quiet, int forked, int restart); static int reshape_container(char *container, char *devname, struct supertype *st, @@ -1285,6 +1286,7 @@ static int reshape_container(char *container, char *devname, 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, + struct mddev_dev *devlist, int force) { /* Make some changes in the shape of an array. @@ -1315,6 +1317,9 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, char container_buf[20]; int cfd = -1; + struct mddev_dev *dv; + int added_disks; + struct mdinfo info; struct mdinfo *sra; @@ -1390,10 +1395,13 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, if (mdmon_running(container_dev)) st->update_tail = &st->updates; - } + } + added_disks = 0; + for (dv = devlist; dv; dv = dv->next) + added_disks++; if (raid_disks > array.raid_disks && - array.spare_disks < (raid_disks - 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," @@ -1401,7 +1409,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, " Use --force to over-ride this check.\n", raid_disks - array.raid_disks, raid_disks - array.raid_disks == 1 ? "" : "s", - array.spare_disks); + array.spare_disks + added_disks); return 1; } @@ -1614,7 +1622,7 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file, } sync_metadata(st); rv = reshape_array(container, fd, devname, st, &info, force, - backup_file, quiet, 0, 0); + devlist, backup_file, quiet, 0, 0); frozen = 0; } release: @@ -1625,7 +1633,7 @@ release: static int reshape_array(char *container, int fd, char *devname, struct supertype *st, struct mdinfo *info, - int force, + int force, struct mddev_dev *devlist, char *backup_file, int quiet, int forked, int restart) { @@ -1638,6 +1646,9 @@ static int reshape_array(char *container, int fd, char *devname, struct mdu_array_info_s array; char *c; + struct mddev_dev *dv; + int added_disks; + int *fdlist; unsigned long long *offsets; int d; @@ -1697,20 +1708,23 @@ static int reshape_array(char *container, int fd, char *devname, */ sysfs_freeze_array(info); /* Check we have enough spares to not be degraded */ + added_disks = 0; + for (dv = devlist; dv ; dv=dv->next) + added_disks++; spares_needed = max(reshape.before.data_disks, reshape.after.data_disks) + reshape.parity - array.raid_disks; if (!force && - info->new_level > 1 && - spares_needed > info->array.spare_disks) { + 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); + info->array.spare_disks + added_disks); goto release; } /* Check we have enough spares to not fail */ @@ -1718,13 +1732,13 @@ static int reshape_array(char *container, int fd, char *devname, reshape.after.data_disks) - array.raid_disks; if ((info->new_level > 1 || info->new_level == 0) && - spares_needed > info->array.spare_disks) { + 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); + info->array.spare_disks + added_disks); goto release; } @@ -1783,6 +1797,13 @@ static int reshape_array(char *container, int fd, char *devname, sysfs_free(info2); } } + /* We might have been given some devices to add to the + * array. Now that the array has been changed to the right + * level and frozen, we can safely add them. + */ + if (devlist) + Manage_subdevs(devname, fd, devlist, !quiet, + 0,NULL); if (reshape.backup_blocks == 0) { /* No restriping needed, but we might need to impose @@ -2263,7 +2284,7 @@ int reshape_container(char *container, char *devname, sysfs_init(content, fd, mdstat->devnum); rv = reshape_array(container, fd, adev, st, - content, force, + content, force, NULL, backup_file, quiet, 1, restart); close(fd); restart = 0; @@ -3399,5 +3420,5 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info, } } return reshape_array(container, mdfd, "array", st, info, 1, - backup_file, 0, 0, 1); + NULL, backup_file, 0, 0, 1); } diff --git a/mdadm.c b/mdadm.c index 443c88a..c44c432 100644 --- a/mdadm.c +++ b/mdadm.c @@ -1630,22 +1630,26 @@ int main(int argc, char *argv[]) break; } } - if (devs_found > 1) { - + if (devs_found > 1 && raiddisks == 0) { /* must be '-a'. */ - if (size >= 0 || raiddisks || chunk || layout_str != NULL || bitmap_file) { - fprintf(stderr, Name ": --add cannot be used with other geometry changes in --grow mode\n"); + if (size >= 0 || chunk || layout_str != NULL || bitmap_file) { + fprintf(stderr, Name ": --add cannot be used with " + "other geometry changes in --grow mode\n"); rv = 1; break; } for (dv=devlist->next; dv ; dv=dv->next) { - rv = Grow_Add_device(devlist->devname, mdfd, dv->devname); + rv = Grow_Add_device(devlist->devname, mdfd, + dv->devname); if (rv) break; } } else if (bitmap_file) { - if (size >= 0 || raiddisks || chunk || layout_str != NULL) { - fprintf(stderr, Name ": --bitmap changes cannot be used with other geometry changes in --grow mode\n"); + if (size >= 0 || raiddisks || chunk || + layout_str != NULL || devs_found) { + fprintf(stderr, Name ": --bitmap changes cannot be " + "used with other geometry changes " + "in --grow mode\n"); rv = 1; break; } @@ -1657,6 +1661,7 @@ int main(int argc, char *argv[]) || chunk != 0 || level != UnSet) { rv = Grow_reshape(devlist->devname, mdfd, quiet, backup_file, size, level, layout_str, chunk, raiddisks, + devlist->next, force); } else if (array_size < 0) fprintf(stderr, Name ": no changes to --grow\n"); diff --git a/mdadm.h b/mdadm.h index db15175..fa84ad2 100644 --- a/mdadm.h +++ b/mdadm.h @@ -1008,6 +1008,7 @@ extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int dela 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, + struct mddev_dev *devlist, int force); extern int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, int cnt, char *backup_file, int verbose);