hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8WPQW CVE: NA
--------------------------------
Restrictions of negative dentry can avoid softlock when too many dentry in memory, but restrictions before do not always take effect. For example, removing files which has been created would not enter retain_dentry(), because the dentry of file maybe has been added to lru list of superblock, it caused that fast_dput() reutrn true in last dput().
So, add restriction logic for the file which has been added to the lru list in fast_dput(), it prevents the negative dentry exceeding the limit when deleting existing file.
Fixes: c44e1f780873 ("fs/dcache.c: avoid softlock since too many negative dentry") Signed-off-by: Long Li leo.lilong@huawei.com --- fs/dcache.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/fs/dcache.c b/fs/dcache.c index f5b78cc80a00..6fb18d83aaf8 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -776,6 +776,7 @@ static inline bool fast_dput(struct dentry *dentry) { int ret; unsigned int d_flags; + struct dentry *parent;
/* * If we have a d_op->d_delete() operation, we sould not @@ -837,8 +838,25 @@ static inline bool fast_dput(struct dentry *dentry) d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST | DCACHE_DISCONNECTED;
/* Nothing to do? Dropping the reference was all we needed? */ - if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) - return true; + if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) { + parent = dentry->d_parent; + if (!parent) + return true; + + WARN_ON((atomic_read(&parent->d_neg_dnum) < 0)); + if (!dentry->d_inode) { + if (!(dentry->d_flags & DCACHE_NEGATIVE_ACCOUNT)) { + unsigned int flags = READ_ONCE(dentry->d_flags); + + flags |= DCACHE_NEGATIVE_ACCOUNT; + WRITE_ONCE(dentry->d_flags, flags); + atomic_inc(&parent->d_neg_dnum); + } + } + if (dentry->d_inode || + atomic_read(&parent->d_neg_dnum) < NEG_DENTRY_LIMIT) + return true; + }
/* * Not the fast normal case? Get the lock. We've already decremented