From 57569871375dd857a89e5e03524d0eec093fef5d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 16 Aug 2021 14:41:22 -0400 Subject: [PATCH] LU-9868 lustre: switch to use of ->d_init() 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 Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/44135 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Neil Brown Reviewed-by: Oleg Drokin --- lustre/autoconf/lustre-core.m4 | 21 +++++++++++++ lustre/llite/dcache.c | 71 ++++++++++++++++++++++++++---------------- lustre/llite/llite_internal.h | 30 +++++++++--------- lustre/llite/llite_nfs.c | 31 ++++++++---------- lustre/llite/namei.c | 16 ++++------ lustre/llite/statahead.c | 7 ++--- 6 files changed, 102 insertions(+), 74 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index b9bfbaa..99d4365 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -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 +],[ + 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 diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index 7116920..a1ca583 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -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, }; diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index c28d7ca..c3f8a4e 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -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); } diff --git a/lustre/llite/llite_nfs.c b/lustre/llite/llite_nfs.c index 1415cbd..ae15e1f 100644 --- a/lustre/llite/llite_nfs.c +++ b/lustre/llite/llite_nfs.c @@ -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); diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 3d17ade..6b56934 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -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 diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c index 810f380..1238b17 100644 --- a/lustre/llite/statahead.c +++ b/lustre/llite/statahead.c @@ -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) -- 1.8.3.1