From a71369eb9cb0aa89ede41cb01b2cd9cdcd8e9680 Mon Sep 17 00:00:00 2001 From: Yang Sheng Date: Wed, 13 Nov 2024 18:25:17 -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. Lustre-change: https://review.whamcloud.com/55984 Lustre-commit: 983999bda71115595df48d614ca1aaf9b746c75f Signed-off-by: Yang Sheng Change-Id: I58713bfbf22749d6c0a5e40f710549662248e32f Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/57007 Tested-by: jenkins Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- lustre/llite/llite_internal.h | 40 ++++++++++++++++++++++++++++------------ lustre/llite/namei.c | 3 +-- lustre/llite/statahead.c | 9 +++++++-- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index f248bc8..04615f2 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -86,6 +86,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 @@ -1238,14 +1249,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 *); @@ -1638,10 +1643,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(); return true; } @@ -1697,7 +1706,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; } /* @@ -1713,16 +1731,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 2742820..148b748 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -183,8 +183,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 9df5137..e459826 100644 --- a/lustre/llite/statahead.c +++ b/lustre/llite/statahead.c @@ -1491,6 +1491,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); int rc = 0; @@ -1607,8 +1608,12 @@ 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(sai, entry); spin_lock(&lli->lli_sa_lock); if (sai->sai_task) -- 1.8.3.1