fs: refactor ksys_umount
authorChristoph Hellwig <hch@lst.de>
Tue, 21 Jul 2020 08:54:34 +0000 (10:54 +0200)
committerChristoph Hellwig <hch@lst.de>
Fri, 31 Jul 2020 06:17:50 +0000 (08:17 +0200)
Factor out a path_umount helper that takes a struct path * instead of the
actual file name.  This will allow to convert the init and devtmpfs code
to properly mount based on a kernel pointer instead of relying on the
implicit set_fs(KERNEL_DS) during early init.

Signed-off-by: Christoph Hellwig <hch@lst.de>
fs/namespace.c

index 6f8234f..43834b5 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)
+static 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;
 }
 
+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);