Skip to content

Commit

Permalink
drbd: report congestion if we are waiting for some userland callback
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Lars Ellenberg authored and Philipp Reisner committed Jul 24, 2012
1 parent 383606e commit c2ba686
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 0 deletions.
7 changes: 7 additions & 0 deletions drivers/block/drbd/drbd_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,13 @@ enum {
AL_SUSPENDED, /* Activity logging is currently suspended. */
AHEAD_TO_SYNC_SOURCE, /* Ahead -> SyncSource queued */
STATE_SENT, /* Do not change state/UUIDs while this is set */

CALLBACK_PENDING, /* Whether we have a call_usermodehelper(, UMH_WAIT_PROC)
* pending, from drbd worker context.
* If set, bdi_write_congested() returns true,
* so shrink_page_list() would not recurse into,
* and potentially deadlock on, this drbd worker.
*/
};

struct drbd_bitmap; /* opaque for drbd_conf */
Expand Down
16 changes: 16 additions & 0 deletions drivers/block/drbd/drbd_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3553,6 +3553,22 @@ static int drbd_congested(void *congested_data, int bdi_bits)
goto out;
}

if (test_bit(CALLBACK_PENDING, &mdev->flags)) {
r |= (1 << BDI_async_congested);
/* Without good local data, we would need to read from remote,
* and that would need the worker thread as well, which is
* currently blocked waiting for that usermode helper to
* finish.
*/
if (!get_ldev_if_state(mdev, D_UP_TO_DATE))
r |= (1 << BDI_sync_congested);
else
put_ldev(mdev);
r &= bdi_bits;
reason = 'c';
goto out;
}

if (get_ldev(mdev)) {
q = bdev_get_queue(mdev->ldev->backing_bdev);
r = bdi_congested(&q->backing_dev_info, bdi_bits);
Expand Down
6 changes: 6 additions & 0 deletions drivers/block/drbd/drbd_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
char *argv[] = {usermode_helper, cmd, mb, NULL };
int ret;

if (current == mdev->worker.task)
set_bit(CALLBACK_PENDING, &mdev->flags);

snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev));

if (get_net_conf(mdev)) {
Expand Down Expand Up @@ -189,6 +192,9 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
usermode_helper, cmd, mb,
(ret >> 8) & 0xff, ret);

if (current == mdev->worker.task)
clear_bit(CALLBACK_PENDING, &mdev->flags);

if (ret < 0) /* Ignore any ERRNOs we got. */
ret = 0;

Expand Down

0 comments on commit c2ba686

Please sign in to comment.