diff options
author | Daniel Rosenberg <drosen@google.com> | 2016-10-26 15:29:51 -0700 |
---|---|---|
committer | Amit Pundir <amit.pundir@linaro.org> | 2019-02-15 12:34:40 +0530 |
commit | 9044dc844c427d742047cdda3e4f557537cb4dc5 (patch) | |
tree | 49ddd711b5e2a10af7aff0d14299daf7f98cfe35 | |
parent | f944a6f3270cc46d78dc3699035b5dd9f726fb77 (diff) | |
download | kernel_replicant_linux-9044dc844c427d742047cdda3e4f557537cb4dc5.tar.gz kernel_replicant_linux-9044dc844c427d742047cdda3e4f557537cb4dc5.tar.bz2 kernel_replicant_linux-9044dc844c427d742047cdda3e4f557537cb4dc5.zip |
ANDROID: mnt: Add filesystem private data to mount points
This starts to add private data associated directly
to mount points. The intent is to give filesystems
a sense of where they have come from, as a means of
letting a filesystem take different actions based on
this information.
Bug: 62094374
Bug: 120446149
Change-Id: Ie769d7b3bb2f5972afe05c1bf16cf88c91647ab2
Signed-off-by: Daniel Rosenberg <drosen@google.com>
[astrachan: Folded 89a54ed3bf68 ("ANDROID: mnt: Fix next_descendent")
into this patch]
Signed-off-by: Alistair Strachan <astrachan@google.com>
-rw-r--r-- | fs/namespace.c | 23 | ||||
-rw-r--r-- | fs/pnode.c | 34 | ||||
-rw-r--r-- | fs/pnode.h | 1 | ||||
-rw-r--r-- | include/linux/fs.h | 3 | ||||
-rw-r--r-- | include/linux/mount.h | 1 |
5 files changed, 62 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index a677b59efd74..f057ccfcf73b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -201,6 +201,7 @@ static struct mount *alloc_vfsmnt(const char *name) mnt->mnt_count = 1; mnt->mnt_writers = 0; #endif + mnt->mnt.data = NULL; INIT_HLIST_NODE(&mnt->mnt_hash); INIT_LIST_HEAD(&mnt->mnt_child); @@ -550,6 +551,7 @@ int sb_prepare_remount_readonly(struct super_block *sb) static void free_vfsmnt(struct mount *mnt) { + kfree(mnt->mnt.data); kfree_const(mnt->mnt_devname); #ifdef CONFIG_SMP free_percpu(mnt->mnt_pcp); @@ -953,6 +955,14 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void if (!mnt) return ERR_PTR(-ENOMEM); + if (type->alloc_mnt_data) { + mnt->mnt.data = type->alloc_mnt_data(); + if (!mnt->mnt.data) { + mnt_free_id(mnt); + free_vfsmnt(mnt); + return ERR_PTR(-ENOMEM); + } + } if (flags & SB_KERNMOUNT) mnt->mnt.mnt_flags = MNT_INTERNAL; @@ -1000,6 +1010,14 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, if (!mnt) return ERR_PTR(-ENOMEM); + if (sb->s_op->clone_mnt_data) { + mnt->mnt.data = sb->s_op->clone_mnt_data(old->mnt.data); + if (!mnt->mnt.data) { + err = -ENOMEM; + goto out_free; + } + } + if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE)) mnt->mnt_group_id = 0; /* not a peer of original */ else @@ -2336,6 +2354,11 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, err = -EPERM; if (ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) { err = do_remount_sb(sb, sb_flags, data, 0); + namespace_lock(); + lock_mount_hash(); + propagate_remount(mnt); + unlock_mount_hash(); + namespace_unlock(); if (!err) set_mount_attributes(mnt, mnt_flags); } diff --git a/fs/pnode.c b/fs/pnode.c index 1100e810d855..7f11e46d4418 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -608,3 +608,37 @@ int propagate_umount(struct list_head *list) return 0; } + +/* + * Iterates over all slaves, and slaves of slaves. + */ +static struct mount *next_descendent(struct mount *root, struct mount *cur) +{ + if (!IS_MNT_NEW(cur) && !list_empty(&cur->mnt_slave_list)) + return first_slave(cur); + do { + struct mount *master = cur->mnt_master; + + if (!master || cur->mnt_slave.next != &master->mnt_slave_list) { + struct mount *next = next_slave(cur); + + return (next == root) ? NULL : next; + } + cur = master; + } while (cur != root); + return NULL; +} + +void propagate_remount(struct mount *mnt) +{ + struct mount *m = mnt; + struct super_block *sb = mnt->mnt.mnt_sb; + + if (sb->s_op->copy_mnt_data) { + m = next_descendent(mnt, m); + while (m) { + sb->s_op->copy_mnt_data(m->mnt.data, mnt->mnt.data); + m = next_descendent(mnt, m); + } + } +} diff --git a/fs/pnode.h b/fs/pnode.h index dc87e65becd2..a9a6576540ad 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -44,6 +44,7 @@ int propagate_mnt(struct mount *, struct mountpoint *, struct mount *, int propagate_umount(struct list_head *); int propagate_mount_busy(struct mount *, int); void propagate_mount_unlock(struct mount *); +void propagate_remount(struct mount *); void mnt_release_group_id(struct mount *); int get_dominating_id(struct mount *mnt, const struct path *root); unsigned int mnt_get_count(struct mount *mnt); diff --git a/include/linux/fs.h b/include/linux/fs.h index 29d8e2cfed0e..9915ee7b3a51 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1913,6 +1913,8 @@ struct super_operations { int (*unfreeze_fs) (struct super_block *); int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (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 *); @@ -2175,6 +2177,7 @@ 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 *); + void *(*alloc_mnt_data) (void); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; diff --git a/include/linux/mount.h b/include/linux/mount.h index 037eed52164b..0a314bb9aabd 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -68,6 +68,7 @@ struct vfsmount { struct dentry *mnt_root; /* root of the mounted tree */ struct super_block *mnt_sb; /* pointer to superblock */ int mnt_flags; + void *data; } __randomize_layout; struct file; /* forward dec */ |