Whamcloud - gitweb
LU-17453 llite: use dget_parent to access dentry.d_parent 57/53757/10
authorShaun Tancheff <shaun.tancheff@hpe.com>
Mon, 5 Feb 2024 06:47:49 +0000 (13:47 +0700)
committerOleg Drokin <green@whamcloud.com>
Fri, 23 Feb 2024 07:14:19 +0000 (07:14 +0000)
Use dget_parent() to aquire the d_parent member of a dentry
to ensure dentry is valid while it is accessed.

HPE-bug-id: LUS-11889
Signed-off-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Change-Id: Icb0a25ece5a3a3d50da076708fcd631176652a1b
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53757
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Neil Brown <neilb@suse.de>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/dcache.c
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/pcc.c
lustre/llite/statahead.c
lustre/llite/xattr.c

index 7746563..03a8dcd 100644 (file)
@@ -277,8 +277,12 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request,
                if (!ll_d_setup(de, true))
                        RETURN(-ENOMEM);
                d_lustre_revalidate(de);
-               if (S_ISDIR(inode->i_mode))
-                       ll_update_dir_depth_dmv(de->d_parent->d_inode, de);
+               if (S_ISDIR(inode->i_mode)) {
+                       struct dentry *parent = dget_parent(de);
+
+                       ll_update_dir_depth_dmv(d_inode(parent), de);
+                       dput(parent);
+               }
        }
 
        RETURN(rc);
@@ -306,7 +310,8 @@ void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry)
 static int ll_revalidate_dentry(struct dentry *dentry,
                                unsigned int lookup_flags)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct dentry *parent;
+       struct inode *dir;
        int rc;
 
        CDEBUG(D_VFSTRACE, "VFS Op:name=%s, flags=%u\n",
@@ -320,8 +325,11 @@ static int ll_revalidate_dentry(struct dentry *dentry,
         * to this dentry, then its lock has not been revoked and the
         * path component is valid. */
        if (lookup_flags & (LOOKUP_CONTINUE | LOOKUP_PARENT)) {
-               if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
-                       ll_update_dir_depth_dmv(dir, dentry);
+               if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
+                       parent = dget_parent(dentry);
+                       ll_update_dir_depth_dmv(d_inode(parent), dentry);
+                       dput(parent);
+               }
                return 1;
        }
 
@@ -351,11 +359,14 @@ static int ll_revalidate_dentry(struct dentry *dentry,
        if (lookup_flags & LOOKUP_RCU)
                return -ECHILD;
 
+       parent = dget_parent(dentry);
+       dir = d_inode(parent);
        if (dentry_may_statahead(dir, dentry))
                ll_revalidate_statahead(dir, &dentry, dentry->d_inode == NULL);
 
        if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
                ll_update_dir_depth_dmv(dir, dentry);
+       dput(parent);
 
        return 1;
 }
index 253fbf7..c4b770b 100644 (file)
@@ -349,17 +349,18 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir)
                GOTO(out, rc = 0);
 
        if (unlikely(ll_dir_striped(inode))) {
+               struct dentry *parent = dget_parent(file_dentry(filp));
+               struct inode *i_dir = d_inode(parent);
+
                /* Only needed for striped dir to fill ..see lmv_read_page() */
-               if (file_dentry(filp)->d_parent != NULL &&
-                   file_dentry(filp)->d_parent->d_inode != NULL) {
+               if (i_dir) {
+                       struct obd_export *exp = ll_i2mdexp(i_dir);
                        __u64 ibits = MDS_INODELOCK_LOOKUP;
-                       struct inode *parent =
-                               file_dentry(filp)->d_parent->d_inode;
 
-                       if (ll_have_md_lock(ll_i2mdexp(parent), parent, &ibits,
-                                           LCK_MINMODE))
-                               pfid = *ll_inode2fid(parent);
+                       if (ll_have_md_lock(exp, i_dir, &ibits, LCK_MINMODE))
+                               pfid = *ll_inode2fid(i_dir);
                }
+               dput(parent);
 
                /* If it can not find in cache, do lookup .. on the master
                 * object */
index da15b10..945f49c 100644 (file)
@@ -636,7 +636,7 @@ static int ll_intent_file_open(struct dentry *de, void *lmm, int lmmsize,
                                struct lookup_intent *itp)
 {
        struct ll_sb_info *sbi = ll_i2sbi(de->d_inode);
-       struct dentry *parent = de->d_parent;
+       struct dentry *parent = dget_parent(de);
        char *name = NULL;
        int len = 0;
        struct md_op_data *op_data;
@@ -655,7 +655,7 @@ retry:
                len = de->d_name.len;
                name = kmalloc(len + 1, GFP_NOFS);
                if (!name)
-                       RETURN(-ENOMEM);
+                       GOTO(out_put, rc = -ENOMEM);
 
                /* race here */
                spin_lock(&de->d_lock);
@@ -670,7 +670,7 @@ retry:
 
                if (!lu_name_is_valid_2(name, len)) {
                        kfree(name);
-                       RETURN(-ESTALE);
+                       GOTO(out_put, rc = -ESTALE);
                }
        }
 
@@ -678,7 +678,7 @@ retry:
                                     name, len, 0, LUSTRE_OPC_OPEN, NULL);
        if (IS_ERR(op_data)) {
                kfree(name);
-               RETURN(PTR_ERR(op_data));
+               GOTO(out_put, rc = PTR_ERR(op_data));
        }
        op_data->op_data = lmm;
        op_data->op_data_size = lmmsize;
@@ -754,7 +754,8 @@ out:
         */
        if (rc == -ENOENT)
                rc = -ESTALE;
-
+out_put:
+       dput(parent);
        RETURN(rc);
 }
 
@@ -5471,7 +5472,8 @@ static int ll_inode_revalidate_fini(struct inode *inode, int rc)
 
 static int ll_inode_revalidate(struct dentry *dentry, enum ldlm_intent_flags op)
 {
-       struct inode *parent;
+       struct dentry *parent = NULL;
+       struct inode *dir;
        struct inode *inode = dentry->d_inode;
        struct obd_export *exp = ll_i2mdexp(inode);
        struct lookup_intent oit = {
@@ -5488,15 +5490,18 @@ static int ll_inode_revalidate(struct dentry *dentry, enum ldlm_intent_flags op)
               PFID(ll_inode2fid(inode)), inode, dentry->d_name.name);
 
        if (exp_connect_flags2(exp) & OBD_CONNECT2_GETATTR_PFID) {
-               parent = dentry->d_parent->d_inode;
+               parent = dget_parent(dentry);
+               dir = d_inode(parent);
                name = dentry->d_name.name;
                namelen = dentry->d_name.len;
        } else {
-               parent = inode;
+               dir = inode;
        }
 
-       op_data = ll_prep_md_op_data(NULL, parent, inode, name, namelen, 0,
+       op_data = ll_prep_md_op_data(NULL, dir, inode, name, namelen, 0,
                                     LUSTRE_OPC_ANY, NULL);
+       if (parent)
+               dput(parent);
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));
 
@@ -5576,7 +5581,8 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat, u32 request_mask,
        struct inode *inode = de->d_inode;
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ll_inode_info *lli = ll_i2info(inode);
-       struct inode *dir = de->d_parent->d_inode;
+       struct dentry *parent;
+       struct inode *dir;
        bool need_glimpse = true;
        ktime_t kstart = ktime_get();
        int rc;
@@ -5591,10 +5597,13 @@ int ll_getattr_dentry(struct dentry *de, struct kstat *stat, u32 request_mask,
              request_mask & STATX_MTIME))
                need_glimpse = false;
 
+       parent = dget_parent(de);
+       dir = d_inode(parent);
        ll_statahead_enter(dir, de);
        if (dentry_may_statahead(dir, de))
                ll_start_statahead(dir, de, need_glimpse &&
                                   !(flags & AT_STATX_DONT_SYNC));
+       dput(parent);
 
        if (flags & AT_STATX_DONT_SYNC)
                GOTO(fill_attr, rc = 0);
index 9471e10..99447f9 100644 (file)
@@ -2112,14 +2112,15 @@ void pcc_layout_invalidate(struct inode *inode)
 
 static int pcc_inode_remove(struct inode *inode, struct dentry *pcc_dentry)
 {
+       struct dentry *parent = dget_parent(pcc_dentry);
        int rc;
 
-       rc = vfs_unlink(&nop_mnt_idmap,
-                       pcc_dentry->d_parent->d_inode, pcc_dentry);
+       rc = vfs_unlink(&nop_mnt_idmap, d_inode(parent), pcc_dentry);
        if (rc)
                CWARN("%s: failed to unlink PCC file %pd, rc = %d\n",
                      ll_i2sbi(inode)->ll_fsname, pcc_dentry, rc);
 
+       dput(parent);
        return rc;
 }
 
@@ -2347,13 +2348,16 @@ void pcc_create_attach_cleanup(struct super_block *sb,
                return;
 
        if (pca->pca_dentry) {
+               struct dentry *parent;
+               struct inode *i_dir;
                const struct cred *old_cred;
                int rc;
 
                old_cred = override_creds(pcc_super_cred(sb));
-               rc = vfs_unlink(&nop_mnt_idmap,
-                               pca->pca_dentry->d_parent->d_inode,
-                               pca->pca_dentry);
+               parent = dget_parent(pca->pca_dentry);
+               i_dir = d_inode(parent);
+               rc = vfs_unlink(&nop_mnt_idmap, i_dir, pca->pca_dentry);
+               dput(parent);
                if (rc)
                        CWARN("%s: failed to unlink PCC file %pd: rc = %d\n",
                              ll_s2sbi(sb)->ll_fsname, pca->pca_dentry, rc);
index 35aae94..f798e3b 100644 (file)
@@ -2089,9 +2089,9 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry,
        struct ll_inode_info *lli = ll_i2info(dir);
        struct ll_statahead_info *sai = NULL;
        struct ll_statahead_context *ctx = NULL;
-       struct dentry *parent = dentry->d_parent;
+       struct dentry *parent;
        struct task_struct *task;
-       struct ll_sb_info *sbi = ll_i2sbi(parent->d_inode);
+       struct ll_sb_info *sbi;
        int first = LS_FIRST_DE;
        int rc = 0;
 
@@ -2100,14 +2100,19 @@ static int start_statahead_thread(struct inode *dir, struct dentry *dentry,
        if (sa_pattern_detect(dir, dentry, &first) == false)
                RETURN(0);
 
+       parent = dget_parent(dentry);
+       sbi = ll_i2sbi(d_inode(parent));
        if (unlikely(atomic_inc_return(&sbi->ll_sa_running) >
                                       sbi->ll_sa_running_max)) {
                CDEBUG(D_READA,
                       "Too many concurrent statahead instances, avoid new statahead instance temporarily.\n");
+               dput(parent);
                GOTO(out, rc = -EMFILE);
        }
 
+       /* on success ll_sai_alloc holds a ref on parent */
        sai = ll_sai_alloc(parent);
+       dput(parent);
        if (!sai)
                GOTO(out, rc = -ENOMEM);
 
index 500dc66..9839128 100644 (file)
@@ -714,13 +714,15 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
                 */
                if (xh && xh->flags == XATTR_TRUSTED_T &&
                    strcmp(xattr_name, XATTR_NAME_PROJID) == 0) {
-                       struct inode *dir = d_inode(dentry->d_parent);
+                       struct dentry *parent = dget_parent(dentry);
+                       struct inode *dir = d_inode(parent);
 
                        if ((ll_i2info(inode)->lli_projid ==
                             ll_i2info(dir)->lli_projid) &&
                            test_bit(LLIF_PROJECT_INHERIT,
                                     &ll_i2info(dir)->lli_flags))
                                hide_xattr = true;
+                       dput(parent);
                } else if (xh && xh->flags == XATTR_SECURITY_T &&
                           strcmp(xattr_name, "security.c") == 0) {
                        /* Listing xattrs should not expose encryption