diff --git a/Incremental.c b/Incremental.c index 9399f5b..bc4531a 100644 --- a/Incremental.c +++ b/Incremental.c @@ -980,7 +980,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol, close(dfd); *dfdp = -1; rv = Manage_subdevs(chosen->sys_name, mdfd, &devlist, - -1, 0); + -1, 0, NULL); close(mdfd); } if (verbose > 0) { @@ -1549,15 +1549,16 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) int subfd = open_dev(memb->devnum); if (subfd >= 0) { Manage_subdevs(memb->dev, subfd, - &devlist, verbose, 0); + &devlist, verbose, 0, + NULL); close(subfd); } } free_mdstat(mdstat); } else - Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0); + Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL); devlist.disposition = 'r'; - rv = Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0); + rv = Manage_subdevs(ent->dev, mdfd, &devlist, verbose, 0, NULL); close(mdfd); free_mdstat(ent); return rv; diff --git a/Manage.c b/Manage.c index a203ec9..81fa986 100644 --- a/Manage.c +++ b/Manage.c @@ -325,7 +325,8 @@ int Manage_resize(char *devname, int fd, long long size, int raid_disks) } int Manage_subdevs(char *devname, int fd, - struct mddev_dev *devlist, int verbose, int test) + struct mddev_dev *devlist, int verbose, int test, + char *update) { /* do something to each dev. * devmode can be @@ -691,6 +692,24 @@ int Manage_subdevs(char *devname, int fd, remove_partitions(tfd); close(tfd); tfd = -1; + if (update) { + int rv = -1; + tfd = dev_open(dv->devname, O_RDWR); + + if (tfd >= 0) + rv = st->ss->update_super( + st, NULL, update, + devname, verbose, 0, NULL); + if (rv == 0) + rv = tst->ss->store_super(st, tfd); + close(tfd); + tfd = -1; + if (rv != 0) { + fprintf(stderr, Name ": failed to update" + " superblock during re-add\n"); + return 1; + } + } /* don't even try if disk is marked as faulty */ errno = 0; if (ioctl(fd, ADD_NEW_DISK, &disc) == 0) { diff --git a/Monitor.c b/Monitor.c index 61550ee..af70193 100644 --- a/Monitor.c +++ b/Monitor.c @@ -739,9 +739,9 @@ static int move_spare(struct state *from, struct state *to, sprintf(devname, "%d:%d", major(devid), minor(devid)); devlist.disposition = 'r'; - if (Manage_subdevs(from->devname, fd2, &devlist, -1, 0) == 0) { + if (Manage_subdevs(from->devname, fd2, &devlist, -1, 0, NULL) == 0) { devlist.disposition = 'a'; - if (Manage_subdevs(to->devname, fd1, &devlist, -1, 0) == 0) { + if (Manage_subdevs(to->devname, fd1, &devlist, -1, 0, NULL) == 0) { alert("MoveSpare", to->devname, from->devname, info); /* make sure we will see newly added spare before next * time through loop @@ -752,7 +752,7 @@ static int move_spare(struct state *from, struct state *to, close(fd2); return 1; } - else Manage_subdevs(from->devname, fd2, &devlist, -1, 0); + else Manage_subdevs(from->devname, fd2, &devlist, -1, 0, NULL); } close(fd1); close(fd2); diff --git a/mdadm.8.in b/mdadm.8.in index fed5b62..ac87b47 100644 --- a/mdadm.8.in +++ b/mdadm.8.in @@ -1053,7 +1053,7 @@ will report failure if these specifiers didn't find any match. .BR \-a ", " \-\-add hot-add listed devices. If a device appears to have recently been part of the array -(possibly it failed or was removed) the device is re-added as describe +(possibly it failed or was removed) the device is re\-added as describe in the next point. If that fails or the device was never part of the array, the device is added as a hot-spare. @@ -1079,6 +1079,13 @@ When used on an array that has no metadata (i.e. it was built with it will be assumed that bitmap-based recovery is enough to make the device fully consistent with the array. +When +.B \-\-re\-add +can be accompanied by +.BR \-\-update=devicesize . +See the description of this option when used in Assemble mode for an +explanation of its use. + If the device name given is .B missing then mdadm will try to find any device that looks like it should be diff --git a/mdadm.c b/mdadm.c index dd5311d..2ffe94f 100644 --- a/mdadm.c +++ b/mdadm.c @@ -666,12 +666,14 @@ int main(int argc, char *argv[]) case O(ASSEMBLE,'U'): /* update the superblock */ case O(MISC,'U'): if (update) { - fprintf(stderr, Name ": Can only update one aspect of superblock, both %s and %s given.\n", + fprintf(stderr, Name ": Can only update one aspect" + " of superblock, both %s and %s given.\n", update, optarg); exit(2); } if (mode == MISC && !subarray) { - fprintf(stderr, Name ": Only subarrays can be updated in misc mode\n"); + fprintf(stderr, Name ": Only subarrays can be" + " updated in misc mode\n"); exit(2); } update = optarg; @@ -695,13 +697,17 @@ int main(int argc, char *argv[]) continue; if (strcmp(update, "byteorder")==0) { if (ss) { - fprintf(stderr, Name ": must not set metadata type with --update=byteorder.\n"); + fprintf(stderr, + Name ": must not set metadata" + " type with --update=byteorder.\n"); exit(2); } for(i=0; !ss && superlist[i]; i++) - ss = superlist[i]->match_metadata_desc("0.swap"); + ss = superlist[i]->match_metadata_desc( + "0.swap"); if (!ss) { - fprintf(stderr, Name ": INTERNAL ERROR cannot find 0.swap\n"); + fprintf(stderr, Name ": INTERNAL ERROR" + " cannot find 0.swap\n"); exit(2); } @@ -723,6 +729,27 @@ int main(int argc, char *argv[]) " 'no-bitmap'\n"); exit(outf == stdout ? 0 : 2); + case O(MANAGE,'U'): + /* update=devicesize is allowed with --re-add */ + if (devmode != 'a' || re_add != 1) { + fprintf(stderr, Name "--update in Manage mode only" + " allowed with --re-add.\n"); + exit(1); + } + if (update) { + fprintf(stderr, Name ": Can only update one aspect" + " of superblock, both %s and %s given.\n", + update, optarg); + exit(2); + } + update = optarg; + if (strcmp(update, "devicesize") != 0) { + fprintf(stderr, Name ": only 'devicesize' can be" + " updated with --re-add\n"); + exit(2); + } + continue; + case O(INCREMENTAL,NoDegraded): fprintf(stderr, Name ": --no-degraded is deprecated in Incremental mode\n"); case O(ASSEMBLE,NoDegraded): /* --no-degraded */ @@ -1153,7 +1180,8 @@ int main(int argc, char *argv[]) rv = Manage_ro(devlist->devname, mdfd, readonly); if (!rv && devs_found>1) rv = Manage_subdevs(devlist->devname, mdfd, - devlist->next, verbose-quiet, test); + devlist->next, verbose-quiet, test, + update); if (!rv && readonly < 0) rv = Manage_ro(devlist->devname, mdfd, readonly); if (!rv && runstop) diff --git a/mdadm.h b/mdadm.h index 8e2c231..a5d94d7 100644 --- a/mdadm.h +++ b/mdadm.h @@ -959,7 +959,8 @@ extern int Manage_ro(char *devname, int fd, int readonly); extern int Manage_runstop(char *devname, int fd, int runstop, int quiet); extern int Manage_resize(char *devname, int fd, long long size, int raid_disks); extern int Manage_subdevs(char *devname, int fd, - struct mddev_dev *devlist, int verbose, int test); + struct mddev_dev *devlist, int verbose, int test, + char *update); extern int autodetect(void); 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);