Merge branch 'hch.init_path' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[sfrench/cifs-2.6.git] / fs / namespace.c
index 4a0f600a3328595d6630491e3077ee4209521adc..016553d0f9256f68ebe61edd4b540501db93d953 100644 (file)
@@ -1706,36 +1706,19 @@ static inline bool may_mandlock(void)
 }
 #endif
 
-/*
- * Now umount can handle mount points as well as block devices.
- * This is important for filesystems which use unnamed block devices.
- *
- * We now support a flag for forced unmount like the other 'big iron'
- * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
- */
-
-int ksys_umount(char __user *name, int flags)
+int path_umount(struct path *path, int flags)
 {
-       struct path path;
        struct mount *mnt;
        int retval;
-       int lookup_flags = LOOKUP_MOUNTPOINT;
 
        if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
                return -EINVAL;
-
        if (!may_mount())
                return -EPERM;
 
-       if (!(flags & UMOUNT_NOFOLLOW))
-               lookup_flags |= LOOKUP_FOLLOW;
-
-       retval = user_path_at(AT_FDCWD, name, lookup_flags, &path);
-       if (retval)
-               goto out;
-       mnt = real_mount(path.mnt);
+       mnt = real_mount(path->mnt);
        retval = -EINVAL;
-       if (path.dentry != path.mnt->mnt_root)
+       if (path->dentry != path->mnt->mnt_root)
                goto dput_and_out;
        if (!check_mnt(mnt))
                goto dput_and_out;
@@ -1748,12 +1731,25 @@ int ksys_umount(char __user *name, int flags)
        retval = do_umount(mnt, flags);
 dput_and_out:
        /* we mustn't call path_put() as that would clear mnt_expiry_mark */
-       dput(path.dentry);
+       dput(path->dentry);
        mntput_no_expire(mnt);
-out:
        return retval;
 }
 
+static int ksys_umount(char __user *name, int flags)
+{
+       int lookup_flags = LOOKUP_MOUNTPOINT;
+       struct path path;
+       int ret;
+
+       if (!(flags & UMOUNT_NOFOLLOW))
+               lookup_flags |= LOOKUP_FOLLOW;
+       ret = user_path_at(AT_FDCWD, name, lookup_flags, &path);
+       if (ret)
+               return ret;
+       return path_umount(&path, flags);
+}
+
 SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
 {
        return ksys_umount(name, flags);
@@ -3116,12 +3112,11 @@ char *copy_mount_string(const void __user *data)
  * Therefore, if this magic number is present, it carries no information
  * and must be discarded.
  */
-long do_mount(const char *dev_name, const char __user *dir_name,
+int path_mount(const char *dev_name, struct path *path,
                const char *type_page, unsigned long flags, void *data_page)
 {
-       struct path path;
        unsigned int mnt_flags = 0, sb_flags;
-       int retval = 0;
+       int ret;
 
        /* Discard magic */
        if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
@@ -3134,19 +3129,13 @@ long do_mount(const char *dev_name, const char __user *dir_name,
        if (flags & MS_NOUSER)
                return -EINVAL;
 
-       /* ... and get the mountpoint */
-       retval = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
-       if (retval)
-               return retval;
-
-       retval = security_sb_mount(dev_name, &path,
-                                  type_page, flags, data_page);
-       if (!retval && !may_mount())
-               retval = -EPERM;
-       if (!retval && (flags & SB_MANDLOCK) && !may_mandlock())
-               retval = -EPERM;
-       if (retval)
-               goto dput_out;
+       ret = security_sb_mount(dev_name, path, type_page, flags, data_page);
+       if (ret)
+               return ret;
+       if (!may_mount())
+               return -EPERM;
+       if ((flags & SB_MANDLOCK) && !may_mandlock())
+               return -EPERM;
 
        /* Default to relatime unless overriden */
        if (!(flags & MS_NOATIME))
@@ -3173,7 +3162,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
            ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
                       MS_STRICTATIME)) == 0)) {
                mnt_flags &= ~MNT_ATIME_MASK;
-               mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK;
+               mnt_flags |= path->mnt->mnt_flags & MNT_ATIME_MASK;
        }
 
        sb_flags = flags & (SB_RDONLY |
@@ -3186,22 +3175,32 @@ long do_mount(const char *dev_name, const char __user *dir_name,
                            SB_I_VERSION);
 
        if ((flags & (MS_REMOUNT | MS_BIND)) == (MS_REMOUNT | MS_BIND))
-               retval = do_reconfigure_mnt(&path, mnt_flags);
-       else if (flags & MS_REMOUNT)
-               retval = do_remount(&path, flags, sb_flags, mnt_flags,
-                                   data_page);
-       else if (flags & MS_BIND)
-               retval = do_loopback(&path, dev_name, flags & MS_REC);
-       else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
-               retval = do_change_type(&path, flags);
-       else if (flags & MS_MOVE)
-               retval = do_move_mount_old(&path, dev_name);
-       else
-               retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
-                                     dev_name, data_page);
-dput_out:
+               return do_reconfigure_mnt(path, mnt_flags);
+       if (flags & MS_REMOUNT)
+               return do_remount(path, flags, sb_flags, mnt_flags, data_page);
+       if (flags & MS_BIND)
+               return do_loopback(path, dev_name, flags & MS_REC);
+       if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
+               return do_change_type(path, flags);
+       if (flags & MS_MOVE)
+               return do_move_mount_old(path, dev_name);
+
+       return do_new_mount(path, type_page, sb_flags, mnt_flags, dev_name,
+                           data_page);
+}
+
+long do_mount(const char *dev_name, const char __user *dir_name,
+               const char *type_page, unsigned long flags, void *data_page)
+{
+       struct path path;
+       int ret;
+
+       ret = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
+       if (ret)
+               return ret;
+       ret = path_mount(dev_name, &path, type_page, flags, data_page);
        path_put(&path);
-       return retval;
+       return ret;
 }
 
 static struct ucounts *inc_mnt_namespaces(struct user_namespace *ns)