devices[devcnt].i = *content;
devices[devcnt].i.disk.major = major(stb.st_rdev);
devices[devcnt].i.disk.minor = minor(stb.st_rdev);
- if (most_recent < devcnt) {
- if (devices[devcnt].i.events
- > devices[most_recent].i.events)
+
+ if (devices[devcnt].i.events
+ > devices[most_recent].i.events &&
+ devices[devcnt].i.disk.state == 6)
most_recent = devcnt;
- }
+
if (content->array.level == LEVEL_MULTIPATH)
/* with multipath, the raid_disk from the superblock is meaningless */
i = devcnt;
unsigned int rebuilding_cnt,
struct context *c,
int clean, char *avail,
- int start_partial_ok
+ int start_partial_ok,
+ int was_forced
)
{
int rv;
}
}
}
+ printf("l=%d o=%d r=%d w=%d\n",content->array.level,
+ okcnt, content->array.raid_disks, was_forced);
+ if (content->array.level == 6 &&
+ okcnt + 1 == (unsigned)content->array.raid_disks &&
+ was_forced) {
+ struct mdinfo *sra = sysfs_read(mdfd, NULL, 0);
+ if (sra)
+ sysfs_set_str(sra, NULL,
+ "sync_action", "repair");
+ sysfs_free(sra);
+ }
return 0;
}
pr_err("failed to RUN_ARRAY %s: %s\n",
int devcnt;
unsigned int okcnt, sparecnt, rebuilding_cnt, replcnt;
int i;
+ int was_forced = 0;
int most_recent = 0;
int chosen_drive;
int change = 0;
inargv, auto_assem);
if (num_devs < 0)
return 1;
-
+
if (!st || !st->sb || !content)
return 2;
best[i] = -1;
continue;
}
+ /* Require event counter to be same as, or just less than,
+ * most recent. If it is bigger, it must be a stray spare and
+ * should be ignored.
+ */
if (devices[j].i.events+event_margin >=
- devices[most_recent].i.events) {
+ devices[most_recent].i.events &&
+ devices[j].i.events <=
+ devices[most_recent].i.events
+ ) {
devices[j].uptodate = 1;
if (i < content->array.raid_disks * 2) {
if (devices[j].i.recovery_start == MaxSector ||
}
}
free(devmap);
- if (c->force)
- okcnt += force_array(content, devices, best, bestcnt,
- avail, most_recent, st, c);
-
+ if (c->force) {
+ int force_ok = force_array(content, devices, best, bestcnt,
+ avail, most_recent, st, c);
+ okcnt += force_ok;
+ if (force_ok)
+ was_forced = 1;
+ }
/* 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
* superblock thinks are working.
change += st->ss->update_super(st, content, "force-array",
devices[chosen_drive].devname, c->verbose,
0, NULL);
+ was_forced = 1;
clean = 1;
}
chosen_drive, devices, okcnt, sparecnt,
rebuilding_cnt,
c,
- clean, avail, start_partial_ok);
+ clean, avail, start_partial_ok, was_forced);
if (rv == 1 && !pre_exist)
ioctl(mdfd, STOP_ARRAY, NULL);
free(devices);
}
}
#endif
-