aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fs-writeback.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-07-25 07:29:17 -0400
committerJens Axboe <jaxboe@fusionio.com>2010-08-07 12:53:56 -0400
commit78c40cb6581a74adc48821f3de6b864a54d4c34d (patch)
tree9ef19e68f6c28ded34f42de8a21b139006bfceaa /fs/fs-writeback.c
parent080dcec41709be72613133f695be75b98dd43e88 (diff)
writeback: do not remove bdi from bdi_list
The forker thread removes bdis from 'bdi_list' before forking the bdi thread. But this is wrong for at least 2 reasons. Reason #1: if we temporary remove a bdi from the list, we may miss works which would otherwise be given to us. Reason #2: this is racy; indeed, 'bdi_wb_shutdown()' expects that bdis are always in the 'bdi_list' (see 'bdi_remove_from_list()'), and when it races with the forker thread, it can shut down the bdi thread at the same time as the forker creates it. This patch makes sure the forker thread never removes bdis from 'bdi_list' (which was suggested by Christoph Hellwig). In order to make sure that we do not race with 'bdi_wb_shutdown()', we have to hold the 'bdi_lock' while walking the 'bdi_list' and setting the 'BDI_pending' flag. NOTE! The error path is interesting. Currently, when we fail to create a bdi thread, we move the bdi to the tail of 'bdi_list'. But if we never remove the bdi from the list, we cannot move it to the tail either, because then we can mess up the RCU readers which walk the list. And also, we'll have the race described above in "Reason #2". But I not think that adding to the tail is any important so I just do not do that. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'fs/fs-writeback.c')
-rw-r--r--fs/fs-writeback.c7
1 files changed, 0 insertions, 7 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 05444eaa3f36..57fbfd0ebc52 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -804,13 +804,6 @@ int bdi_writeback_thread(void *data)
804 unsigned long wait_jiffies = -1UL; 804 unsigned long wait_jiffies = -1UL;
805 long pages_written; 805 long pages_written;
806 806
807 /*
808 * Add us to the active bdi_list
809 */
810 spin_lock_bh(&bdi_lock);
811 list_add_rcu(&bdi->bdi_list, &bdi_list);
812 spin_unlock_bh(&bdi_lock);
813
814 current->flags |= PF_FLUSHER | PF_SWAPWRITE; 807 current->flags |= PF_FLUSHER | PF_SWAPWRITE;
815 set_freezable(); 808 set_freezable();
816 809