Whamcloud - gitweb
LU-9868 lustre: switch to use of ->d_init() 35/44135/21
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 16 Aug 2021 18:41:22 +0000 (14:41 -0400)
committerOleg Drokin <green@whamcloud.com>
Sat, 11 Sep 2021 06:19:38 +0000 (06:19 +0000)
Starting with 4.7 kernels the initialization of dentries
is now managed by the VFS layer at allocation time. Any
time a dentry is created by the VFS ll_d_init will be
called.

Linux-commit: 7126bc2e8d60c2a00539bf96b1005f3015be87a5

Change-Id: I02f9b83afd5007658ce88c1010c669d642665d39
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: James Simmons <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/44135
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Neil Brown <neilb@suse.de>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/autoconf/lustre-core.m4
lustre/llite/dcache.c
lustre/llite/llite_internal.h
lustre/llite/llite_nfs.c
lustre/llite/namei.c
lustre/llite/statahead.c

index b9bfbaa..99d4365 100644 (file)
@@ -1576,6 +1576,26 @@ lock_page_memcg, [
 ]) # LC_LOCK_PAGE_MEMCG
 
 #
+# LC_D_INIT
+#
+# Kernel version 4.7-rc5 commit 285b102d3b745f3c2c110c9c327741d87e64aacc
+# add new d_init to initialize dentry at allocation time
+#
+AC_DEFUN([LC_D_INIT], [
+LB_CHECK_COMPILE([if dentry operations supports 'd_init'],
+d_init, [
+       #include <linux/dcache.h>
+],[
+       struct dentry_operations ops = { };
+       int rc;
+
+       rc = ops.d_init(NULL);
+],[
+       AC_DEFINE(HAVE_D_INIT, 1, ['d_init' exists])
+])
+]) # LC_D_INIT
+
+#
 # LC_DIRECTIO_2ARGS
 #
 # Kernel version 4.7 commit c8b8e32d700fe943a935e435ae251364d016c497
@@ -2505,6 +2525,7 @@ AC_DEFUN([LC_PROG_LINUX], [
 
        # 4.7
        LC_D_IN_LOOKUP
+       LC_D_INIT
        LC_DIRECTIO_2ARGS
        LC_GENERIC_WRITE_SYNC_2ARGS
        LC_FOP_ITERATE_SHARED
index 7116920..a1ca583 100644 (file)
@@ -140,36 +140,50 @@ static int ll_ddelete(const struct dentry *de)
        RETURN(0);
 }
 
-int ll_d_init(struct dentry *de)
+#ifdef HAVE_D_INIT
+static int ll_d_init(struct dentry *de)
 {
-       ENTRY;
-       LASSERT(de != NULL);
+       struct ll_dentry_data *lld;
 
-       CDEBUG(D_DENTRY, "ldd on dentry %pd (%p) parent %p inode %p refc %d\n",
-              de, de, de->d_parent, de->d_inode,
-              ll_d_count(de));
-
-       if (de->d_fsdata == NULL) {
-               struct ll_dentry_data *lld;
-
-               OBD_ALLOC_PTR(lld);
-               if (likely(lld != NULL)) {
-                       spin_lock(&de->d_lock);
-                       if (likely(de->d_fsdata == NULL)) {
-                               de->d_fsdata = lld;
-                               __d_lustre_invalidate(de);
-                       } else {
-                               OBD_FREE_PTR(lld);
-                       }
-                       spin_unlock(&de->d_lock);
-               } else {
-                       RETURN(-ENOMEM);
+       OBD_ALLOC_PTR(lld);
+       lld->lld_invalid = 1;
+       de->d_fsdata = lld;
+       return 0;
+}
+#else /* !HAVE_D_INIT */
+
+bool ll_d_setup(struct dentry *de, bool do_put)
+{
+       struct ll_dentry_data *lld;
+       bool success = true;
+
+       if (de->d_fsdata)
+               return success;
+
+       OBD_ALLOC_PTR(lld);
+       if (likely(lld)) {
+               spin_lock(&de->d_lock);
+               /* Since the first d_fsdata test was not
+                * done under the spinlock it could have
+                * changed by time the memory is allocated.
+                */
+               if (!de->d_fsdata) {
+                       lld->lld_invalid = 1;
+                       de->d_fsdata = lld;
                }
+               spin_unlock(&de->d_lock);
+               /* See if we lost the race to set d_fsdata. */
+               if (de->d_fsdata != lld)
+                       OBD_FREE_PTR(lld);
+       } else {
+               success = false;
+               if (do_put)
+                       dput(de);
        }
-       LASSERT(de->d_op == &ll_d_ops);
 
-       RETURN(0);
+       return success;
 }
+#endif /* !HAVE_D_INIT */
 
 void ll_intent_drop_lock(struct lookup_intent *it)
 {
@@ -322,8 +336,11 @@ static int ll_revalidate_dentry(struct dentry *dentry,
 }
 
 const struct dentry_operations ll_d_ops = {
+#ifdef HAVE_D_INIT
+       .d_init         = ll_d_init,
+#endif
        .d_revalidate   = ll_revalidate_dentry,
-        .d_release = ll_release,
-        .d_delete  = ll_ddelete,
-        .d_compare = ll_dcompare,
+       .d_release      = ll_release,
+       .d_delete       = ll_ddelete,
+       .d_compare      = ll_dcompare,
 };
index c28d7ca..c3f8a4e 100644 (file)
@@ -1187,8 +1187,19 @@ void ll_io_set_mirror(struct cl_io *io, const struct file *file);
 
 /* llite/dcache.c */
 
-int ll_d_init(struct dentry *de);
 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 *);
 void ll_intent_release(struct lookup_intent *);
 void ll_prune_aliases(struct inode *inode);
@@ -1633,17 +1644,7 @@ static inline void ll_set_lock_data(struct obd_export *exp, struct inode *inode,
 
 static inline int d_lustre_invalid(const struct dentry *dentry)
 {
-       struct ll_dentry_data *lld = ll_d2d(dentry);
-
-       return (lld == NULL) || lld->lld_invalid;
-}
-
-static inline void __d_lustre_invalidate(struct dentry *dentry)
-{
-       struct ll_dentry_data *lld = ll_d2d(dentry);
-
-       if (lld != NULL)
-               lld->lld_invalid = 1;
+       return !ll_d2d(dentry) || ll_d2d(dentry)->lld_invalid;
 }
 
 /*
@@ -1659,14 +1660,15 @@ static inline void d_lustre_invalidate(struct dentry *dentry)
               dentry->d_parent, dentry->d_inode, ll_d_count(dentry));
 
        spin_lock(&dentry->d_lock);
-       __d_lustre_invalidate(dentry);
+       if (lld_is_init(dentry))
+               ll_d2d(dentry)->lld_invalid = 1;
        spin_unlock(&dentry->d_lock);
 }
 
 static inline void d_lustre_revalidate(struct dentry *dentry)
 {
        spin_lock(&dentry->d_lock);
-       LASSERT(ll_d2d(dentry) != NULL);
+       LASSERT(ll_d2d(dentry));
        ll_d2d(dentry)->lld_invalid = 0;
        spin_unlock(&dentry->d_lock);
 }
index 1415cbd..ae15e1f 100644 (file)
@@ -137,24 +137,19 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren
        /* N.B. d_obtain_alias() drops inode ref on error */
        result = d_obtain_alias(inode);
        if (!IS_ERR(result)) {
-               int rc;
-
-               rc = ll_d_init(result);
-               if (rc < 0) {
-                       dput(result);
-                       result = ERR_PTR(rc);
-               } else {
-                       struct ll_dentry_data *ldd = ll_d2d(result);
-
-                       /*
-                        * Need to signal to the ll_file_open that
-                        * we came from NFS and so opencache needs to be
-                        * enabled for this one
-                        */
-                       spin_lock(&result->d_lock);
-                       ldd->lld_nfs_dentry = 1;
-                       spin_unlock(&result->d_lock);
-               }
+               struct ll_dentry_data *ldd;
+
+               if (!ll_d_setup(result, true))
+                       RETURN(ERR_PTR(-ENOMEM));
+               ldd = ll_d2d(result);
+               /*
+                * Need to signal to the ll_file_open that
+                * we came from NFS and so opencache needs to be
+                * enabled for this one
+                */
+               spin_lock(&result->d_lock);
+               ldd->lld_nfs_dentry = 1;
+               spin_unlock(&result->d_lock);
        }
 
        RETURN(result);
index 3d17ade..6b56934 100644 (file)
@@ -171,7 +171,8 @@ restart:
                                continue;
 
                        spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
-                       __d_lustre_invalidate(child);
+                       if (lld_is_init(child))
+                               ll_d2d(child)->lld_invalid = 1;
                        if (!ll_d_count(child)) {
                                dget_dlock(child);
                                __d_drop(child);
@@ -592,16 +593,12 @@ 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) {
-                       rc = ll_d_init(new);
-                       if (rc < 0) {
-                               dput(new);
-                               return ERR_PTR(rc);
-                       }
+                       if (!ll_d_setup(new, true))
+                               return ERR_PTR(-ENOMEM);
                        d_move(new, de);
                        iput(inode);
                        CDEBUG(D_DENTRY,
@@ -610,9 +607,8 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
                        return new;
                }
        }
-       rc = ll_d_init(de);
-       if (rc < 0)
-               return ERR_PTR(rc);
+       if (!ll_d_setup(de, false))
+               return ERR_PTR(-ENOMEM);
        d_add(de, inode);
 
        /* this needs only to be done for foreign symlink dirs as
index 810f380..1238b17 100644 (file)
@@ -1409,7 +1409,6 @@ static int revalidate_statahead_dentry(struct inode *dir,
                                       bool unplug)
 {
        struct sa_entry *entry = NULL;
-       struct ll_dentry_data *ldd;
        struct ll_inode_info *lli = ll_i2info(dir);
        int rc = 0;
 
@@ -1526,10 +1525,8 @@ out:
         * stat this file again, we know we've done statahead before, see
         * dentry_may_statahead().
         */
-       ldd = ll_d2d(*dentryp);
-       /* ldd can be NULL if llite lookup failed. */
-       if (ldd)
-               ldd->lld_sa_generation = lli->lli_sa_generation;
+       if (lld_is_init(*dentryp))
+               ll_d2d(*dentryp)->lld_sa_generation = lli->lli_sa_generation;
        sa_put(sai, entry);
        spin_lock(&lli->lli_sa_lock);
        if (sai->sai_task)