Skip to content

Commit

Permalink
writeback: ensure that WB_SYNC_NONE writeback with sb pinned is sync
Browse files Browse the repository at this point in the history
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 e913fc8.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
  • Loading branch information
Jens Axboe committed May 21, 2010
1 parent 2db4e42 commit 7c8a355
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions fs/fs-writeback.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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);
}

/*
Expand Down Expand Up @@ -909,18 +912,21 @@ 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
*/
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);
Expand All @@ -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);
}

Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 7c8a355

Please sign in to comment.