From 983999bda71115595df48d614ca1aaf9b746c75f Mon Sep 17 00:00:00 2001 From: Yang Sheng Date: Sat, 10 Aug 2024 00:11:14 +0800 Subject: [PATCH] LU-18085 llite: use RCU to protect the dentry_data The upstream has changed the rule of dentry kill since v6.7-rc1-20-g1c18edd1b7a0. The d_release callback will be invoked before the dentry was removed from children list. This means the changes of d_fsdata could be seen for others. We have already used call_rcu to handle the release. So just apply RCU in read side to ensure access safety. Test-Parameters: mdtcount=4 mdscount=2 env=SANITY_EXCEPT="17e 27J 103 244a" clientdistro=ubuntu2404 testlist=sanity Signed-off-by: Yang Sheng Change-Id: I58713bfbf22749d6c0a5e40f710549662248e32f Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55984 Reviewed-by: jsimmons Reviewed-by: Andreas Dilger Reviewed-by: Neil Brown Reviewed-by: Oleg Drokin Tested-by: Maloo Tested-by: jenkins --- lustre/llite/llite_internal.h | 40 ++++++++++++++++++++++++++++------------ lustre/llite/namei.c | 3 +-- lustre/llite/statahead.c | 8 ++++++-- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 768d23f..557370e 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -83,6 +83,17 @@ struct ll_dentry_data { #define ll_d2d(de) ((struct ll_dentry_data *)((de)->d_fsdata)) +static inline void set_lld_invalid(struct dentry *de, int flag) +{ + struct ll_dentry_data *lld; + + rcu_read_lock(); + lld = ll_d2d(de); + if (lld) + lld->lld_invalid = flag; + rcu_read_unlock(); +} + #define LLI_INODE_MAGIC 0x111d0de5 #define LLI_INODE_DEAD 0xdeadd00d @@ -1459,14 +1470,8 @@ void ll_io_set_mirror(struct cl_io *io, const struct file *file); extern const struct dentry_operations ll_d_ops; #ifndef HAVE_D_INIT bool ll_d_setup(struct dentry *de, bool do_put); - -static inline bool lld_is_init(struct dentry *dentry) -{ - return ll_d2d(dentry); -} #else #define ll_d_setup(de, do_put) (true) -#define lld_is_init(dentry) (true) #endif void ll_intent_drop_lock(struct lookup_intent *lookup); @@ -1935,10 +1940,14 @@ dentry_may_statahead(struct inode *dir, struct dentry *dentry) * bypass interacting with statahead cache by checking * 'lld_sa_generation == lli->lli_sa_generation'. */ + rcu_read_lock(); ldd = ll_d2d(dentry); if (ldd != NULL && lli->lli_sa_generation && - ldd->lld_sa_generation == lli->lli_sa_generation) + ldd->lld_sa_generation == lli->lli_sa_generation) { + rcu_read_unlock(); return false; + } + rcu_read_unlock(); if (lli->lli_sa_pattern & LSA_PATTERN_ADVISE) return true; @@ -2005,7 +2014,16 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode, static inline int d_lustre_invalid(const struct dentry *dentry) { - return !ll_d2d(dentry) || ll_d2d(dentry)->lld_invalid; + struct ll_dentry_data *lld; + int rc = 1; + + rcu_read_lock(); + lld = ll_d2d(dentry); + if (lld) + rc = lld->lld_invalid; + rcu_read_unlock(); + + return rc; } /* 8 MiB is where reads are reliably better as DIO on most configs */ @@ -2026,16 +2044,14 @@ static inline void d_lustre_invalidate(struct dentry *dentry) dentry->d_parent, dentry->d_inode, ll_d_count(dentry)); spin_lock(&dentry->d_lock); - if (lld_is_init(dentry)) - ll_d2d(dentry)->lld_invalid = 1; + set_lld_invalid(dentry, 1); spin_unlock(&dentry->d_lock); } static inline void d_lustre_revalidate(struct dentry *dentry) { spin_lock(&dentry->d_lock); - LASSERT(ll_d2d(dentry)); - ll_d2d(dentry)->lld_invalid = 0; + set_lld_invalid(dentry, 0); spin_unlock(&dentry->d_lock); } diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 1724909..653b8b2 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -189,8 +189,7 @@ restart: continue; spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); - if (lld_is_init(child)) - ll_d2d(child)->lld_invalid = 1; + set_lld_invalid(child, 1); if (!ll_d_count(child)) { dget_dlock(child); __d_drop(child); diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c index 4f9bbd7..5746de2 100644 --- a/lustre/llite/statahead.c +++ b/lustre/llite/statahead.c @@ -1946,6 +1946,7 @@ static int revalidate_statahead_dentry(struct inode *dir, bool unplug) { struct sa_entry *entry = NULL; + struct ll_dentry_data *lld; struct ll_inode_info *lli = ll_i2info(dir); struct ll_statahead_info *sai = lli->lli_sai; struct ll_statahead_info *info = NULL; @@ -2090,8 +2091,11 @@ out: * stat this file again, we know we've done statahead before, see * dentry_may_statahead(). */ - if (lld_is_init(*dentryp)) - ll_d2d(*dentryp)->lld_sa_generation = lli->lli_sa_generation; + rcu_read_lock(); + lld = ll_d2d(*dentryp); + if (lld) + lld->lld_sa_generation = lli->lli_sa_generation; + rcu_read_unlock(); sa_put(dir, sai, entry); RETURN(rc); -- 1.8.3.1