From: NeilBrown Date: Thu, 18 Oct 2012 06:30:51 +0000 (+1100) Subject: Assemble: split out force_array() X-Git-Tag: mdadm-3.3-rc1~178 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9f5470ce8d8feb9038a2a696c0bd5cd59851bf8e;p=thirdparty%2Fmdadm.git Assemble: split out force_array() force_array() is called if --force was specified to update and metadata necessary to make the array assemble. Signed-off-by: NeilBrown --- diff --git a/Assemble.c b/Assemble.c index 7b3681dd..68de1695 100644 --- a/Assemble.c +++ b/Assemble.c @@ -739,6 +739,108 @@ static int load_devices(struct devs *devices, char *devmap, return devcnt; } +static int force_array(struct mdinfo *content, + struct devs *devices, + int *best, int bestcnt, char *avail, + int most_recent, + struct supertype *st, + struct context *c) +{ + int okcnt = 0; + while (!enough(content->array.level, content->array.raid_disks, + content->array.layout, 1, + avail) + || + (content->reshape_active && content->delta_disks > 0 && + !enough(content->array.level, (content->array.raid_disks + - content->delta_disks), + content->new_layout, 1, + avail) + )) { + /* Choose the newest best drive which is + * not up-to-date, update the superblock + * and add it. + */ + int fd; + struct supertype *tst; + unsigned long long current_events; + int chosen_drive = -1; + int i; + + for (i = 0; i < content->array.raid_disks && i < bestcnt; i++) { + int j = best[i]; + if (j>=0 && + !devices[j].uptodate && + devices[j].i.recovery_start == MaxSector && + (chosen_drive < 0 || + devices[j].i.events + > devices[chosen_drive].i.events)) + chosen_drive = j; + } + if (chosen_drive < 0) + break; + current_events = devices[chosen_drive].i.events; + add_another: + if (c->verbose >= 0) + pr_err("forcing event count in %s(%d) from %d upto %d\n", + devices[chosen_drive].devname, + devices[chosen_drive].i.disk.raid_disk, + (int)(devices[chosen_drive].i.events), + (int)(devices[most_recent].i.events)); + fd = dev_open(devices[chosen_drive].devname, + devices[chosen_drive].included ? O_RDWR + : (O_RDWR|O_EXCL)); + if (fd < 0) { + pr_err("Couldn't open %s for write - not updating\n", + devices[chosen_drive].devname); + devices[chosen_drive].i.events = 0; + continue; + } + tst = dup_super(st); + if (tst->ss->load_super(tst,fd, NULL)) { + close(fd); + pr_err("RAID superblock disappeared from %s - not updating.\n", + devices[chosen_drive].devname); + devices[chosen_drive].i.events = 0; + continue; + } + content->events = devices[most_recent].i.events; + tst->ss->update_super(tst, content, "force-one", + devices[chosen_drive].devname, c->verbose, + 0, NULL); + + if (tst->ss->store_super(tst, fd)) { + close(fd); + pr_err("Could not re-write superblock on %s\n", + devices[chosen_drive].devname); + devices[chosen_drive].i.events = 0; + tst->ss->free_super(tst); + continue; + } + close(fd); + devices[chosen_drive].i.events = devices[most_recent].i.events; + devices[chosen_drive].uptodate = 1; + avail[chosen_drive] = 1; + okcnt++; + tst->ss->free_super(tst); + + /* If there are any other drives of the same vintage, + * add them in as well. We can't lose and we might gain + */ + for (i = 0; i < content->array.raid_disks && i < bestcnt ; i++) { + int j = best[i]; + if (j >= 0 && + !devices[j].uptodate && + devices[j].i.recovery_start == MaxSector && + devices[j].i.events == current_events) { + chosen_drive = j; + goto add_another; + } + } + } + return okcnt; +} + int Assemble(struct supertype *st, char *mddev, struct mddev_ident *ident, struct mddev_dev *devlist, @@ -1097,96 +1199,9 @@ int Assemble(struct supertype *st, char *mddev, } } free(devmap); - while (c->force && - (!enough(content->array.level, content->array.raid_disks, - content->array.layout, 1, - avail) - || - (content->reshape_active && content->delta_disks > 0 && - !enough(content->array.level, (content->array.raid_disks - - content->delta_disks), - content->new_layout, 1, - avail) - ))) { - /* Choose the newest best drive which is - * not up-to-date, update the superblock - * and add it. - */ - int fd; - struct supertype *tst; - unsigned long long current_events; - chosen_drive = -1; - for (i = 0; i < content->array.raid_disks && i < bestcnt; i++) { - int j = best[i]; - if (j>=0 && - !devices[j].uptodate && - devices[j].i.recovery_start == MaxSector && - (chosen_drive < 0 || - devices[j].i.events - > devices[chosen_drive].i.events)) - chosen_drive = j; - } - if (chosen_drive < 0) - break; - current_events = devices[chosen_drive].i.events; - add_another: - if (c->verbose >= 0) - pr_err("forcing event count in %s(%d) from %d upto %d\n", - devices[chosen_drive].devname, - devices[chosen_drive].i.disk.raid_disk, - (int)(devices[chosen_drive].i.events), - (int)(devices[most_recent].i.events)); - fd = dev_open(devices[chosen_drive].devname, - devices[chosen_drive].included ? O_RDWR - : (O_RDWR|O_EXCL)); - if (fd < 0) { - pr_err("Couldn't open %s for write - not updating\n", - devices[chosen_drive].devname); - devices[chosen_drive].i.events = 0; - continue; - } - tst = dup_super(st); - if (tst->ss->load_super(tst,fd, NULL)) { - close(fd); - pr_err("RAID superblock disappeared from %s - not updating.\n", - devices[chosen_drive].devname); - devices[chosen_drive].i.events = 0; - continue; - } - content->events = devices[most_recent].i.events; - tst->ss->update_super(tst, content, "force-one", - devices[chosen_drive].devname, c->verbose, - 0, NULL); - - if (tst->ss->store_super(tst, fd)) { - close(fd); - pr_err("Could not re-write superblock on %s\n", - devices[chosen_drive].devname); - devices[chosen_drive].i.events = 0; - tst->ss->free_super(tst); - continue; - } - close(fd); - devices[chosen_drive].i.events = devices[most_recent].i.events; - devices[chosen_drive].uptodate = 1; - avail[chosen_drive] = 1; - okcnt++; - tst->ss->free_super(tst); - - /* If there are any other drives of the same vintage, - * add them in as well. We can't lose and we might gain - */ - for (i = 0; i < content->array.raid_disks && i < bestcnt ; i++) { - int j = best[i]; - if (j >= 0 && - !devices[j].uptodate && - devices[j].i.recovery_start == MaxSector && - devices[j].i.events == current_events) { - chosen_drive = j; - goto add_another; - } - } - } + if (c->force) + okcnt += force_array(content, devices, best, bestcnt, + avail, most_recent, st, c); /* Now we want to look at the superblock which the kernel will base things on * and compare the devices that we think are working with the devices that the