Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f3465ed authored by Lars Ellenberg's avatar Lars Ellenberg Committed by Philipp Reisner
Browse files

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: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 0c849666
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -815,6 +815,12 @@ enum {
	CONN_DRY_RUN,		/* Expect disconnect after resync handshake. */
	CONN_DRY_RUN,		/* Expect disconnect after resync handshake. */
	CREATE_BARRIER,		/* next P_DATA is preceded by a P_BARRIER */
	CREATE_BARRIER,		/* next P_DATA is preceded by a P_BARRIER */
	STATE_SENT,		/* Do not change state/UUIDs while this is set */
	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_tconn {			/* is a resource from the config file */
struct drbd_tconn {			/* is a resource from the config file */
+16 −0
Original line number Original line Diff line number Diff line
@@ -2338,6 +2338,22 @@ static int drbd_congested(void *congested_data, int bdi_bits)
		goto out;
		goto out;
	}
	}


	if (test_bit(CALLBACK_PENDING, &mdev->tconn->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)) {
	if (get_ldev(mdev)) {
		q = bdev_get_queue(mdev->ldev->backing_bdev);
		q = bdev_get_queue(mdev->ldev->backing_bdev);
		r = bdi_congested(&q->backing_dev_info, bdi_bits);
		r = bdi_congested(&q->backing_dev_info, bdi_bits);
+8 −1
Original line number Original line Diff line number Diff line
@@ -323,11 +323,15 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
			NULL };
			NULL };
	char mb[12];
	char mb[12];
	char *argv[] = {usermode_helper, cmd, mb, NULL };
	char *argv[] = {usermode_helper, cmd, mb, NULL };
	struct drbd_tconn *tconn = mdev->tconn;
	struct sib_info sib;
	struct sib_info sib;
	int ret;
	int ret;


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

	snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev));
	snprintf(mb, 12, "minor-%d", mdev_to_minor(mdev));
	setup_khelper_env(mdev->tconn, envp);
	setup_khelper_env(tconn, envp);


	/* The helper may take some time.
	/* The helper may take some time.
	 * write out any unsynced meta data changes now */
	 * write out any unsynced meta data changes now */
@@ -350,6 +354,9 @@ int drbd_khelper(struct drbd_conf *mdev, char *cmd)
	sib.helper_exit_code = ret;
	sib.helper_exit_code = ret;
	drbd_bcast_event(mdev, &sib);
	drbd_bcast_event(mdev, &sib);


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

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