From a2d5b2e83c0a512a3ea59698e8481621ab5856c2 Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Wed, 13 Nov 2013 15:56:25 +0800 Subject: [PATCH] LU-4185 llite: Revise create with no open optimization Currently ll_lookup_nd just returns a negative when we are trying to create something with no open (read mkdir). This is all fine most of the cases, except if the directory where we are trying to do is not writeable by us. In that case vfs_create would return EPERM seeing as how a negative dentry means the create cannot proceed. But in reality if there is an existing name there that we just did not have cached, the proper return is EEXIST that could only happen if we did do the lookup. So amend the optimization to only take place if the directory is writeable by us, otherwise do the full lookup. Signed-off-by: Oleg Drokin Signed-off-by: Bobi Jam Change-Id: I1480320bd56431a2e47ae686450678324ca17633 Reviewed-on: http://review.whamcloud.com/8257 Tested-by: Maloo Reviewed-by: Fan Yong Reviewed-by: Niu Yawei --- lustre/llite/namei.c | 21 +++++++++++++++++---- lustre/tests/sanity.sh | 9 +++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index a8f961d..c07879f2 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -674,8 +674,13 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, dentry->d_name.len, dentry->d_name.name, PFID(ll_inode2fid(parent)), parent, flags); - /* Optimize away (CREATE && !OPEN). Let .create handle the race. */ - if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN)) + /* + * Optimize away (CREATE && !OPEN). Let .create handle the race. + * but only if we have write permissions there, otherwise we need + * to proceed with lookup. LU-4185 + */ + if ((flags & LOOKUP_CREATE) && !(flags & LOOKUP_OPEN) && + (inode_permission(parent, MAY_WRITE | MAY_EXEC) == 0)) return NULL; if (flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) @@ -827,9 +832,17 @@ 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 { + /* + * Optimize away (CREATE && !OPEN). Let .create handle + * the race. But only if we have write permissions + * there, otherwise we need to proceed with lookup. + * LU-4185 + */ if ((nd->flags & LOOKUP_CREATE) && - !(nd->flags & LOOKUP_OPEN)) - RETURN(NULL); + !(nd->flags & LOOKUP_OPEN) && + (inode_permission(parent, + MAY_WRITE | MAY_EXEC) == 0)) + RETURN(NULL); it = ll_convert_intent(&nd->intent.open, nd->flags); if (IS_ERR(it)) diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index f8478a2..320c39a 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -2850,6 +2850,15 @@ test_33f() { } run_test 33f "nonroot user can create, access, and remove a striped directory" +test_33g() { + mkdir -p $DIR/$tdir/dir2 + + local err=$($RUNAS mkdir $DIR/$tdir/dir2 2>&1) + echo $err + [[ $err =~ "exists" ]] || error "Not exists error" +} +run_test 33g "nonroot user create already existing root created file" + TEST_34_SIZE=${TEST_34_SIZE:-2000000000000} test_34a() { rm -f $DIR/f34 -- 1.8.3.1