summaryrefslogtreecommitdiffstats
path: root/fs/fs-writeback.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2015-06-02 10:39:48 -0400
committerJens Axboe <axboe@fb.com>2015-06-02 10:39:48 -0400
commitb16b1deb553adcd7b3b7ce3e6d6fd1b923f314da (patch)
tree90818c22fd780699cdcb7c35b12f47b860de682a /fs/fs-writeback.c
parent21c6321fbb3a3787af07f1bc031d713a707fb69c (diff)
writeback: make writeback_control track the inode being written back
Currently, for cgroup writeback, the IO submission paths directly associate the bio's with the blkcg from inode_to_wb_blkcg_css(); however, it'd be necessary to keep more writeback context to implement foreign inode writeback detection. wbc (writeback_control) is the natural fit for the extra context - it persists throughout the writeback of each inode and is passed all the way down to IO submission paths. This patch adds wbc_attach_and_unlock_inode(), wbc_detach_inode(), and wbc_attach_fdatawrite_inode() which are used to associate wbc with the inode being written back. IO submission paths now use wbc_init_bio() instead of directly associating bio's with blkcg themselves. This leaves inode_to_wb_blkcg_css() w/o any user. The function is removed. wbc currently only tracks the associated wb (bdi_writeback). Future patches will add more for foreign inode detection. The association is established under i_lock which will be depended upon when migrating foreign inodes to other wb's. As currently, once established, inode to wb association never changes, going through wbc when initializing bio's doesn't cause any behavior changes. v2: submit_blk_blkcg() now checks whether the wbc is associated with a wb before dereferencing it. This can happen when pageout() is writing pages directly without going through the usual writeback path. As pageout() path is single-threaded, we don't want it to be blocked behind a slow cgroup and ultimately want it to delegate actual writing to the usual writeback path. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Jens Axboe <axboe@kernel.dk> Cc: Jan Kara <jack@suse.cz> Cc: Wu Fengguang <fengguang.wu@intel.com> Cc: Greg Thelen <gthelen@google.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'fs/fs-writeback.c')
-rw-r--r--fs/fs-writeback.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index cf6ccfb01e03..755e8ef8d1f0 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -245,6 +245,37 @@ void __inode_attach_wb(struct inode *inode, struct page *page)
245} 245}
246 246
247/** 247/**
248 * wbc_attach_and_unlock_inode - associate wbc with target inode and unlock it
249 * @wbc: writeback_control of interest
250 * @inode: target inode
251 *
252 * @inode is locked and about to be written back under the control of @wbc.
253 * Record @inode's writeback context into @wbc and unlock the i_lock. On
254 * writeback completion, wbc_detach_inode() should be called. This is used
255 * to track the cgroup writeback context.
256 */
257void wbc_attach_and_unlock_inode(struct writeback_control *wbc,
258 struct inode *inode)
259{
260 wbc->wb = inode_to_wb(inode);
261 wb_get(wbc->wb);
262 spin_unlock(&inode->i_lock);
263}
264
265/**
266 * wbc_detach_inode - disassociate wbc from its target inode
267 * @wbc: writeback_control of interest
268 *
269 * To be called after a writeback attempt of an inode finishes and undoes
270 * wbc_attach_and_unlock_inode(). Can be called under any context.
271 */
272void wbc_detach_inode(struct writeback_control *wbc)
273{
274 wb_put(wbc->wb);
275 wbc->wb = NULL;
276}
277
278/**
248 * inode_congested - test whether an inode is congested 279 * inode_congested - test whether an inode is congested
249 * @inode: inode to test for congestion 280 * @inode: inode to test for congestion
250 * @cong_bits: mask of WB_[a]sync_congested bits to test 281 * @cong_bits: mask of WB_[a]sync_congested bits to test
@@ -877,10 +908,11 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
877 !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK))) 908 !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
878 goto out; 909 goto out;
879 inode->i_state |= I_SYNC; 910 inode->i_state |= I_SYNC;
880 spin_unlock(&inode->i_lock); 911 wbc_attach_and_unlock_inode(wbc, inode);
881 912
882 ret = __writeback_single_inode(inode, wbc); 913 ret = __writeback_single_inode(inode, wbc);
883 914
915 wbc_detach_inode(wbc);
884 spin_lock(&wb->list_lock); 916 spin_lock(&wb->list_lock);
885 spin_lock(&inode->i_lock); 917 spin_lock(&inode->i_lock);
886 /* 918 /*
@@ -1013,7 +1045,7 @@ static long writeback_sb_inodes(struct super_block *sb,
1013 continue; 1045 continue;
1014 } 1046 }
1015 inode->i_state |= I_SYNC; 1047 inode->i_state |= I_SYNC;
1016 spin_unlock(&inode->i_lock); 1048 wbc_attach_and_unlock_inode(&wbc, inode);
1017 1049
1018 write_chunk = writeback_chunk_size(wb, work); 1050 write_chunk = writeback_chunk_size(wb, work);
1019 wbc.nr_to_write = write_chunk; 1051 wbc.nr_to_write = write_chunk;
@@ -1025,6 +1057,7 @@ static long writeback_sb_inodes(struct super_block *sb,
1025 */ 1057 */
1026 __writeback_single_inode(inode, &wbc); 1058 __writeback_single_inode(inode, &wbc);
1027 1059
1060 wbc_detach_inode(&wbc);
1028 work->nr_pages -= write_chunk - wbc.nr_to_write; 1061 work->nr_pages -= write_chunk - wbc.nr_to_write;
1029 wrote += write_chunk - wbc.nr_to_write; 1062 wrote += write_chunk - wbc.nr_to_write;
1030 spin_lock(&wb->list_lock); 1063 spin_lock(&wb->list_lock);