aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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