[PATCH] cleanup in fs/super.c (do_kern_mount())

From: Alexander Viro (viro@math.psu.edu)
Date: Sun Sep 02 2001 - 22:46:56 EST


New helper function: do_kern_mount() (aka. kern_mount() donw right).
do_add_mount() and kern_mount() are using it - it does all work of
do_add_mount() except actual attaching new vfsmount to the tree. Unlike
kern_mount() it allows to pass flags/options - as the matter of fact, that's
what kern_mount() should've been: mount(2) without attaching to any mountpoint.
Quite a few people (intermezzo folks, supermount, yodda, yodda) had been
asking for that for quite a while.

Please, apply.

diff -urN S10-pre4/fs/super.c S10-pre4-do_kern_mount/fs/super.c
--- S10-pre4/fs/super.c Sun Sep 2 23:22:20 2001
+++ S10-pre4-do_kern_mount/fs/super.c Sun Sep 2 23:28:26 2001
@@ -418,6 +418,9 @@
 
 static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
 {
+ if (mnt->mnt_sb->s_flags & MS_NOUSER)
+ return -EINVAL;
+
         if (S_ISDIR(nd->dentry->d_inode->i_mode) !=
               S_ISDIR(mnt->mnt_root->d_inode->i_mode))
                 return -ENOTDIR;
@@ -1177,31 +1180,6 @@
         return 0;
 }
 
-struct vfsmount *kern_mount(struct file_system_type *type)
-{
- struct super_block *sb;
- struct vfsmount *mnt = alloc_vfsmnt();
-
- if (!mnt)
- return ERR_PTR(-ENOMEM);
-
- if (type->fs_flags & FS_SINGLE)
- sb = get_sb_single(type, 0, NULL);
- else
- sb = get_sb_nodev(type, 0, NULL);
- if (IS_ERR(sb)) {
- kmem_cache_free(mnt_cache, mnt);
- return (struct vfsmount *)sb;
- }
- mnt->mnt_sb = sb;
- mnt->mnt_root = dget(sb->s_root);
- mnt->mnt_mountpoint = mnt->mnt_root;
- mnt->mnt_parent = mnt;
- up_write(&sb->s_umount);
- up(&mount_sem);
- return mnt;
-}
-
 /*
  * Doesn't take quota and stuff into account. IOW, in some cases it will
  * give false negatives. The main reason why it's here is that we need
@@ -1428,31 +1406,30 @@
         return err;
 }
 
-static int do_add_mount(struct nameidata *nd, char *type, int flags,
- char *name, void *data)
+struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data)
 {
         struct file_system_type * fstype;
         struct vfsmount *mnt = NULL;
         struct super_block *sb;
- int retval = 0;
 
         if (!type || !memchr(type, 0, PAGE_SIZE))
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
 
         /* we need capabilities... */
         if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ return ERR_PTR(-EPERM);
 
         /* ... filesystem driver... */
         fstype = get_fs_type(type);
         if (!fstype)
- return -ENODEV;
+ return ERR_PTR(-ENODEV);
 
         /* ... allocated vfsmount... */
- retval = -ENOMEM;
         mnt = alloc_vfsmnt();
- if (!mnt)
+ if (!mnt) {
+ mnt = ERR_PTR(-ENOMEM);
                 goto fs_out;
+ }
         if (name) {
                 mnt->mnt_devname = kmalloc(strlen(name)+1, GFP_KERNEL);
                 if (mnt->mnt_devname)
@@ -1460,42 +1437,62 @@
         }
 
         /* get superblock, locks mount_sem on success */
- if (fstype->fs_flags & FS_NOMOUNT)
- sb = ERR_PTR(-EINVAL);
- else if (fstype->fs_flags & FS_REQUIRES_DEV)
+ if (fstype->fs_flags & FS_REQUIRES_DEV)
                 sb = get_sb_bdev(fstype, name, flags, data);
         else if (fstype->fs_flags & FS_SINGLE)
                 sb = get_sb_single(fstype, flags, data);
         else
                 sb = get_sb_nodev(fstype, flags, data);
 
- retval = PTR_ERR(sb);
         if (IS_ERR(sb)) {
                 if (mnt->mnt_devname)
                         kfree(mnt->mnt_devname);
                 kmem_cache_free(mnt_cache, mnt);
+ mnt = (struct vfsmount *)sb;
                 goto fs_out;
         }
+ if (fstype->fs_flags & FS_NOMOUNT)
+ sb->s_flags |= MS_NOUSER;
 
         mnt->mnt_sb = sb;
         mnt->mnt_root = dget(sb->s_root);
         mnt->mnt_mountpoint = mnt->mnt_root;
         mnt->mnt_parent = mnt;
         up_write(&sb->s_umount);
+fs_out:
+ put_filesystem(fstype);
+ return mnt;
+}
+
+struct vfsmount *kern_mount(struct file_system_type *type)
+{
+ char *name = (char *)type->name;
+ struct vfsmount *mnt = do_kern_mount(name, 0, name, NULL);
+ up(&mount_sem);
+ return mnt;
+}
+
+static int do_add_mount(struct nameidata *nd, char *type, int flags,
+ char *name, void *data)
+{
+ struct vfsmount *mnt = do_kern_mount(type, flags, name, data);
+ int retval = PTR_ERR(mnt);
+
+ if (IS_ERR(mnt))
+ goto out;
 
         /* Something was mounted here while we slept */
         while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
                 ;
 
         /* Refuse the same filesystem on the same mount point */
- if (nd->mnt->mnt_sb == sb && nd->mnt->mnt_root == nd->dentry)
+ if (nd->mnt->mnt_sb == mnt->mnt_sb && nd->mnt->mnt_root == nd->dentry)
                 retval = -EBUSY;
         else
                 retval = graft_tree(mnt, nd);
         mntput(mnt);
         up(&mount_sem);
-fs_out:
- put_filesystem(fstype);
+out:
         return retval;
 }
 
diff -urN S10-pre4/include/linux/fs.h S10-pre4-do_kern_mount/include/linux/fs.h
--- S10-pre4/include/linux/fs.h Sun Sep 2 23:22:20 2001
+++ S10-pre4-do_kern_mount/include/linux/fs.h Sun Sep 2 23:28:26 2001
@@ -108,6 +108,7 @@
 #define MS_NOATIME 1024 /* Do not update access times. */
 #define MS_NODIRATIME 2048 /* Do not update directory access times */
 #define MS_BIND 4096
+#define MS_NOUSER (1<<31)
 
 /*
  * Flags that can be altered by MS_REMOUNT

-
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 : Fri Sep 07 2001 - 21:00:17 EST