Whamcloud - gitweb
LU-18085 llite: use RCU to protect the dentry_data 84/55984/8
authorYang Sheng <ys@whamcloud.com>
Fri, 9 Aug 2024 16:11:14 +0000 (00:11 +0800)
committerOleg Drokin <green@whamcloud.com>
Fri, 23 Aug 2024 22:09:57 +0000 (22:09 +0000)
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 <ys@whamcloud.com>
Change-Id: I58713bfbf22749d6c0a5e40f710549662248e32f
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55984
Reviewed-by: jsimmons <jsimmons@infradead.org>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Neil Brown <neilb@suse.de>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
lustre/llite/llite_internal.h
lustre/llite/namei.c
lustre/llite/statahead.c

index 768d23f..557370e 100644 (file)
@@ -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);
 }
 
index 1724909..653b8b2 100644 (file)
@@ -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);
index 4f9bbd7..5746de2 100644 (file)
@@ -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);