From 1f9b0e2845e1ec22dc24dcef275a733c09ff2edd Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 3 Oct 2012 14:41:31 +1000 Subject: [PATCH] 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 --- Grow.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Grow.c b/Grow.c index 20fe907..6da9397 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);