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

Commit 32db80f6 authored by Philipp Reisner's avatar Philipp Reisner
Browse files

drbd: Consider the disk-timeout also for meta-data IO operations



If the backing device is already frozen during attach, we failed
to recognize that. The current disk-timeout code works on top
of the drbd_request objects. During attach we do not allow IO
and therefore never generate a drbd_request object but block
before that in drbd_make_request().

This patch adds the timeout to all drbd_md_sync_page_io().

Before this patch we used to go from D_ATTACHING directly
to D_DISKLESS if IO failed during attach. We can no longer
do this since we have to stay in D_FAILED until all IO
ops issued to the backing device returned.

Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 25b0d6c8
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -129,9 +129,21 @@ static bool md_io_allowed(struct drbd_conf *mdev)
	return ds >= D_NEGOTIATING || ds == D_ATTACHING;
}

void wait_until_done_or_disk_failure(struct drbd_conf *mdev, unsigned int *done)
void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
				     unsigned int *done)
{
	wait_event(mdev->misc_wait, *done || !md_io_allowed(mdev));
	long dt;

	rcu_read_lock();
	dt = rcu_dereference(bdev->disk_conf)->disk_timeout;
	rcu_read_unlock();
	dt = dt * HZ / 10;
	if (dt == 0)
		dt = MAX_SCHEDULE_TIMEOUT;

	dt = wait_event_timeout(mdev->misc_wait, *done || !md_io_allowed(mdev), dt);
	if (dt == 0)
		dev_err(DEV, "meta-data IO operation timed out\n");
}

static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
@@ -171,7 +183,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
		bio_endio(bio, -EIO);
	else
		submit_bio(rw, bio);
	wait_until_done_or_disk_failure(mdev, &mdev->md_io.done);
	wait_until_done_or_disk_failure(mdev, bdev, &mdev->md_io.done);
	if (bio_flagged(bio, BIO_UPTODATE))
		err = mdev->md_io.error;

+2 −2
Original line number Diff line number Diff line
@@ -1123,7 +1123,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
	 * "in_flight reached zero, all done" event.
	 */
	if (!atomic_dec_and_test(&ctx->in_flight))
		wait_until_done_or_disk_failure(mdev, &ctx->done);
		wait_until_done_or_disk_failure(mdev, mdev->ldev, &ctx->done);
	else
		kref_put(&ctx->kref, &bm_aio_ctx_destroy);

@@ -1242,7 +1242,7 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc
	}

	bm_page_io_async(ctx, idx, WRITE_SYNC);
	wait_until_done_or_disk_failure(mdev, &ctx->done);
	wait_until_done_or_disk_failure(mdev, mdev->ldev, &ctx->done);

	if (ctx->error)
		drbd_chk_io_error(mdev, 1, true);
+2 −1
Original line number Diff line number Diff line
@@ -1428,7 +1428,8 @@ extern void drbd_md_put_buffer(struct drbd_conf *mdev);
extern int drbd_md_sync_page_io(struct drbd_conf *mdev,
		struct drbd_backing_dev *bdev, sector_t sector, int rw);
extern void drbd_ov_out_of_sync_found(struct drbd_conf *, sector_t, int);
extern void wait_until_done_or_disk_failure(struct drbd_conf *mdev, unsigned int *done);
extern void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
					    unsigned int *done);
extern void drbd_rs_controller_reset(struct drbd_conf *mdev);

static inline void ov_out_of_sync_print(struct drbd_conf *mdev)
+29 −25
Original line number Diff line number Diff line
@@ -1308,14 +1308,17 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
	/* first half of local IO error, failure to attach,
	 * or administrative detach */
	if (os.disk != D_FAILED && ns.disk == D_FAILED) {
		enum drbd_io_error_p eh;
		int was_io_error;
		enum drbd_io_error_p eh = EP_PASS_ON;
		int was_io_error = 0;
		/* corresponding get_ldev was in __drbd_set_state, to serialize
		 * our cleanup here with the transition to D_DISKLESS,
		 * so it is safe to dreference ldev here. */
		 * our cleanup here with the transition to D_DISKLESS.
		 * But is is still not save to dreference ldev here, since
		 * we might come from an failed Attach before ldev was set. */
		if (mdev->ldev) {
			rcu_read_lock();
			eh = rcu_dereference(mdev->ldev->disk_conf)->on_io_error;
			rcu_read_unlock();

			was_io_error = test_and_clear_bit(WAS_IO_ERROR, &mdev->flags);

			/* Immediately allow completion of all application IO, that waits
@@ -1339,6 +1342,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
			 * this may be the last chance.
			 * Following put_ldev may transition to D_DISKLESS. */
			drbd_md_sync(mdev);
		}
		put_ldev(mdev);

		if (was_io_error && eh == EP_CALL_HELPER)