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

Alexander Viro (viro@math.psu.edu)
Sun, 2 Sep 2001 23:46:56 -0400 (EDT)


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/