summaryrefslogtreecommitdiffstats
path: root/Grow.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-10-03 06:41:31 +0200
committerNeilBrown <neilb@suse.de>2012-10-03 06:41:31 +0200
commit1f9b0e2845e1ec22dc24dcef275a733c09ff2edd (patch)
tree825a0082f7b68de6a5a4813270dec3cb27a104c8 /Grow.c
parentUse --offroot flag when assembling md arrays via --incrmental (diff)
downloadmdadm-1f9b0e2845e1ec22dc24dcef275a733c09ff2edd.tar.xz
mdadm-1f9b0e2845e1ec22dc24dcef275a733c09ff2edd.zip
Grow - be careful about 'delayed' reshapes.
If multiple reshapes are activated on the same devices (different partitions) then one might be forced to wait for the other to complete. As reshaping suspends access to small sections of the array at time, this cause a region to be suspended for a long time, which isn't good. To try to detect this and don't start suspending until the reshape is actually happening. This is only effective on 3.7 and later as prior kernels don't report when the delayed reshape can progress. For the earlier kernels, just give a warning. Signed-off-by; NeilBrown <neilb@suse.de>
Diffstat (limited to '')
-rw-r--r--Grow.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/Grow.c b/Grow.c
index 20fe9078..6da93978 100644
--- a/Grow.c
+++ b/Grow.c
@@ -2087,6 +2087,7 @@ static int reshape_array(char *container, int fd, char *devname,
char *msg;
int orig_level = UnSet;
int disks, odisks;
+ int delayed;
struct mdu_array_info_s array;
char *c;
@@ -2573,6 +2574,39 @@ started:
break;
}
+ /* If another array on the same devices is busy, the
+ * reshape will wait for them. This would mean that
+ * the first section that we suspend will stay suspended
+ * for a long time. So check on that possibility
+ * by looking for "DELAYED" in /proc/mdstat, and if found,
+ * wait a while
+ */
+ do {
+ struct mdstat_ent *mds, *m;
+ delayed = 0;
+ mds = mdstat_read(0, 0);
+ for (m = mds; m; m = mds->next)
+ if (m->devnum == devname2devnum(sra->sys_name)) {
+ if (m->resync &&
+ m->percent == RESYNC_DELAYED)
+ delayed = 1;
+ if (m->resync == 0)
+ /* Haven't started the reshape thread
+ * yet, wait a bit
+ */
+ delayed = 2;
+ break;
+ }
+ free_mdstat(mds);
+ if (delayed == 1 && get_linux_version() < 3007000) {
+ pr_err("Reshape is delayed, but cannot wait carefully with this kernel.\n"
+ " You might experience problems until other reshapes complete.\n");
+ delayed = 0;
+ }
+ if (delayed)
+ sleep(30 - (delayed-1) * 25);
+ } while (delayed);
+
close(fd);
if (check_env("MDADM_GROW_VERIFY"))
fd = open(devname, O_RDONLY | O_DIRECT);