md: use interruptible wait when duration is controlled by userspace.
authorNeilBrown <neilb@suse.de>
Wed, 1 Jul 2009 03:15:35 +0000 (13:15 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 1 Jul 2009 03:15:35 +0000 (13:15 +1000)
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>
drivers/md/md.c
drivers/md/raid5.c

index 65fe35b5e34a252e0aebb637e893afb6a17ff65b..0f4a70c43ffcb1d60aa6eaa2d3f183e6221519a2 100644 (file)
@@ -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;
index 1f444ae07f89efb4e4aeaa81078ef96abde53eda..37835538b58ef8aa4e07595274b1ea5ec27e7c81 100644 (file)
@@ -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;
                        }