aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2012-06-14 09:14:06 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-07-24 08:07:18 -0400
commitc2ba686f353972cc89a006ffb6bab7ba1822271e (patch)
tree666920e336f5e85cdf4d03ecafa165c6a65743a4 /drivers/block
parent383606e0dea6a380097dbcb0c319b09ca372f36b (diff)
drbd: report congestion if we are waiting for some userland callback
If the drbd worker thread is synchronously waiting for some userland callback, we don't want some casual pageout to block on us. Have drbd_congested() report congestion in that case. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_int.h7
-rw-r--r--drivers/block/drbd/drbd_main.c16
-rw-r--r--drivers/block/drbd/drbd_nl.c6
3 files changed, 29 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 79c69ebb0653..5136510ec8be 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -850,6 +850,13 @@ enum {
850 AL_SUSPENDED, /* Activity logging is currently suspended. */ 850 AL_SUSPENDED, /* Activity logging is currently suspended. */
851 AHEAD_TO_SYNC_SOURCE, /* Ahead -> SyncSource queued */ 851 AHEAD_TO_SYNC_SOURCE, /* Ahead -> SyncSource queued */
852 STATE_SENT, /* Do not change state/UUIDs while this is set */ 852 STATE_SENT, /* Do not change state/UUIDs while this is set */
853
854 CALLBACK_PENDING, /* Whether we have a call_usermodehelper(, UMH_WAIT_PROC)
855 * pending, from drbd worker context.
856 * If set, bdi_write_congested() returns true,
857 * so shrink_page_list() would not recurse into,
858 * and potentially deadlock on, this drbd worker.
859 */
853}; 860};
854 861
855struct drbd_bitmap; /* opaque for drbd_conf */ 862struct drbd_bitmap; /* opaque for drbd_conf */
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 5bebe8d8ace3..41ccb580d5ac 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -3553,6 +3553,22 @@ static int drbd_congested(void *congested_data, int bdi_bits)
3553 goto out; 3553 goto out;
3554 } 3554 }
3555 3555
3556 if (test_bit(CALLBACK_PENDING, &mdev->flags)) {
3557 r |= (1 << BDI_async_congested);
3558 /* Without good local data, we would need to read from remote,
3559 * and that would need the worker thread as well, which is
3560 * currently blocked waiting for that usermode helper to
3561 * finish.
3562 */
3563 if (!get_ldev_if_state(mdev, D_UP_TO_DATE))
3564 r |= (1 << BDI_sync_congested);
3565 else
3566 put_ldev(mdev);
3567 r &= bdi_bits;
3568 reason = 'c';
3569 goto out;
3570 }
3571
3556 if (get_ldev(mdev)) { 3572 if (get_ldev(mdev)) {
3557 q = bdev_get_queue(mdev->ldev->backing_bdev); 3573 q = bdev_get_queue(mdev->ldev->backing_bdev);
3558 r = bdi_congested(&q->backing_dev_info, bdi_bits); 3574 r = bdi_congested(&q->backing_dev_info, bdi_bits);
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 40a1c4f07190..03fc853be2b9 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -147,6 +147,9 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
147 char *argv[] = {usermode_helper, cmd, mb, NULL }; 147 char *argv[] = {usermode_helper, cmd, mb, NULL };
148 int ret; 148 int ret;
149 149
150 if (current == mdev->worker.task)
151 set_bit(CALLBACK_PENDING, &mdev->flags);
152
150 snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev)); 153 snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev));
151 154
152 if (get_net_conf(mdev)) { 155 if (get_net_conf(mdev)) {
@@ -189,6 +192,9 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
189 usermode_helper, cmd, mb, 192 usermode_helper, cmd, mb,
190 (ret >> 8) & 0xff, ret); 193 (ret >> 8) & 0xff, ret);
191 194
195 if (current == mdev->worker.task)
196 clear_bit(CALLBACK_PENDING, &mdev->flags);
197
192 if (ret < 0) /* Ignore any ERRNOs we got. */ 198 if (ret < 0) /* Ignore any ERRNOs we got. */
193 ret = 0; 199 ret = 0;
194 200