From 845539a4aa7ca30dd2192fd84ba2a9e90b5c2284 Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Mon, 5 Feb 2024 13:47:49 +0700 Subject: [PATCH] LU-17453 llite: use dget_parent to access dentry.d_parent 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 Change-Id: Icb0a25ece5a3a3d50da076708fcd631176652a1b Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53757 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Neil Brown Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lustre/llite/dcache.c | 21 ++++++++++++++++----- lustre/llite/dir.c | 15 ++++++++------- lustre/llite/file.c | 29 +++++++++++++++++++---------- lustre/llite/pcc.c | 14 +++++++++----- lustre/llite/statahead.c | 9 +++++++-- lustre/llite/xattr.c | 4 +++- 6 files changed, 62 insertions(+), 30 deletions(-) diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index 7746563..03a8dcd 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -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; } diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 253fbf7..c4b770b 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -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 */ diff --git a/lustre/llite/file.c b/lustre/llite/file.c index da15b10..945f49c8 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -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); diff --git a/lustre/llite/pcc.c b/lustre/llite/pcc.c index 9471e10..99447f9 100644 --- a/lustre/llite/pcc.c +++ b/lustre/llite/pcc.c @@ -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); diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c index 35aae94..f798e3b 100644 --- a/lustre/llite/statahead.c +++ b/lustre/llite/statahead.c @@ -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); diff --git a/lustre/llite/xattr.c b/lustre/llite/xattr.c index 500dc66..9839128 100644 --- a/lustre/llite/xattr.c +++ b/lustre/llite/xattr.c @@ -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 -- 1.8.3.1