[PATCH] vfs: move dentry shrinking outside the inode lock in 'rmdir()'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Yafang Shao reports that he has seen loads that generate billions of
negative dentries in a directory, which then when the directory is
removed causes excessive latencies for other users because the dentry
shrinking is done under the directory inode lock.

There seems to be no actual reason for holding the inode lock any more
by the time we get rid of the now uninteresting negative dentries, and
it's an effect of just code layout (the shared error path).

Reorganize the code trivially to just have a separate success path,
which simplifies the code (since 'd_delete_notify()' is only called in
the success path anyway) and makes it trivial to just move the dentry
shrinking outside the inode lock.

Reported-by: Yafang Shao <laoar.shao@xxxxxxxxx>
Link: https://lore.kernel.org/all/20240511022729.35144-1-laoar.shao@xxxxxxxxx/
Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
Cc: Christian Brauner <brauner@xxxxxxxxxx>
Cc: Jan Kara <jack@xxxxxxx>
Cc: Waiman Long <longman@xxxxxxxxxx>
Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx>
Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
---

Ok, this is the same patch, just with a commit message.  And I actually
am running a kernel with that patch, so it compiles and boots.

Very limited testing: I created a directory with ten million negative
dentries, and then did a "rmdir" in one terminal window while doing a
"ls" inside that directory in another to kind of reproduce (on a smaller
scale) what Yafang was reporting. 

The "ls" was not affected at all.  But honestly, this was *ONE* single
trivial test, so it's almost completely worthless. 

 fs/namei.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 28e62238346e..474b1ee3266d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4217,16 +4217,19 @@ int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir,
 	if (error)
 		goto out;
 
-	shrink_dcache_parent(dentry);
 	dentry->d_inode->i_flags |= S_DEAD;
 	dont_mount(dentry);
 	detach_mounts(dentry);
+	inode_unlock(dentry->d_inode);
+
+	shrink_dcache_parent(dentry);
+	dput(dentry);
+	d_delete_notify(dir, dentry);
+	return 0;
 
 out:
 	inode_unlock(dentry->d_inode);
 	dput(dentry);
-	if (!error)
-		d_delete_notify(dir, dentry);
 	return error;
 }
 EXPORT_SYMBOL(vfs_rmdir);
-- 
2.44.0.330.g4d18c88175





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux