From 00fa5e8ef45592fbf2a783a1985dc9fd989f419b Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Tue, 5 May 2020 17:20:06 +0000 Subject: [PATCH] LU-13486 llite: restore ll_dcompare() Revert "LU-9868 llite: Get rid of ll_dcompare" as it is causing failures in conf-sanity test_32* due to errors with sub-mounted ext2 filesystem dentries being invalidated. This reverts commit 787231f53ab63c72634250f8fe9d27bc66cc4e46. Change-Id: I5cff42df30cf91523c1dbb8ee5b8eefa1ba3a5ad Signed-off-by: Andreas Dilger Reviewed-on: https://review.whamcloud.com/38498 Reviewed-by: James Simmons Reviewed-by: Alex Zhuravlev Tested-by: jenkins Reviewed-by: Neil Brown Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/autoconf/lustre-core.m4 | 37 +++++++++++++++++++++++++++ lustre/llite/dcache.c | 58 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 09240cb..6b5915d 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -428,6 +428,23 @@ dir_context, [ ]) # LC_HAVE_DIR_CONTEXT # +# LC_D_COMPARE_5ARGS +# +# 3.11 dentry_operations.d_compare() taken 5 arguments. +# +AC_DEFUN([LC_D_COMPARE_5ARGS], [ +LB_CHECK_COMPILE([if 'd_compare' taken 5 arguments], +d_compare_5args, [ + #include +],[ + ((struct dentry_operations*)0)->d_compare(NULL,NULL,0,NULL,NULL); +],[ + AC_DEFINE(HAVE_D_COMPARE_5ARGS, 1, + [d_compare need 5 arguments]) +]) +]) # LC_D_COMPARE_5ARGS + +# # LC_HAVE_DCOUNT # # 3.11 need to access d_count to get dentry reference count @@ -1519,6 +1536,24 @@ posix_acl_valid, [ ]) # LC_HAVE_POSIX_ACL_VALID_USER_NS # +# LC_D_COMPARE_4ARGS +# +# Kernel version 4.8 commit 6fa67e707559303e086303aeecc9e8b91ef497d5 +# get rid of 'parent' argument of ->d_compare() +# +AC_DEFUN([LC_D_COMPARE_4ARGS], [ +LB_CHECK_COMPILE([if 'd_compare' taken 4 arguments], +d_compare_4args, [ + #include +],[ + ((struct dentry_operations*)0)->d_compare(NULL,0,NULL,NULL); +],[ + AC_DEFINE(HAVE_D_COMPARE_4ARGS, 1, + [d_compare need 4 arguments]) +]) +]) # LC_D_COMPARE_4ARGS + +# # LC_FULL_NAME_HASH_3ARGS # # Kernel version 4.8 commit 8387ff2577eb9ed245df9a39947f66976c6bcd02 @@ -2198,6 +2233,7 @@ AC_DEFUN([LC_PROG_LINUX], [ # 3.11 LC_INVALIDATE_RANGE LC_HAVE_DIR_CONTEXT + LC_D_COMPARE_5ARGS LC_HAVE_DCOUNT LC_HAVE_DENTRY_D_U_D_ALIAS LC_HAVE_DENTRY_D_CHILD @@ -2289,6 +2325,7 @@ AC_DEFUN([LC_PROG_LINUX], [ # 4.8 LC_HAVE_POSIX_ACL_VALID_USER_NS + LC_D_COMPARE_4ARGS LC_FULL_NAME_HASH_3ARGS LC_STRUCT_POSIX_ACL_XATTR LC_IOP_XATTR diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index cc03462..d33e680 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -66,6 +66,55 @@ static void ll_release(struct dentry *de) EXIT; } +/* Compare if two dentries are the same. Don't match if the existing dentry + * is marked invalid. Returns 1 if different, 0 if the same. + * + * This avoids a race where ll_lookup_it() instantiates a dentry, but we get + * an AST before calling d_revalidate_it(). The dentry still exists (marked + * INVALID) so d_lookup() matches it, but we have no lock on it (so + * lock_match() fails) and we spin around real_lookup(). + * + * This race doesn't apply to lookups in d_alloc_parallel(), and for + * those we want to ensure that only one dentry with a given name is + * in ll_lookup_nd() at a time. So allow invalid dentries to match + * while d_in_lookup(). We will be called again when the lookup + * completes, and can give a different answer then. + */ +#if defined(HAVE_D_COMPARE_5ARGS) +static int ll_dcompare(const struct dentry *parent, const struct dentry *dentry, + unsigned int len, const char *str, + const struct qstr *name) +#elif defined(HAVE_D_COMPARE_4ARGS) +static int ll_dcompare(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +#endif +{ + ENTRY; + + if (len != name->len) + RETURN(1); + + if (memcmp(str, name->name, len)) + RETURN(1); + + CDEBUG(D_DENTRY, "found name %.*s(%p) flags %#x refc %d\n", + name->len, name->name, dentry, dentry->d_flags, + ll_d_count(dentry)); + + /* mountpoint is always valid */ + if (d_mountpoint((struct dentry *)dentry)) + RETURN(0); + + /* ensure exclusion against parallel lookup of the same name */ + if (d_in_lookup((struct dentry *)dentry)) + return 0; + + if (d_lustre_invalid(dentry)) + RETURN(1); + + RETURN(0); +} + /** * Called when last reference to a dentry is dropped and dcache wants to know * whether or not it should cache it: @@ -241,14 +290,6 @@ static int ll_revalidate_dentry(struct dentry *dentry, CDEBUG(D_VFSTRACE, "VFS Op:name=%s, flags=%u\n", dentry->d_name.name, lookup_flags); - /* mountpoint is always valid */ - if (d_mountpoint((struct dentry *)dentry)) - return 1; - - /* No lock -> invalid dentry */ - if (d_lustre_invalid(dentry)) - return 0; - /* If this is intermediate component path lookup and we were able to get * to this dentry, then its lock has not been revoked and the * path component is valid. */ @@ -285,4 +326,5 @@ const struct dentry_operations ll_d_ops = { .d_revalidate = ll_revalidate_dentry, .d_release = ll_release, .d_delete = ll_ddelete, + .d_compare = ll_dcompare, }; -- 1.8.3.1