Whamcloud - gitweb
LU-2523 mdt: handle -ENOENT && !MDS_OPEN_CREAT in reint open
authorJohn L. Hammond <john.hammond@intel.com>
Wed, 27 Feb 2013 07:12:39 +0000 (01:12 -0600)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 13 Mar 2013 06:05:53 +0000 (02:05 -0400)
If mdt_open_by_fid_lock() returns -ENOENT and MDS_OPEN_CREAT is not
set in create flags then bail out and return -ENOENT from
mdt_reint_open().  In mdt_open_by_fid_lock() if -ENOENT is returned
then ensure that DISP_IT_EXECD is set in the reply disposition.  Add
sanity test_27B to call the LL_IOC_LOV_SETSTRIPE ioctl() on an open
unlinked file, a situation which triggers the first case.  In sanityn
test 30, remote the requirement that opening an unlinked file via
/proc/PID/exe return -ESTALE.  In racer's file_create.sh, reinstate
the call to 'lfs setstripe' before dd is started, effectively
reverting commit 0be1c87fe2d4ffddaca9e568cc137518b7368b2d.

Signed-off-by: John L. Hammond <john.hammond@intel.com>
Change-Id: I74e2297c4210ff18acbf60efdf51049d9a88cbea
Reviewed-on: http://review.whamcloud.com/5417
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Tested-by: Hudson
Reviewed-by: Fan Yong <fan.yong@intel.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/mdt/mdt_open.c
lustre/tests/multiop.c
lustre/tests/racer/file_create.sh
lustre/tests/sanity.sh
lustre/tests/sanityn.sh

index 46dc11e..bfb10f8 100644 (file)
@@ -1295,8 +1295,10 @@ int mdt_open_by_fid_lock(struct mdt_thread_info *info, struct ldlm_reply *rep,
                       PFID(rr->rr_fid2));
                GOTO(out, rc = -EREMOTE);
        } else if (!mdt_object_exists(o)) {
-               mdt_set_disposition(info, rep, (DISP_LOOKUP_EXECD |
-                                   DISP_LOOKUP_NEG));
+               mdt_set_disposition(info, rep,
+                                   DISP_IT_EXECD |
+                                   DISP_LOOKUP_EXECD |
+                                   DISP_LOOKUP_NEG);
                GOTO(out, rc = -ENOENT);
        }
 
@@ -1486,11 +1488,21 @@ int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc)
        } else if ((rr->rr_namelen == 0 && create_flags & MDS_OPEN_LOCK) ||
                   (create_flags & MDS_OPEN_BY_FID)) {
                result = mdt_open_by_fid_lock(info, ldlm_rep, lhc);
-               if ((result != -ENOENT && !(create_flags & MDS_OPEN_CREAT)) &&
-                    result != -EREMOTE)
+               /* If result is 0 then open by FID has found the file
+                * and there is nothing left for us to do here.  More
+                * generally if it is anything other than -ENOENT or
+                * -EREMOTE then we return that now.  If -ENOENT and
+                * MDS_OPEN_CREAT is set then we must create the file
+                * below.  If -EREMOTE then we need to return a LOOKUP
+                * lock to the client, which we do below.  Hence this
+                * odd looking condition.  See LU-2523. */
+               if (!(result == -ENOENT && (create_flags & MDS_OPEN_CREAT)) &&
+                   result != -EREMOTE)
                        GOTO(out, result);
+
                if (unlikely(rr->rr_namelen == 0))
                        GOTO(out, result = -EINVAL);
+
                CDEBUG(D_INFO, "No object(2), continue as regular open.\n");
        }
 
index 814bd88..7a21869 100644 (file)
@@ -64,9 +64,10 @@ sem_t sem;
 #define ALIGN_LEN 65535
 
 char usage[] =
-"Usage: %s filename command-sequence\n"
+"Usage: %s filename command-sequence [path...]\n"
 "    command-sequence items:\n"
 "        c  close\n"
+"        B[num] call setstripe ioctl to create stripes\n"
 "        C[num] create with optional stripes\n"
 "        d  mkdir\n"
 "        D  open(O_DIRECTORY)\n"
@@ -74,11 +75,13 @@ char usage[] =
 "       F  print FID\n"
 "        G gid get grouplock\n"
 "        g gid put grouplock\n"
-"        L  link\n"
-"        l  symlink\n"
+"        K  link path to filename\n"
+"        L  link filename to path\n"
+"        l  symlink filename to path\n"
 "        m  mknod\n"
 "        M  rw mmap to EOF (must open and stat prior)\n"
-"        N  rename\n"
+"        n  rename path to filename\n"
+"        N  rename filename to path\n"
 "        o  open(O_RDONLY)\n"
 "        O  open(O_CREAT|O_RDWR)\n"
 "        r[num] read [optional length]\n"
@@ -125,27 +128,28 @@ pop_arg(int argc, char *argv[])
 }
 
 struct flag_mapping {
-       const char *string;
-       const int  flag;
+       const char *string;
+       const int  flag;
 } flag_table[] = {
-       {"O_RDONLY", O_RDONLY},
-       {"O_WRONLY", O_WRONLY},
-       {"O_RDWR", O_RDWR},
-       {"O_CREAT", O_CREAT},
-       {"O_EXCL", O_EXCL},
-       {"O_NOCTTY", O_NOCTTY},
-       {"O_TRUNC", O_TRUNC},
-       {"O_APPEND", O_APPEND},
-       {"O_NONBLOCK", O_NONBLOCK},
-       {"O_NDELAY", O_NDELAY},
-       {"O_SYNC", O_SYNC},
+       {"O_RDONLY", O_RDONLY},
+       {"O_WRONLY", O_WRONLY},
+       {"O_RDWR", O_RDWR},
+       {"O_CREAT", O_CREAT},
+       {"O_EXCL", O_EXCL},
+       {"O_NOCTTY", O_NOCTTY},
+       {"O_TRUNC", O_TRUNC},
+       {"O_APPEND", O_APPEND},
+       {"O_NONBLOCK", O_NONBLOCK},
+       {"O_NDELAY", O_NDELAY},
+       {"O_SYNC", O_SYNC},
 #ifdef O_DIRECT
-       {"O_DIRECT", O_DIRECT},
+       {"O_DIRECT", O_DIRECT},
 #endif
-       {"O_LARGEFILE", O_LARGEFILE},
-       {"O_DIRECTORY", O_DIRECTORY},
-       {"O_NOFOLLOW", O_NOFOLLOW},
-       {"", -1}
+       {"O_LARGEFILE", O_LARGEFILE},
+       {"O_DIRECTORY", O_DIRECTORY},
+       {"O_NOFOLLOW", O_NOFOLLOW},
+       {"O_LOV_DELAY_CREATE", O_LOV_DELAY_CREATE},
+       {"", -1}
 };
 
 int get_flags(char *data, int *rflags)
@@ -193,6 +197,7 @@ int main(int argc, char **argv)
 {
        char            *fname, *commands;
        const char      *newfile;
+       const char      *oldpath;
        struct stat      st;
        struct statfs    stfs;
        size_t           mmap_len = 0, i;
@@ -204,6 +209,7 @@ int main(int argc, char **argv)
        int              gid = 0;
        lustre_fid       fid;
        struct timespec  ts;
+       struct lov_user_md_v3 lum;
 
         if (argc < 3) {
                 fprintf(stderr, usage, argv[0]);
@@ -240,6 +246,18 @@ int main(int argc, char **argv)
                         }
                         fd = -1;
                         break;
+               case 'B':
+                       lum = (struct lov_user_md_v3) {
+                               .lmm_magic = LOV_USER_MAGIC_V3,
+                               .lmm_stripe_count = atoi(commands + 1),
+                       };
+
+                       if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum) < 0) {
+                               save_errno = errno;
+                               perror("LL_IOC_LOV_SETSTRIPE");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'C':
                         len = atoi(commands+1);
                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
@@ -300,6 +318,17 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
+               case 'K':
+                       oldpath = POP_ARG();
+                       if (oldpath == NULL)
+                               oldpath = fname;
+
+                       if (link(oldpath, fname)) {
+                               save_errno = errno;
+                               perror("link()");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'l':
                         newfile = POP_ARG();
                         if (!newfile)
@@ -310,16 +339,17 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
-                case 'L':
-                        newfile = POP_ARG();
-                        if (!newfile)
-                                newfile = fname;
-                        if (link(fname, newfile)) {
-                                save_errno = errno;
-                                perror("symlink()");
-                                exit(save_errno);
-                        }
-                        break;
+               case 'L':
+                       newfile = POP_ARG();
+                       if (newfile == NULL)
+                               newfile = fname;
+
+                       if (link(fname, newfile)) {
+                               save_errno = errno;
+                               perror("link()");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'm':
                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
                                 save_errno = errno;
@@ -342,6 +372,17 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
+               case 'n':
+                       oldpath = POP_ARG();
+                       if (oldpath == NULL)
+                               oldpath = fname;
+
+                       if (rename(oldpath, fname) < 0) {
+                               save_errno = errno;
+                               perror("rename()");
+                               exit(save_errno);
+                       }
+                       break;
                 case 'N':
                         newfile = POP_ARG();
                         if (!newfile)
@@ -520,6 +561,7 @@ int main(int argc, char **argv)
                                 exit(save_errno);
                         }
                         break;
+               case '-':
                 case '0':
                 case '1':
                 case '2':
index 7de46b6..828e69c 100755 (executable)
@@ -4,15 +4,13 @@ DIR=$1
 MAX=$2
 MAX_MB=256
 
-# disable until LU-2523 and LU-2789 are fixed
-[ -z "$RACER_SETSTRIPE" ] && RACER_SETSTRIPE=false
 OSTCOUNT=${OSTCOUNT:-$(lfs df $DIR 2> /dev/null | grep -c OST)}
 
 while /bin/true ; do 
        file=$((RANDOM % MAX))
        SIZE=$((RANDOM * MAX_MB / 32))
        echo "file_create: FILE=$DIR/$file SIZE=$SIZE"
-       [ $OSTCOUNT -gt 0 ] && $RACER_SETSTRIPE &&
+       [ $OSTCOUNT -gt 0 ] &&
                lfs setstripe -c $((RANDOM % OSTCOUNT)) $DIR/$file 2> /dev/null
        dd if=/dev/zero of=$DIR/$file bs=1k count=$SIZE 2> /dev/null
 done
index 234dd48..f16be85 100644 (file)
@@ -1781,6 +1781,29 @@ test_27A() { # b=19102
 }
 run_test 27A "check filesystem-wide default LOV EA values"
 
+test_27B() { # LU-2523
+       test_mkdir -p $DIR/$tdir
+       rm -f $DIR/$tdir/f0 $DIR/$tdir/f1
+       touch $DIR/$tdir/f0
+       # open f1 with O_LOV_DELAY_CREATE
+       # rename f0 onto f1
+       # call setstripe ioctl on open file descriptor for f1
+       # close
+       multiop $DIR/$tdir/f1 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:nB1c \
+               $DIR/$tdir/f0
+
+       rm -f $DIR/$tdir/f1
+       # open f1 with O_LOV_DELAY_CREATE
+       # unlink f1
+       # call setstripe ioctl on open file descriptor for f1
+       # close
+       multiop $DIR/$tdir/f1 oO_RDWR:O_CREAT:O_LOV_DELAY_CREATE:uB1c
+
+       # Allow multiop to fail in imitation of NFS's busted semantics.
+       true
+}
+run_test 27B "call setstripe on open unlinked file/rename victim"
+
 # createtest also checks that device nodes are created and
 # then visible correctly (#2091)
 test_28() { # bug 2091
index 63b2aa7..1944a15 100644 (file)
@@ -687,16 +687,14 @@ test_29() { # bug 10999
 #bug 11549 - permanently turn test off in b1_5
 run_test 29 "lock put race between glimpse and enqueue ========="
 
-test_30() { #bug #11110
+test_30() { #bug #11110, LU-2523
        test_mkdir -p $DIR1/$tdir
        cp -f /bin/bash $DIR1/$tdir/bash
        /bin/sh -c 'sleep 1; rm -f $DIR2/$tdir/bash;
                    cp /bin/bash $DIR2/$tdir' &
-       local err=$($DIR1/$tdir/bash -c 'sleep 2;
-               openfile -f O_RDONLY /proc/$$/exe >& /dev/null; echo $?')
+       $DIR1/$tdir/bash -c 'sleep 2;
+               openfile -f O_RDONLY /proc/$$/exe >& /dev/null; echo $?'
        wait
-       [ $err -ne 116 ] &&
-               error_ignore 12900 "return code ($err) != -ESTALE" && return
        true
 }