diff options
author | NeilBrown <neilb@suse.de> | 2012-10-03 06:41:31 +0200 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-10-03 06:41:31 +0200 |
commit | 1f9b0e2845e1ec22dc24dcef275a733c09ff2edd (patch) | |
tree | 825a0082f7b68de6a5a4813270dec3cb27a104c8 /Grow.c | |
parent | Use --offroot flag when assembling md arrays via --incrmental (diff) | |
download | mdadm-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.c | 34 |
1 files changed, 34 insertions, 0 deletions
@@ -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); |