dentry_lru_del() is buggy - it tries to remove a dentry from a shrink list, which is not protected by any locks and can only be safely modified by a caller of dcache shrinker. Previous two patches replaced this function calls with d_lru_del() and corresponding checks in two places where it could result in corrupting shrink lists - dentry_kill() and select_collect(). The only place left, shrink_dcache_for_umount(), should be safe, because shrinker should be already unregistered there.
Still, to make sure that it doesn't race with a shrinker, let's replace dentry_lru_del() with d_lru_del() there and make it issue a warning if it encounters a dentry which is on a shrink list. After that dentry_lru_del() is not used anywhere and can be removed. Note, it was removed upstream either, but there are quite a few patches to be backported. Signed-off-by: Vladimir Davydov <[email protected]> --- fs/dcache.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index cba54cf702f5..518c519010e3 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -427,22 +427,6 @@ static void dentry_lru_add(struct dentry *dentry) d_lru_add(dentry); } -/* - * Remove a dentry with references from the LRU. - * - * If we are on the shrink list, then we can get to try_prune_one_dentry() and - * lose our last reference through the parent walk. In this case, we need to - * remove ourselves from the shrink list, not the LRU. - */ -static void dentry_lru_del(struct dentry *dentry) -{ - if (dentry->d_flags & DCACHE_LRU_LIST) { - if (dentry->d_flags & DCACHE_SHRINK_LIST) - return d_shrink_del(dentry); - d_lru_del(dentry); - } -} - /** * d_kill - kill dentry and return parent * @dentry: dentry to kill @@ -1109,7 +1093,9 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) !d_unhashed(dentry)) dentry->d_op->d_prune(dentry); - dentry_lru_del(dentry); + WARN_ON_ONCE(dentry->d_flags & DCACHE_SHRINK_LIST); + if (dentry->d_flags & DCACHE_LRU_LIST) + d_lru_del(dentry); __d_shrink(dentry); if (dentry->d_lockref.count != 0) { -- 2.1.4 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
