diff options
author | Tejun Heo <tj@kernel.org> | 2017-12-12 08:38:30 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-03-05 17:58:01 +0100 |
commit | 494c4399ef3bbc1efa4bd7f2f36454a5f4ef9e64 (patch) | |
tree | 82cbdf10f112dfad248055bbb6553301fb4bfd65 /mm/backing-dev.c | |
parent | 1f13744bc3e00ea7f0332253a11378b67e2b4ddb (diff) | |
download | linux-stable-494c4399ef3bbc1efa4bd7f2f36454a5f4ef9e64.tar.gz linux-stable-494c4399ef3bbc1efa4bd7f2f36454a5f4ef9e64.tar.bz2 linux-stable-494c4399ef3bbc1efa4bd7f2f36454a5f4ef9e64.zip |
writeback: synchronize sync(2) against cgroup writeback membership switches
[ Upstream commit 7fc5854f8c6efae9e7624970ab49a1eac2faefb1 ]
sync_inodes_sb() can race against cgwb (cgroup writeback) membership
switches and fail to writeback some inodes. For example, if an inode
switches to another wb while sync_inodes_sb() is in progress, the new
wb might not be visible to bdi_split_work_to_wbs() at all or the inode
might jump from a wb which hasn't issued writebacks yet to one which
already has.
This patch adds backing_dev_info->wb_switch_rwsem to synchronize cgwb
switch path against sync_inodes_sb() so that sync_inodes_sb() is
guaranteed to see all the target wbs and inodes can't jump wbs to
escape syncing.
v2: Fixed misplaced rwsem init. Spotted by Jiufei.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Jiufei Xue <xuejiufei@gmail.com>
Link: http://lkml.kernel.org/r/dc694ae2-f07f-61e1-7097-7c8411cee12d@gmail.com
Acked-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r-- | mm/backing-dev.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 9386c98dac12..6fa31754eadd 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -684,6 +684,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi) INIT_RADIX_TREE(&bdi->cgwb_tree, GFP_ATOMIC); bdi->cgwb_congested_tree = RB_ROOT; mutex_init(&bdi->cgwb_release_mutex); + init_rwsem(&bdi->wb_switch_rwsem); ret = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL); if (!ret) { |