Whamcloud - gitweb
- using TASK_INTERRUPTIBLE in OBD_SLEEP_ON at Andreas' suggestion.
authoryury <yury>
Sun, 8 May 2005 16:57:53 +0000 (16:57 +0000)
committeryury <yury>
Sun, 8 May 2005 16:57:53 +0000 (16:57 +0000)
- using IT_CHDIR in sys_chdir() vfs-intent_api-vanilla-2.6.10-fc3.patch. This fixes GNS with cd into mnt point.

- different fixes in GNS stuff.
- gns_enabled flag is moved to separate space instead of using LL_GNS_DISABLED
- removed error messages after inode_setattr(). Only comment is added.
- many changes in sanity-gns.sh, added checks for "cd" case. Deadlock tests are disabled for a while.

lustre/include/linux/obd_support.h
lustre/kernel_patches/patches/vfs-intent_api-vanilla-2.6.10-fc3.patch
lustre/kernel_patches/patches/vfs_gns-2.6.10-fc3.patch
lustre/llite/dcache.c
lustre/llite/llite_gns.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/lproc_llite.c
lustre/llite/namei.c
lustre/tests/sanity-gns.sh

index f00483c..6653615 100644 (file)
@@ -220,7 +220,7 @@ do {                                                                         \
 #define OBD_SLEEP_ON(wq)                                                     \
 do {                                                                         \
         DEFINE_WAIT(__wait);                                                 \
-        prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);                 \
+        prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);                   \
         schedule();                                                          \
         finish_wait(&wq, &__wait);                                           \
 } while (0)
index dfcf347..6f58815 100644 (file)
@@ -38,7 +38,7 @@ Index: linux-2.6.10/fs/open.c
        int error;
  
 -      error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
-+      intent_init(&nd.intent.open, IT_GETATTR);
++      intent_init(&nd.intent.open, IT_CHDIR);
 +      error = __user_walk_it(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
        if (error)
                goto out;
index ab6a0ab..89d066a 100644 (file)
@@ -30,8 +30,8 @@ Index: linux-2.6.10/include/linux/dcache.h
  
 -#define DCACHE_CROSS_REF       0x0040  /* entry points to inode on another MDS */
 +#define DCACHE_CROSS_REF        0x0040  /* entry points to inode on another MDS */
-+#define DCACHE_GNS_PENDING      0x0080  /* entry is GNS pending mount point */
-+#define DCACHE_GNS_MOUNTING     0x0100  /* entry is GNS mount in progress */
++
++
 +
  
  extern spinlock_t dcache_lock;
index 0526985..c8570be 100644 (file)
@@ -312,7 +312,7 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
         struct it_cb_data icbd;
         struct lustre_id pid;
         struct lustre_id cid;
-        int orig_it, rc = 0;
+        int gns_it, rc = 0;
         ENTRY;
 
         CDEBUG(D_VFSTRACE, "VFS Op:name=%s (%p), intent=%s\n", de->d_name.name,
@@ -351,8 +351,10 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
                 nd->mnt->mnt_last_used = jiffies;
 
         OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5);
-        orig_it = it ? it->it_op : IT_OPEN;
+
+        gns_it = it ? it->it_op : IT_OPEN;
         ll_frob_intent(&it, &lookup_it);
+
         LASSERT(it != NULL);
 
         if (it->it_op == IT_GETATTR) { /* We need to check for LOOKUP lock as
@@ -388,7 +390,7 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
                 ll_intent_release(&lookup_it);
         }
 
-#if 1
+        /* open lock stuff */
         if ((it->it_op == IT_OPEN) && de->d_inode) {
                 struct inode *inode = de->d_inode;
                 struct ll_inode_info *lli = ll_i2info(inode);
@@ -444,7 +446,6 @@ int ll_revalidate_it(struct dentry *de, int flags, struct nameidata *nd,
                         ldlm_lock_decref(&lockh, lockmode);
                 }
         }
-#endif
 
 do_lock:
         rc = md_intent_lock(exp, &pid, de->d_name.name, de->d_name.len,
@@ -498,16 +499,6 @@ out:
                 return 0;
         }
 
-        CDEBUG(D_DENTRY, "revalidated dentry %*s (%p) parent %p "
-               "inode %p refc %d\n", de->d_name.len,
-               de->d_name.name, de, de->d_parent, de->d_inode,
-               atomic_read(&de->d_count));
-
-        ll_lookup_finish_locks(it, de);
-        de->d_flags &= ~DCACHE_LUSTRE_INVALID;
-        if (it == &lookup_it)
-                ll_intent_release(it);
-
         /* 
          * if we found that this is possible GNS mount and dentry is still valid
          * and may be used by system, we drop the lock and return 0, that means
@@ -515,19 +506,29 @@ out:
          * lookup control path, which is always made with parent's i_sem taken.
          * --umka
          */
-        if (((de->d_inode->i_mode & S_ISUID) && S_ISDIR(de->d_inode->i_mode)) ||
-            !(flags & LOOKUP_CONTINUE || (orig_it & (IT_CHDIR | IT_OPEN | IT_GETATTR)))) {
-                
-                /* special "." and ".." has to be always revalidated */
-                if (rc && !ll_special_name(de) && nd != NULL && !(nd->flags & LOOKUP_LAST)) {
+        if (rc &&
+            !(!((de->d_inode->i_mode & S_ISUID) && S_ISDIR(de->d_inode->i_mode)) ||
+              !(flags & LOOKUP_CONTINUE || (gns_it & (IT_CHDIR | IT_OPEN))))) {
+                /* 
+                 * special "." and ".." has to be always revalidated because
+                 * they never should be passed to lookup()
+                 */
+                if (!ll_special_name(de)) {
                         ll_intent_drop_lock(it);
-                        rc = 0;
+                        ll_intent_free(it);
+                        ll_unhash_aliases(de->d_inode);
+                        return 0;
                 }
-                
-                ll_intent_release(it);
-               return rc;
         }
-           
+
+        CDEBUG(D_DENTRY, "revalidated dentry %*s (%p) parent %p "
+               "inode %p refc %d\n", de->d_name.len,
+               de->d_name.name, de, de->d_parent, de->d_inode,
+               atomic_read(&de->d_count));
+
+        ll_lookup_finish_locks(it, de);
+        de->d_flags &= ~DCACHE_LUSTRE_INVALID;
+        ll_intent_release(it);
         return rc;
 do_lookup:
         it = &lookup_it;
index 0e37b51..ab076db 100644 (file)
@@ -40,6 +40,8 @@ static spinlock_t gns_lock = SPIN_LOCK_UNLOCKED;
 static struct ptlrpc_thread gns_thread;
 static struct ll_gns_ctl gns_ctl;
 
+#define CONCUR_GNS_RESTART_APPROACH 0
+
 /*
  * waits until passed dentry gets mountpoint or timeout and attempts are
  * exhausted. Returns 1 if dentry became mountpoint and 0 otherwise.
@@ -69,6 +71,7 @@ ll_gns_wait_for_mount(struct dentry *dentry,
         RETURN(-ETIME);
 }
 
+#if (CONCUR_GNS_RESTART_APPROACH == 1)
 /* 
  * sending a signal known to be ignored to cause restarting syscall if GNS mount
  * function returns -ERESTARTSYS.
@@ -86,6 +89,7 @@ ll_gns_send_signal(void)
         read_unlock(&tasklist_lock);
         set_tsk_thread_flag(task, TIF_SIGPENDING);
 }
+#endif
 
 /*
  * tries to mount the mount object under passed @dentry. In the case of success
@@ -108,14 +112,6 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
                 RETURN(-EINVAL);
 
         sbi = ll_i2sbi(dentry->d_inode);
-        LASSERT(sbi != NULL);
-
-        spin_lock(&sbi->ll_gns_lock);
-
-        if (sbi->ll_gns_state == LL_GNS_DISABLED) {
-                spin_unlock(&sbi->ll_gns_lock);
-                RETURN(-EINVAL);
-        }
         
         if (mnt == NULL) {
                 CERROR("suid directory found, but no "
@@ -123,6 +119,11 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
                 RETURN(-EINVAL);
         }
 
+        if (atomic_read(&sbi->ll_gns_enabled) == 0)
+                RETURN(-EINVAL);
+
+        spin_lock(&sbi->ll_gns_lock);
+
         /* 
          * another thead is in progress or just finished mounting the
          * dentry. Handling that.
@@ -142,14 +143,18 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
                 if (d_mountpoint(dentry))
                         RETURN(0);
 
+#if (CONCUR_GNS_RESTART_APPROACH == 1)
                 /* 
-                 * causing syscall to restart and find this dentry already
-                 * mounted.
+                 * causing syscall to restart and possibly find this dentry
+                 * already mounted.
                  */
                 ll_gns_send_signal();
                 RETURN(-ERESTARTSYS);
-
-#if 0
+#else
+                /* 
+                 * waiting for GNS complete and check dentry again, it may be
+                 * mounted already.
+                 */
                 wait_for_completion(&sbi->ll_gns_mount_finished);
                 if (d_mountpoint(dentry))
                         RETURN(0);
@@ -212,7 +217,7 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
 
         /* check if found child is regular file */
         if (!S_ISREG(dchild->d_inode->i_mode))
-                GOTO(cleanup, rc = -EOPNOTSUPP);
+                GOTO(cleanup, rc = -EBADF);
 
         mntget(mnt);
 
@@ -280,7 +285,7 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
         up(&sbi->ll_gns_sem);
 
         /* do not wait for helper complete here. */
-        rc = call_usermodehelper(argv[0], argv, NULL, 0);
+        rc = call_usermodehelper(argv[0], argv, NULL, 1);
         if (rc) {
                 CWARN("failed to call GNS upcall %s, err = %d, "
                       "checking for mount anyway\n", sbi->ll_gns_upcall, rc);
@@ -291,12 +296,10 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
          * second.
          */
         rc = ll_gns_wait_for_mount(dentry, 1, GNS_WAIT_ATTEMPTS);
-        complete_all(&sbi->ll_gns_mount_finished);
         if (rc == 0) {
                 struct dentry *rdentry;
                 struct vfsmount *rmnt;
-                
-                /* mount is successful */
+               
                 LASSERT(sbi->ll_gns_state == LL_GNS_FINISHED);
 
                 rmnt = mntget(mnt);
@@ -337,11 +340,11 @@ cleanup:
                         dput(dchild);
         case 1:
                 free_page((unsigned long)pathpage);
-                complete_all(&sbi->ll_gns_mount_finished);
         case 0:
                 spin_lock(&sbi->ll_gns_lock);
                 sbi->ll_gns_state = LL_GNS_IDLE;
                 spin_unlock(&sbi->ll_gns_lock);
+                complete_all(&sbi->ll_gns_mount_finished);
         }
         return rc;
 }
index 46e05a3..1058df5 100644 (file)
@@ -93,6 +93,7 @@ struct ll_sb_info {
         struct semaphore          ll_gns_sem;
         spinlock_t                ll_gns_lock;
         wait_queue_head_t         ll_gns_waitq;
+        atomic_t                  ll_gns_enabled;
         int                       ll_gns_state;
         struct timer_list         ll_gns_timer;
         struct list_head          ll_gns_sbi_head;
@@ -117,7 +118,6 @@ struct ll_gns_ctl {
 #define LL_GNS_IDLE               (1 << 0)
 #define LL_GNS_MOUNTING           (1 << 1)
 #define LL_GNS_FINISHED           (1 << 2)
-#define LL_GNS_DISABLED           (1 << 3)
 
 /* mounts checking flags */
 #define LL_GNS_UMOUNT             (1 << 0)
index ab5ce26..deb06cf 100644 (file)
@@ -83,6 +83,7 @@ struct ll_sb_info *lustre_init_sbi(struct super_block *sb)
 
         /* default values, may be changed via /proc/fs/... */
         sbi->ll_gns_state = LL_GNS_IDLE;
+        atomic_set(&sbi->ll_gns_enabled, 1);
         sbi->ll_gns_tick = GNS_TICK_TIMEOUT;
         sbi->ll_gns_timeout = GNS_MOUNT_TIMEOUT;
 
@@ -1108,14 +1109,13 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr)
                  * NB: ATTR_SIZE will only be set at this point if the size
                  * resides on the MDS, ie, this file has no objects. */
                 attr->ia_valid &= ~ATTR_SIZE;
+
+                /* 
+                 * assigning inode_setattr() to @err to disable warning that
+                 * function's result should be checked by by caller. error is
+                 * impossible here, as vmtruncate() control path is disabled.
+                 */
                 err = inode_setattr(inode, attr);
-                if (err) {
-                        CERROR("inode_setattr() failed, inode=%lu/%u(%p), "
-                               "err = %d\n", (unsigned long)inode->i_ino,
-                               inode->i_generation, inode, err);
-                        /* should we go to error path here? --umka */
-                }
-                 
                 ll_update_inode(inode, &md);
                 ptlrpc_req_finished(request);
 
@@ -1142,14 +1142,13 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr)
                         }
                 }
 
-                /* Won't invoke vmtruncate, as we already cleared ATTR_SIZE */
+                /* won't invoke vmtruncate, as we already cleared ATTR_SIZE */
                 err = inode_setattr(inode, attr);
-                if (err) {
-                        CERROR("inode_setattr() failed, inode=%lu/%u(%p), "
-                               "err = %d\n", (unsigned long)inode->i_ino,
-                               inode->i_generation, inode, err);
-                        /* should we go to error path here? --umka */
-                }
+                /* 
+                 * assigning inode_setattr() to @err to disable warning that
+                 * function's result should be checked by by caller. error is
+                 * impossible here, as vmtruncate() control path is disabled.
+                 */
         }
 
         /* We really need to get our PW lock before we change inode->i_size.
index 6b86eb3..6e630a6 100644 (file)
@@ -419,13 +419,9 @@ static int ll_rd_gns_enabled(char *page, char **start, off_t off,
 {
         struct super_block *sb = (struct super_block *)data;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
-        int enabled = 0;
-
-        spin_lock(&sbi->ll_gns_lock);
-        enabled = (sbi->ll_gns_state == LL_GNS_DISABLED ? 0 : 1);
-        spin_unlock(&sbi->ll_gns_lock);
-
-        return snprintf(page, count, "%d\n", enabled);
+        
+        return snprintf(page, count, "%d\n",
+                        atomic_read(&sbi->ll_gns_enabled));
 }
 
 static int ll_wr_gns_enabled(struct file *file, const char *buffer,
@@ -439,17 +435,7 @@ static int ll_wr_gns_enabled(struct file *file, const char *buffer,
         if (rc)
                 return rc;
 
-        spin_lock(&sbi->ll_gns_lock);
-        if (val == 0 && sbi->ll_gns_state == LL_GNS_IDLE) {
-                sbi->ll_gns_state = LL_GNS_DISABLED;
-                goto out;
-        }
-        if (val == 1 && sbi->ll_gns_state == LL_GNS_DISABLED) {
-                sbi->ll_gns_state = LL_GNS_IDLE;
-                goto out;
-        }
-out:
-        spin_unlock(&sbi->ll_gns_lock);
+        atomic_set(&sbi->ll_gns_enabled, (val != 0 ? 1 : 0));
         return count;
 }
 
index 06afbe4..1ef0e23 100644 (file)
@@ -362,7 +362,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
         struct it_cb_data icbd;
         struct ptlrpc_request *req = NULL;
         struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
-        int rc, orig_it;
+        int rc, gns_it;
         ENTRY;
 
         if (dentry->d_name.len > EXT3_NAME_LEN)
@@ -378,7 +378,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
         if (nd != NULL)
                 nd->mnt->mnt_last_used = jiffies;
 
-        orig_it = it ? it->it_op : IT_OPEN;
+        gns_it = nd ? nd->intent.open.it_op : IT_OPEN;
         ll_frob_intent(&it, &lookup_it);
 
         icbd.icbd_childp = &dentry;
@@ -399,10 +399,9 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
 
         ll_lookup_finish_locks(it, dentry);
 
-        if (nd &&
-            dentry->d_inode != NULL && dentry->d_inode->i_mode & S_ISUID &&
-            S_ISDIR(dentry->d_inode->i_mode) &&
-            ((flags & LOOKUP_CONTINUE) || (orig_it & (IT_CHDIR | IT_OPEN | IT_GETATTR))))
+        if (nd && dentry->d_inode != NULL &&
+            dentry->d_inode->i_mode & S_ISUID && S_ISDIR(dentry->d_inode->i_mode) &&
+            ((flags & LOOKUP_CONTINUE) || (gns_it & (IT_CHDIR | IT_OPEN))))
         {
                 rc = ll_gns_mount_object(dentry, nd->mnt);
                 if (rc == -ERESTARTSYS) {
@@ -415,9 +414,9 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
                          * just reporting about GNS failures, lookup() is
                          * successful, do not stop it.
                          *
-                         * GNS failure may be that found object is found in SUID
-                         * bit marked dir but it is not regular file and we
-                         * should lookup further until we find correct mount
+                         * GNS failure may be that object is found in SUID bit
+                         * marked dir but it is not regular file and we should
+                         * lookup further until we find correct mount
                          * object. This will allow to perform GNS mount is the
                          * following case for instance:
                          *
index 009f1f3..a8ff371 100644 (file)
@@ -189,7 +189,7 @@ rm -rf $DIR/[Rdfs][1-9]*
 build_test_filter
 
 echo preparing for tests involving mounts
-EXT2_DEV=${EXT2_DEV:-/tmp/SANITY.LOOP}
+EXT2_DEV=${EXT2_DEV:-$TMP/SANITY.LOOP}
 touch $EXT2_DEV
 mke2fs -j -F $EXT2_DEV 8000 >/dev/null 2>&1
 
@@ -245,11 +245,11 @@ setup_upcall() {
     local LOG=$3
     local BG=$4
     
-    test "x$BG" = "xBACKGROUND" && 
+    test "x$BG" = "xBG" && 
        BG="&" || BG=""
     
-    test "x$MODE" = "xDEADLOCK" &&
-       INJECTION="touch \$MNTPATH/file"
+#    test "x$MODE" = "xDEADLOCK" &&
+#      INJECTION="touch \$MNTPATH/file"
     
     cat > $UPCALL <<- EOF
 #!/bin/sh
@@ -303,7 +303,7 @@ check_mnt()
 }
 
 check_gns() {
-    local LOG="/tmp/gns-log"
+    local LOG="$TMP/gns-log"
     local UPCALL_PATH=""
     
     local UPCALL=$1
@@ -313,9 +313,10 @@ check_gns() {
     local TICK=$5
     local MODE=$6
     local BG=$7
+    local OP=$8
     
     rm -fr $LOG >/dev/null 2>&1
-    UPCALL_PATH="/tmp/gns-upcall-$UPCALL.sh"
+    UPCALL_PATH="$TMP/gns-upcall-$UPCALL.sh"
     
     echo "generating upcall $UPCALL_PATH"
     setup_upcall $UPCALL_PATH $UPCALL $LOG $BG || return $rc
@@ -327,20 +328,40 @@ check_gns() {
     echo "$UPCALL_PATH" > /proc/fs/lustre/llite/fs0/gns_upcall || return $?
     echo "upcall:  $(cat /proc/fs/lustre/llite/fs0/gns_upcall)"
 
-#    local OLD_PWD=$(pwd)
+    echo -n "mount on $OP: "
+
+    local OLD_PWD=$(pwd)
+    
     case "$MODE" in
        GENERIC)
-           echo -n "mount on open $OBJECT1/test_file1 (generic): "
-           echo -n "test data" > $OBJECT1/test_file1 >/dev/null 2>&1 || return $?
-#          cd $OBJECT1 || return $?
+           case "$OP" in
+               OPEN)
+                   echo -n "test data" > $OBJECT1/test_file1 >/dev/null 2>&1
+                   ;;
+               CHDIR)
+                   cd $OBJECT1 || return $?
+                   ;;
+               *)
+                   echo "invalid testing operation $OP"
+                   return 1
+           esac
            ;;
        CONCUR1)
            local i=1
            local nr=20
        
-           echo -n "mount on open $OBJECT1/test_file1 ($nr threads): "
            for ((;i<=$nr;i++)); do 
-               echo -n "test data" > $OBJECT1/test_file$i >/dev/null 2>&1 &
+               case "$OP" in
+                   OPEN)
+                       echo -n "test data" > $OBJECT1/test_file$i >/dev/null 2>&1 &
+                       ;;
+                   CHDIR)
+                       cd $OBJECT1 >/dev/null 2>&1 &
+                       ;;
+                   *)
+                       echo "invalid testing operation $OP"
+                       return 1
+               esac
            done
        
            wait
@@ -355,10 +376,19 @@ check_gns() {
                echo "not defined object2 for concurrent2 testing"
                return 1
            }
-           echo -n "mount on open $OBJECT1/test_file1: "
-           echo -n "mount on open $OBJECT2/test_file1: "
-           echo -n "test data" > $OBJECT1/test_file1 >/dev/null 2>&1 &
-           echo -n "test data" > $OBJECT2/test_file1 >/dev/null 2>&1 &
+           case "$OP" in
+               OPEN)
+                   echo -n "test data" > $OBJECT1/test_file1 >/dev/null 2>&1 &
+                   echo -n "test data" > $OBJECT2/test_file1 >/dev/null 2>&1 &
+                   ;;
+               CHDIR)
+                   cd $OBJECT1 >/dev/null 2>&1 &
+                   cd $OBJECT2 >/dev/null 2>&1 &
+                   ;;
+               *)
+                   echo "invalid testing operation $OP"
+                   return 1
+           esac
            
            wait
            
@@ -368,15 +398,25 @@ check_gns() {
                return $RETVAL
            ;;
        CONCUR3)
-           echo -n "mount on open $OBJECT1/test_file1: "
-           
            local i=1
            local nr=20
            
            for ((;i<$nr;i++)); do
-               touch $OBJECT1/file$i &
-               echo -n "test data" > $OBJECT1/test_file$i >/dev/null 2>&1 &
-               mkdir $OBJECT1/dir$i &
+               case "$OP" in
+                   OPEN)
+                       touch $OBJECT1/file$i &
+                       echo -n "test data" > $OBJECT1/test_file$i >/dev/null 2>&1 &
+                       mkdir $OBJECT1/dir$i &
+                       ;;
+                   CHDIR)
+                       touch $OBJECT1/file$i &
+                       cd $OBJECT1 >/dev/null 2>&1 &
+                       mkdir $OBJECT1/dir$i &
+                       ;;
+                   *)
+                       echo "invalid testing operation $OP"
+                       return 1
+               esac
            done
 
            wait
@@ -391,7 +431,7 @@ check_gns() {
            return 1
     esac
 
-#    cd $OLD_PWD
+    test "x$OP" = "xCHDIR" && cd $OLD_PWD
     
     check_mnt $OBJECT1 || {
        echo "fail"
@@ -487,7 +527,7 @@ disable_gns()
 
 test_1a() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local LOOP_FILE="/tmp/gns_loop_1a"
+    local LOOP_FILE="$TMP/gns_loop_1a"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -512,8 +552,23 @@ test_1a() {
     echo ""
     echo "testing GNS with GENERIC upcall 3 times on the row"
     
+    echo ""
+    echo "testing OPEN operation"
+    
     for ((i=0;i<3;i++)); do
-       check_gns GENERIC $DIR/gns_test_1a $DIR/gns_test_1a $TIMOUT $TICK GENERIC || {
+       check_gns GENERIC $DIR/gns_test_1a $DIR/gns_test_1a $TIMOUT $TICK GENERIC FG OPEN || {
+           disable_gns
+           cleanup_object $DIR/gns_test_1a
+           cleanup_loop $LOOP_DEV $LOOP_FILE
+           error
+       }
+    done
+    
+    echo ""
+    echo "testing CHDIR operation"
+    
+    for ((i=0;i<3;i++)); do
+       check_gns GENERIC $DIR/gns_test_1a $DIR/gns_test_1a $TIMOUT $TICK GENERIC FG CHDIR || {
            disable_gns
            cleanup_object $DIR/gns_test_1a
            cleanup_loop $LOOP_DEV $LOOP_FILE
@@ -525,13 +580,14 @@ test_1a() {
 
     cleanup_object $DIR/gns_test_1a
     cleanup_loop $LOOP_DEV $LOOP_FILE
+    return 0
 }
 
 run_test 1a " general GNS test - mount/umount (GENERIC) ================"
 
 test_1b() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local LOOP_FILE="/tmp/gns_loop_1b"
+    local LOOP_FILE="$TMP/gns_loop_1b"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -557,25 +613,21 @@ test_1b() {
     echo "testing GNS with DEADLOCK upcall 3 times on the row"
     
     for ((i=0;i<3;i++)); do
-       check_gns DEADLOCK $DIR/gns_test_1b $DIR/gns_test_1b $TIMOUT $TICK GENERIC || {
-           disable_gns
-           cleanup_object $DIR/gns_test_1b
-           cleanup_loop $LOOP_DEV $LOOP_FILE
-           error
-       }
+       check_gns DEADLOCK $DIR/gns_test_1b $DIR/gns_test_1b $TIMOUT $TICK GENERIC FG OPEN
     done
     
     disable_gns
 
     cleanup_object $DIR/gns_test_1b
     cleanup_loop $LOOP_DEV $LOOP_FILE
+    return 0
 }
 
 run_test 1b " general GNS test - mount/umount (DEADLOCK) ==============="
 
 test_1c() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local LOOP_FILE="/tmp/gns_loop_1c"
+    local LOOP_FILE="$TMP/gns_loop_1c"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -602,29 +654,31 @@ test_1c() {
     local i=0
     
     for ((;i<4;i++)); do
-       local MODE="GENERIC"
-       
-       test $(($i%2)) -eq 1 && MODE="DEADLOCK"
-       
-       check_gns $MODE $DIR/gns_test_1c $DIR/gns_test_1c $TIMOUT $TICK GENERIC || {
-           disable_gns
-           cleanup_object $DIR/gns_test_1c
-           cleanup_loop $LOOP_DEV $LOOP_FILE
-           error
+       test $(($i%2)) -eq 1 && {
+           check_gns DEADLOCK $DIR/gns_test_1c $DIR/gns_test_1c $TIMOUT $TICK GENERIC FG OPEN
+       } || {
+           check_gns GENERIC $DIR/gns_test_1c $DIR/gns_test_1c $TIMOUT $TICK GENERIC FG OPEN || {
+               disable_gns
+               cleanup_object $DIR/gns_test_1c
+               cleanup_loop $LOOP_DEV $LOOP_FILE
+               error "generic upcall does not work!"
+           }
        }
+       
     done
     
     disable_gns
 
     cleanup_object $DIR/gns_test_1c
     cleanup_loop $LOOP_DEV $LOOP_FILE
+    return 0
 }
 
 run_test 1c " general GNS test - mount/umount (GENERIC/DEADLOCK) ========"
 
 test_1d() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local LOOP_FILE="/tmp/gns_loop_1d"
+    local LOOP_FILE="$TMP/gns_loop_1d"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -647,15 +701,11 @@ test_1d() {
     enable_gns
 
     echo ""
-    echo "testing GNS with GENERIC/DEADLOCK upcall 4 times on the row in CONCUR1 mode"
+    echo "testing GNS with GENERIC upcall 4 times on the row in CONCUR1 mode"
     local i=0
     
     for ((;i<4;i++)); do
-       local MODE="GENERIC"
-       
-       test $(($i%2)) -eq 1 && MODE="DEADLOCK"
-       
-       check_gns $MODE $DIR/gns_test_1d $DIR/gns_test_1d $TIMOUT $TICK CONCUR1 || {
+       check_gns GENERIC $DIR/gns_test_1d $DIR/gns_test_1d $TIMOUT $TICK CONCUR1 FG OPEN || {
            disable_gns
            cleanup_object $DIR/gns_test_1d
            cleanup_loop $LOOP_DEV $LOOP_FILE
@@ -667,13 +717,14 @@ test_1d() {
 
     cleanup_object $DIR/gns_test_1d
     cleanup_loop $LOOP_DEV $LOOP_FILE
+    return 0
 }
 
 run_test 1d " general GNS test - concurrent mount ======================="
 
 test_1e() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local LOOP_FILE="/tmp/gns_loop_1e"
+    local LOOP_FILE="$TMP/gns_loop_1e"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -701,7 +752,7 @@ test_1e() {
     echo ""
     echo "testing GNS with GENERIC upcall in CONCUR2 mode"
     
-    check_gns GENERIC $DIR/gns_test_1e1 $DIR/gns_test_1e2 $TIMOUT $TICK CONCUR2 || {
+    check_gns GENERIC $DIR/gns_test_1e1 $DIR/gns_test_1e2 $TIMOUT $TICK CONCUR2 FG OPEN || {
        disable_gns
         cleanup_object $DIR/gns_test_1e1
         cleanup_object $DIR/gns_test_1e2
@@ -714,6 +765,7 @@ test_1e() {
     cleanup_object $DIR/gns_test_1e1
     cleanup_object $DIR/gns_test_1e2
     cleanup_loop $LOOP_DEV $LOOP_FILE
+    return 0
 }
 
 run_test 1e " general GNS test - concurrent mount of 2 GNS mounts ======="
@@ -738,7 +790,7 @@ test_2a() {
     echo ""
     echo "testing GNS with GENERIC upcall"
     
-    check_gns GENERIC $DIR/gns_test_2a $DIR/gns_test_2a $TIMOUT $TICK GENERIC && {
+    check_gns GENERIC $DIR/gns_test_2a $DIR/gns_test_2a $TIMOUT $TICK GENERIC FG OPEN && {
        disable_gns
        chmod u-s $DIR/gns_test_2a
        rm -fr $DIR/gns_test_2a
@@ -748,6 +800,7 @@ test_2a() {
     disable_gns
     chmod u-s $DIR/gns_test_2a
     rm -fr $DIR/gns_test_2a
+    return 0
 }
 
 run_test 2a " odd conditions (mount object is symlink) ============="
@@ -771,7 +824,7 @@ test_2b() {
     echo ""
     echo "testing GNS with GENERIC upcall"
     
-    check_gns GENERIC $DIR/gns_test_2b $DIR/gns_test_2b $TIMOUT $TICK GENERIC && {
+    check_gns GENERIC $DIR/gns_test_2b $DIR/gns_test_2b $TIMOUT $TICK GENERIC FG OPEN && {
        disable_gns
        chmod u-s $DIR/gns_test_2b
        rm -fr $DIR/gns_test_2b
@@ -781,6 +834,7 @@ test_2b() {
     disable_gns
     chmod u-s $DIR/gns_test_2b
     rm -fr $DIR/gns_test_2b
+    return 0
 }
 
 run_test 2b " odd conditions (mount object is directory) ==========="
@@ -804,7 +858,7 @@ test_2c() {
     echo ""
     echo "testing GNS with GENERIC upcall"
     
-    check_gns GENERIC $DIR/gns_test_2c $DIR/gns_test_2c $TIMOUT $TICK GENERIC && {
+    check_gns GENERIC $DIR/gns_test_2c $DIR/gns_test_2c $TIMOUT $TICK GENERIC FG OPEN && {
        disable_gns
        chmod u-s -R $DIR/gns_test_2c
        rm -fr $DIR/gns_test_2c
@@ -814,6 +868,7 @@ test_2c() {
     disable_gns
     chmod u-s $DIR/gns_test_2c
     rm -fr $DIR/gns_test_2c
+    return 0
 }
 
 run_test 2c " odd conditions (mount object is recursive dir) ======="
@@ -837,7 +892,7 @@ test_2d() {
     echo ""
     echo "testing GNS with GENERIC upcall"
     
-    check_gns GENERIC $DIR/gns_test_2d $DIR/gns_test_2d $TIMOUT $TICK GENERIC && {
+    check_gns GENERIC $DIR/gns_test_2d $DIR/gns_test_2d $TIMOUT $TICK GENERIC FG OPEN && {
        disable_gns
        chmod u-s $DIR/gns_test_2d
        rm -fr $DIR/gns_test_2d
@@ -847,6 +902,7 @@ test_2d() {
     disable_gns
     chmod u-s $DIR/gns_test_2d
     rm -fr $DIR/gns_test_2d
+    return 0
 }
 
 run_test 2d " odd conditions (mount object is absent) =============="
@@ -874,13 +930,14 @@ test_2e() {
     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"
+    return 0
 }
 
 run_test 2e " odd conditions ('.' and '..' as mount object) ============="
 
 test_2f() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local LOOP_FILE="/tmp/gns_loop_2f"
+    local LOOP_FILE="$TMP/gns_loop_2f"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -903,28 +960,27 @@ test_2f() {
     enable_gns
 
     echo ""
-    echo "testing GNS with DEADLOCK upcall in CONCUR3 mode"
+    echo "testing GNS with GENERIC upcall in CONCUR3 mode"
     
-    local MODE="DEADLOCK"
-       
-    check_gns $MODE $DIR/gns_test_2f $DIR/gns_test_2f $TIMOUT $TICK CONCUR3 || {
+    check_gns GENERIC $DIR/gns_test_2f $DIR/gns_test_2f $TIMOUT $TICK CONCUR3 FG OPEN || {
         disable_gns
         cleanup_object $DIR/gns_test_2f
         cleanup_loop $LOOP_DEV $LOOP_FILE
-        error
+        error "mount during modifying mount point does not work"
     }
     
     disable_gns
 
     cleanup_object $DIR/gns_test_2f
     cleanup_loop $LOOP_DEV $LOOP_FILE
+    return 0
 }
 
 run_test 2f " odd conditions (mount point is modifying during mount) ===="
 
 test_2g() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local LOOP_FILE="/tmp/gns_loop_2g"
+    local LOOP_FILE="$TMP/gns_loop_2g"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -949,12 +1005,10 @@ $OBJECT "-t ext2 $LOOP_DEV" || error
     enable_gns
 
     echo ""
-    echo "testing GNS with DEADLOCK upcall in GENERIC mode"
+    echo "testing GNS with GENERIC upcall in GENERIC mode"
     
-    local MODE="DEADLOCK"
-       
-    check_gns $MODE $DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT \
-$DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT $TIMOUT $TICK GENERIC || {
+    check_gns GENERIC $DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT \
+$DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT $TIMOUT $TICK GENERIC FG OPEN || {
         disable_gns
         cleanup_object $DIR/gns_test_2g
         cleanup_loop $LOOP_DEV $LOOP_FILE
@@ -969,8 +1023,8 @@ $DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT $TIMOUT $TICK GENERIC || {
 
     enable_gns
 
-    check_gns $MODE $DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT \
-$DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT $TIMOUT $TICK GENERIC && {
+    check_gns GENERIC $DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT \
+$DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT $TIMOUT $TICK GENERIC FG OPEN && {
         disable_gns
         cleanup_object $DIR/gns_test_2g
         cleanup_loop $LOOP_DEV $LOOP_FILE
@@ -981,13 +1035,14 @@ $DIR/gns_test_2g/$OBJECT/$OBJECT/$OBJECT $TIMOUT $TICK GENERIC && {
 
     cleanup_object $DIR/gns_test_2g
     cleanup_loop $LOOP_DEV $LOOP_FILE
+    return 0
 }
 
 run_test 2g " odd conditions (mount point is recursive marked SUID dir) ="
 
 test_2h() {
     local LOOP_DEV=$(find_free_loop 2>/dev/null)
-    local LOOP_FILE="/tmp/gns_loop_2h"
+    local LOOP_FILE="$TMP/gns_loop_2h"
     local OBJECT=".mntinfo"
     local TIMOUT=5
     local TICK=1
@@ -1013,7 +1068,7 @@ test_2h() {
     echo "testing GNS with GENERIC upcall in GENERIC mode"
     
     check_gns GENERIC $DIR/gns_test_2h $DIR/gns_test_2h \
-$TIMOUT $TICK GENERIC BACKGROUND || {
+$TIMOUT $TICK GENERIC BG OPEN || {
         disable_gns
         cleanup_object $DIR/gns_test_2h
         cleanup_loop $LOOP_DEV $LOOP_FILE
@@ -1024,6 +1079,7 @@ $TIMOUT $TICK GENERIC BACKGROUND || {
 
     cleanup_object $DIR/gns_test_2h
     cleanup_loop $LOOP_DEV $LOOP_FILE
+    return 0
 }
 
 run_test 2h " odd conditions (mounting in background) ==================="