aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Rosenberg <drosen@google.com>2016-10-26 15:58:22 -0700
committerAmit Pundir <amit.pundir@linaro.org>2019-02-15 12:34:40 +0530
commit20c0639e482473d67cafa7ac351ab61cdda39236 (patch)
treec77e5afda6eae1e2fe9da45806558fc8c4e703de
parent9044dc844c427d742047cdda3e4f557537cb4dc5 (diff)
downloadkernel_replicant_linux-20c0639e482473d67cafa7ac351ab61cdda39236.tar.gz
kernel_replicant_linux-20c0639e482473d67cafa7ac351ab61cdda39236.tar.bz2
kernel_replicant_linux-20c0639e482473d67cafa7ac351ab61cdda39236.zip
ANDROID: vfs: Allow filesystems to access their private mount data
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. Bug: 120446149 Change-Id: If80670bfad9f287abb8ac22457e1b034c9697097 Signed-off-by: Daniel Rosenberg <drosen@google.com>
-rw-r--r--fs/internal.h4
-rw-r--r--fs/namespace.c4
-rw-r--r--fs/proc_namespace.c8
-rw-r--r--fs/super.c28
-rw-r--r--include/linux/fs.h4
5 files changed, 38 insertions, 10 deletions
diff --git a/fs/internal.h b/fs/internal.h
index d410186bc369..a1ac9427243f 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -100,9 +100,11 @@ extern struct file *alloc_empty_file_noaccount(int, const struct cred *);
* 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);
/*
diff --git a/fs/namespace.c b/fs/namespace.c
index f057ccfcf73b..035fdfb60179 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -966,7 +966,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);
@@ -2353,7 +2353,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
down_write(&sb->s_umount);
err = -EPERM;
if (ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) {
- 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);
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
index e16fb8f2049e..bd07f0f4f06b 100644
--- a/fs/proc_namespace.c
+++ b/fs/proc_namespace.c
@@ -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:
diff --git a/fs/super.c b/fs/super.c
index 48e25eba8465..2c887f077012 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -835,7 +835,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
@@ -843,7 +844,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;
@@ -885,7 +886,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)
@@ -917,6 +927,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_callback(struct super_block *sb)
{
down_write(&sb->s_umount);
@@ -1242,7 +1257,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;
@@ -1255,7 +1270,10 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
return ERR_PTR(error);
}
- 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;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9915ee7b3a51..0acaebdc4e4e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1913,11 +1913,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 *);
@@ -2177,6 +2179,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;