aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2010-08-11 17:17:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-12 11:43:30 -0400
commit81d73a32d775ae9674ea6edf0b5b721fc3bc57d9 (patch)
treec4097c3c7715a128cf54252b2ff906d3d8946ae0
parenta50aeb40144982eb766053309b6fc33e14ca46f0 (diff)
mm: fix writeback_in_progress()
Commit 83ba7b071f3 ("writeback: simplify the write back thread queue") broke writeback_in_progress() as in that commit we started to remove work items from the list at the moment we start working on them and not at the moment they are finished. Thus if the flusher thread was doing some work but there was no other work queued, writeback_in_progress() returned false. This could in particular cause unnecessary queueing of background writeback from balance_dirty_pages() or writeout work from writeback_sb_if_idle(). This patch fixes the problem by introducing a bit in the bdi state which indicates that the flusher thread is processing some work and uses this bit for writeback_in_progress() test. NOTE: Both callsites of writeback_in_progress() (namely, writeback_inodes_sb_if_idle() and balance_dirty_pages()) would actually need a different information than what writeback_in_progress() provides. They would need to know whether *the kind of writeback they are going to submit* is already queued. But this information isn't that simple to provide so let's fix writeback_in_progress() for the time being. Signed-off-by: Jan Kara <jack@suse.cz> Cc: Christoph Hellwig <hch@lst.de> Cc: Wu Fengguang <fengguang.wu@intel.com> Acked-by: Jens Axboe <jaxboe@fusionio.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/fs-writeback.c4
-rw-r--r--include/linux/backing-dev.h1
2 files changed, 4 insertions, 1 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 8a5807d2fb9d..7d9d06ba184b 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -68,7 +68,7 @@ int nr_pdflush_threads;
68 */ 68 */
69int writeback_in_progress(struct backing_dev_info *bdi) 69int writeback_in_progress(struct backing_dev_info *bdi)
70{ 70{
71 return !list_empty(&bdi->work_list); 71 return test_bit(BDI_writeback_running, &bdi->state);
72} 72}
73 73
74static void bdi_queue_work(struct backing_dev_info *bdi, 74static void bdi_queue_work(struct backing_dev_info *bdi,
@@ -740,6 +740,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
740 struct wb_writeback_work *work; 740 struct wb_writeback_work *work;
741 long wrote = 0; 741 long wrote = 0;
742 742
743 set_bit(BDI_writeback_running, &wb->bdi->state);
743 while ((work = get_next_work_item(bdi)) != NULL) { 744 while ((work = get_next_work_item(bdi)) != NULL) {
744 /* 745 /*
745 * Override sync mode, in case we must wait for completion 746 * Override sync mode, in case we must wait for completion
@@ -766,6 +767,7 @@ long wb_do_writeback(struct bdi_writeback *wb, int force_wait)
766 * Check for periodic writeback, kupdated() style 767 * Check for periodic writeback, kupdated() style
767 */ 768 */
768 wrote += wb_check_old_data_flush(wb); 769 wrote += wb_check_old_data_flush(wb);
770 clear_bit(BDI_writeback_running, &wb->bdi->state);
769 771
770 return wrote; 772 return wrote;
771} 773}
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 7628219e5386..35b00746c712 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -31,6 +31,7 @@ enum bdi_state {
31 BDI_async_congested, /* The async (write) queue is getting full */ 31 BDI_async_congested, /* The async (write) queue is getting full */
32 BDI_sync_congested, /* The sync queue is getting full */ 32 BDI_sync_congested, /* The sync queue is getting full */
33 BDI_registered, /* bdi_register() was done */ 33 BDI_registered, /* bdi_register() was done */
34 BDI_writeback_running, /* Writeback is in progress */
34 BDI_unused, /* Available bits start here */ 35 BDI_unused, /* Available bits start here */
35}; 36};
36 37