When notification starts/stops listening events from inode's children it have to update dentry->d_flags of all positive child dentries. Scanning may took a long time if directory has a lot of negative child dentries. This is main beneficiary of sweeping cached negative dentries to the end. Before patch: nr_dentry = 24172597 24.2M nr_buckets = 8388608 2.9 avg nr_unused = 24158110 99.9% nr_negative = 24142810 99.9% inotify time: 0.507182 seconds After patch: nr_dentry = 24562747 24.6M nr_buckets = 8388608 2.9 avg nr_unused = 24548714 99.9% nr_negative = 24543867 99.9% inotify time: 0.000010 seconds Negative dentries no longer slow down inotify op at parent directory. Signed-off-by: Konstantin Khlebnikov <khlebnikov@xxxxxxxxxxxxxx> --- fs/notify/fsnotify.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 72d332ce8e12..072974302950 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -127,8 +127,12 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) * original inode) */ spin_lock(&alias->d_lock); list_for_each_entry(child, &alias->d_subdirs, d_child) { - if (!child->d_inode) + if (!child->d_inode) { + /* all remaining children are negative */ + if (d_is_tail_negative(child)) + break; continue; + } spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); if (watched)