summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-07-01 13:15:35 +1000
committerNeilBrown <neilb@suse.de>2009-07-01 13:15:35 +1000
commite62e58a5ffdc98ac28d8dbd070c857620d541f99 (patch)
tree0ec3471f4e66e3a376ac8cb2da79d6123e7aa2cf
parenta5c308d4d1659b1f4833b863394e3e24cdbdfc6e (diff)
md: use interruptible wait when duration is controlled by userspace.
User space can set various limits on an md array so that resync waits when it gets to a certain point, or so that I/O is blocked for a short while. When md is waiting against one of these limit, it should use an interruptible wait so as not to add to the load average, and so are not to trigger a warning if the wait goes on for too long. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--drivers/md/md.c14
-rw-r--r--drivers/md/raid5.c15
2 files changed, 21 insertions, 8 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 65fe35b5e34..0f4a70c43ff 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -6336,10 +6336,16 @@ void md_do_sync(mddev_t *mddev)
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
}
- if (j >= mddev->resync_max)
- wait_event(mddev->recovery_wait,
- mddev->resync_max > j
- || kthread_should_stop());
+ while (j >= mddev->resync_max && !kthread_should_stop()) {
+ /* As this condition is controlled by user-space,
+ * we can block indefinitely, so use '_interruptible'
+ * to avoid triggering warnings.
+ */
+ flush_signals(current); /* just in case */
+ wait_event_interruptible(mddev->recovery_wait,
+ mddev->resync_max > j
+ || kthread_should_stop());
+ }
if (kthread_should_stop())
goto interrupted;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 1f444ae07f8..37835538b58 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3699,14 +3699,21 @@ static int make_request(struct request_queue *q, struct bio * bi)
goto retry;
}
}
- /* FIXME what if we get a false positive because these
- * are being updated.
- */
+
if (bio_data_dir(bi) == WRITE &&
logical_sector >= mddev->suspend_lo &&
logical_sector < mddev->suspend_hi) {
release_stripe(sh);
- schedule();
+ /* As the suspend_* range is controlled by
+ * userspace, we want an interruptible
+ * wait.
+ */
+ flush_signals(current);
+ prepare_to_wait(&conf->wait_for_overlap,
+ &w, TASK_INTERRUPTIBLE);
+ if (logical_sector >= mddev->suspend_lo &&
+ logical_sector < mddev->suspend_hi)
+ schedule();
goto retry;
}