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

Commit 7c8a3554 authored by Jens Axboe's avatar Jens Axboe
Browse files

writeback: ensure that WB_SYNC_NONE writeback with sb pinned is sync



Even if the writeout itself isn't a data integrity operation, we need
to ensure that the caller doesn't drop the sb umount sem before we
have actually done the writeback.

This is a fixup for commit e913fc82.

Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 2db4e42e
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -193,7 +193,8 @@ static void bdi_wait_on_work_clear(struct bdi_work *work)
}

static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
				 struct wb_writeback_args *args)
				 struct wb_writeback_args *args,
				 int wait)
{
	struct bdi_work *work;

@@ -205,6 +206,8 @@ static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
	if (work) {
		bdi_work_init(work, args);
		bdi_queue_work(bdi, work);
		if (wait)
			bdi_wait_on_work_clear(work);
	} else {
		struct bdi_writeback *wb = &bdi->wb;

@@ -279,7 +282,7 @@ void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
		args.for_background = 1;
	}

	bdi_alloc_queue_work(bdi, &args);
	bdi_alloc_queue_work(bdi, &args, sb_locked);
}

/*
@@ -909,6 +912,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)

	while ((work = get_next_work_item(bdi, wb)) != NULL) {
		struct wb_writeback_args args = work->args;
		int post_clear;

		/*
		 * Override sync mode, in case we must wait for completion
@@ -916,11 +920,13 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
		if (force_wait)
			work->args.sync_mode = args.sync_mode = WB_SYNC_ALL;

		post_clear = WB_SYNC_ALL || args.sb_pinned;

		/*
		 * If this isn't a data integrity operation, just notify
		 * that we have seen this work and we are now starting it.
		 */
		if (args.sync_mode == WB_SYNC_NONE)
		if (!post_clear)
			wb_clear_pending(wb, work);

		wrote += wb_writeback(wb, &args);
@@ -929,7 +935,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
		 * This is a data integrity writeback, so only do the
		 * notification when we have completed the work.
		 */
		if (args.sync_mode == WB_SYNC_ALL)
		if (post_clear)
			wb_clear_pending(wb, work);
	}

@@ -1000,7 +1006,7 @@ static void bdi_writeback_all(struct super_block *sb, long nr_pages)
		if (!bdi_has_dirty_io(bdi))
			continue;

		bdi_alloc_queue_work(bdi, &args);
		bdi_alloc_queue_work(bdi, &args, 0);
	}

	rcu_read_unlock();