Whamcloud - gitweb
LU-4185 llite: Revise create with no open optimization 57/8257/10
authorBobi Jam <bobijam.xu@intel.com>
Wed, 13 Nov 2013 07:56:25 +0000 (15:56 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 5 Oct 2016 03:51:18 +0000 (03:51 +0000)
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 <oleg.drokin@intel.com>
Signed-off-by: Bobi Jam <bobijam.xu@intel.com>
Change-Id: I1480320bd56431a2e47ae686450678324ca17633
Reviewed-on: http://review.whamcloud.com/8257
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
lustre/llite/namei.c
lustre/tests/sanity.sh

index a8f961d..c07879f 100644 (file)
@@ -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);
 
               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))
                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 {
                         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) &&
                        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))
 
                         it = ll_convert_intent(&nd->intent.open, nd->flags);
                         if (IS_ERR(it))
index f8478a2..320c39a 100755 (executable)
@@ -2850,6 +2850,15 @@ test_33f() {
 }
 run_test 33f "nonroot user can create, access, and remove a striped directory"
 
 }
 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
 TEST_34_SIZE=${TEST_34_SIZE:-2000000000000}
 test_34a() {
        rm -f $DIR/f34