[PATCH] more fs/super.c fixes (2)

From: Alexander Viro (viro@math.psu.edu)
Date: Tue Jun 05 2001 - 15:45:09 EST


Chunk 2:
        Since all branches of do_mount() (mounting, binding, remounting)
do the same thing (lookup of directory) we can take that lookup in the
beginning of do_mount() and pass to do_loopback() and do_remount()
nameidata instead of name.

Please, apply
                                                        Al

diff -urN S6-pre1-do_remount/fs/super.c S6-pre1-do_mount/fs/super.c
--- S6-pre1-do_remount/fs/super.c Tue Jun 5 08:14:29 2001
+++ S6-pre1-do_mount/fs/super.c Tue Jun 5 08:15:33 2001
@@ -1151,9 +1151,9 @@
 /*
  * do loopback mount.
  */
-static int do_loopback(char *old_name, char *new_name)
+static int do_loopback(struct nameidata *nd, char *old_name)
 {
- struct nameidata old_nd, new_nd;
+ struct nameidata old_nd;
         int err = 0;
         if (!old_name || !*old_name)
                 return -EINVAL;
@@ -1161,31 +1161,25 @@
                 err = path_walk(old_name, &old_nd);
         if (err)
                 goto out;
- if (path_init(new_name, LOOKUP_POSITIVE, &new_nd))
- err = path_walk(new_name, &new_nd);
+ err = mount_is_safe(nd);
         if (err)
                 goto out1;
- err = mount_is_safe(&new_nd);
- if (err)
- goto out2;
         err = -EINVAL;
- if (S_ISDIR(new_nd.dentry->d_inode->i_mode) !=
+ if (S_ISDIR(nd->dentry->d_inode->i_mode) !=
               S_ISDIR(old_nd.dentry->d_inode->i_mode))
- goto out2;
+ goto out1;
 
         err = -ENOMEM;
                 
         down(&mount_sem);
         /* there we go */
- down(&new_nd.dentry->d_inode->i_zombie);
- if (IS_DEADDIR(new_nd.dentry->d_inode))
+ down(&nd->dentry->d_inode->i_zombie);
+ if (IS_DEADDIR(nd->dentry->d_inode))
                 err = -ENOENT;
- else if (add_vfsmnt(&new_nd, old_nd.dentry, old_nd.mnt->mnt_devname))
+ else if (add_vfsmnt(nd, old_nd.dentry, old_nd.mnt->mnt_devname))
                 err = 0;
- up(&new_nd.dentry->d_inode->i_zombie);
+ up(&nd->dentry->d_inode->i_zombie);
         up(&mount_sem);
-out2:
- path_release(&new_nd);
 out1:
         path_release(&old_nd);
 out:
@@ -1198,25 +1192,15 @@
  * on it - tough luck.
  */
 
-static int do_remount(const char *dir,int flags,char *data)
+static int do_remount(struct nameidata *nd, int flags, char *data)
 {
- struct nameidata nd;
- int retval = 0;
-
         if (!capable(CAP_SYS_ADMIN))
                 return -EPERM;
 
- if (path_init(dir, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))
- retval = path_walk(dir, &nd);
- if (retval)
- return retval;
-
- retval = -EINVAL;
- if (nd.dentry == nd.mnt->mnt_root)
- retval = do_remount_sb(nd.mnt->mnt_sb, flags, data);
+ if (nd->dentry != nd->mnt->mnt_root)
+ return -EINVAL;
 
- path_release(&nd);
- return retval;
+ return do_remount_sb(nd->mnt->mnt_sb, flags, data);
 }
 
 static int copy_mount_options (const void *data, unsigned long *where)
@@ -1286,38 +1270,41 @@
         if (dev_name && !memchr(dev_name, 0, PAGE_SIZE))
                 return -EINVAL;
 
- /* OK, looks good, now let's see what do they want */
+ /* ... and get the mountpoint */
+ if (path_init(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))
+ retval = path_walk(dir_name, &nd);
+ if (retval)
+ return retval;
 
         /* just change the flags? - capabilities are checked in do_remount() */
- if (flags & MS_REMOUNT)
- return do_remount(dir_name, flags & ~MS_REMOUNT,
- (char *) data_page);
+ if (flags & MS_REMOUNT) {
+ retval = do_remount(&nd, flags&~MS_REMOUNT, (char *)data_page);
+ goto nd_out;
+ }
 
         /* "mount --bind"? Equivalent to older "mount -t bind" */
         /* No capabilities? What if users do thousands of these? */
- if (flags & MS_BIND)
- return do_loopback(dev_name, dir_name);
+ if (flags & MS_BIND) {
+ retval = do_loopback(&nd, dev_name);
+ goto nd_out;
+ }
 
         /* For the rest we need the type */
 
+ retval = -EINVAL;
         if (!type_page || !memchr(type_page, 0, PAGE_SIZE))
- return -EINVAL;
+ goto nd_out;
 
+ retval = -EPERM;
         /* for the rest we _really_ need capabilities... */
         if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ goto nd_out;
 
+ retval = -ENODEV;
         /* ... filesystem driver... */
         fstype = get_fs_type(type_page);
         if (!fstype)
- return -ENODEV;
-
- /* ... and mountpoint. Do the lookup first to force automounting. */
- if (path_init(dir_name,
- LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &nd))
- retval = path_walk(dir_name, &nd);
- if (retval)
- goto fs_out;
+ goto nd_out;
 
         /* get superblock, locks mount_sem on success */
         if (fstype->fs_flags & FS_NOMOUNT)
@@ -1331,7 +1318,7 @@
 
         retval = PTR_ERR(sb);
         if (IS_ERR(sb))
- goto dput_out;
+ goto fs_out;
 
         /* Something was mounted here while we slept */
         while(d_mountpoint(nd.dentry) && follow_down(&nd.mnt, &nd.dentry))
@@ -1346,6 +1333,9 @@
         retval = -ENOENT;
         if (!nd.dentry->d_inode)
                 goto fail;
+ retval = -ENOTDIR;
+ if (!S_ISDIR(nd.dentry->d_inode->i_mode))
+ goto fail;
         down(&nd.dentry->d_inode->i_zombie);
         if (!IS_DEADDIR(nd.dentry->d_inode)) {
                 retval = -ENOMEM;
@@ -1357,10 +1347,10 @@
         retval = 0;
 unlock_out:
         up(&mount_sem);
-dput_out:
- path_release(&nd);
 fs_out:
         put_filesystem(fstype);
+nd_out:
+ path_release(&nd);
         return retval;
 
 fail:

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Jun 07 2001 - 21:00:41 EST