summaryrefslogtreecommitdiff
path: root/Assemble.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-10-18 17:30:51 +1100
committerNeilBrown <neilb@suse.de>2012-10-18 17:30:51 +1100
commit9f5470ce8d8feb9038a2a696c0bd5cd59851bf8e (patch)
treea4f7f834305db868967c620bc10dd9b52eec0f86 /Assemble.c
parent2c355c225e6d2238e9fe701af0b10e6fbca44474 (diff)
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 <neilb@suse.de>
Diffstat (limited to 'Assemble.c')
-rw-r--r--Assemble.c195
1 files changed, 105 insertions, 90 deletions
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