ANDROID: 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)
committerDaniel Rosenberg <drosen@google.com>
Tue, 30 Jan 2018 03:39:58 +0000 (19:39 -0800)
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 48cee21b4f146f5da86b3e485a1f9c155c33a5fe..b4338451c1e41a837b28d1698c05d927c18ef81c 100644 (file)
@@ -90,9 +90,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 trylock_super(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 247d1ca13be105dbbe2091104ab3304e4ab838e0..166ed0bcf7754dbd4129fbf0aa5bc0e63ec551f8 100644 (file)
@@ -1044,7 +1044,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
        if (flags & SB_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)) {
                mnt_free_id(mnt);
                free_vfsmnt(mnt);
@@ -2348,7 +2348,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
        else if (!capable(CAP_SYS_ADMIN))
                err = -EPERM;
        else {
-               err = do_remount_sb(sb, sb_flags, data, 0);
+               err = do_remount_sb2(path->mnt, sb, sb_flags, data, 0);
                namespace_lock();
                lock_mount_hash();
                propagate_remount(mnt);
index 7626ee11b06c67edac5d9c021516ff6ea3390b98..b859aaeecb270676a6ba94c57e1c309f61f7b97e 100644 (file)
@@ -121,7 +121,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:
@@ -183,7 +185,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 417d548f534b41392a42836fa176c573991ec7ad..5dcfc793ce3e74f934fb54af947412996d388f34 100644 (file)
@@ -800,7 +800,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
  *     @sb_flags: revised superblock flags
  *     @data:  the rest of options
@@ -808,7 +809,7 @@ rescan:
  *
  *     Alters the mount options of a mounted file system.
  */
-int do_remount_sb(struct super_block *sb, int sb_flags, void *data, int force)
+int do_remount_sb2(struct vfsmount *mnt, struct super_block *sb, int sb_flags, void *data, int force)
 {
        int retval;
        int remount_ro;
@@ -850,7 +851,16 @@ int do_remount_sb(struct super_block *sb, int sb_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, &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, &sb_flags, data);
                if (retval) {
                        if (!force)
@@ -882,6 +892,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);
+}
+
 static void do_emergency_remount(struct work_struct *work)
 {
        struct super_block *sb, *p = NULL;
@@ -1203,7 +1218,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;
@@ -1220,7 +1235,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 905bd2e9e4baf7390b7547e347097668a8a675ae..361de61fe230b074b9dda45a27cd124822636288 100644 (file)
@@ -1815,11 +1815,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 *);
@@ -2079,6 +2081,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;