From 6784a15c6ee32019237151a63755103c68ff51dd Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Thu, 27 Jun 2013 18:22:59 +0800 Subject: [PATCH] LU-3486 llite: remove ll_d_root_ops Mnt root dentry will never be revalidated, but its d_op->d_compare will be called for its children, to simplify code, we use the same ll_d_ops as normal dentries. But its attribute may be invalid before access, this won't cause any issue because it always exists, and the only operation depends on its attribute is .permission, which has revalidated it in lustre code. So it's okay to remove ll_d_root_ops, and remove unnecessary checks in lookup/revalidate/statahead. This patch also includes several small fixes: * don't d_add() for create only files, because the dentry is fake, and will be released right after use. * alloc ll_dentry_data may fail, add check for this. Signed-off-by: Lai Siyao Change-Id: I97b71a9540146809171d80aa5d1a9d4f308faf7f Reviewed-on: http://review.whamcloud.com/6797 Tested-by: Hudson Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Peng Tao Reviewed-by: Bobi Jam Reviewed-by: Fan Yong Reviewed-by: Alexey Shvetsov Reviewed-by: Oleg Drokin --- lustre/llite/dcache.c | 49 +++++++++++------------------------------ lustre/llite/llite_internal.h | 7 +++--- lustre/llite/llite_lib.c | 16 +++++--------- lustre/llite/llite_nfs.c | 10 ++++----- lustre/llite/namei.c | 51 +++++++++++++++++++------------------------ lustre/llite/statahead.c | 7 +++--- 6 files changed, 54 insertions(+), 86 deletions(-) diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index 3a85a13..0dbb96d 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -37,6 +37,7 @@ #include #include #include +#include #define DEBUG_SUBSYSTEM S_LLITE @@ -205,7 +206,7 @@ static int ll_ddelete(HAVE_D_DELETE_CONST struct dentry *de) RETURN(0); } -static int ll_set_dd(struct dentry *de) +int ll_d_init(struct dentry *de) { ENTRY; LASSERT(de != NULL); @@ -220,44 +221,26 @@ static int ll_set_dd(struct dentry *de) OBD_ALLOC_PTR(lld); if (likely(lld != NULL)) { spin_lock(&de->d_lock); - if (likely(de->d_fsdata == NULL)) + if (likely(de->d_fsdata == NULL)) { de->d_fsdata = lld; - else + __d_lustre_invalidate(de); +#ifdef HAVE_DCACHE_LOCK + /* kernel >= 2.6.38 d_op is set in d_alloc() */ + de->d_op = &ll_d_ops; +#endif + } else { OBD_FREE_PTR(lld); + } spin_unlock(&de->d_lock); } else { RETURN(-ENOMEM); } } + LASSERT(de->d_op == &ll_d_ops); RETURN(0); } -int ll_dops_init(struct dentry *de, int block, int init_sa) -{ - struct ll_dentry_data *lld = ll_d2d(de); - int rc = 0; - - if (lld == NULL && block != 0) { - rc = ll_set_dd(de); - if (rc) - return rc; - - lld = ll_d2d(de); - } - - if (lld != NULL && init_sa != 0) - lld->lld_sa_generation = 0; - -#ifdef HAVE_DCACHE_LOCK - de->d_op = &ll_d_ops; -#else - /* kernel >= 2.6.38 d_op is set in d_alloc() */ - LASSERT(de->d_op == &ll_d_ops); -#endif - return rc; -} - void ll_intent_drop_lock(struct lookup_intent *it) { if (it->it_op && it->d.lustre.it_lock_mode) { @@ -401,6 +384,8 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name, LL_IT2STR(it)); + LASSERT(de != de->d_sb->s_root); + if (de->d_inode == NULL) { __u64 ibits; @@ -425,14 +410,6 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, if (d_mountpoint(de)) GOTO(out_sa, rc = 1); - /* need to get attributes in case root got changed from other client */ - if (de == de->d_sb->s_root) { - rc = __ll_inode_revalidate_it(de, it, MDS_INODELOCK_LOOKUP); - if (rc == 0) - rc = 1; - GOTO(out_sa, rc); - } - exp = ll_i2mdexp(de->d_inode); OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5); diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index b7113c5..64055b4 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -853,7 +853,7 @@ int ll_lease_close(struct obd_client_handle *och, struct inode *inode, /* llite/dcache.c */ -int ll_dops_init(struct dentry *de, int block, int init_sa); +int ll_d_init(struct dentry *de); extern struct dentry_operations ll_d_ops; void ll_intent_drop_lock(struct lookup_intent *); void ll_intent_release(struct lookup_intent *); @@ -1341,8 +1341,9 @@ ll_statahead_mark(struct inode *dir, struct dentry *dentry) if (lli->lli_opendir_pid != cfs_curproc_pid()) return; - if (sai != NULL && ldd != NULL) - ldd->lld_sa_generation = sai->sai_generation; + LASSERT(ldd != NULL); + if (sai != NULL) + ldd->lld_sa_generation = sai->sai_generation; } static inline int diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 3623dbd..e2dd3a2 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -162,11 +162,6 @@ void ll_free_sbi(struct super_block *sb) EXIT; } -static struct dentry_operations ll_d_root_ops = { - .d_compare = ll_dcompare, - .d_revalidate = ll_revalidate_nd, -}; - static int client_common_fill_super(struct super_block *sb, char *md, char *dt, struct vfsmount *mnt) { @@ -589,13 +584,8 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, ll_get_fsname(sb, NULL, 0)); GOTO(out_root, err = -ENOMEM); } - #ifdef HAVE_DCACHE_LOCK - sb->s_root->d_op = &ll_d_root_ops; -#else - /* kernel >= 2.6.38 store dentry operations in sb->s_d_op. */ - d_set_d_op(sb->s_root, &ll_d_root_ops); - sb->s_d_op = &ll_d_ops; + sb->s_root->d_op = &ll_d_ops; #endif sbi->ll_sdev_orig = sb->s_dev; @@ -1037,6 +1027,10 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) GOTO(out_free, err); sb->s_bdi = &lsi->lsi_bdi; +#ifndef HAVE_DCACHE_LOCK + /* kernel >= 2.6.38 store dentry operations in sb->s_d_op. */ + sb->s_d_op = &ll_d_ops; +#endif /* Generate a string unique to this super, in case some joker tries to mount the same fs at two mount points. diff --git a/lustre/llite/llite_nfs.c b/lustre/llite/llite_nfs.c index e23a44f..cd5b957 100644 --- a/lustre/llite/llite_nfs.c +++ b/lustre/llite/llite_nfs.c @@ -168,11 +168,11 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren spin_unlock(&lli->lli_lock); } - result = d_obtain_alias(inode); - if (IS_ERR(result)) - RETURN(result); - - ll_dops_init(result, 1, 0); + result = d_obtain_alias(inode); + if (IS_ERR(result)) { + iput(inode); + RETURN(result); + } RETURN(result); } diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 8c15781..2ff3910 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -404,11 +404,16 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de) { struct dentry *new; + int rc; if (inode) { new = ll_find_alias(inode, de); if (new) { - ll_dops_init(new, 1, 1); + rc = ll_d_init(new); + if (rc < 0) { + dput(new); + return ERR_PTR(rc); + } d_move(new, de); iput(inode); CDEBUG(D_DENTRY, @@ -417,8 +422,9 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de) return new; } } - ll_dops_init(de, 1, 1); - __d_lustre_invalidate(de); + rc = ll_d_init(de); + if (rc < 0) + return ERR_PTR(rc); d_add(de, inode); CDEBUG(D_DENTRY, "Add dentry %p inode %p refc %d flags %#x\n", de, de->d_inode, d_refcount(de), de->d_flags); @@ -460,8 +466,11 @@ int ll_lookup_it_finish(struct ptlrpc_request *request, /* Only hash *de if it is unhashed (new dentry). * Atoimc_open may passin hashed dentries for open. */ - if (d_unhashed(*de)) + if (d_unhashed(*de)) { *de = ll_splice_alias(inode, *de); + if (IS_ERR(*de)) + RETURN(PTR_ERR(*de)); + } if (!it_disposition(it, DISP_LOOKUP_NEG)) { /* we have lookup look - unhide dentry */ @@ -511,16 +520,6 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, ll_frob_intent(&it, &lookup_it); - /* As do_lookup is called before follow_mount, root dentry may be left - * not valid, revalidate it here. */ - if (parent->i_sb->s_root && (parent->i_sb->s_root->d_inode == parent) && - (it->it_op & (IT_OPEN | IT_CREAT))) { - rc = ll_inode_revalidate_it(parent->i_sb->s_root, it, - MDS_INODELOCK_LOOKUP); - if (rc) - RETURN(ERR_PTR(rc)); - } - if (it->it_op == IT_GETATTR) { rc = ll_statahead_enter(parent, &dentry, 0); if (rc == 1) { @@ -591,12 +590,8 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, parent->i_generation, parent, flags); /* Optimize away (CREATE && !OPEN). Let .create handle the race. */ - if ((flags & LOOKUP_CREATE ) && !(flags & LOOKUP_OPEN)) { - ll_dops_init(dentry, 1, 1); - __d_lustre_invalidate(dentry); - d_add(dentry, NULL); + if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN)) return NULL; - } if (flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) itp = NULL; @@ -729,14 +724,10 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, it = ll_d2d(dentry)->lld_it; ll_d2d(dentry)->lld_it = NULL; } else { - if ((nd->flags & LOOKUP_CREATE ) && !(nd->flags & LOOKUP_OPEN)) { - /* We are sure this is new dentry, so we need to create - our private data and set the dentry ops */ - ll_dops_init(dentry, 1, 1); - __d_lustre_invalidate(dentry); - d_add(dentry, NULL); + if ((nd->flags & LOOKUP_CREATE) && + !(nd->flags & LOOKUP_OPEN)) RETURN(NULL); - } + it = ll_convert_intent(&nd->intent.open, nd->flags); if (IS_ERR(it)) RETURN((struct dentry *)it); @@ -991,13 +982,17 @@ static int ll_create_nd(struct inode *dir, struct dentry *dentry, static int ll_create_nd(struct inode *dir, struct dentry *dentry, ll_umode_t mode, struct nameidata *nd) { - struct lookup_intent *it = ll_d2d(dentry)->lld_it; + struct ll_dentry_data *lld = ll_d2d(dentry); + struct lookup_intent *it = NULL; int rc; + if (lld != NULL) + it = lld->lld_it; + if (!it) return ll_mknod_generic(dir, &dentry->d_name, mode, 0, dentry); - ll_d2d(dentry)->lld_it = NULL; + lld->lld_it = NULL; /* Was there an error? Propagate it! */ if (it->d.lustre.it_status) { diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c index 19ca1b4..d8d2187 100644 --- a/lustre/llite/statahead.c +++ b/lustre/llite/statahead.c @@ -893,9 +893,6 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry, if (d_mountpoint(dentry)) RETURN(1); - if (unlikely(dentry == dentry->d_sb->s_root)) - RETURN(1); - entry->se_inode = igrab(inode); rc = md_revalidate_lock(ll_i2mdexp(dir), &it, ll_inode2fid(inode),NULL); if (rc == 1) { @@ -1620,6 +1617,10 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, if ((*dentryp)->d_inode == NULL) { *dentryp = ll_splice_alias(inode, *dentryp); + if (IS_ERR(*dentryp)) { + ll_sai_unplug(sai, entry); + RETURN(PTR_ERR(*dentryp)); + } } else if ((*dentryp)->d_inode != inode) { /* revalidate, but inode is recreated */ CDEBUG(D_READA, -- 1.8.3.1