Whamcloud - gitweb
LU-3486 llite: remove ll_d_root_ops 97/6797/7
authorLai Siyao <laisiyao@whamcloud.com>
Thu, 27 Jun 2013 10:22:59 +0000 (18:22 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 1 Aug 2013 01:35:35 +0000 (01:35 +0000)
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 <lai.siyao@intel.com>
Change-Id: I97b71a9540146809171d80aa5d1a9d4f308faf7f
Reviewed-on: http://review.whamcloud.com/6797
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: James Simmons <uja.ornl@gmail.com>
Reviewed-by: Peng Tao <bergwolf@gmail.com>
Reviewed-by: Bobi Jam <bobijam@gmail.com>
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Alexey Shvetsov <alexxy@gentoo.org>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/llite/dcache.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/llite_nfs.c
lustre/llite/namei.c
lustre/llite/statahead.c

index 3a85a13..0dbb96d 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/quotaops.h>
+#include <linux/kernel.h>
 
 #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);
index b7113c5..64055b4 100644 (file)
@@ -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
index 3623dbd..e2dd3a2 100644 (file)
@@ -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.
index e23a44f..cd5b957 100644 (file)
@@ -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);
 }
index 8c15781..2ff3910 100644 (file)
@@ -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) {
index 19ca1b4..d8d2187 100644 (file)
@@ -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,