aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2010-05-18 08:29:29 -0400
committerJens Axboe <jens.axboe@oracle.com>2010-05-21 14:00:25 -0400
commit7c8a3554c683f512dbcee26faedb42e4c05f12fa (patch)
treeece0d1b79ccc1f596b0ccd0217b584c27a3ff414 /fs
parent2db4e42eaceabec42f738f3895300632cd375e67 (diff)
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: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/fs-writeback.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 0f629571234f..76f546d56a64 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -193,7 +193,8 @@ static void bdi_wait_on_work_clear(struct bdi_work *work)
193} 193}
194 194
195static void bdi_alloc_queue_work(struct backing_dev_info *bdi, 195static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
196 struct wb_writeback_args *args) 196 struct wb_writeback_args *args,
197 int wait)
197{ 198{
198 struct bdi_work *work; 199 struct bdi_work *work;
199 200
@@ -205,6 +206,8 @@ static void bdi_alloc_queue_work(struct backing_dev_info *bdi,
205 if (work) { 206 if (work) {
206 bdi_work_init(work, args); 207 bdi_work_init(work, args);
207 bdi_queue_work(bdi, work); 208 bdi_queue_work(bdi, work);
209 if (wait)
210 bdi_wait_on_work_clear(work);
208 } else { 211 } else {
209 struct bdi_writeback *wb = &bdi->wb; 212 struct bdi_writeback *wb = &bdi->wb;
210 213
@@ -279,7 +282,7 @@ void bdi_start_writeback(struct backing_dev_info *bdi, struct super_block *sb,
279 args.for_background = 1; 282 args.for_background = 1;
280 } 283 }
281 284
282 bdi_alloc_queue_work(bdi, &args); 285 bdi_alloc_queue_work(bdi, &args, sb_locked);
283} 286}
284 287
285/* 288/*
@@ -909,6 +912,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
909 912
910 while ((work = get_next_work_item(bdi, wb)) != NULL) { 913 while ((work = get_next_work_item(bdi, wb)) != NULL) {
911 struct wb_writeback_args args = work->args; 914 struct wb_writeback_args args = work->args;
915 int post_clear;
912 916
913 /* 917 /*
914 * Override sync mode, in case we must wait for completion 918 * 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)
916 if (force_wait) 920 if (force_wait)
917 work->args.sync_mode = args.sync_mode = WB_SYNC_ALL; 921 work->args.sync_mode = args.sync_mode = WB_SYNC_ALL;
918 922
923 post_clear = WB_SYNC_ALL || args.sb_pinned;
924
919 /* 925 /*
920 * If this isn't a data integrity operation, just notify 926 * If this isn't a data integrity operation, just notify
921 * that we have seen this work and we are now starting it. 927 * that we have seen this work and we are now starting it.
922 */ 928 */
923 if (args.sync_mode == WB_SYNC_NONE) 929 if (!post_clear)
924 wb_clear_pending(wb, work); 930 wb_clear_pending(wb, work);
925 931
926 wrote += wb_writeback(wb, &args); 932 wrote += wb_writeback(wb, &args);
@@ -929,7 +935,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
929 * This is a data integrity writeback, so only do the 935 * This is a data integrity writeback, so only do the
930 * notification when we have completed the work. 936 * notification when we have completed the work.
931 */ 937 */
932 if (args.sync_mode == WB_SYNC_ALL) 938 if (post_clear)
933 wb_clear_pending(wb, work); 939 wb_clear_pending(wb, work);
934 } 940 }
935 941
@@ -1000,7 +1006,7 @@ static void bdi_writeback_all(struct super_block *sb, long nr_pages)
1000 if (!bdi_has_dirty_io(bdi)) 1006 if (!bdi_has_dirty_io(bdi))
1001 continue; 1007 continue;
1002 1008
1003 bdi_alloc_queue_work(bdi, &args); 1009 bdi_alloc_queue_work(bdi, &args, 0);
1004 } 1010 }
1005 1011
1006 rcu_read_unlock(); 1012 rcu_read_unlock();