Whamcloud - gitweb
- more fixes and improvements in GNS stuff:
authoryury <yury>
Mon, 18 Apr 2005 16:37:32 +0000 (16:37 +0000)
committeryury <yury>
Mon, 18 Apr 2005 16:37:32 +0000 (16:37 +0000)
  - small optimization in ll_gns_wait_for_mount(), changing return code semantics to
    usual 0 - ok, < 0 error.

  - handled possible nested mount with returning -ERETSARTSYS and causing endless loop
    of mounting.

  - check if found mount object is regular file to prevent from evil cases like it is
    suid bit marked directory, etc.

  - fix with completting all waiters for dentry mounting in progress.
  - added check for "." and ".." names in setting gns_object_name.
  - fixed default gns_object_name value.

lustre/llite/llite_gns.c
lustre/llite/llite_lib.c
lustre/llite/lproc_llite.c

index b65824b..f28c11e 100644 (file)
@@ -50,27 +50,23 @@ ll_gns_wait_for_mount(struct dentry *dentry,
 {
         struct l_wait_info lwi;
         struct ll_sb_info *sbi;
-        int rc;
         ENTRY;
 
         LASSERT(dentry != NULL);
         LASSERT(!IS_ERR(dentry));
         sbi = ll_s2sbi(dentry->d_sb);
         
-        for (; !d_mountpoint(dentry) && tries > 0; tries--) {
-                lwi = LWI_TIMEOUT(timeout * HZ, NULL, NULL);
+        lwi = LWI_TIMEOUT(timeout * HZ, NULL, NULL);
+        for (; !d_mountpoint(dentry) && tries > 0; tries--)
                 l_wait_event(sbi->ll_gns_waitq, d_mountpoint(dentry), &lwi);
-        }
 
-        if ((rc = d_mountpoint(dentry) ? 1 : 0)) {
+        if (d_mountpoint(dentry)) {
                 spin_lock(&sbi->ll_gns_lock);
-                LASSERT(sbi->ll_gns_state == LL_GNS_MOUNTING);
                 sbi->ll_gns_state = LL_GNS_FINISHED;
                 spin_unlock(&sbi->ll_gns_lock);
+                RETURN(0);
         }
-
-        complete_all(&sbi->ll_gns_mount_finished);
-        RETURN(rc);
+        RETURN(-ETIME);
 }
 
 /*
@@ -110,8 +106,7 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
          */
         spin_lock(&sbi->ll_gns_lock);
         if (sbi->ll_gns_state == LL_GNS_MOUNTING ||
-            sbi->ll_gns_state == LL_GNS_FINISHED)
-        {
+            sbi->ll_gns_state == LL_GNS_FINISHED) {
                 spin_unlock(&sbi->ll_gns_lock);
                 CDEBUG(D_INODE, "GNS is in progress now, throwing "
                        "-ERESTARTSYS to restart syscall and let "
@@ -149,6 +144,13 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
          * mount object name is taken from sbi, where it is set in mount time or
          * via /proc/fs... tunable. It may be ".mntinfo" or so.
          */
+
+        /* 
+         * FIXME: lookup_one_len() requires dentry->d_inode->i_sem to be locked,
+         * but we can't use ll_lookup_one_len() as this function is called from
+         * different contol paths and some of them take dentry->d_inode->i_sem
+         * and others do not.
+         */
         dchild = lookup_one_len(sbi->ll_gns_oname, dentry,
                                 strlen(sbi->ll_gns_oname));
         up(&sbi->ll_gns_sem);
@@ -157,17 +159,30 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
                 GOTO(cleanup, rc = -ENOENT);
         
         if (IS_ERR(dchild)) {
+                rc = PTR_ERR(dchild);
+                
+                if (rc == -ERESTARTSYS) {
+                        CDEBUG(D_INODE, "possible endless loop is detected "
+                               "due to mount object is directory marked by "
+                               "SUID bit.\n");
+                        GOTO(cleanup, rc = -ELOOP);
+                }
+
                 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,
-                       (int)PTR_ERR(dchild));
-                GOTO(cleanup, rc = PTR_ERR(dchild));
+                       rc);
+                GOTO(cleanup, rc);
         }
 
         /* mount object is not found */
         if (!dchild->d_inode)
                 GOTO(cleanup, rc = -ENOENT);
 
+        /* check if found child is regular file */
+        if (!S_ISREG(dchild->d_inode->i_mode))
+                GOTO(cleanup, rc = -EOPNOTSUPP);
+
         mntget(mnt);
 
         /* ok, mount object if found, opening it. */
@@ -240,7 +255,10 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
          * or usermode upcall program will start mounting in backgound and
          * return instantly. --umka
          */
-        if (ll_gns_wait_for_mount(dentry, 1, GNS_WAIT_ATTEMPTS)) {
+
+        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;
                 
@@ -271,11 +289,10 @@ ll_gns_mount_object(struct dentry *dentry, struct vfsmount *mnt)
                 dentry->d_flags &= ~DCACHE_GNS_PENDING;
                 spin_unlock(&dentry->d_lock);
         } else {
-                CERROR("usermode upcall %s failed to mount %s\n",
-                       sbi->ll_gns_upcall, path);
-                rc = -ETIME;
+                CERROR("usermode upcall %s failed to mount %s, err %d\n",
+                       sbi->ll_gns_upcall, path, rc);
         }
-
+                
         EXIT;
 cleanup:
         switch (cleanup_phase) {
@@ -286,14 +303,13 @@ cleanup:
                         fput(mntinfo_fd);
         case 1:
                 free_page((unsigned long)pathpage);
-        case 0:
+                
                 /* 
                  * waking up all waiters after gns state is set to
                  * LL_GNS_MOUNTING
                  */
-                if (cleanup_phase > 0)
-                        complete_all(&sbi->ll_gns_mount_finished);
-                
+                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);
index 500d95a..50e56f9 100644 (file)
@@ -74,7 +74,7 @@ struct ll_sb_info *lustre_init_sbi(struct super_block *sb)
 
         /* this later may be reset via /proc/fs/... */
         memcpy(sbi->ll_gns_oname, ".mntinfo", strlen(".mntinfo"));
-        sbi->ll_gns_oname[strlen(sbi->ll_gns_oname) - 1] = '\0';
+        sbi->ll_gns_oname[strlen(sbi->ll_gns_oname)] = '\0';
         
         /* this later may be reset via /proc/fs/... */
         memset(sbi->ll_gns_upcall, 0, sizeof(sbi->ll_gns_upcall));
index e796f4d..2871ab7 100644 (file)
@@ -312,6 +312,17 @@ static int ll_wr_gns_object_name(struct file *file, const char *buffer,
         struct super_block *sb = (struct super_block *)data;
         struct ll_sb_info *sbi = ll_s2sbi(sb);
 
+        /* checking for setting "." and ".." as object name */
+        if (buffer[0] == '.') switch (count) {
+                case 2:
+                        /* this is "." case with terminating zero */
+                        return -EINVAL;
+                case 3:
+                        /* this is ".." case with terminating zero */
+                        if (buffer[1] == '.')
+                                return -EINVAL;
+        }
+        
         down(&sbi->ll_gns_sem);
         snprintf(sbi->ll_gns_oname, count, "%s", buffer);
         up(&sbi->ll_gns_sem);