vfs: Allow filesystems to access their private mount data
authorDaniel Rosenberg <drosen@google.com>
Wed, 26 Oct 2016 22:58:22 +0000 (15:58 -0700)
committerStricted <info@stricted.net>
Thu, 11 Oct 2018 16:03:53 +0000 (18:03 +0200)
Now we pass the vfsmount when mounting and remounting.
This allows the filesystem to actually set up the mount
specific data, although we can't quite do anything with
it yet. show_options is expanded to include data that
lives with the mount.

To avoid changing existing filesystems, these have
been added as new vfs functions.

Change-Id: If80670bfad9f287abb8ac22457e1b034c9697097
Signed-off-by: Daniel Rosenberg <drosen@google.com>
fs/internal.h
fs/namespace.c
fs/proc_namespace.c
fs/super.c
include/linux/fs.h

index 68121584ae37d40a074bf81e55184ecb1674d882..8c894601fadab756bd2bf7e00054c2301545e604 100644 (file)
@@ -83,9 +83,11 @@ extern struct file *get_empty_filp(void);
  * super.c
  */
 extern int do_remount_sb(struct super_block *, int, void *, int);
+extern int do_remount_sb2(struct vfsmount *, struct super_block *, int,
+                                                               void *, int);
 extern bool grab_super_passive(struct super_block *sb);
 extern struct dentry *mount_fs(struct file_system_type *,
-                              int, const char *, void *);
+                              int, const char *, struct vfsmount *, void *);
 extern struct super_block *user_get_super(dev_t);
 
 /*
index 6deff2e63e51bdfe9a10537fd53e6352810171cb..d2f30db1d80f3bc421848530c6897079ae6dee9a 100644 (file)
@@ -800,7 +800,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
        if (flags & MS_KERNMOUNT)
                mnt->mnt.mnt_flags = MNT_INTERNAL;
 
-       root = mount_fs(type, flags, name, data);
+       root = mount_fs(type, flags, name, &mnt->mnt, data);
        if (IS_ERR(root)) {
                kfree(mnt->mnt.data);
                free_vfsmnt(mnt);
@@ -1867,7 +1867,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
        else if (!capable(CAP_SYS_ADMIN))
                err = -EPERM;
        else {
-               err = do_remount_sb(sb, flags, data, 0);
+               err = do_remount_sb2(path->mnt, sb, flags, data, 0);
                namespace_lock();
                br_write_lock(&vfsmount_lock);
                propagate_remount(mnt);
index 5fe34c355e85e9bb7175cbfb2367e5c49928837a..9243966026c3183629b4f9d6c73d57b8d769a5fc 100644 (file)
@@ -112,7 +112,9 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
        if (err)
                goto out;
        show_mnt_opts(m, mnt);
-       if (sb->s_op->show_options)
+       if (sb->s_op->show_options2)
+                       err = sb->s_op->show_options2(mnt, m, mnt_path.dentry);
+       else if (sb->s_op->show_options)
                err = sb->s_op->show_options(m, mnt_path.dentry);
        seq_puts(m, " 0 0\n");
 out:
@@ -173,7 +175,9 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
        err = show_sb_opts(m, sb);
        if (err)
                goto out;
-       if (sb->s_op->show_options)
+       if (sb->s_op->show_options2) {
+               err = sb->s_op->show_options2(mnt, m, mnt->mnt_root);
+       } else if (sb->s_op->show_options)
                err = sb->s_op->show_options(m, mnt->mnt_root);
        seq_putc(m, '\n');
 out:
index a33381b02ed4500fe7bb276acb39660047ccf81b..08273e126c2887cb008cf5f409c59b4b40e41d9b 100644 (file)
@@ -695,7 +695,8 @@ rescan:
 }
 
 /**
- *     do_remount_sb - asks filesystem to change mount options.
+ *     do_remount_sb2 - asks filesystem to change mount options.
+ *     @mnt:   mount we are looking at
  *     @sb:    superblock in question
  *     @flags: numeric part of options
  *     @data:  the rest of options
@@ -703,7 +704,7 @@ rescan:
  *
  *     Alters the mount options of a mounted file system.
  */
-int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+int do_remount_sb2(struct vfsmount *mnt, struct super_block *sb, int flags, void *data, int force)
 {
        int retval;
        int remount_ro;
@@ -735,7 +736,16 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
                }
        }
 
-       if (sb->s_op->remount_fs) {
+       if (mnt && sb->s_op->remount_fs2) {
+               retval = sb->s_op->remount_fs2(mnt, sb, &flags, data);
+               if (retval) {
+                       if (!force)
+                               goto cancel_readonly;
+                       /* If forced remount, go ahead despite any errors */
+                       WARN(1, "forced remount of a %s fs returned %i\n",
+                            sb->s_type->name, retval);
+               }
+       } else if (sb->s_op->remount_fs) {
                retval = sb->s_op->remount_fs(sb, &flags, data);
                if (retval) {
                        if (!force)
@@ -767,6 +777,11 @@ cancel_readonly:
        return retval;
 }
 
+int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
+{
+       return do_remount_sb2(NULL, sb, flags, data, force);
+}
+
 void do_emergency_remount(struct work_struct *work)
 {
        struct super_block *sb, *p = NULL;
@@ -1086,7 +1101,7 @@ struct dentry *mount_single(struct file_system_type *fs_type,
 EXPORT_SYMBOL(mount_single);
 
 struct dentry *
-mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
+mount_fs(struct file_system_type *type, int flags, const char *name, struct vfsmount *mnt, void *data)
 {
        struct dentry *root;
        struct super_block *sb;
@@ -1103,7 +1118,10 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
                        goto out_free_secdata;
        }
 
-       root = type->mount(type, flags, name, data);
+       if (type->mount2)
+               root = type->mount2(mnt, type, flags, name, data);
+       else
+               root = type->mount(type, flags, name, data);
        if (IS_ERR(root)) {
                error = PTR_ERR(root);
                goto out_free_secdata;
index 6ff36d296468820f5039840c7ffe95f4348c3db5..abf286d24ce4411d3cc91f7347aac2eaf96ba08b 100644 (file)
@@ -1625,11 +1625,13 @@ struct super_operations {
        int (*unfreeze_fs) (struct super_block *);
        int (*statfs) (struct dentry *, struct kstatfs *);
        int (*remount_fs) (struct super_block *, int *, char *);
+       int (*remount_fs2) (struct vfsmount *, struct super_block *, int *, char *);
        void *(*clone_mnt_data) (void *);
        void (*copy_mnt_data) (void *, void *);
        void (*umount_begin) (struct super_block *);
 
        int (*show_options)(struct seq_file *, struct dentry *);
+       int (*show_options2)(struct vfsmount *,struct seq_file *, struct dentry *);
        int (*show_devname)(struct seq_file *, struct dentry *);
        int (*show_path)(struct seq_file *, struct dentry *);
        int (*show_stats)(struct seq_file *, struct dentry *);
@@ -1837,6 +1839,8 @@ struct file_system_type {
 #define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move() during rename() internally. */
        struct dentry *(*mount) (struct file_system_type *, int,
                       const char *, void *);
+       struct dentry *(*mount2) (struct vfsmount *, struct file_system_type *, int,
+                              const char *, void *);
        void *(*alloc_mnt_data) (void);
        void (*kill_sb) (struct super_block *);
        struct module *owner;