Whamcloud - gitweb
- cosmetic changes in mdapi DLD
authoryury <yury>
Tue, 19 Apr 2005 12:08:05 +0000 (12:08 +0000)
committeryury <yury>
Tue, 19 Apr 2005 12:08:05 +0000 (12:08 +0000)
- more fixes in GNS stuff:
  - fixes with refcount onto @dchild in ll_gns_mount_object() for error control paths
  - fixing using accessing @dchild in the case of IS_ERR(dchild)

  - disabled checking for GNS file in mds_open(), thus GNS mount points are also
    opening by now. This is needed, because in taking lock we can't reliable to detect
    GNS objects on MDS. Checking just suid bit and skip open such a dirs is not correct
    as one may create structure like dir/dir/dir and mark all of them by suid.

  - cleanups in sanity-gns.sh. Added few new tests for odd conditions like mount object
    is symlink, dir, etc. Added test for changing mount object name to "." and "..".
    Grouping tests into 2 groups:

    (1) general GNS tests - mounting/umounting on timeout with different conditions
    with possible deadlocks, races, etc.

    (2) checking for odd conditions like recursive suid bit marked mount points, etc

lustre/llite/llite_gns.c
lustre/mds/mds_open.c
lustre/tests/sanity-gns.sh

index f28c11e..a8e73c3 100644 (file)
@@ -155,8 +155,7 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
                                 strlen(sbi->ll_gns_oname));
         up(&sbi->ll_gns_sem);
 
-        if (!dchild)
-                GOTO(cleanup, rc = -ENOENT);
+        cleanup_phase = 2;
         
         if (IS_ERR(dchild)) {
                 rc = PTR_ERR(dchild);
@@ -170,7 +169,7 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
 
                 CERROR("can't find mount object %*s/%*s err = %d.\n",
                        (int)dentry->d_name.len, dentry->d_name.name,
-                       (int)dchild->d_name.len, dchild->d_name.name,
+                       strlen(sbi->ll_gns_oname), sbi->ll_gns_oname,
                        rc);
                 GOTO(cleanup, rc);
         }
@@ -190,18 +189,17 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
         if (IS_ERR(mntinfo_fd)) {
                 CERROR("can't open mount object %*s/%*s err = %d.\n",
                        (int)dentry->d_name.len, dentry->d_name.name,
-                       (int)dchild->d_name.len, dchild->d_name.name,
+                       strlen(sbi->ll_gns_oname), sbi->ll_gns_oname,
                        (int)PTR_ERR(mntinfo_fd));
-                dput(dchild);
                 mntput(mnt);
                 GOTO(cleanup, rc = PTR_ERR(mntinfo_fd));
         }
-        cleanup_phase = 2;
+        cleanup_phase = 3;
 
         if (mntinfo_fd->f_dentry->d_inode->i_size > PAGE_SIZE) {
                 CERROR("mount object %*s/%*s is too big (%Ld)\n",
                        (int)dentry->d_name.len, dentry->d_name.name,
-                       (int)dchild->d_name.len, dchild->d_name.name,
+                       strlen(sbi->ll_gns_oname), sbi->ll_gns_oname,
                        mntinfo_fd->f_dentry->d_inode->i_size);
                 GOTO(cleanup, rc = -EFBIG);
         }
@@ -210,14 +208,14 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
         if (!datapage)
                 GOTO(cleanup, rc = -ENOMEM);
 
-        cleanup_phase = 3;
+        cleanup_phase = 4;
         
         /* read data from mount object. */
         rc = kernel_read(mntinfo_fd, 0, datapage, PAGE_SIZE);
         if (rc < 0) {
                 CERROR("can't read mount object %*s/%*s data, err %d\n",
                        (int)dentry->d_name.len, dentry->d_name.name,
-                       (int)dchild->d_name.len, dchild->d_name.name,
+                       strlen(sbi->ll_gns_oname), sbi->ll_gns_oname,
                        rc);
                 GOTO(cleanup, rc);
         }
@@ -226,6 +224,7 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
 
         fput(mntinfo_fd);
         mntinfo_fd = NULL;
+        dchild = NULL;
 
         /* synchronizing with possible /proc/fs/...write */
         down(&sbi->ll_gns_sem);
@@ -255,7 +254,6 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
          * or usermode upcall program will start mounting in backgound and
          * return instantly. --umka
          */
-
         rc = ll_gns_wait_for_mount(dentry, 1, GNS_WAIT_ATTEMPTS);
         complete_all(&sbi->ll_gns_mount_finished);
         if (rc == 0) {
@@ -296,11 +294,14 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
         EXIT;
 cleanup:
         switch (cleanup_phase) {
-        case 3:
+        case 4:
                 free_page((unsigned long)datapage);
-        case 2:
+        case 3:
                 if (mntinfo_fd != NULL)
                         fput(mntinfo_fd);
+        case 2:
+                if (dchild != NULL)
+                        dput(dchild);
         case 1:
                 free_page((unsigned long)pathpage);
                 
index 7cbc483..1e55c57 100644 (file)
@@ -1182,12 +1182,14 @@ got_child:
                 if (ll_permission(dchild->d_inode, acc_mode, NULL))
                         GOTO(cleanup, rc = -EACCES);
 
+#if 0
                 /* skip GNS suid bit marked directories. */
                 if (dchild->d_inode->i_mode & S_ISUID) {
                         CDEBUG(D_INODE, "found GNS mount object %*s, not opening.\n", 
                                dchild->d_name.len, dchild->d_name.name);
                         GOTO(cleanup, rc = 0); // success, but don't really open
                 }
+#endif
         }
 
         /* if we are following a symlink, don't open */
index 5ae7e25..73c24e2 100644 (file)
@@ -279,8 +279,6 @@ show_log() {
        echo "======================== upcall log ==========================="
        cat $LOG
        echo "==============================================================="
-    } || {
-       echo "upcall log file $LOG is not found"
     }
 }
 
@@ -427,7 +425,6 @@ setup_gns() {
 
 test_1a() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local UPCALL="/tmp/gns-upcall.sh"
     local LOOP_FILE="/tmp/gns_loop_1a"
     local OBJECT=".mntinfo"
     local TIMOUT=5
@@ -462,10 +459,9 @@ test_1a() {
 
 run_test 1a " general GNS test - mount/umount (GENERIC) ================"
 
-test_2a() {
+test_1b() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local UPCALL="/tmp/gns-upcall.sh"
-    local LOOP_FILE="/tmp/gns_loop_2a"
+    local LOOP_FILE="/tmp/gns_loop_1b"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -480,29 +476,28 @@ test_2a() {
     echo "setting up GNS timeouts and mount object..."
     setup_gns $OBJECT $TIMOUT $TICK || error
 
-    echo "preparing mount object at $DIR/gns_test_2a/$OBJECT..."
-    setup_object $DIR/gns_test_2a $OBJECT "-t ext2 $LOOP_DEV" || error
+    echo "preparing mount object at $DIR/gns_test_1b/$OBJECT..."
+    setup_object $DIR/gns_test_1b $OBJECT "-t ext2 $LOOP_DEV" || error
 
     echo ""
     echo "testing GNS with DEADLOCK upcall 3 times on the row"
     for ((i=0;i<3;i++)); do
-       check_gns DEADLOCK $DIR/gns_test_2a $DIR/gns_test_2a $TIMOUT $TICK GENERIC || {
-           cleanup_object $DIR/gns_test_2a
+       check_gns DEADLOCK $DIR/gns_test_1b $DIR/gns_test_1b $TIMOUT $TICK GENERIC || {
+           cleanup_object $DIR/gns_test_1b
            cleanup_loop $LOOP_DEV $LOOP_FILE
            error
        }
     done
     
-    cleanup_object $DIR/gns_test_2a
+    cleanup_object $DIR/gns_test_1b
     cleanup_loop $LOOP_DEV $LOOP_FILE
 }
 
-run_test 2a " general GNS test - mount/umount (DEADLOCK) ==============="
+run_test 1b " general GNS test - mount/umount (DEADLOCK) ==============="
 
-test_3a() {
+test_1c() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local UPCALL="/tmp/gns-upcall.sh"
-    local LOOP_FILE="/tmp/gns_loop_3a"
+    local LOOP_FILE="/tmp/gns_loop_1c"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -517,8 +512,8 @@ test_3a() {
     echo "setting up GNS timeouts and mount object..."
     setup_gns $OBJECT $TIMOUT $TICK || error
 
-    echo "preparing mount object at $DIR/gns_test_3a/$OBJECT..."
-    setup_object $DIR/gns_test_3a $OBJECT "-t ext2 $LOOP_DEV" || error
+    echo "preparing mount object at $DIR/gns_test_1c/$OBJECT..."
+    setup_object $DIR/gns_test_1c $OBJECT "-t ext2 $LOOP_DEV" || error
 
     echo ""
     echo "testing GNS with DEADLOCK upcall 4 times on the row"
@@ -529,23 +524,22 @@ test_3a() {
        
        test $(($i%2)) -eq 1 && MODE="DEADLOCK"
        
-       check_gns $MODE $DIR/gns_test_3a $DIR/gns_test_3a $TIMOUT $TICK GENERIC || {
-           cleanup_object $DIR/gns_test_3a
+       check_gns $MODE $DIR/gns_test_1c $DIR/gns_test_1c $TIMOUT $TICK GENERIC || {
+           cleanup_object $DIR/gns_test_1c
            cleanup_loop $LOOP_DEV $LOOP_FILE
            error
        }
     done
     
-    cleanup_object $DIR/gns_test_3a
+    cleanup_object $DIR/gns_test_1c
     cleanup_loop $LOOP_DEV $LOOP_FILE
 }
 
-run_test 3a " general GNS test - mount/umount (GENERIC/DEADLOCK) ========"
+run_test 1c " general GNS test - mount/umount (GENERIC/DEADLOCK) ========"
 
-test_4a() {
+test_1d() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local UPCALL="/tmp/gns-upcall.sh"
-    local LOOP_FILE="/tmp/gns_loop_4a"
+    local LOOP_FILE="/tmp/gns_loop_1d"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -560,8 +554,8 @@ test_4a() {
     echo "setting up GNS timeouts and mount object..."
     setup_gns $OBJECT $TIMOUT $TICK || error
 
-    echo "preparing mount object at $DIR/gns_test_4a/$OBJECT..."
-    setup_object $DIR/gns_test_4a $OBJECT "-t ext2 $LOOP_DEV" || error
+    echo "preparing mount object at $DIR/gns_test_1d/$OBJECT..."
+    setup_object $DIR/gns_test_1d $OBJECT "-t ext2 $LOOP_DEV" || error
 
     echo ""
     echo "testing GNS with DEADLOCK upcall 4 times on the row"
@@ -572,23 +566,22 @@ test_4a() {
        
        test $(($i%2)) -eq 1 && MODE="DEADLOCK"
        
-       check_gns $MODE $DIR/gns_test_4a $DIR/gns_test_4a $TIMOUT $TICK CONCUR1 || {
-           cleanup_object $DIR/gns_test_4a
+       check_gns $MODE $DIR/gns_test_1d $DIR/gns_test_1d $TIMOUT $TICK CONCUR1 || {
+           cleanup_object $DIR/gns_test_1d
            cleanup_loop $LOOP_DEV $LOOP_FILE
            error
        }
     done
     
-    cleanup_object $DIR/gns_test_4a
+    cleanup_object $DIR/gns_test_1d
     cleanup_loop $LOOP_DEV $LOOP_FILE
 }
 
-run_test 4a " general GNS test - concurrent mount ======================="
+run_test 1d " general GNS test - concurrent mount ======================="
 
-test_5a() {
+test_1e() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local UPCALL="/tmp/gns-upcall.sh"
-    local LOOP_FILE="/tmp/gns_loop_5a"
+    local LOOP_FILE="/tmp/gns_loop_1e"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -603,27 +596,133 @@ test_5a() {
     echo "setting up GNS timeouts and mount object..."
     setup_gns $OBJECT $TIMOUT $TICK || error
 
-    echo "preparing mount object at $DIR/gns_test_5a1/$OBJECT..."
-    setup_object $DIR/gns_test_5a1 $OBJECT "-t ext2 $LOOP_DEV" || error
+    echo "preparing mount object at $DIR/gns_test_1e1/$OBJECT..."
+    setup_object $DIR/gns_test_1e1 $OBJECT "-t ext2 $LOOP_DEV" || error
     
-    echo "preparing mount object at $DIR/gns_test_5a2/$OBJECT..."
-    setup_object $DIR/gns_test_5a2 $OBJECT "-t ext2 $LOOP_DEV" || error
+    echo "preparing mount object at $DIR/gns_test_1e2/$OBJECT..."
+    setup_object $DIR/gns_test_1e2 $OBJECT "-t ext2 $LOOP_DEV" || error
 
     echo ""
     echo "testing GNS with GENERIC upcall"
-    check_gns GENERIC $DIR/gns_test_5a1 $DIR/gns_test_5a2 $TIMOUT $TICK CONCUR2 || {
-        cleanup_object $DIR/gns_test_5a1
-        cleanup_object $DIR/gns_test_5a2
+    check_gns GENERIC $DIR/gns_test_1e1 $DIR/gns_test_1e2 $TIMOUT $TICK CONCUR2 || {
+        cleanup_object $DIR/gns_test_1e1
+        cleanup_object $DIR/gns_test_1e2
         cleanup_loop $LOOP_DEV $LOOP_FILE
         error
     }
     
-    cleanup_object $DIR/gns_test_5a1
-    cleanup_object $DIR/gns_test_5a2
+    cleanup_object $DIR/gns_test_1e1
+    cleanup_object $DIR/gns_test_1e2
     cleanup_loop $LOOP_DEV $LOOP_FILE
 }
 
-run_test 5a " general GNS test - concurrent mount of 2 GNS mounts ======="
+run_test 1e " general GNS test - concurrent mount of 2 GNS mounts ======="
+
+test_2a() {
+    local OBJECT=".mntinfo"
+    local TIMOUT=5
+    local TICK=1
+
+    echo "setting up GNS timeouts and mount object..."
+    setup_gns $OBJECT $TIMOUT $TICK || error
+
+    echo "preparing mount object at $DIR/gns_test_2a/$OBJECT..."
+    mkdir -p $DIR/gns_test_2a
+    ln -s $DIR/gns_test_2a $DIR/gns_test_2a/$OBJECT
+    chmod u+s $DIR/gns_test_2a
+    
+    echo ""
+    echo "testing GNS with GENERIC upcall"
+    check_gns GENERIC $DIR/gns_test_2a $DIR/gns_test_2a $TIMOUT $TICK GENERIC && {
+       chmod u-s $DIR/gns_test_2a
+       rm -fr $DIR/gns_test_2a
+        error "symlink as mount object works?"
+    }
+    
+    chmod u-s $DIR/gns_test_2a
+    rm -fr $DIR/gns_test_2a
+}
+
+run_test 2a " check for evil conditions (object is symlink) ============="
+
+test_2b() {
+    local OBJECT=".mntinfo"
+    local TIMOUT=5
+    local TICK=1
+
+    echo "setting up GNS timeouts and mount object..."
+    setup_gns $OBJECT $TIMOUT $TICK || error
+
+    echo "preparing mount object at $DIR/gns_test_2b/$OBJECT..."
+    mkdir -p $DIR/gns_test_2b/$OBJECT
+    chmod u+s $DIR/gns_test_2b
+    
+    echo ""
+    echo "testing GNS with GENERIC upcall"
+    check_gns GENERIC $DIR/gns_test_2b $DIR/gns_test_2b $TIMOUT $TICK GENERIC && {
+       chmod u-s $DIR/gns_test_2b
+       rm -fr $DIR/gns_test_2b
+        error "dir as mount object works?"
+    }
+    
+    chmod u-s $DIR/gns_test_2b
+    rm -fr $DIR/gns_test_2b
+}
+
+run_test 2b " check for evil conditions (object is directory) ==========="
+
+test_2c() {
+    local OBJECT=".mntinfo"
+    local TIMOUT=5
+    local TICK=1
+
+    echo "setting up GNS timeouts and mount object..."
+    setup_gns $OBJECT $TIMOUT $TICK || error
+
+    echo "preparing mount object at $DIR/gns_test_2c/$OBJECT..."
+    mkdir -p $DIR/gns_test_2c/$OBJECT/$OBJECT/$OBJECT/$OBJECT
+    chmod u+s -R $DIR/gns_test_2c
+    
+    echo ""
+    echo "testing GNS with GENERIC upcall"
+    check_gns GENERIC $DIR/gns_test_2c $DIR/gns_test_2c $TIMOUT $TICK GENERIC && {
+       chmod u-s $DIR/gns_test_2c
+       rm -fr $DIR/gns_test_2c
+        error "recursive mounting of dir as mount object works?"
+    }
+    
+    chmod u-s $DIR/gns_test_2c
+    rm -fr $DIR/gns_test_2c
+}
+
+run_test 2c " check for evil conditions (object is recursive dirs) ======"
+
+test_3a() {
+    local OBJECT=".mntinfo"
+    local TIMOUT=5
+    local TICK=1
+
+    echo "setting up GNS timeouts and mount object..."
+    setup_gns $OBJECT $TIMOUT $TICK || error
+
+    echo "." > /proc/fs/lustre/llite/fs0/gns_object_name
+    test "x$(cat /proc/fs/lustre/llite/fs0/gns_object_name)" = "x." && 
+       error "'.' is set as mount object name"
+
+    echo ".." > /proc/fs/lustre/llite/fs0/gns_object_name
+    test "x$(cat /proc/fs/lustre/llite/fs0/gns_object_name)" = "x.." && 
+       error "'..' is set as mount object name"
+
+    echo ".a" > /proc/fs/lustre/llite/fs0/gns_object_name
+    test "x$(cat /proc/fs/lustre/llite/fs0/gns_object_name)" = "x.a" || 
+       error "'.a' is not set as mount object name"
+
+    echo "..a" > /proc/fs/lustre/llite/fs0/gns_object_name
+    test "x$(cat /proc/fs/lustre/llite/fs0/gns_object_name)" = "x..a" || 
+       error "'..a' is not set as mount object name"
+}
+
+run_test 3a " check for evil conditions ('.' and '..' as mount object) =="
 
 TMPDIR=$OLDTMPDIR
 TMP=$OLDTMP