From a127e2d518269ad95364639c293c8a5c1a1cdd3c Mon Sep 17 00:00:00 2001 From: Kautuk Consul Date: Fri, 23 Sep 2011 22:08:29 +0530 Subject: namespace: mnt_want_write: Remove unused label 'out' I was studying the code and I saw that the out label is not being used at all so I removed it and its usage from the function. Signed-off-by: Kautuk Consul Signed-off-by: Jiri Kosina --- fs/namespace.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index b4febb29d3bb..9a1ddcda655f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -352,9 +352,7 @@ int mnt_want_write(struct vfsmount *mnt) if (__mnt_is_readonly(mnt)) { mnt_dec_writers(mnt); ret = -EROFS; - goto out; } -out: preempt_enable(); return ret; } -- cgit v1.2.3 From 02125a826459a6ad142f8d91c5b6357562f96615 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 5 Dec 2011 08:43:34 -0500 Subject: fix apparmor dereferencing potentially freed dentry, sanitize __d_path() API __d_path() API is asking for trouble and in case of apparmor d_namespace_path() getting just that. The root cause is that when __d_path() misses the root it had been told to look for, it stores the location of the most remote ancestor in *root. Without grabbing references. Sure, at the moment of call it had been pinned down by what we have in *path. And if we raced with umount -l, we could have very well stopped at vfsmount/dentry that got freed as soon as prepend_path() dropped vfsmount_lock. It is safe to compare these pointers with pre-existing (and known to be still alive) vfsmount and dentry, as long as all we are asking is "is it the same address?". Dereferencing is not safe and apparmor ended up stepping into that. d_namespace_path() really wants to examine the place where we stopped, even if it's not connected to our namespace. As the result, it looked at ->d_sb->s_magic of a dentry that might've been already freed by that point. All other callers had been careful enough to avoid that, but it's really a bad interface - it invites that kind of trouble. The fix is fairly straightforward, even though it's bigger than I'd like: * prepend_path() root argument becomes const. * __d_path() is never called with NULL/NULL root. It was a kludge to start with. Instead, we have an explicit function - d_absolute_root(). Same as __d_path(), except that it doesn't get root passed and stops where it stops. apparmor and tomoyo are using it. * __d_path() returns NULL on path outside of root. The main caller is show_mountinfo() and that's precisely what we pass root for - to skip those outside chroot jail. Those who don't want that can (and do) use d_path(). * __d_path() root argument becomes const. Everyone agrees, I hope. * apparmor does *NOT* try to use __d_path() or any of its variants when it sees that path->mnt is an internal vfsmount. In that case it's definitely not mounted anywhere and dentry_path() is exactly what we want there. Handling of sysctl()-triggered weirdness is moved to that place. * if apparmor is asked to do pathname relative to chroot jail and __d_path() tells it we it's not in that jail, the sucker just calls d_absolute_path() instead. That's the other remaining caller of __d_path(), BTW. * seq_path_root() does _NOT_ return -ENAMETOOLONG (it's stupid anyway - the normal seq_file logics will take care of growing the buffer and redoing the call of ->show() just fine). However, if it gets path not reachable from root, it returns SEQ_SKIP. The only caller adjusted (i.e. stopped ignoring the return value as it used to do). Reviewed-by: John Johansen ACKed-by: John Johansen Signed-off-by: Al Viro Cc: stable@vger.kernel.org --- fs/namespace.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 6d3a1963879b..cfc6d4448aa5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1048,15 +1048,12 @@ static int show_mountinfo(struct seq_file *m, void *v) if (err) goto out; seq_putc(m, ' '); - seq_path_root(m, &mnt_path, &root, " \t\n\\"); - if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) { - /* - * Mountpoint is outside root, discard that one. Ugly, - * but less so than trying to do that in iterator in a - * race-free way (due to renames). - */ - return SEQ_SKIP; - } + + /* mountpoints outside of chroot jail will give SEQ_SKIP on this */ + err = seq_path_root(m, &mnt_path, &root, " \t\n\\"); + if (err) + goto out; + seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); show_mnt_opts(m, mnt); @@ -2776,3 +2773,8 @@ void kern_unmount(struct vfsmount *mnt) } } EXPORT_SYMBOL(kern_unmount); + +bool our_mnt(struct vfsmount *mnt) +{ + return check_mnt(mnt); +} -- cgit v1.2.3 From aa9c0e07bb90589186f3b5a0ca97660c2cb50806 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 Nov 2011 19:04:52 -0500 Subject: vfs: kill pointless helpers in namespace.c mnt_{inc,dec}_count() is not cleaner than doing the corresponding mnt_add_count() directly and mnt_set_count() is not used at all. Signed-off-by: Al Viro --- fs/namespace.c | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index cfc6d4448aa5..31d357450f7f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -152,31 +152,6 @@ static inline void mnt_add_count(struct vfsmount *mnt, int n) #endif } -static inline void mnt_set_count(struct vfsmount *mnt, int n) -{ -#ifdef CONFIG_SMP - this_cpu_write(mnt->mnt_pcp->mnt_count, n); -#else - mnt->mnt_count = n; -#endif -} - -/* - * vfsmount lock must be held for read - */ -static inline void mnt_inc_count(struct vfsmount *mnt) -{ - mnt_add_count(mnt, 1); -} - -/* - * vfsmount lock must be held for read - */ -static inline void mnt_dec_count(struct vfsmount *mnt) -{ - mnt_add_count(mnt, -1); -} - /* * vfsmount lock must be held for write */ @@ -780,20 +755,20 @@ put_again: #ifdef CONFIG_SMP br_read_lock(vfsmount_lock); if (likely(atomic_read(&mnt->mnt_longterm))) { - mnt_dec_count(mnt); + mnt_add_count(mnt, -1); br_read_unlock(vfsmount_lock); return; } br_read_unlock(vfsmount_lock); br_write_lock(vfsmount_lock); - mnt_dec_count(mnt); + mnt_add_count(mnt, -1); if (mnt_get_count(mnt)) { br_write_unlock(vfsmount_lock); return; } #else - mnt_dec_count(mnt); + mnt_add_count(mnt, -1); if (likely(mnt_get_count(mnt))) return; br_write_lock(vfsmount_lock); @@ -823,7 +798,7 @@ EXPORT_SYMBOL(mntput); struct vfsmount *mntget(struct vfsmount *mnt) { if (mnt) - mnt_inc_count(mnt); + mnt_add_count(mnt, 1); return mnt; } EXPORT_SYMBOL(mntget); @@ -840,7 +815,7 @@ void mnt_unpin(struct vfsmount *mnt) { br_write_lock(vfsmount_lock); if (mnt->mnt_pinned) { - mnt_inc_count(mnt); + mnt_add_count(mnt, 1); mnt->mnt_pinned--; } br_write_unlock(vfsmount_lock); -- cgit v1.2.3 From b2dba1af3c4157040303a76d25216b1713d333d0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 Nov 2011 19:26:23 -0500 Subject: vfs: new internal helper: mnt_has_parent(mnt) vfsmounts have ->mnt_parent pointing either to a different vfsmount or to itself; it's never NULL and termination condition in loops traversing the tree towards root is mnt == mnt->mnt_parent. At least one place (see the next patch) is confused about what's going on; let's add an explicit helper checking it right way and use it in all places where we need it. Not that there had been too many, but... Signed-off-by: Al Viro --- fs/namespace.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 31d357450f7f..ec8512478b04 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1182,7 +1182,7 @@ void release_mounts(struct list_head *head) while (!list_empty(head)) { mnt = list_first_entry(head, struct vfsmount, mnt_hash); list_del_init(&mnt->mnt_hash); - if (mnt->mnt_parent != mnt) { + if (mnt_has_parent(mnt)) { struct dentry *dentry; struct vfsmount *m; @@ -1222,7 +1222,7 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) p->mnt_ns = NULL; __mnt_make_shortterm(p); list_del_init(&p->mnt_child); - if (p->mnt_parent != p) { + if (mnt_has_parent(p)) { p->mnt_parent->mnt_ghosts++; dentry_reset_mounted(p->mnt_parent, p->mnt_mountpoint); } @@ -1867,7 +1867,7 @@ static int do_move_mount(struct path *path, char *old_name) if (old_path.dentry != old_path.mnt->mnt_root) goto out1; - if (old_path.mnt == old_path.mnt->mnt_parent) + if (!mnt_has_parent(old_path.mnt)) goto out1; if (S_ISDIR(path->dentry->d_inode->i_mode) != @@ -1887,7 +1887,7 @@ static int do_move_mount(struct path *path, char *old_name) tree_contains_unbindable(old_path.mnt)) goto out1; err = -ELOOP; - for (p = path->mnt; p->mnt_parent != p; p = p->mnt_parent) + for (p = path->mnt; mnt_has_parent(p); p = p->mnt_parent) if (p == old_path.mnt) goto out1; @@ -2604,17 +2604,17 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, error = -EINVAL; if (root.mnt->mnt_root != root.dentry) goto out4; /* not a mountpoint */ - if (root.mnt->mnt_parent == root.mnt) + if (!mnt_has_parent(root.mnt)) goto out4; /* not attached */ if (new.mnt->mnt_root != new.dentry) goto out4; /* not a mountpoint */ - if (new.mnt->mnt_parent == new.mnt) + if (!mnt_has_parent(new.mnt)) goto out4; /* not attached */ /* make sure we can reach put_old from new_root */ tmp = old.mnt; if (tmp != new.mnt) { for (;;) { - if (tmp->mnt_parent == tmp) + if (!mnt_has_parent(tmp)) goto out4; /* already mounted on put_old */ if (tmp->mnt_parent == new.mnt) break; -- cgit v1.2.3 From afac7cba7ed31968a95e181dc25e204e45009ea8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 Nov 2011 19:34:49 -0500 Subject: vfs: more mnt_parent cleanups a) mount --move is checking that ->mnt_parent is non-NULL before looking if that parent happens to be shared; ->mnt_parent is never NULL and it's not even an misspelled !mnt_has_parent() b) pivot_root open-codes is_path_reachable(), poorly. c) so does path_is_under(), while we are at it. Signed-off-by: Al Viro --- fs/namespace.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index ec8512478b04..7aad258dcaf6 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1876,8 +1876,7 @@ static int do_move_mount(struct path *path, char *old_name) /* * Don't move a mount residing in a shared parent. */ - if (old_path.mnt->mnt_parent && - IS_MNT_SHARED(old_path.mnt->mnt_parent)) + if (IS_MNT_SHARED(old_path.mnt->mnt_parent)) goto out1; /* * Don't move a mount tree containing unbindable mounts to a destination @@ -2533,6 +2532,31 @@ out_type: return ret; } +/* + * Return true if path is reachable from root + * + * namespace_sem or vfsmount_lock is held + */ +bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry, + const struct path *root) +{ + while (mnt != root->mnt && mnt_has_parent(mnt)) { + dentry = mnt->mnt_mountpoint; + mnt = mnt->mnt_parent; + } + return mnt == root->mnt && is_subdir(dentry, root->dentry); +} + +int path_is_under(struct path *path1, struct path *path2) +{ + int res; + br_read_lock(vfsmount_lock); + res = is_path_reachable(path1->mnt, path1->dentry, path2); + br_read_unlock(vfsmount_lock); + return res; +} +EXPORT_SYMBOL(path_is_under); + /* * pivot_root Semantics: * Moves the root file system of the current process to the directory put_old, @@ -2561,7 +2585,6 @@ out_type: SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, const char __user *, put_old) { - struct vfsmount *tmp; struct path new, old, parent_path, root_parent, root; int error; @@ -2611,18 +2634,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, if (!mnt_has_parent(new.mnt)) goto out4; /* not attached */ /* make sure we can reach put_old from new_root */ - tmp = old.mnt; - if (tmp != new.mnt) { - for (;;) { - if (!mnt_has_parent(tmp)) - goto out4; /* already mounted on put_old */ - if (tmp->mnt_parent == new.mnt) - break; - tmp = tmp->mnt_parent; - } - if (!is_subdir(tmp->mnt_mountpoint, new.dentry)) - goto out4; - } else if (!is_subdir(old.dentry, new.dentry)) + if (!is_path_reachable(old.mnt, old.dentry, &new)) goto out4; br_write_lock(vfsmount_lock); detach_mnt(new.mnt, &parent_path); -- cgit v1.2.3 From 6c449c8dfe30142b3ced5f052e8ed3cce308801a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 16 Nov 2011 22:01:36 -0500 Subject: unexport put_mnt_ns(), make create_mnt_ns() static outright Signed-off-by: Al Viro --- fs/namespace.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 7aad258dcaf6..0953a3a6d45e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2444,7 +2444,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, * create_mnt_ns - creates a private namespace and adds a root filesystem * @mnt: pointer to the new root filesystem mountpoint */ -struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) +static struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) { struct mnt_namespace *new_ns; @@ -2459,7 +2459,6 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) } return new_ns; } -EXPORT_SYMBOL(create_mnt_ns); struct dentry *mount_subtree(struct vfsmount *mnt, const char *name) { @@ -2734,7 +2733,6 @@ void put_mnt_ns(struct mnt_namespace *ns) release_mounts(&umount_list); kfree(ns); } -EXPORT_SYMBOL(put_mnt_ns); struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) { -- cgit v1.2.3 From aa0a4cf0ab4b03db21133a0ba62f558ed1bfcd1d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 19:31:36 -0500 Subject: vfs: dentry_reset_mounted() doesn't use vfsmount argument lose it Signed-off-by: Al Viro --- fs/namespace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 0953a3a6d45e..ed21ac4f7c69 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -523,7 +523,7 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) * Clear dentry's mounted state if it has no remaining mounts. * vfsmount_lock must be held for write. */ -static void dentry_reset_mounted(struct vfsmount *mnt, struct dentry *dentry) +static void dentry_reset_mounted(struct dentry *dentry) { unsigned u; @@ -551,7 +551,7 @@ static void detach_mnt(struct vfsmount *mnt, struct path *old_path) mnt->mnt_mountpoint = mnt->mnt_root; list_del_init(&mnt->mnt_child); list_del_init(&mnt->mnt_hash); - dentry_reset_mounted(old_path->mnt, old_path->dentry); + dentry_reset_mounted(old_path->dentry); } /* @@ -1224,7 +1224,7 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) list_del_init(&p->mnt_child); if (mnt_has_parent(p)) { p->mnt_parent->mnt_ghosts++; - dentry_reset_mounted(p->mnt_parent, p->mnt_mountpoint); + dentry_reset_mounted(p->mnt_mountpoint); } change_mnt_propagation(p, MS_PRIVATE); } -- cgit v1.2.3 From 79e801a906db46cb8efad66c400b01df874b3f12 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 12 Dec 2011 23:07:05 -0500 Subject: vfs: make do_kern_mount() static the only user outside of fs/namespace.c has died Signed-off-by: Al Viro --- fs/namespace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index ed21ac4f7c69..7a8f949cec1b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1929,7 +1929,7 @@ static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype) return ERR_PTR(err); } -struct vfsmount * +static struct vfsmount * do_kern_mount(const char *fstype, int flags, const char *name, void *data) { struct file_system_type *type = get_fs_type(fstype); @@ -1943,7 +1943,6 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) put_filesystem(type); return mnt; } -EXPORT_SYMBOL_GPL(do_kern_mount); /* * add a mount into a namespace's mount tree -- cgit v1.2.3 From 2a79f17e4a641a2f463cb512cb0ec349844a147b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 9 Dec 2011 08:06:57 -0500 Subject: vfs: mnt_drop_write_file() new helper (wrapper around mnt_drop_write()) to be used in pair with mnt_want_write_file(). Signed-off-by: Al Viro --- fs/namespace.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 7a8f949cec1b..86b4f6406470 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -392,6 +392,12 @@ void mnt_drop_write(struct vfsmount *mnt) } EXPORT_SYMBOL_GPL(mnt_drop_write); +void mnt_drop_write_file(struct file *file) +{ + mnt_drop_write(file->f_path.mnt); +} +EXPORT_SYMBOL(mnt_drop_write_file); + static int mnt_make_readonly(struct vfsmount *mnt) { int ret = 0; -- cgit v1.2.3 From 7d6fec45a5131918b51dcd76da52f2ec86a85be6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 Nov 2011 12:14:10 -0500 Subject: vfs: start hiding vfsmount guts series Almost all fields of struct vfsmount are used only by core VFS (and a fairly small part of it, at that). The plan: embed struct vfsmount into struct mount, making the latter visible only to core parts of VFS. Then move fields from vfsmount to mount, eventually leaving only mnt_root/mnt_sb/mnt_flags in struct vfsmount. Filesystem code still gets pointers to struct vfsmount and remains unchanged; all such pointers go to struct vfsmount embedded into the instances of struct mount allocated by fs/namespace.c. When fs/namespace.c et.al. get a pointer to vfsmount, they turn it into pointer to mount (using container_of) and work with that. This is the first part of series; struct mount is introduced, allocation switched to using it. Signed-off-by: Al Viro --- fs/namespace.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 86b4f6406470..dda47fee6fdf 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -173,8 +173,9 @@ unsigned int mnt_get_count(struct vfsmount *mnt) static struct vfsmount *alloc_vfsmnt(const char *name) { - struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); - if (mnt) { + struct mount *p = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); + if (p) { + struct vfsmount *mnt = &p->mnt; int err; err = mnt_alloc_id(mnt); @@ -210,16 +211,16 @@ static struct vfsmount *alloc_vfsmnt(const char *name) INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); #endif } - return mnt; + return &p->mnt; #ifdef CONFIG_SMP out_free_devname: - kfree(mnt->mnt_devname); + kfree(p->mnt.mnt_devname); #endif out_free_id: - mnt_free_id(mnt); + mnt_free_id(&p->mnt); out_free_cache: - kmem_cache_free(mnt_cache, mnt); + kmem_cache_free(mnt_cache, p); return NULL; } @@ -449,12 +450,13 @@ static void __mnt_unmake_readonly(struct vfsmount *mnt) static void free_vfsmnt(struct vfsmount *mnt) { + struct mount *p = real_mount(mnt); kfree(mnt->mnt_devname); mnt_free_id(mnt); #ifdef CONFIG_SMP free_percpu(mnt->mnt_pcp); #endif - kmem_cache_free(mnt_cache, mnt); + kmem_cache_free(mnt_cache, p); } /* @@ -2698,7 +2700,7 @@ void __init mnt_init(void) init_rwsem(&namespace_sem); - mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount), + mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC); -- cgit v1.2.3 From c71053659e3bb27d44b79da0bb4abf5838c2060a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 18:22:03 -0500 Subject: vfs: spread struct mount - __lookup_mnt() result switch __lookup_mnt() to returning struct mount *; callers adjusted. Signed-off-by: Al Viro --- fs/namespace.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index dda47fee6fdf..398eb2421494 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -464,20 +464,20 @@ static void free_vfsmnt(struct vfsmount *mnt) * @dir. If @dir is set return the first mount else return the last mount. * vfsmount_lock must be held for read or write. */ -struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, +struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, int dir) { struct list_head *head = mount_hashtable + hash(mnt, dentry); struct list_head *tmp = head; - struct vfsmount *p, *found = NULL; + struct mount *p, *found = NULL; for (;;) { tmp = dir ? tmp->next : tmp->prev; p = NULL; if (tmp == head) break; - p = list_entry(tmp, struct vfsmount, mnt_hash); - if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) { + p = list_entry(tmp, struct mount, mnt.mnt_hash); + if (p->mnt.mnt_parent == mnt && p->mnt.mnt_mountpoint == dentry) { found = p; break; } @@ -491,13 +491,18 @@ struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, */ struct vfsmount *lookup_mnt(struct path *path) { - struct vfsmount *child_mnt; + struct mount *child_mnt; br_read_lock(vfsmount_lock); - if ((child_mnt = __lookup_mnt(path->mnt, path->dentry, 1))) - mntget(child_mnt); - br_read_unlock(vfsmount_lock); - return child_mnt; + child_mnt = __lookup_mnt(path->mnt, path->dentry, 1); + if (child_mnt) { + mnt_add_count(child_mnt, 1); + br_read_unlock(vfsmount_lock); + return &child_mnt->mnt; + } else { + br_read_unlock(vfsmount_lock); + return NULL; + } } static inline int check_mnt(struct vfsmount *mnt) -- cgit v1.2.3 From 315fc83e56c6998f67af24b49c619f40a6ff2803 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 18:57:30 -0500 Subject: vfs: spread struct mount - namespace.c internal iterators next_mnt() return value, first argument skip_mnt_tree() return value and argument Signed-off-by: Al Viro --- fs/namespace.c | 145 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 74 insertions(+), 71 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 398eb2421494..7226dc514b3b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -632,28 +632,28 @@ static void commit_tree(struct vfsmount *mnt) touch_mnt_namespace(n); } -static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) +static struct mount *next_mnt(struct mount *p, struct vfsmount *root) { - struct list_head *next = p->mnt_mounts.next; - if (next == &p->mnt_mounts) { + struct list_head *next = p->mnt.mnt_mounts.next; + if (next == &p->mnt.mnt_mounts) { while (1) { - if (p == root) + if (&p->mnt == root) return NULL; - next = p->mnt_child.next; - if (next != &p->mnt_parent->mnt_mounts) + next = p->mnt.mnt_child.next; + if (next != &p->mnt.mnt_parent->mnt_mounts) break; - p = p->mnt_parent; + p = real_mount(p->mnt.mnt_parent); } } - return list_entry(next, struct vfsmount, mnt_child); + return list_entry(next, struct mount, mnt.mnt_child); } -static struct vfsmount *skip_mnt_tree(struct vfsmount *p) +static struct mount *skip_mnt_tree(struct mount *p) { - struct list_head *prev = p->mnt_mounts.prev; - while (prev != &p->mnt_mounts) { - p = list_entry(prev, struct vfsmount, mnt_child); - prev = p->mnt_mounts.prev; + struct list_head *prev = p->mnt.mnt_mounts.prev; + while (prev != &p->mnt.mnt_mounts) { + p = list_entry(prev, struct mount, mnt.mnt_child); + prev = p->mnt.mnt_mounts.prev; } return p; } @@ -1144,12 +1144,13 @@ int may_umount_tree(struct vfsmount *mnt) { int actual_refs = 0; int minimum_refs = 0; - struct vfsmount *p; + struct mount *p; + BUG_ON(!mnt); /* write lock needed for mnt_get_count */ br_write_lock(vfsmount_lock); - for (p = mnt; p; p = next_mnt(p, mnt)) { - actual_refs += mnt_get_count(p); + for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) { + actual_refs += mnt_get_count(&p->mnt); minimum_refs += 2; } br_write_unlock(vfsmount_lock); @@ -1220,26 +1221,26 @@ void release_mounts(struct list_head *head) void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) { LIST_HEAD(tmp_list); - struct vfsmount *p; + struct mount *p; - for (p = mnt; p; p = next_mnt(p, mnt)) - list_move(&p->mnt_hash, &tmp_list); + for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) + list_move(&p->mnt.mnt_hash, &tmp_list); if (propagate) propagate_umount(&tmp_list); - list_for_each_entry(p, &tmp_list, mnt_hash) { - list_del_init(&p->mnt_expire); - list_del_init(&p->mnt_list); - __touch_mnt_namespace(p->mnt_ns); - p->mnt_ns = NULL; - __mnt_make_shortterm(p); - list_del_init(&p->mnt_child); - if (mnt_has_parent(p)) { - p->mnt_parent->mnt_ghosts++; - dentry_reset_mounted(p->mnt_mountpoint); + list_for_each_entry(p, &tmp_list, mnt.mnt_hash) { + list_del_init(&p->mnt.mnt_expire); + list_del_init(&p->mnt.mnt_list); + __touch_mnt_namespace(p->mnt.mnt_ns); + p->mnt.mnt_ns = NULL; + __mnt_make_shortterm(&p->mnt); + list_del_init(&p->mnt.mnt_child); + if (mnt_has_parent(&p->mnt)) { + p->mnt.mnt_parent->mnt_ghosts++; + dentry_reset_mounted(p->mnt.mnt_mountpoint); } - change_mnt_propagation(p, MS_PRIVATE); + change_mnt_propagation(&p->mnt, MS_PRIVATE); } list_splice(&tmp_list, kill); } @@ -1411,7 +1412,7 @@ static int mount_is_safe(struct path *path) struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, int flag) { - struct vfsmount *res, *p, *q, *r, *s; + struct vfsmount *res, *p, *q, *r; struct path path; if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) @@ -1424,19 +1425,20 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, p = mnt; list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { + struct mount *s; if (!is_subdir(r->mnt_mountpoint, dentry)) continue; - for (s = r; s; s = next_mnt(s, r)) { - if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(s)) { + for (s = real_mount(r); s; s = next_mnt(s, r)) { + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(&s->mnt)) { s = skip_mnt_tree(s); continue; } - while (p != s->mnt_parent) { + while (p != s->mnt.mnt_parent) { p = p->mnt_parent; q = q->mnt_parent; } - p = s; + p = &s->mnt; path.mnt = q; path.dentry = p->mnt_mountpoint; q = clone_mnt(p, p->mnt_root, flag); @@ -1497,23 +1499,23 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) { - struct vfsmount *p; + struct mount *p; - for (p = mnt; p != end; p = next_mnt(p, mnt)) { - if (p->mnt_group_id && !IS_MNT_SHARED(p)) - mnt_release_group_id(p); + for (p = real_mount(mnt); &p->mnt != end; p = next_mnt(p, mnt)) { + if (p->mnt.mnt_group_id && !IS_MNT_SHARED(&p->mnt)) + mnt_release_group_id(&p->mnt); } } static int invent_group_ids(struct vfsmount *mnt, bool recurse) { - struct vfsmount *p; + struct mount *p; - for (p = mnt; p; p = recurse ? next_mnt(p, mnt) : NULL) { - if (!p->mnt_group_id && !IS_MNT_SHARED(p)) { - int err = mnt_alloc_group_id(p); + for (p = real_mount(mnt); p; p = recurse ? next_mnt(p, mnt) : NULL) { + if (!p->mnt.mnt_group_id && !IS_MNT_SHARED(&p->mnt)) { + int err = mnt_alloc_group_id(&p->mnt); if (err) { - cleanup_group_ids(mnt, p); + cleanup_group_ids(mnt, &p->mnt); return err; } } @@ -1591,7 +1593,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, LIST_HEAD(tree_list); struct vfsmount *dest_mnt = path->mnt; struct dentry *dest_dentry = path->dentry; - struct vfsmount *child, *p; + struct mount *child, *p; int err; if (IS_MNT_SHARED(dest_mnt)) { @@ -1606,8 +1608,8 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, br_write_lock(vfsmount_lock); if (IS_MNT_SHARED(dest_mnt)) { - for (p = source_mnt; p; p = next_mnt(p, source_mnt)) - set_mnt_shared(p); + for (p = real_mount(source_mnt); p; p = next_mnt(p, source_mnt)) + set_mnt_shared(&p->mnt); } if (parent_path) { detach_mnt(source_mnt, parent_path); @@ -1618,9 +1620,9 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, commit_tree(source_mnt); } - list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { - list_del_init(&child->mnt_hash); - commit_tree(child); + list_for_each_entry_safe(child, p, &tree_list, mnt.mnt_hash) { + list_del_init(&child->mnt.mnt_hash); + commit_tree(&child->mnt); } br_write_unlock(vfsmount_lock); @@ -1697,7 +1699,8 @@ static int flags_to_propagation_type(int flags) */ static int do_change_type(struct path *path, int flag) { - struct vfsmount *m, *mnt = path->mnt; + struct mount *m; + struct vfsmount *mnt = path->mnt; int recurse = flag & MS_REC; int type; int err = 0; @@ -1720,8 +1723,8 @@ static int do_change_type(struct path *path, int flag) } br_write_lock(vfsmount_lock); - for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) - change_mnt_propagation(m, type); + for (m = real_mount(mnt); m; m = (recurse ? next_mnt(m, mnt) : NULL)) + change_mnt_propagation(&m->mnt, type); br_write_unlock(vfsmount_lock); out_unlock: @@ -1844,9 +1847,9 @@ static int do_remount(struct path *path, int flags, int mnt_flags, static inline int tree_contains_unbindable(struct vfsmount *mnt) { - struct vfsmount *p; - for (p = mnt; p; p = next_mnt(p, mnt)) { - if (IS_MNT_UNBINDABLE(p)) + struct mount *p; + for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) { + if (IS_MNT_UNBINDABLE(&p->mnt)) return 1; } return 0; @@ -2379,7 +2382,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, { struct mnt_namespace *new_ns; struct vfsmount *rootmnt = NULL, *pwdmnt = NULL; - struct vfsmount *p, *q; + struct mount *p, *q; new_ns = alloc_mnt_ns(); if (IS_ERR(new_ns)) @@ -2403,23 +2406,23 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, * as belonging to new namespace. We have already acquired a private * fs_struct, so tsk->fs->lock is not needed. */ - p = mnt_ns->root; - q = new_ns->root; + p = real_mount(mnt_ns->root); + q = real_mount(new_ns->root); while (p) { - q->mnt_ns = new_ns; - __mnt_make_longterm(q); + q->mnt.mnt_ns = new_ns; + __mnt_make_longterm(&q->mnt); if (fs) { - if (p == fs->root.mnt) { - fs->root.mnt = mntget(q); - __mnt_make_longterm(q); - mnt_make_shortterm(p); - rootmnt = p; + if (&p->mnt == fs->root.mnt) { + fs->root.mnt = mntget(&q->mnt); + __mnt_make_longterm(&q->mnt); + mnt_make_shortterm(&p->mnt); + rootmnt = &p->mnt; } - if (p == fs->pwd.mnt) { - fs->pwd.mnt = mntget(q); - __mnt_make_longterm(q); - mnt_make_shortterm(p); - pwdmnt = p; + if (&p->mnt == fs->pwd.mnt) { + fs->pwd.mnt = mntget(&q->mnt); + __mnt_make_longterm(&q->mnt); + mnt_make_shortterm(&p->mnt); + pwdmnt = &p->mnt; } } p = next_mnt(p, mnt_ns->root); -- cgit v1.2.3 From 419148da6e76dd0d379b5ec33c461cee1015322e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 19:41:16 -0500 Subject: vfs: spread struct mount - attach_mnt/detach_mnt Signed-off-by: Al Viro --- fs/namespace.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 7226dc514b3b..444557e04b38 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -556,14 +556,14 @@ static void dentry_reset_mounted(struct dentry *dentry) /* * vfsmount lock must be held for write */ -static void detach_mnt(struct vfsmount *mnt, struct path *old_path) -{ - old_path->dentry = mnt->mnt_mountpoint; - old_path->mnt = mnt->mnt_parent; - mnt->mnt_parent = mnt; - mnt->mnt_mountpoint = mnt->mnt_root; - list_del_init(&mnt->mnt_child); - list_del_init(&mnt->mnt_hash); +static void detach_mnt(struct mount *mnt, struct path *old_path) +{ + old_path->dentry = mnt->mnt.mnt_mountpoint; + old_path->mnt = mnt->mnt.mnt_parent; + mnt->mnt.mnt_parent = &mnt->mnt; + mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; + list_del_init(&mnt->mnt.mnt_child); + list_del_init(&mnt->mnt.mnt_hash); dentry_reset_mounted(old_path->dentry); } @@ -583,12 +583,12 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, /* * vfsmount lock must be held for write */ -static void attach_mnt(struct vfsmount *mnt, struct path *path) +static void attach_mnt(struct mount *mnt, struct path *path) { - mnt_set_mountpoint(path->mnt, path->dentry, mnt); - list_add_tail(&mnt->mnt_hash, mount_hashtable + + mnt_set_mountpoint(path->mnt, path->dentry, &mnt->mnt); + list_add_tail(&mnt->mnt.mnt_hash, mount_hashtable + hash(path->mnt, path->dentry)); - list_add_tail(&mnt->mnt_child, &path->mnt->mnt_mounts); + list_add_tail(&mnt->mnt.mnt_child, &path->mnt->mnt_mounts); } static inline void __mnt_make_longterm(struct vfsmount *mnt) @@ -1446,7 +1446,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, goto Enomem; br_write_lock(vfsmount_lock); list_add_tail(&q->mnt_list, &res->mnt_list); - attach_mnt(q, &path); + attach_mnt(real_mount(q), &path); br_write_unlock(vfsmount_lock); } } @@ -1612,8 +1612,8 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, set_mnt_shared(&p->mnt); } if (parent_path) { - detach_mnt(source_mnt, parent_path); - attach_mnt(source_mnt, path); + detach_mnt(real_mount(source_mnt), parent_path); + attach_mnt(real_mount(source_mnt), path); touch_mnt_namespace(parent_path->mnt->mnt_ns); } else { mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); @@ -2600,6 +2600,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, const char __user *, put_old) { struct path new, old, parent_path, root_parent, root; + struct mount *new_mnt, *root_mnt; int error; if (!capable(CAP_SYS_ADMIN)) @@ -2623,6 +2624,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, goto out3; error = -EINVAL; + new_mnt = real_mount(new.mnt); + root_mnt = real_mount(root.mnt); if (IS_MNT_SHARED(old.mnt) || IS_MNT_SHARED(new.mnt->mnt_parent) || IS_MNT_SHARED(root.mnt->mnt_parent)) @@ -2651,12 +2654,12 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, if (!is_path_reachable(old.mnt, old.dentry, &new)) goto out4; br_write_lock(vfsmount_lock); - detach_mnt(new.mnt, &parent_path); - detach_mnt(root.mnt, &root_parent); + detach_mnt(new_mnt, &parent_path); + detach_mnt(root_mnt, &root_parent); /* mount old root on put_old */ - attach_mnt(root.mnt, &old); + attach_mnt(root_mnt, &old); /* mount new_root on / */ - attach_mnt(new.mnt, &root_parent); + attach_mnt(new_mnt, &root_parent); touch_mnt_namespace(current->nsproxy->mnt_ns); br_write_unlock(vfsmount_lock); chroot_fs_refs(&root, &new); -- cgit v1.2.3 From 4b2619a571f9fbb46649f968eea284103734f718 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 19:47:15 -0500 Subject: vfs: spread struct mount - commit_tree Signed-off-by: Al Viro --- fs/namespace.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 444557e04b38..fad3b218679d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -609,16 +609,16 @@ static inline void __mnt_make_shortterm(struct vfsmount *mnt) /* * vfsmount lock must be held for write */ -static void commit_tree(struct vfsmount *mnt) +static void commit_tree(struct mount *mnt) { - struct vfsmount *parent = mnt->mnt_parent; + struct vfsmount *parent = mnt->mnt.mnt_parent; struct vfsmount *m; LIST_HEAD(head); struct mnt_namespace *n = parent->mnt_ns; - BUG_ON(parent == mnt); + BUG_ON(parent == &mnt->mnt); - list_add_tail(&head, &mnt->mnt_list); + list_add_tail(&head, &mnt->mnt.mnt_list); list_for_each_entry(m, &head, mnt_list) { m->mnt_ns = n; __mnt_make_longterm(m); @@ -626,9 +626,9 @@ static void commit_tree(struct vfsmount *mnt) list_splice(&head, n->list.prev); - list_add_tail(&mnt->mnt_hash, mount_hashtable + - hash(parent, mnt->mnt_mountpoint)); - list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); + list_add_tail(&mnt->mnt.mnt_hash, mount_hashtable + + hash(parent, mnt->mnt.mnt_mountpoint)); + list_add_tail(&mnt->mnt.mnt_child, &parent->mnt_mounts); touch_mnt_namespace(n); } @@ -1617,12 +1617,12 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, touch_mnt_namespace(parent_path->mnt->mnt_ns); } else { mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); - commit_tree(source_mnt); + commit_tree(real_mount(source_mnt)); } list_for_each_entry_safe(child, p, &tree_list, mnt.mnt_hash) { list_del_init(&child->mnt.mnt_hash); - commit_tree(&child->mnt); + commit_tree(child); } br_write_unlock(vfsmount_lock); -- cgit v1.2.3 From 4b8b21f4fe16ee15eec5c69ea5fb41b30e428e59 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 19:54:23 -0500 Subject: vfs: spread struct mount - mount group id handling Signed-off-by: Al Viro --- fs/namespace.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index fad3b218679d..60d5c15c0879 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -110,7 +110,7 @@ static void mnt_free_id(struct vfsmount *mnt) * * mnt_group_ida is protected by namespace_sem */ -static int mnt_alloc_group_id(struct vfsmount *mnt) +static int mnt_alloc_group_id(struct mount *mnt) { int res; @@ -119,9 +119,9 @@ static int mnt_alloc_group_id(struct vfsmount *mnt) res = ida_get_new_above(&mnt_group_ida, mnt_group_start, - &mnt->mnt_group_id); + &mnt->mnt.mnt_group_id); if (!res) - mnt_group_start = mnt->mnt_group_id + 1; + mnt_group_start = mnt->mnt.mnt_group_id + 1; return res; } @@ -129,13 +129,13 @@ static int mnt_alloc_group_id(struct vfsmount *mnt) /* * Release a peer group ID */ -void mnt_release_group_id(struct vfsmount *mnt) +void mnt_release_group_id(struct mount *mnt) { - int id = mnt->mnt_group_id; + int id = mnt->mnt.mnt_group_id; ida_remove(&mnt_group_ida, id); if (mnt_group_start > id) mnt_group_start = id; - mnt->mnt_group_id = 0; + mnt->mnt.mnt_group_id = 0; } /* @@ -701,7 +701,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, mnt->mnt_group_id = old->mnt_group_id; if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) { - int err = mnt_alloc_group_id(mnt); + int err = mnt_alloc_group_id(real_mount(mnt)); if (err) goto out_free; } @@ -1497,25 +1497,25 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, return 0; } -static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) +static void cleanup_group_ids(struct mount *mnt, struct mount *end) { struct mount *p; - for (p = real_mount(mnt); &p->mnt != end; p = next_mnt(p, mnt)) { + for (p = mnt; p != end; p = next_mnt(p, &mnt->mnt)) { if (p->mnt.mnt_group_id && !IS_MNT_SHARED(&p->mnt)) - mnt_release_group_id(&p->mnt); + mnt_release_group_id(p); } } -static int invent_group_ids(struct vfsmount *mnt, bool recurse) +static int invent_group_ids(struct mount *mnt, bool recurse) { struct mount *p; - for (p = real_mount(mnt); p; p = recurse ? next_mnt(p, mnt) : NULL) { + for (p = mnt; p; p = recurse ? next_mnt(p, &mnt->mnt) : NULL) { if (!p->mnt.mnt_group_id && !IS_MNT_SHARED(&p->mnt)) { - int err = mnt_alloc_group_id(&p->mnt); + int err = mnt_alloc_group_id(p); if (err) { - cleanup_group_ids(mnt, &p->mnt); + cleanup_group_ids(mnt, p); return err; } } @@ -1597,7 +1597,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, int err; if (IS_MNT_SHARED(dest_mnt)) { - err = invent_group_ids(source_mnt, true); + err = invent_group_ids(real_mount(source_mnt), true); if (err) goto out; } @@ -1630,7 +1630,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, out_cleanup_ids: if (IS_MNT_SHARED(dest_mnt)) - cleanup_group_ids(source_mnt, NULL); + cleanup_group_ids(real_mount(source_mnt), NULL); out: return err; } @@ -1700,7 +1700,7 @@ static int flags_to_propagation_type(int flags) static int do_change_type(struct path *path, int flag) { struct mount *m; - struct vfsmount *mnt = path->mnt; + struct mount *mnt = real_mount(path->mnt); int recurse = flag & MS_REC; int type; int err = 0; @@ -1723,7 +1723,7 @@ static int do_change_type(struct path *path, int flag) } br_write_lock(vfsmount_lock); - for (m = real_mount(mnt); m; m = (recurse ? next_mnt(m, mnt) : NULL)) + for (m = mnt; m; m = (recurse ? next_mnt(m, &mnt->mnt) : NULL)) change_mnt_propagation(&m->mnt, type); br_write_unlock(vfsmount_lock); -- cgit v1.2.3 From 0fb54e50562d8d6f4b1a4517ba9783a9c7c5c2b7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 19:59:16 -0500 Subject: vfs: spread struct mount - attach_recursive_mnt Signed-off-by: Al Viro --- fs/namespace.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 60d5c15c0879..64ae40c91079 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1587,7 +1587,7 @@ static int invent_group_ids(struct mount *mnt, bool recurse) * Must be called without spinlocks held, since this function can sleep * in allocations. */ -static int attach_recursive_mnt(struct vfsmount *source_mnt, +static int attach_recursive_mnt(struct mount *source_mnt, struct path *path, struct path *parent_path) { LIST_HEAD(tree_list); @@ -1597,27 +1597,27 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, int err; if (IS_MNT_SHARED(dest_mnt)) { - err = invent_group_ids(real_mount(source_mnt), true); + err = invent_group_ids(source_mnt, true); if (err) goto out; } - err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list); + err = propagate_mnt(dest_mnt, dest_dentry, &source_mnt->mnt, &tree_list); if (err) goto out_cleanup_ids; br_write_lock(vfsmount_lock); if (IS_MNT_SHARED(dest_mnt)) { - for (p = real_mount(source_mnt); p; p = next_mnt(p, source_mnt)) + for (p = source_mnt; p; p = next_mnt(p, &source_mnt->mnt)) set_mnt_shared(&p->mnt); } if (parent_path) { - detach_mnt(real_mount(source_mnt), parent_path); - attach_mnt(real_mount(source_mnt), path); + detach_mnt(source_mnt, parent_path); + attach_mnt(source_mnt, path); touch_mnt_namespace(parent_path->mnt->mnt_ns); } else { - mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); - commit_tree(real_mount(source_mnt)); + mnt_set_mountpoint(dest_mnt, dest_dentry, &source_mnt->mnt); + commit_tree(source_mnt); } list_for_each_entry_safe(child, p, &tree_list, mnt.mnt_hash) { @@ -1630,7 +1630,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, out_cleanup_ids: if (IS_MNT_SHARED(dest_mnt)) - cleanup_group_ids(real_mount(source_mnt), NULL); + cleanup_group_ids(source_mnt, NULL); out: return err; } @@ -1674,7 +1674,7 @@ static int graft_tree(struct vfsmount *mnt, struct path *path) if (d_unlinked(path->dentry)) return -ENOENT; - return attach_recursive_mnt(mnt, path, NULL); + return attach_recursive_mnt(real_mount(mnt), path, NULL); } /* @@ -1859,6 +1859,7 @@ static int do_move_mount(struct path *path, char *old_name) { struct path old_path, parent_path; struct vfsmount *p; + struct mount *old; int err = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1883,6 +1884,8 @@ static int do_move_mount(struct path *path, char *old_name) if (old_path.dentry != old_path.mnt->mnt_root) goto out1; + old = real_mount(old_path.mnt); + if (!mnt_has_parent(old_path.mnt)) goto out1; @@ -1906,7 +1909,7 @@ static int do_move_mount(struct path *path, char *old_name) if (p == old_path.mnt) goto out1; - err = attach_recursive_mnt(old_path.mnt, path, &parent_path); + err = attach_recursive_mnt(old, path, &parent_path); if (err) goto out1; -- cgit v1.2.3 From cbbe362cd68441edf1ebbafeea1c8e09cce4a7f9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 20:01:19 -0500 Subject: vfs: spread struct mount - tree_contains_unbindable Signed-off-by: Al Viro --- fs/namespace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 64ae40c91079..91bd15d9b2cd 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1845,10 +1845,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags, return err; } -static inline int tree_contains_unbindable(struct vfsmount *mnt) +static inline int tree_contains_unbindable(struct mount *mnt) { struct mount *p; - for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) { + for (p = mnt; p; p = next_mnt(p, &mnt->mnt)) { if (IS_MNT_UNBINDABLE(&p->mnt)) return 1; } @@ -1902,7 +1902,7 @@ static int do_move_mount(struct path *path, char *old_name) * mount which is shared. */ if (IS_MNT_SHARED(path->mnt) && - tree_contains_unbindable(old_path.mnt)) + tree_contains_unbindable(old)) goto out1; err = -ELOOP; for (p = path->mnt; mnt_has_parent(p); p = p->mnt_parent) -- cgit v1.2.3 From b105e270b4e9419f4b9536f6862b1b32985bc9d2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 20:38:33 -0500 Subject: vfs: spread struct mount - alloc_vfsmnt/free_vfsmnt/mnt_alloc_id/mnt_free_id Signed-off-by: Al Viro --- fs/namespace.c | 81 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 41 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 91bd15d9b2cd..98b49351fbde 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -78,16 +78,16 @@ static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) * allocation is serialized by namespace_sem, but we need the spinlock to * serialize with freeing. */ -static int mnt_alloc_id(struct vfsmount *mnt) +static int mnt_alloc_id(struct mount *mnt) { int res; retry: ida_pre_get(&mnt_id_ida, GFP_KERNEL); spin_lock(&mnt_id_lock); - res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id); + res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt.mnt_id); if (!res) - mnt_id_start = mnt->mnt_id + 1; + mnt_id_start = mnt->mnt.mnt_id + 1; spin_unlock(&mnt_id_lock); if (res == -EAGAIN) goto retry; @@ -95,9 +95,9 @@ retry: return res; } -static void mnt_free_id(struct vfsmount *mnt) +static void mnt_free_id(struct mount *mnt) { - int id = mnt->mnt_id; + int id = mnt->mnt.mnt_id; spin_lock(&mnt_id_lock); ida_remove(&mnt_id_ida, id); if (mnt_id_start > id) @@ -171,14 +171,14 @@ unsigned int mnt_get_count(struct vfsmount *mnt) #endif } -static struct vfsmount *alloc_vfsmnt(const char *name) +static struct mount *alloc_vfsmnt(const char *name) { struct mount *p = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); if (p) { struct vfsmount *mnt = &p->mnt; int err; - err = mnt_alloc_id(mnt); + err = mnt_alloc_id(p); if (err) goto out_free_cache; @@ -211,14 +211,14 @@ static struct vfsmount *alloc_vfsmnt(const char *name) INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); #endif } - return &p->mnt; + return p; #ifdef CONFIG_SMP out_free_devname: kfree(p->mnt.mnt_devname); #endif out_free_id: - mnt_free_id(&p->mnt); + mnt_free_id(p); out_free_cache: kmem_cache_free(mnt_cache, p); return NULL; @@ -448,15 +448,14 @@ static void __mnt_unmake_readonly(struct vfsmount *mnt) br_write_unlock(vfsmount_lock); } -static void free_vfsmnt(struct vfsmount *mnt) +static void free_vfsmnt(struct mount *mnt) { - struct mount *p = real_mount(mnt); - kfree(mnt->mnt_devname); + kfree(mnt->mnt.mnt_devname); mnt_free_id(mnt); #ifdef CONFIG_SMP - free_percpu(mnt->mnt_pcp); + free_percpu(mnt->mnt.mnt_pcp); #endif - kmem_cache_free(mnt_cache, p); + kmem_cache_free(mnt_cache, mnt); } /* @@ -661,7 +660,7 @@ static struct mount *skip_mnt_tree(struct mount *p) struct vfsmount * vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) { - struct vfsmount *mnt; + struct mount *mnt; struct dentry *root; if (!type) @@ -672,7 +671,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void return ERR_PTR(-ENOMEM); if (flags & MS_KERNMOUNT) - mnt->mnt_flags = MNT_INTERNAL; + mnt->mnt.mnt_flags = MNT_INTERNAL; root = mount_fs(type, flags, name, data); if (IS_ERR(root)) { @@ -680,11 +679,11 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void return ERR_CAST(root); } - mnt->mnt_root = root; - mnt->mnt_sb = root->d_sb; - mnt->mnt_mountpoint = mnt->mnt_root; - mnt->mnt_parent = mnt; - return mnt; + mnt->mnt.mnt_root = root; + mnt->mnt.mnt_sb = root->d_sb; + mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; + mnt->mnt.mnt_parent = &mnt->mnt; + return &mnt->mnt; } EXPORT_SYMBOL_GPL(vfs_kern_mount); @@ -692,49 +691,49 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, int flag) { struct super_block *sb = old->mnt_sb; - struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname); + struct mount *mnt = alloc_vfsmnt(old->mnt_devname); if (mnt) { if (flag & (CL_SLAVE | CL_PRIVATE)) - mnt->mnt_group_id = 0; /* not a peer of original */ + mnt->mnt.mnt_group_id = 0; /* not a peer of original */ else - mnt->mnt_group_id = old->mnt_group_id; + mnt->mnt.mnt_group_id = old->mnt_group_id; - if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) { - int err = mnt_alloc_group_id(real_mount(mnt)); + if ((flag & CL_MAKE_SHARED) && !mnt->mnt.mnt_group_id) { + int err = mnt_alloc_group_id(mnt); if (err) goto out_free; } - mnt->mnt_flags = old->mnt_flags & ~MNT_WRITE_HOLD; + mnt->mnt.mnt_flags = old->mnt_flags & ~MNT_WRITE_HOLD; atomic_inc(&sb->s_active); - mnt->mnt_sb = sb; - mnt->mnt_root = dget(root); - mnt->mnt_mountpoint = mnt->mnt_root; - mnt->mnt_parent = mnt; + mnt->mnt.mnt_sb = sb; + mnt->mnt.mnt_root = dget(root); + mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; + mnt->mnt.mnt_parent = &mnt->mnt; if (flag & CL_SLAVE) { - list_add(&mnt->mnt_slave, &old->mnt_slave_list); - mnt->mnt_master = old; - CLEAR_MNT_SHARED(mnt); + list_add(&mnt->mnt.mnt_slave, &old->mnt_slave_list); + mnt->mnt.mnt_master = old; + CLEAR_MNT_SHARED(&mnt->mnt); } else if (!(flag & CL_PRIVATE)) { if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old)) - list_add(&mnt->mnt_share, &old->mnt_share); + list_add(&mnt->mnt.mnt_share, &old->mnt_share); if (IS_MNT_SLAVE(old)) - list_add(&mnt->mnt_slave, &old->mnt_slave); - mnt->mnt_master = old->mnt_master; + list_add(&mnt->mnt.mnt_slave, &old->mnt_slave); + mnt->mnt.mnt_master = old->mnt_master; } if (flag & CL_MAKE_SHARED) - set_mnt_shared(mnt); + set_mnt_shared(&mnt->mnt); /* stick the duplicate mount on the same expiry list * as the original if that was on one */ if (flag & CL_EXPIRE) { if (!list_empty(&old->mnt_expire)) - list_add(&mnt->mnt_expire, &old->mnt_expire); + list_add(&mnt->mnt.mnt_expire, &old->mnt_expire); } } - return mnt; + return &mnt->mnt; out_free: free_vfsmnt(mnt); @@ -758,7 +757,7 @@ static inline void mntfree(struct vfsmount *mnt) WARN_ON(mnt_get_writers(mnt)); fsnotify_vfsmount_delete(mnt); dput(mnt->mnt_root); - free_vfsmnt(mnt); + free_vfsmnt(real_mount(mnt)); deactivate_super(sb); } -- cgit v1.2.3 From 0f0afb1dcf01afc44581b3c0da251ac07dfb6e4a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 20:43:10 -0500 Subject: vfs: spread struct mount - change_mnt_propagation/set_mnt_shared Signed-off-by: Al Viro --- fs/namespace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 98b49351fbde..c7fa75f0fd92 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -724,7 +724,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, mnt->mnt.mnt_master = old->mnt_master; } if (flag & CL_MAKE_SHARED) - set_mnt_shared(&mnt->mnt); + set_mnt_shared(mnt); /* stick the duplicate mount on the same expiry list * as the original if that was on one */ @@ -1239,7 +1239,7 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) p->mnt.mnt_parent->mnt_ghosts++; dentry_reset_mounted(p->mnt.mnt_mountpoint); } - change_mnt_propagation(&p->mnt, MS_PRIVATE); + change_mnt_propagation(p, MS_PRIVATE); } list_splice(&tmp_list, kill); } @@ -1608,7 +1608,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, if (IS_MNT_SHARED(dest_mnt)) { for (p = source_mnt; p; p = next_mnt(p, &source_mnt->mnt)) - set_mnt_shared(&p->mnt); + set_mnt_shared(p); } if (parent_path) { detach_mnt(source_mnt, parent_path); @@ -1723,7 +1723,7 @@ static int do_change_type(struct path *path, int flag) br_write_lock(vfsmount_lock); for (m = mnt; m; m = (recurse ? next_mnt(m, &mnt->mnt) : NULL)) - change_mnt_propagation(&m->mnt, type); + change_mnt_propagation(m, type); br_write_unlock(vfsmount_lock); out_unlock: -- cgit v1.2.3 From cb338d06e9716c92d5a7855e7c67b8f111ced722 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 20:55:08 -0500 Subject: vfs: spread struct mount - clone_mnt/copy_tree result Signed-off-by: Al Viro --- fs/namespace.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index c7fa75f0fd92..6051a034db96 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -687,7 +687,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void } EXPORT_SYMBOL_GPL(vfs_kern_mount); -static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, +static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, int flag) { struct super_block *sb = old->mnt_sb; @@ -733,7 +733,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, list_add(&mnt->mnt.mnt_expire, &old->mnt_expire); } } - return &mnt->mnt; + return mnt; out_free: free_vfsmnt(mnt); @@ -1408,10 +1408,11 @@ static int mount_is_safe(struct path *path) #endif } -struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, +struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, int flag) { - struct vfsmount *res, *p, *q, *r; + struct mount *res, *q; + struct vfsmount *p, *r; struct path path; if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) @@ -1420,7 +1421,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, res = q = clone_mnt(mnt, dentry, flag); if (!q) goto Enomem; - q->mnt_mountpoint = mnt->mnt_mountpoint; + q->mnt.mnt_mountpoint = mnt->mnt_mountpoint; p = mnt; list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { @@ -1435,17 +1436,17 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, } while (p != s->mnt.mnt_parent) { p = p->mnt_parent; - q = q->mnt_parent; + q = real_mount(q->mnt.mnt_parent); } p = &s->mnt; - path.mnt = q; + path.mnt = &q->mnt; path.dentry = p->mnt_mountpoint; q = clone_mnt(p, p->mnt_root, flag); if (!q) goto Enomem; br_write_lock(vfsmount_lock); - list_add_tail(&q->mnt_list, &res->mnt_list); - attach_mnt(real_mount(q), &path); + list_add_tail(&q->mnt.mnt_list, &res->mnt.mnt_list); + attach_mnt(q, &path); br_write_unlock(vfsmount_lock); } } @@ -1454,7 +1455,7 @@ Enomem: if (res) { LIST_HEAD(umount_list); br_write_lock(vfsmount_lock); - umount_tree(res, 0, &umount_list); + umount_tree(&res->mnt, 0, &umount_list); br_write_unlock(vfsmount_lock); release_mounts(&umount_list); } @@ -1463,11 +1464,11 @@ Enomem: struct vfsmount *collect_mounts(struct path *path) { - struct vfsmount *tree; + struct mount *tree; down_write(&namespace_sem); tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE); up_write(&namespace_sem); - return tree; + return tree ? &tree->mnt : NULL; } void drop_collected_mounts(struct vfsmount *mnt) @@ -1739,7 +1740,7 @@ static int do_loopback(struct path *path, char *old_name, { LIST_HEAD(umount_list); struct path old_path; - struct vfsmount *mnt = NULL; + struct mount *mnt = NULL; int err = mount_is_safe(path); if (err) return err; @@ -1769,10 +1770,10 @@ static int do_loopback(struct path *path, char *old_name, if (!mnt) goto out2; - err = graft_tree(mnt, path); + err = graft_tree(&mnt->mnt, path); if (err) { br_write_lock(vfsmount_lock); - umount_tree(mnt, 0, &umount_list); + umount_tree(&mnt->mnt, 0, &umount_list); br_write_unlock(vfsmount_lock); } out2: @@ -2385,6 +2386,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, struct mnt_namespace *new_ns; struct vfsmount *rootmnt = NULL, *pwdmnt = NULL; struct mount *p, *q; + struct mount *new; new_ns = alloc_mnt_ns(); if (IS_ERR(new_ns)) @@ -2392,13 +2394,14 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, down_write(&namespace_sem); /* First pass: copy the tree topology */ - new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, + new = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, CL_COPY_ALL | CL_EXPIRE); - if (!new_ns->root) { + if (!new) { up_write(&namespace_sem); kfree(new_ns); return ERR_PTR(-ENOMEM); } + new_ns->root = &new->mnt; br_write_lock(vfsmount_lock); list_add_tail(&new_ns->list, &new_ns->root->mnt_list); br_write_unlock(vfsmount_lock); @@ -2409,7 +2412,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, * fs_struct, so tsk->fs->lock is not needed. */ p = real_mount(mnt_ns->root); - q = real_mount(new_ns->root); + q = new; while (p) { q->mnt.mnt_ns = new_ns; __mnt_make_longterm(&q->mnt); -- cgit v1.2.3 From d5e50f74dd2ed6dd1bb4bf6fe58e5a7de4b77953 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 20:58:57 -0500 Subject: vfs: spread struct mount to remaining users of ->mnt_hash Signed-off-by: Al Viro --- fs/namespace.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 6051a034db96..76412348d5be 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -199,7 +199,7 @@ static struct mount *alloc_vfsmnt(const char *name) mnt->mnt_writers = 0; #endif - INIT_LIST_HEAD(&mnt->mnt_hash); + INIT_LIST_HEAD(&p->mnt.mnt_hash); INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); @@ -540,10 +540,10 @@ static void dentry_reset_mounted(struct dentry *dentry) unsigned u; for (u = 0; u < HASH_SIZE; u++) { - struct vfsmount *p; + struct mount *p; - list_for_each_entry(p, &mount_hashtable[u], mnt_hash) { - if (p->mnt_mountpoint == dentry) + list_for_each_entry(p, &mount_hashtable[u], mnt.mnt_hash) { + if (p->mnt.mnt_mountpoint == dentry) return; } } @@ -1191,25 +1191,25 @@ EXPORT_SYMBOL(may_umount); void release_mounts(struct list_head *head) { - struct vfsmount *mnt; + struct mount *mnt; while (!list_empty(head)) { - mnt = list_first_entry(head, struct vfsmount, mnt_hash); - list_del_init(&mnt->mnt_hash); - if (mnt_has_parent(mnt)) { + mnt = list_first_entry(head, struct mount, mnt.mnt_hash); + list_del_init(&mnt->mnt.mnt_hash); + if (mnt_has_parent(&mnt->mnt)) { struct dentry *dentry; struct vfsmount *m; br_write_lock(vfsmount_lock); - dentry = mnt->mnt_mountpoint; - m = mnt->mnt_parent; - mnt->mnt_mountpoint = mnt->mnt_root; - mnt->mnt_parent = mnt; + dentry = mnt->mnt.mnt_mountpoint; + m = mnt->mnt.mnt_parent; + mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; + mnt->mnt.mnt_parent = &mnt->mnt; m->mnt_ghosts--; br_write_unlock(vfsmount_lock); dput(dentry); mntput(m); } - mntput(mnt); + mntput(&mnt->mnt); } } -- cgit v1.2.3 From 1b8e5564b9d34cbeb3047dd2be8ec9cd5e2785e2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 21:01:32 -0500 Subject: vfs: the first spoils - mnt_hash moved taken out of struct vfsmount into struct mount Signed-off-by: Al Viro --- fs/namespace.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 76412348d5be..121e0032c9de 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -199,7 +199,7 @@ static struct mount *alloc_vfsmnt(const char *name) mnt->mnt_writers = 0; #endif - INIT_LIST_HEAD(&p->mnt.mnt_hash); + INIT_LIST_HEAD(&p->mnt_hash); INIT_LIST_HEAD(&mnt->mnt_child); INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); @@ -475,7 +475,7 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, p = NULL; if (tmp == head) break; - p = list_entry(tmp, struct mount, mnt.mnt_hash); + p = list_entry(tmp, struct mount, mnt_hash); if (p->mnt.mnt_parent == mnt && p->mnt.mnt_mountpoint == dentry) { found = p; break; @@ -542,7 +542,7 @@ static void dentry_reset_mounted(struct dentry *dentry) for (u = 0; u < HASH_SIZE; u++) { struct mount *p; - list_for_each_entry(p, &mount_hashtable[u], mnt.mnt_hash) { + list_for_each_entry(p, &mount_hashtable[u], mnt_hash) { if (p->mnt.mnt_mountpoint == dentry) return; } @@ -562,7 +562,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) mnt->mnt.mnt_parent = &mnt->mnt; mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; list_del_init(&mnt->mnt.mnt_child); - list_del_init(&mnt->mnt.mnt_hash); + list_del_init(&mnt->mnt_hash); dentry_reset_mounted(old_path->dentry); } @@ -585,7 +585,7 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, static void attach_mnt(struct mount *mnt, struct path *path) { mnt_set_mountpoint(path->mnt, path->dentry, &mnt->mnt); - list_add_tail(&mnt->mnt.mnt_hash, mount_hashtable + + list_add_tail(&mnt->mnt_hash, mount_hashtable + hash(path->mnt, path->dentry)); list_add_tail(&mnt->mnt.mnt_child, &path->mnt->mnt_mounts); } @@ -625,7 +625,7 @@ static void commit_tree(struct mount *mnt) list_splice(&head, n->list.prev); - list_add_tail(&mnt->mnt.mnt_hash, mount_hashtable + + list_add_tail(&mnt->mnt_hash, mount_hashtable + hash(parent, mnt->mnt.mnt_mountpoint)); list_add_tail(&mnt->mnt.mnt_child, &parent->mnt_mounts); touch_mnt_namespace(n); @@ -1193,8 +1193,8 @@ void release_mounts(struct list_head *head) { struct mount *mnt; while (!list_empty(head)) { - mnt = list_first_entry(head, struct mount, mnt.mnt_hash); - list_del_init(&mnt->mnt.mnt_hash); + mnt = list_first_entry(head, struct mount, mnt_hash); + list_del_init(&mnt->mnt_hash); if (mnt_has_parent(&mnt->mnt)) { struct dentry *dentry; struct vfsmount *m; @@ -1223,12 +1223,12 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) struct mount *p; for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) - list_move(&p->mnt.mnt_hash, &tmp_list); + list_move(&p->mnt_hash, &tmp_list); if (propagate) propagate_umount(&tmp_list); - list_for_each_entry(p, &tmp_list, mnt.mnt_hash) { + list_for_each_entry(p, &tmp_list, mnt_hash) { list_del_init(&p->mnt.mnt_expire); list_del_init(&p->mnt.mnt_list); __touch_mnt_namespace(p->mnt.mnt_ns); @@ -1620,8 +1620,8 @@ static int attach_recursive_mnt(struct mount *source_mnt, commit_tree(source_mnt); } - list_for_each_entry_safe(child, p, &tree_list, mnt.mnt_hash) { - list_del_init(&child->mnt.mnt_hash); + list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { + list_del_init(&child->mnt_hash); commit_tree(child); } br_write_unlock(vfsmount_lock); -- cgit v1.2.3 From 761d5c38eb3d8e2aa7394726dccab245bfe2f41c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 21:07:43 -0500 Subject: vfs: spread struct mount - umount_tree argument Signed-off-by: Al Viro --- fs/namespace.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 121e0032c9de..5bb40c52b2af 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1217,12 +1217,12 @@ void release_mounts(struct list_head *head) * vfsmount lock must be held for write * namespace_sem must be held for write */ -void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) +void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) { LIST_HEAD(tmp_list); struct mount *p; - for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) + for (p = mnt; p; p = next_mnt(p, &mnt->mnt)) list_move(&p->mnt_hash, &tmp_list); if (propagate) @@ -1327,7 +1327,7 @@ static int do_umount(struct vfsmount *mnt, int flags) retval = -EBUSY; if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { if (!list_empty(&mnt->mnt_list)) - umount_tree(mnt, 1, &umount_list); + umount_tree(real_mount(mnt), 1, &umount_list); retval = 0; } br_write_unlock(vfsmount_lock); @@ -1455,7 +1455,7 @@ Enomem: if (res) { LIST_HEAD(umount_list); br_write_lock(vfsmount_lock); - umount_tree(&res->mnt, 0, &umount_list); + umount_tree(res, 0, &umount_list); br_write_unlock(vfsmount_lock); release_mounts(&umount_list); } @@ -1476,7 +1476,7 @@ void drop_collected_mounts(struct vfsmount *mnt) LIST_HEAD(umount_list); down_write(&namespace_sem); br_write_lock(vfsmount_lock); - umount_tree(mnt, 0, &umount_list); + umount_tree(real_mount(mnt), 0, &umount_list); br_write_unlock(vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); @@ -1773,7 +1773,7 @@ static int do_loopback(struct path *path, char *old_name, err = graft_tree(&mnt->mnt, path); if (err) { br_write_lock(vfsmount_lock); - umount_tree(&mnt->mnt, 0, &umount_list); + umount_tree(mnt, 0, &umount_list); br_write_unlock(vfsmount_lock); } out2: @@ -2080,7 +2080,7 @@ EXPORT_SYMBOL(mnt_set_expiry); */ void mark_mounts_for_expiry(struct list_head *mounts) { - struct vfsmount *mnt, *next; + struct mount *mnt, *next; LIST_HEAD(graveyard); LIST_HEAD(umounts); @@ -2096,15 +2096,15 @@ void mark_mounts_for_expiry(struct list_head *mounts) * - still marked for expiry (marked on the last call here; marks are * cleared by mntput()) */ - list_for_each_entry_safe(mnt, next, mounts, mnt_expire) { - if (!xchg(&mnt->mnt_expiry_mark, 1) || - propagate_mount_busy(mnt, 1)) + list_for_each_entry_safe(mnt, next, mounts, mnt.mnt_expire) { + if (!xchg(&mnt->mnt.mnt_expiry_mark, 1) || + propagate_mount_busy(&mnt->mnt, 1)) continue; - list_move(&mnt->mnt_expire, &graveyard); + list_move(&mnt->mnt.mnt_expire, &graveyard); } while (!list_empty(&graveyard)) { - mnt = list_first_entry(&graveyard, struct vfsmount, mnt_expire); - touch_mnt_namespace(mnt->mnt_ns); + mnt = list_first_entry(&graveyard, struct mount, mnt.mnt_expire); + touch_mnt_namespace(mnt->mnt.mnt_ns); umount_tree(mnt, 1, &umounts); } br_write_unlock(vfsmount_lock); @@ -2170,14 +2170,14 @@ resume: static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts) { LIST_HEAD(graveyard); - struct vfsmount *m; + struct mount *m; /* extract submounts of 'mountpoint' from the expiration list */ while (select_submounts(mnt, &graveyard)) { while (!list_empty(&graveyard)) { - m = list_first_entry(&graveyard, struct vfsmount, - mnt_expire); - touch_mnt_namespace(m->mnt_ns); + m = list_first_entry(&graveyard, struct mount, + mnt.mnt_expire); + touch_mnt_namespace(m->mnt.mnt_ns); umount_tree(m, 1, umounts); } } @@ -2750,7 +2750,7 @@ void put_mnt_ns(struct mnt_namespace *ns) return; down_write(&namespace_sem); br_write_lock(vfsmount_lock); - umount_tree(ns->root, 0, &umount_list); + umount_tree(real_mount(ns->root), 0, &umount_list); br_write_unlock(vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); -- cgit v1.2.3 From 692afc312b38c9367a1125927941d33ab2ce852a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 21:15:14 -0500 Subject: vfs: spread struct mount - shrink_submounts/select_submounts Signed-off-by: Al Viro --- fs/namespace.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 5bb40c52b2af..fa0f30d862c6 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1244,7 +1244,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) list_splice(&tmp_list, kill); } -static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts); +static void shrink_submounts(struct mount *mnt, struct list_head *umounts); static int do_umount(struct vfsmount *mnt, int flags) { @@ -1322,7 +1322,7 @@ static int do_umount(struct vfsmount *mnt, int flags) event++; if (!(flags & MNT_DETACH)) - shrink_submounts(mnt, &umount_list); + shrink_submounts(real_mount(mnt), &umount_list); retval = -EBUSY; if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { @@ -2121,32 +2121,32 @@ EXPORT_SYMBOL_GPL(mark_mounts_for_expiry); * search the list of submounts for a given mountpoint, and move any * shrinkable submounts to the 'graveyard' list. */ -static int select_submounts(struct vfsmount *parent, struct list_head *graveyard) +static int select_submounts(struct mount *parent, struct list_head *graveyard) { - struct vfsmount *this_parent = parent; + struct mount *this_parent = parent; struct list_head *next; int found = 0; repeat: - next = this_parent->mnt_mounts.next; + next = this_parent->mnt.mnt_mounts.next; resume: - while (next != &this_parent->mnt_mounts) { + while (next != &this_parent->mnt.mnt_mounts) { struct list_head *tmp = next; - struct vfsmount *mnt = list_entry(tmp, struct vfsmount, mnt_child); + struct mount *mnt = list_entry(tmp, struct mount, mnt.mnt_child); next = tmp->next; - if (!(mnt->mnt_flags & MNT_SHRINKABLE)) + if (!(mnt->mnt.mnt_flags & MNT_SHRINKABLE)) continue; /* * Descend a level if the d_mounts list is non-empty. */ - if (!list_empty(&mnt->mnt_mounts)) { + if (!list_empty(&mnt->mnt.mnt_mounts)) { this_parent = mnt; goto repeat; } - if (!propagate_mount_busy(mnt, 1)) { - list_move_tail(&mnt->mnt_expire, graveyard); + if (!propagate_mount_busy(&mnt->mnt, 1)) { + list_move_tail(&mnt->mnt.mnt_expire, graveyard); found++; } } @@ -2154,8 +2154,8 @@ resume: * All done at this level ... ascend and resume the search */ if (this_parent != parent) { - next = this_parent->mnt_child.next; - this_parent = this_parent->mnt_parent; + next = this_parent->mnt.mnt_child.next; + this_parent = real_mount(this_parent->mnt.mnt_parent); goto resume; } return found; @@ -2167,7 +2167,7 @@ resume: * * vfsmount_lock must be held for write */ -static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts) +static void shrink_submounts(struct mount *mnt, struct list_head *umounts) { LIST_HEAD(graveyard); struct mount *m; -- cgit v1.2.3 From 87129cc0e3fcd89a1db3e99d62dc710e05749f77 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 21:24:27 -0500 Subject: vfs: spread struct mount - clone_mnt/copy_tree argument Signed-off-by: Al Viro --- fs/namespace.c | 63 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 30 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index fa0f30d862c6..211455e2cd17 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -687,17 +687,17 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void } EXPORT_SYMBOL_GPL(vfs_kern_mount); -static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, +static struct mount *clone_mnt(struct mount *old, struct dentry *root, int flag) { - struct super_block *sb = old->mnt_sb; - struct mount *mnt = alloc_vfsmnt(old->mnt_devname); + struct super_block *sb = old->mnt.mnt_sb; + struct mount *mnt = alloc_vfsmnt(old->mnt.mnt_devname); if (mnt) { if (flag & (CL_SLAVE | CL_PRIVATE)) mnt->mnt.mnt_group_id = 0; /* not a peer of original */ else - mnt->mnt.mnt_group_id = old->mnt_group_id; + mnt->mnt.mnt_group_id = old->mnt.mnt_group_id; if ((flag & CL_MAKE_SHARED) && !mnt->mnt.mnt_group_id) { int err = mnt_alloc_group_id(mnt); @@ -705,7 +705,7 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, goto out_free; } - mnt->mnt.mnt_flags = old->mnt_flags & ~MNT_WRITE_HOLD; + mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD; atomic_inc(&sb->s_active); mnt->mnt.mnt_sb = sb; mnt->mnt.mnt_root = dget(root); @@ -713,15 +713,15 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, mnt->mnt.mnt_parent = &mnt->mnt; if (flag & CL_SLAVE) { - list_add(&mnt->mnt.mnt_slave, &old->mnt_slave_list); - mnt->mnt.mnt_master = old; + list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list); + mnt->mnt.mnt_master = &old->mnt; CLEAR_MNT_SHARED(&mnt->mnt); } else if (!(flag & CL_PRIVATE)) { - if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old)) - list_add(&mnt->mnt.mnt_share, &old->mnt_share); - if (IS_MNT_SLAVE(old)) - list_add(&mnt->mnt.mnt_slave, &old->mnt_slave); - mnt->mnt.mnt_master = old->mnt_master; + if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(&old->mnt)) + list_add(&mnt->mnt.mnt_share, &old->mnt.mnt_share); + if (IS_MNT_SLAVE(&old->mnt)) + list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave); + mnt->mnt.mnt_master = old->mnt.mnt_master; } if (flag & CL_MAKE_SHARED) set_mnt_shared(mnt); @@ -729,8 +729,8 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, /* stick the duplicate mount on the same expiry list * as the original if that was on one */ if (flag & CL_EXPIRE) { - if (!list_empty(&old->mnt_expire)) - list_add(&mnt->mnt.mnt_expire, &old->mnt_expire); + if (!list_empty(&old->mnt.mnt_expire)) + list_add(&mnt->mnt.mnt_expire, &old->mnt.mnt_expire); } } return mnt; @@ -1408,23 +1408,23 @@ static int mount_is_safe(struct path *path) #endif } -struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, +struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, int flag) { - struct mount *res, *q; - struct vfsmount *p, *r; + struct mount *res, *p, *q; + struct vfsmount *r; struct path path; - if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(&mnt->mnt)) return NULL; res = q = clone_mnt(mnt, dentry, flag); if (!q) goto Enomem; - q->mnt.mnt_mountpoint = mnt->mnt_mountpoint; + q->mnt.mnt_mountpoint = mnt->mnt.mnt_mountpoint; p = mnt; - list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { + list_for_each_entry(r, &mnt->mnt.mnt_mounts, mnt_child) { struct mount *s; if (!is_subdir(r->mnt_mountpoint, dentry)) continue; @@ -1434,14 +1434,14 @@ struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, s = skip_mnt_tree(s); continue; } - while (p != s->mnt.mnt_parent) { - p = p->mnt_parent; + while (p != real_mount(s->mnt.mnt_parent)) { + p = real_mount(p->mnt.mnt_parent); q = real_mount(q->mnt.mnt_parent); } - p = &s->mnt; + p = s; path.mnt = &q->mnt; - path.dentry = p->mnt_mountpoint; - q = clone_mnt(p, p->mnt_root, flag); + path.dentry = p->mnt.mnt_mountpoint; + q = clone_mnt(p, p->mnt.mnt_root, flag); if (!q) goto Enomem; br_write_lock(vfsmount_lock); @@ -1466,7 +1466,8 @@ struct vfsmount *collect_mounts(struct path *path) { struct mount *tree; down_write(&namespace_sem); - tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE); + tree = copy_tree(real_mount(path->mnt), path->dentry, + CL_COPY_ALL | CL_PRIVATE); up_write(&namespace_sem); return tree ? &tree->mnt : NULL; } @@ -1740,7 +1741,7 @@ static int do_loopback(struct path *path, char *old_name, { LIST_HEAD(umount_list); struct path old_path; - struct mount *mnt = NULL; + struct mount *mnt = NULL, *old; int err = mount_is_safe(path); if (err) return err; @@ -1754,6 +1755,8 @@ static int do_loopback(struct path *path, char *old_name, if (err) goto out; + old = real_mount(old_path.mnt); + err = -EINVAL; if (IS_MNT_UNBINDABLE(old_path.mnt)) goto out2; @@ -1763,9 +1766,9 @@ static int do_loopback(struct path *path, char *old_name, err = -ENOMEM; if (recurse) - mnt = copy_tree(old_path.mnt, old_path.dentry, 0); + mnt = copy_tree(old, old_path.dentry, 0); else - mnt = clone_mnt(old_path.mnt, old_path.dentry, 0); + mnt = clone_mnt(old, old_path.dentry, 0); if (!mnt) goto out2; @@ -2394,7 +2397,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, down_write(&namespace_sem); /* First pass: copy the tree topology */ - new = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, + new = copy_tree(real_mount(mnt_ns->root), mnt_ns->root->mnt_root, CL_COPY_ALL | CL_EXPIRE); if (!new) { up_write(&namespace_sem); -- cgit v1.2.3 From 44d964d609c7c11b330a3d1caf30767fa13c7be3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 21:28:22 -0500 Subject: vfs: spread struct mount mnt_set_mountpoint child argument Signed-off-by: Al Viro --- fs/namespace.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 211455e2cd17..c11b99af53cf 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -570,10 +570,10 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) * vfsmount lock must be held for write */ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, - struct vfsmount *child_mnt) + struct mount *child_mnt) { - child_mnt->mnt_parent = mntget(mnt); - child_mnt->mnt_mountpoint = dget(dentry); + child_mnt->mnt.mnt_parent = mntget(mnt); + child_mnt->mnt.mnt_mountpoint = dget(dentry); spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_MOUNTED; spin_unlock(&dentry->d_lock); @@ -584,7 +584,7 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, */ static void attach_mnt(struct mount *mnt, struct path *path) { - mnt_set_mountpoint(path->mnt, path->dentry, &mnt->mnt); + mnt_set_mountpoint(path->mnt, path->dentry, mnt); list_add_tail(&mnt->mnt_hash, mount_hashtable + hash(path->mnt, path->dentry)); list_add_tail(&mnt->mnt.mnt_child, &path->mnt->mnt_mounts); @@ -1617,7 +1617,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, attach_mnt(source_mnt, path); touch_mnt_namespace(parent_path->mnt->mnt_ns); } else { - mnt_set_mountpoint(dest_mnt, dest_dentry, &source_mnt->mnt); + mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); commit_tree(source_mnt); } -- cgit v1.2.3 From 1ab597386205f8dc757cf8750465502aeae65154 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 21:35:16 -0500 Subject: vfs: spread struct mount - do_umount/propagate_mount_busy Signed-off-by: Al Viro --- fs/namespace.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index c11b99af53cf..17927f9eeca4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1180,7 +1180,7 @@ int may_umount(struct vfsmount *mnt) int ret = 1; down_read(&namespace_sem); br_write_lock(vfsmount_lock); - if (propagate_mount_busy(mnt, 2)) + if (propagate_mount_busy(real_mount(mnt), 2)) ret = 0; br_write_unlock(vfsmount_lock); up_read(&namespace_sem); @@ -1246,13 +1246,13 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) static void shrink_submounts(struct mount *mnt, struct list_head *umounts); -static int do_umount(struct vfsmount *mnt, int flags) +static int do_umount(struct mount *mnt, int flags) { - struct super_block *sb = mnt->mnt_sb; + struct super_block *sb = mnt->mnt.mnt_sb; int retval; LIST_HEAD(umount_list); - retval = security_sb_umount(mnt, flags); + retval = security_sb_umount(&mnt->mnt, flags); if (retval) return retval; @@ -1263,7 +1263,7 @@ static int do_umount(struct vfsmount *mnt, int flags) * (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount] */ if (flags & MNT_EXPIRE) { - if (mnt == current->fs->root.mnt || + if (&mnt->mnt == current->fs->root.mnt || flags & (MNT_FORCE | MNT_DETACH)) return -EINVAL; @@ -1272,13 +1272,13 @@ static int do_umount(struct vfsmount *mnt, int flags) * all race cases, but it's a slowpath. */ br_write_lock(vfsmount_lock); - if (mnt_get_count(mnt) != 2) { + if (mnt_get_count(&mnt->mnt) != 2) { br_write_unlock(vfsmount_lock); return -EBUSY; } br_write_unlock(vfsmount_lock); - if (!xchg(&mnt->mnt_expiry_mark, 1)) + if (!xchg(&mnt->mnt.mnt_expiry_mark, 1)) return -EAGAIN; } @@ -1305,7 +1305,7 @@ static int do_umount(struct vfsmount *mnt, int flags) * /reboot - static binary that would close all descriptors and * call reboot(9). Then init(8) could umount root and exec /reboot. */ - if (mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) { + if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) { /* * Special case for "unmounting" root ... * we just try to remount it readonly. @@ -1322,12 +1322,12 @@ static int do_umount(struct vfsmount *mnt, int flags) event++; if (!(flags & MNT_DETACH)) - shrink_submounts(real_mount(mnt), &umount_list); + shrink_submounts(mnt, &umount_list); retval = -EBUSY; if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { - if (!list_empty(&mnt->mnt_list)) - umount_tree(real_mount(mnt), 1, &umount_list); + if (!list_empty(&mnt->mnt.mnt_list)) + umount_tree(mnt, 1, &umount_list); retval = 0; } br_write_unlock(vfsmount_lock); @@ -1369,7 +1369,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) if (!capable(CAP_SYS_ADMIN)) goto dput_and_out; - retval = do_umount(path.mnt, flags); + retval = do_umount(real_mount(path.mnt), flags); dput_and_out: /* we mustn't call path_put() as that would clear mnt_expiry_mark */ dput(path.dentry); @@ -2101,7 +2101,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) */ list_for_each_entry_safe(mnt, next, mounts, mnt.mnt_expire) { if (!xchg(&mnt->mnt.mnt_expiry_mark, 1) || - propagate_mount_busy(&mnt->mnt, 1)) + propagate_mount_busy(mnt, 1)) continue; list_move(&mnt->mnt.mnt_expire, &graveyard); } @@ -2148,7 +2148,7 @@ resume: goto repeat; } - if (!propagate_mount_busy(&mnt->mnt, 1)) { + if (!propagate_mount_busy(mnt, 1)) { list_move_tail(&mnt->mnt.mnt_expire, graveyard); found++; } -- cgit v1.2.3 From 676da58df740f325034b8641311413c2393588e1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 21:47:05 -0500 Subject: vfs: spread struct mount - mnt_has_parent Signed-off-by: Al Viro --- fs/namespace.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 17927f9eeca4..ced3aa53fb38 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1195,7 +1195,7 @@ void release_mounts(struct list_head *head) while (!list_empty(head)) { mnt = list_first_entry(head, struct mount, mnt_hash); list_del_init(&mnt->mnt_hash); - if (mnt_has_parent(&mnt->mnt)) { + if (mnt_has_parent(mnt)) { struct dentry *dentry; struct vfsmount *m; @@ -1235,7 +1235,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) p->mnt.mnt_ns = NULL; __mnt_make_shortterm(&p->mnt); list_del_init(&p->mnt.mnt_child); - if (mnt_has_parent(&p->mnt)) { + if (mnt_has_parent(p)) { p->mnt.mnt_parent->mnt_ghosts++; dentry_reset_mounted(p->mnt.mnt_mountpoint); } @@ -1861,7 +1861,7 @@ static inline int tree_contains_unbindable(struct mount *mnt) static int do_move_mount(struct path *path, char *old_name) { struct path old_path, parent_path; - struct vfsmount *p; + struct mount *p; struct mount *old; int err = 0; if (!capable(CAP_SYS_ADMIN)) @@ -1889,7 +1889,7 @@ static int do_move_mount(struct path *path, char *old_name) old = real_mount(old_path.mnt); - if (!mnt_has_parent(old_path.mnt)) + if (!mnt_has_parent(old)) goto out1; if (S_ISDIR(path->dentry->d_inode->i_mode) != @@ -1908,8 +1908,8 @@ static int do_move_mount(struct path *path, char *old_name) tree_contains_unbindable(old)) goto out1; err = -ELOOP; - for (p = path->mnt; mnt_has_parent(p); p = p->mnt_parent) - if (p == old_path.mnt) + for (p = real_mount(path->mnt); mnt_has_parent(p); p = real_mount(p->mnt.mnt_parent)) + if (p == old) goto out1; err = attach_recursive_mnt(old, path, &parent_path); @@ -2562,7 +2562,7 @@ out_type: bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry, const struct path *root) { - while (mnt != root->mnt && mnt_has_parent(mnt)) { + while (mnt != root->mnt && mnt_has_parent(real_mount(mnt))) { dentry = mnt->mnt_mountpoint; mnt = mnt->mnt_parent; } @@ -2652,11 +2652,11 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, error = -EINVAL; if (root.mnt->mnt_root != root.dentry) goto out4; /* not a mountpoint */ - if (!mnt_has_parent(root.mnt)) + if (!mnt_has_parent(root_mnt)) goto out4; /* not attached */ if (new.mnt->mnt_root != new.dentry) goto out4; /* not a mountpoint */ - if (!mnt_has_parent(new.mnt)) + if (!mnt_has_parent(new_mnt)) goto out4; /* not attached */ /* make sure we can reach put_old from new_root */ if (!is_path_reachable(old.mnt, old.dentry, &new)) -- cgit v1.2.3 From 643822b41e5e0f133438883b0be574cdaf168a2a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 22:00:28 -0500 Subject: vfs: spread struct mount - is_path_reachable Signed-off-by: Al Viro --- fs/namespace.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index ced3aa53fb38..b117d94fcdc1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2559,21 +2559,21 @@ out_type: * * namespace_sem or vfsmount_lock is held */ -bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry, +bool is_path_reachable(struct mount *mnt, struct dentry *dentry, const struct path *root) { - while (mnt != root->mnt && mnt_has_parent(real_mount(mnt))) { - dentry = mnt->mnt_mountpoint; - mnt = mnt->mnt_parent; + while (&mnt->mnt != root->mnt && mnt_has_parent(mnt)) { + dentry = mnt->mnt.mnt_mountpoint; + mnt = real_mount(mnt->mnt.mnt_parent); } - return mnt == root->mnt && is_subdir(dentry, root->dentry); + return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry); } int path_is_under(struct path *path1, struct path *path2) { int res; br_read_lock(vfsmount_lock); - res = is_path_reachable(path1->mnt, path1->dentry, path2); + res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2); br_read_unlock(vfsmount_lock); return res; } @@ -2659,7 +2659,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, if (!mnt_has_parent(new_mnt)) goto out4; /* not attached */ /* make sure we can reach put_old from new_root */ - if (!is_path_reachable(old.mnt, old.dentry, &new)) + if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new)) goto out4; br_write_lock(vfsmount_lock); detach_mnt(new_mnt, &parent_path); -- cgit v1.2.3 From 3376f34fff5be9954fd9a9c4fd68f4a0a36d480e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 22:05:19 -0500 Subject: vfs: mnt_parent moved to struct mount the second victim... Signed-off-by: Al Viro --- fs/namespace.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index b117d94fcdc1..c6384bc39db1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -476,7 +476,7 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, if (tmp == head) break; p = list_entry(tmp, struct mount, mnt_hash); - if (p->mnt.mnt_parent == mnt && p->mnt.mnt_mountpoint == dentry) { + if (p->mnt_parent == mnt && p->mnt.mnt_mountpoint == dentry) { found = p; break; } @@ -558,8 +558,8 @@ static void dentry_reset_mounted(struct dentry *dentry) static void detach_mnt(struct mount *mnt, struct path *old_path) { old_path->dentry = mnt->mnt.mnt_mountpoint; - old_path->mnt = mnt->mnt.mnt_parent; - mnt->mnt.mnt_parent = &mnt->mnt; + old_path->mnt = mnt->mnt_parent; + mnt->mnt_parent = &mnt->mnt; mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; list_del_init(&mnt->mnt.mnt_child); list_del_init(&mnt->mnt_hash); @@ -572,7 +572,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, struct mount *child_mnt) { - child_mnt->mnt.mnt_parent = mntget(mnt); + child_mnt->mnt_parent = mntget(mnt); child_mnt->mnt.mnt_mountpoint = dget(dentry); spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_MOUNTED; @@ -610,7 +610,7 @@ static inline void __mnt_make_shortterm(struct vfsmount *mnt) */ static void commit_tree(struct mount *mnt) { - struct vfsmount *parent = mnt->mnt.mnt_parent; + struct vfsmount *parent = mnt->mnt_parent; struct vfsmount *m; LIST_HEAD(head); struct mnt_namespace *n = parent->mnt_ns; @@ -639,9 +639,9 @@ static struct mount *next_mnt(struct mount *p, struct vfsmount *root) if (&p->mnt == root) return NULL; next = p->mnt.mnt_child.next; - if (next != &p->mnt.mnt_parent->mnt_mounts) + if (next != &p->mnt_parent->mnt_mounts) break; - p = real_mount(p->mnt.mnt_parent); + p = real_mount(p->mnt_parent); } } return list_entry(next, struct mount, mnt.mnt_child); @@ -682,7 +682,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void mnt->mnt.mnt_root = root; mnt->mnt.mnt_sb = root->d_sb; mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; - mnt->mnt.mnt_parent = &mnt->mnt; + mnt->mnt_parent = &mnt->mnt; return &mnt->mnt; } EXPORT_SYMBOL_GPL(vfs_kern_mount); @@ -710,7 +710,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, mnt->mnt.mnt_sb = sb; mnt->mnt.mnt_root = dget(root); mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; - mnt->mnt.mnt_parent = &mnt->mnt; + mnt->mnt_parent = &mnt->mnt; if (flag & CL_SLAVE) { list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list); @@ -1021,12 +1021,13 @@ static int show_mountinfo(struct seq_file *m, void *v) { struct proc_mounts *p = m->private; struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); + struct mount *r = real_mount(mnt); struct super_block *sb = mnt->mnt_sb; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; struct path root = p->root; int err = 0; - seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id, + seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, r->mnt_parent->mnt_id, MAJOR(sb->s_dev), MINOR(sb->s_dev)); if (sb->s_op->show_path) err = sb->s_op->show_path(m, mnt); @@ -1201,9 +1202,9 @@ void release_mounts(struct list_head *head) br_write_lock(vfsmount_lock); dentry = mnt->mnt.mnt_mountpoint; - m = mnt->mnt.mnt_parent; + m = mnt->mnt_parent; mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; - mnt->mnt.mnt_parent = &mnt->mnt; + mnt->mnt_parent = &mnt->mnt; m->mnt_ghosts--; br_write_unlock(vfsmount_lock); dput(dentry); @@ -1236,7 +1237,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) __mnt_make_shortterm(&p->mnt); list_del_init(&p->mnt.mnt_child); if (mnt_has_parent(p)) { - p->mnt.mnt_parent->mnt_ghosts++; + p->mnt_parent->mnt_ghosts++; dentry_reset_mounted(p->mnt.mnt_mountpoint); } change_mnt_propagation(p, MS_PRIVATE); @@ -1434,9 +1435,9 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, s = skip_mnt_tree(s); continue; } - while (p != real_mount(s->mnt.mnt_parent)) { - p = real_mount(p->mnt.mnt_parent); - q = real_mount(q->mnt.mnt_parent); + while (p != real_mount(s->mnt_parent)) { + p = real_mount(p->mnt_parent); + q = real_mount(q->mnt_parent); } p = s; path.mnt = &q->mnt; @@ -1898,7 +1899,7 @@ static int do_move_mount(struct path *path, char *old_name) /* * Don't move a mount residing in a shared parent. */ - if (IS_MNT_SHARED(old_path.mnt->mnt_parent)) + if (IS_MNT_SHARED(old->mnt_parent)) goto out1; /* * Don't move a mount tree containing unbindable mounts to a destination @@ -1908,7 +1909,7 @@ static int do_move_mount(struct path *path, char *old_name) tree_contains_unbindable(old)) goto out1; err = -ELOOP; - for (p = real_mount(path->mnt); mnt_has_parent(p); p = real_mount(p->mnt.mnt_parent)) + for (p = real_mount(path->mnt); mnt_has_parent(p); p = real_mount(p->mnt_parent)) if (p == old) goto out1; @@ -2158,7 +2159,7 @@ resume: */ if (this_parent != parent) { next = this_parent->mnt.mnt_child.next; - this_parent = real_mount(this_parent->mnt.mnt_parent); + this_parent = real_mount(this_parent->mnt_parent); goto resume; } return found; @@ -2564,7 +2565,7 @@ bool is_path_reachable(struct mount *mnt, struct dentry *dentry, { while (&mnt->mnt != root->mnt && mnt_has_parent(mnt)) { dentry = mnt->mnt.mnt_mountpoint; - mnt = real_mount(mnt->mnt.mnt_parent); + mnt = real_mount(mnt->mnt_parent); } return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry); } @@ -2635,8 +2636,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, new_mnt = real_mount(new.mnt); root_mnt = real_mount(root.mnt); if (IS_MNT_SHARED(old.mnt) || - IS_MNT_SHARED(new.mnt->mnt_parent) || - IS_MNT_SHARED(root.mnt->mnt_parent)) + IS_MNT_SHARED(new_mnt->mnt_parent) || + IS_MNT_SHARED(root_mnt->mnt_parent)) goto out4; if (!check_mnt(root.mnt) || !check_mnt(new.mnt)) goto out4; -- cgit v1.2.3 From 0714a533805a0f8ebfc6fdb6bda9f129b8c7c6d7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 22:19:58 -0500 Subject: vfs: now it can be done - make mnt_parent point to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index c6384bc39db1..5e700c6df579 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -476,7 +476,7 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, if (tmp == head) break; p = list_entry(tmp, struct mount, mnt_hash); - if (p->mnt_parent == mnt && p->mnt.mnt_mountpoint == dentry) { + if (&p->mnt_parent->mnt == mnt && p->mnt.mnt_mountpoint == dentry) { found = p; break; } @@ -558,8 +558,8 @@ static void dentry_reset_mounted(struct dentry *dentry) static void detach_mnt(struct mount *mnt, struct path *old_path) { old_path->dentry = mnt->mnt.mnt_mountpoint; - old_path->mnt = mnt->mnt_parent; - mnt->mnt_parent = &mnt->mnt; + old_path->mnt = &mnt->mnt_parent->mnt; + mnt->mnt_parent = mnt; mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; list_del_init(&mnt->mnt.mnt_child); list_del_init(&mnt->mnt_hash); @@ -572,7 +572,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, struct mount *child_mnt) { - child_mnt->mnt_parent = mntget(mnt); + child_mnt->mnt_parent = real_mount(mntget(mnt)); child_mnt->mnt.mnt_mountpoint = dget(dentry); spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_MOUNTED; @@ -610,12 +610,12 @@ static inline void __mnt_make_shortterm(struct vfsmount *mnt) */ static void commit_tree(struct mount *mnt) { - struct vfsmount *parent = mnt->mnt_parent; + struct mount *parent = mnt->mnt_parent; struct vfsmount *m; LIST_HEAD(head); - struct mnt_namespace *n = parent->mnt_ns; + struct mnt_namespace *n = parent->mnt.mnt_ns; - BUG_ON(parent == &mnt->mnt); + BUG_ON(parent == mnt); list_add_tail(&head, &mnt->mnt.mnt_list); list_for_each_entry(m, &head, mnt_list) { @@ -626,8 +626,8 @@ static void commit_tree(struct mount *mnt) list_splice(&head, n->list.prev); list_add_tail(&mnt->mnt_hash, mount_hashtable + - hash(parent, mnt->mnt.mnt_mountpoint)); - list_add_tail(&mnt->mnt.mnt_child, &parent->mnt_mounts); + hash(&parent->mnt, mnt->mnt.mnt_mountpoint)); + list_add_tail(&mnt->mnt.mnt_child, &parent->mnt.mnt_mounts); touch_mnt_namespace(n); } @@ -639,9 +639,9 @@ static struct mount *next_mnt(struct mount *p, struct vfsmount *root) if (&p->mnt == root) return NULL; next = p->mnt.mnt_child.next; - if (next != &p->mnt_parent->mnt_mounts) + if (next != &p->mnt_parent->mnt.mnt_mounts) break; - p = real_mount(p->mnt_parent); + p = p->mnt_parent; } } return list_entry(next, struct mount, mnt.mnt_child); @@ -682,7 +682,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void mnt->mnt.mnt_root = root; mnt->mnt.mnt_sb = root->d_sb; mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; - mnt->mnt_parent = &mnt->mnt; + mnt->mnt_parent = mnt; return &mnt->mnt; } EXPORT_SYMBOL_GPL(vfs_kern_mount); @@ -710,7 +710,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, mnt->mnt.mnt_sb = sb; mnt->mnt.mnt_root = dget(root); mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; - mnt->mnt_parent = &mnt->mnt; + mnt->mnt_parent = mnt; if (flag & CL_SLAVE) { list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list); @@ -1027,7 +1027,7 @@ static int show_mountinfo(struct seq_file *m, void *v) struct path root = p->root; int err = 0; - seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, r->mnt_parent->mnt_id, + seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, r->mnt_parent->mnt.mnt_id, MAJOR(sb->s_dev), MINOR(sb->s_dev)); if (sb->s_op->show_path) err = sb->s_op->show_path(m, mnt); @@ -1202,9 +1202,9 @@ void release_mounts(struct list_head *head) br_write_lock(vfsmount_lock); dentry = mnt->mnt.mnt_mountpoint; - m = mnt->mnt_parent; + m = &mnt->mnt_parent->mnt; mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; - mnt->mnt_parent = &mnt->mnt; + mnt->mnt_parent = mnt; m->mnt_ghosts--; br_write_unlock(vfsmount_lock); dput(dentry); @@ -1237,7 +1237,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) __mnt_make_shortterm(&p->mnt); list_del_init(&p->mnt.mnt_child); if (mnt_has_parent(p)) { - p->mnt_parent->mnt_ghosts++; + p->mnt_parent->mnt.mnt_ghosts++; dentry_reset_mounted(p->mnt.mnt_mountpoint); } change_mnt_propagation(p, MS_PRIVATE); @@ -1435,9 +1435,9 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, s = skip_mnt_tree(s); continue; } - while (p != real_mount(s->mnt_parent)) { - p = real_mount(p->mnt_parent); - q = real_mount(q->mnt_parent); + while (p != s->mnt_parent) { + p = p->mnt_parent; + q = q->mnt_parent; } p = s; path.mnt = &q->mnt; @@ -1899,7 +1899,7 @@ static int do_move_mount(struct path *path, char *old_name) /* * Don't move a mount residing in a shared parent. */ - if (IS_MNT_SHARED(old->mnt_parent)) + if (IS_MNT_SHARED(&old->mnt_parent->mnt)) goto out1; /* * Don't move a mount tree containing unbindable mounts to a destination @@ -1909,7 +1909,7 @@ static int do_move_mount(struct path *path, char *old_name) tree_contains_unbindable(old)) goto out1; err = -ELOOP; - for (p = real_mount(path->mnt); mnt_has_parent(p); p = real_mount(p->mnt_parent)) + for (p = real_mount(path->mnt); mnt_has_parent(p); p = p->mnt_parent) if (p == old) goto out1; @@ -2159,7 +2159,7 @@ resume: */ if (this_parent != parent) { next = this_parent->mnt.mnt_child.next; - this_parent = real_mount(this_parent->mnt_parent); + this_parent = this_parent->mnt_parent; goto resume; } return found; @@ -2565,7 +2565,7 @@ bool is_path_reachable(struct mount *mnt, struct dentry *dentry, { while (&mnt->mnt != root->mnt && mnt_has_parent(mnt)) { dentry = mnt->mnt.mnt_mountpoint; - mnt = real_mount(mnt->mnt_parent); + mnt = mnt->mnt_parent; } return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry); } @@ -2636,8 +2636,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, new_mnt = real_mount(new.mnt); root_mnt = real_mount(root.mnt); if (IS_MNT_SHARED(old.mnt) || - IS_MNT_SHARED(new_mnt->mnt_parent) || - IS_MNT_SHARED(root_mnt->mnt_parent)) + IS_MNT_SHARED(&new_mnt->mnt_parent->mnt) || + IS_MNT_SHARED(&root_mnt->mnt_parent->mnt)) goto out4; if (!check_mnt(root.mnt) || !check_mnt(new.mnt)) goto out4; -- cgit v1.2.3 From a73324da7af4052e1d1ddec6a5980f552420e58b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 22:25:07 -0500 Subject: vfs: move mnt_mountpoint to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 5e700c6df579..ec798e77b726 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -476,7 +476,7 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, if (tmp == head) break; p = list_entry(tmp, struct mount, mnt_hash); - if (&p->mnt_parent->mnt == mnt && p->mnt.mnt_mountpoint == dentry) { + if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry) { found = p; break; } @@ -543,7 +543,7 @@ static void dentry_reset_mounted(struct dentry *dentry) struct mount *p; list_for_each_entry(p, &mount_hashtable[u], mnt_hash) { - if (p->mnt.mnt_mountpoint == dentry) + if (p->mnt_mountpoint == dentry) return; } } @@ -557,10 +557,10 @@ static void dentry_reset_mounted(struct dentry *dentry) */ static void detach_mnt(struct mount *mnt, struct path *old_path) { - old_path->dentry = mnt->mnt.mnt_mountpoint; + old_path->dentry = mnt->mnt_mountpoint; old_path->mnt = &mnt->mnt_parent->mnt; mnt->mnt_parent = mnt; - mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; + mnt->mnt_mountpoint = mnt->mnt.mnt_root; list_del_init(&mnt->mnt.mnt_child); list_del_init(&mnt->mnt_hash); dentry_reset_mounted(old_path->dentry); @@ -573,7 +573,7 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, struct mount *child_mnt) { child_mnt->mnt_parent = real_mount(mntget(mnt)); - child_mnt->mnt.mnt_mountpoint = dget(dentry); + child_mnt->mnt_mountpoint = dget(dentry); spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_MOUNTED; spin_unlock(&dentry->d_lock); @@ -626,7 +626,7 @@ static void commit_tree(struct mount *mnt) list_splice(&head, n->list.prev); list_add_tail(&mnt->mnt_hash, mount_hashtable + - hash(&parent->mnt, mnt->mnt.mnt_mountpoint)); + hash(&parent->mnt, mnt->mnt_mountpoint)); list_add_tail(&mnt->mnt.mnt_child, &parent->mnt.mnt_mounts); touch_mnt_namespace(n); } @@ -681,7 +681,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void mnt->mnt.mnt_root = root; mnt->mnt.mnt_sb = root->d_sb; - mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; + mnt->mnt_mountpoint = mnt->mnt.mnt_root; mnt->mnt_parent = mnt; return &mnt->mnt; } @@ -709,7 +709,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, atomic_inc(&sb->s_active); mnt->mnt.mnt_sb = sb; mnt->mnt.mnt_root = dget(root); - mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; + mnt->mnt_mountpoint = mnt->mnt.mnt_root; mnt->mnt_parent = mnt; if (flag & CL_SLAVE) { @@ -1201,9 +1201,9 @@ void release_mounts(struct list_head *head) struct vfsmount *m; br_write_lock(vfsmount_lock); - dentry = mnt->mnt.mnt_mountpoint; + dentry = mnt->mnt_mountpoint; m = &mnt->mnt_parent->mnt; - mnt->mnt.mnt_mountpoint = mnt->mnt.mnt_root; + mnt->mnt_mountpoint = mnt->mnt.mnt_root; mnt->mnt_parent = mnt; m->mnt_ghosts--; br_write_unlock(vfsmount_lock); @@ -1238,7 +1238,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) list_del_init(&p->mnt.mnt_child); if (mnt_has_parent(p)) { p->mnt_parent->mnt.mnt_ghosts++; - dentry_reset_mounted(p->mnt.mnt_mountpoint); + dentry_reset_mounted(p->mnt_mountpoint); } change_mnt_propagation(p, MS_PRIVATE); } @@ -1412,8 +1412,7 @@ static int mount_is_safe(struct path *path) struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, int flag) { - struct mount *res, *p, *q; - struct vfsmount *r; + struct mount *res, *p, *q, *r; struct path path; if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(&mnt->mnt)) @@ -1422,15 +1421,15 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, res = q = clone_mnt(mnt, dentry, flag); if (!q) goto Enomem; - q->mnt.mnt_mountpoint = mnt->mnt.mnt_mountpoint; + q->mnt_mountpoint = mnt->mnt_mountpoint; p = mnt; - list_for_each_entry(r, &mnt->mnt.mnt_mounts, mnt_child) { + list_for_each_entry(r, &mnt->mnt.mnt_mounts, mnt.mnt_child) { struct mount *s; if (!is_subdir(r->mnt_mountpoint, dentry)) continue; - for (s = real_mount(r); s; s = next_mnt(s, r)) { + for (s = r; s; s = next_mnt(s, &r->mnt)) { if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(&s->mnt)) { s = skip_mnt_tree(s); continue; @@ -1441,7 +1440,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, } p = s; path.mnt = &q->mnt; - path.dentry = p->mnt.mnt_mountpoint; + path.dentry = p->mnt_mountpoint; q = clone_mnt(p, p->mnt.mnt_root, flag); if (!q) goto Enomem; @@ -2564,7 +2563,7 @@ bool is_path_reachable(struct mount *mnt, struct dentry *dentry, const struct path *root) { while (&mnt->mnt != root->mnt && mnt_has_parent(mnt)) { - dentry = mnt->mnt.mnt_mountpoint; + dentry = mnt->mnt_mountpoint; mnt = mnt->mnt_parent; } return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry); -- cgit v1.2.3 From 83adc7532229f1909cf37c429780f02f06fe05ee Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 22:37:54 -0500 Subject: vfs: spread struct mount - work with counters Signed-off-by: Al Viro --- fs/namespace.c | 124 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 64 insertions(+), 60 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index ec798e77b726..a13165c871c2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -141,13 +141,13 @@ void mnt_release_group_id(struct mount *mnt) /* * vfsmount lock must be held for read */ -static inline void mnt_add_count(struct vfsmount *mnt, int n) +static inline void mnt_add_count(struct mount *mnt, int n) { #ifdef CONFIG_SMP - this_cpu_add(mnt->mnt_pcp->mnt_count, n); + this_cpu_add(mnt->mnt.mnt_pcp->mnt_count, n); #else preempt_disable(); - mnt->mnt_count += n; + mnt->mnt.mnt_count += n; preempt_enable(); #endif } @@ -155,19 +155,19 @@ static inline void mnt_add_count(struct vfsmount *mnt, int n) /* * vfsmount lock must be held for write */ -unsigned int mnt_get_count(struct vfsmount *mnt) +unsigned int mnt_get_count(struct mount *mnt) { #ifdef CONFIG_SMP unsigned int count = 0; int cpu; for_each_possible_cpu(cpu) { - count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_count; + count += per_cpu_ptr(mnt->mnt.mnt_pcp, cpu)->mnt_count; } return count; #else - return mnt->mnt_count; + return mnt->mnt.mnt_count; #endif } @@ -253,32 +253,32 @@ int __mnt_is_readonly(struct vfsmount *mnt) } EXPORT_SYMBOL_GPL(__mnt_is_readonly); -static inline void mnt_inc_writers(struct vfsmount *mnt) +static inline void mnt_inc_writers(struct mount *mnt) { #ifdef CONFIG_SMP - this_cpu_inc(mnt->mnt_pcp->mnt_writers); + this_cpu_inc(mnt->mnt.mnt_pcp->mnt_writers); #else - mnt->mnt_writers++; + mnt->mnt.mnt_writers++; #endif } -static inline void mnt_dec_writers(struct vfsmount *mnt) +static inline void mnt_dec_writers(struct mount *mnt) { #ifdef CONFIG_SMP - this_cpu_dec(mnt->mnt_pcp->mnt_writers); + this_cpu_dec(mnt->mnt.mnt_pcp->mnt_writers); #else - mnt->mnt_writers--; + mnt->mnt.mnt_writers--; #endif } -static unsigned int mnt_get_writers(struct vfsmount *mnt) +static unsigned int mnt_get_writers(struct mount *mnt) { #ifdef CONFIG_SMP unsigned int count = 0; int cpu; for_each_possible_cpu(cpu) { - count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_writers; + count += per_cpu_ptr(mnt->mnt.mnt_pcp, cpu)->mnt_writers; } return count; @@ -297,7 +297,7 @@ static unsigned int mnt_get_writers(struct vfsmount *mnt) */ /** * mnt_want_write - get write access to a mount - * @mnt: the mount on which to take a write + * @m: the mount on which to take a write * * This tells the low-level filesystem that a write is * about to be performed to it, and makes sure that @@ -305,8 +305,9 @@ static unsigned int mnt_get_writers(struct vfsmount *mnt) * the write operation is finished, mnt_drop_write() * must be called. This is effectively a refcount. */ -int mnt_want_write(struct vfsmount *mnt) +int mnt_want_write(struct vfsmount *m) { + struct mount *mnt = real_mount(m); int ret = 0; preempt_disable(); @@ -317,7 +318,7 @@ int mnt_want_write(struct vfsmount *mnt) * incremented count after it has set MNT_WRITE_HOLD. */ smp_mb(); - while (mnt->mnt_flags & MNT_WRITE_HOLD) + while (mnt->mnt.mnt_flags & MNT_WRITE_HOLD) cpu_relax(); /* * After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will @@ -325,7 +326,7 @@ int mnt_want_write(struct vfsmount *mnt) * MNT_WRITE_HOLD is cleared. */ smp_rmb(); - if (__mnt_is_readonly(mnt)) { + if (__mnt_is_readonly(m)) { mnt_dec_writers(mnt); ret = -EROFS; goto out; @@ -354,7 +355,7 @@ int mnt_clone_write(struct vfsmount *mnt) if (__mnt_is_readonly(mnt)) return -EROFS; preempt_disable(); - mnt_inc_writers(mnt); + mnt_inc_writers(real_mount(mnt)); preempt_enable(); return 0; } @@ -388,7 +389,7 @@ EXPORT_SYMBOL_GPL(mnt_want_write_file); void mnt_drop_write(struct vfsmount *mnt) { preempt_disable(); - mnt_dec_writers(mnt); + mnt_dec_writers(real_mount(mnt)); preempt_enable(); } EXPORT_SYMBOL_GPL(mnt_drop_write); @@ -399,12 +400,12 @@ void mnt_drop_write_file(struct file *file) } EXPORT_SYMBOL(mnt_drop_write_file); -static int mnt_make_readonly(struct vfsmount *mnt) +static int mnt_make_readonly(struct mount *mnt) { int ret = 0; br_write_lock(vfsmount_lock); - mnt->mnt_flags |= MNT_WRITE_HOLD; + mnt->mnt.mnt_flags |= MNT_WRITE_HOLD; /* * After storing MNT_WRITE_HOLD, we'll read the counters. This store * should be visible before we do. @@ -430,21 +431,21 @@ static int mnt_make_readonly(struct vfsmount *mnt) if (mnt_get_writers(mnt) > 0) ret = -EBUSY; else - mnt->mnt_flags |= MNT_READONLY; + mnt->mnt.mnt_flags |= MNT_READONLY; /* * MNT_READONLY must become visible before ~MNT_WRITE_HOLD, so writers * that become unheld will see MNT_READONLY. */ smp_wmb(); - mnt->mnt_flags &= ~MNT_WRITE_HOLD; + mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD; br_write_unlock(vfsmount_lock); return ret; } -static void __mnt_unmake_readonly(struct vfsmount *mnt) +static void __mnt_unmake_readonly(struct mount *mnt) { br_write_lock(vfsmount_lock); - mnt->mnt_flags &= ~MNT_READONLY; + mnt->mnt.mnt_flags &= ~MNT_READONLY; br_write_unlock(vfsmount_lock); } @@ -590,18 +591,18 @@ static void attach_mnt(struct mount *mnt, struct path *path) list_add_tail(&mnt->mnt.mnt_child, &path->mnt->mnt_mounts); } -static inline void __mnt_make_longterm(struct vfsmount *mnt) +static inline void __mnt_make_longterm(struct mount *mnt) { #ifdef CONFIG_SMP - atomic_inc(&mnt->mnt_longterm); + atomic_inc(&mnt->mnt.mnt_longterm); #endif } /* needs vfsmount lock for write */ -static inline void __mnt_make_shortterm(struct vfsmount *mnt) +static inline void __mnt_make_shortterm(struct mount *mnt) { #ifdef CONFIG_SMP - atomic_dec(&mnt->mnt_longterm); + atomic_dec(&mnt->mnt.mnt_longterm); #endif } @@ -611,15 +612,15 @@ static inline void __mnt_make_shortterm(struct vfsmount *mnt) static void commit_tree(struct mount *mnt) { struct mount *parent = mnt->mnt_parent; - struct vfsmount *m; + struct mount *m; LIST_HEAD(head); struct mnt_namespace *n = parent->mnt.mnt_ns; BUG_ON(parent == mnt); list_add_tail(&head, &mnt->mnt.mnt_list); - list_for_each_entry(m, &head, mnt_list) { - m->mnt_ns = n; + list_for_each_entry(m, &head, mnt.mnt_list) { + m->mnt.mnt_ns = n; __mnt_make_longterm(m); } @@ -740,9 +741,10 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, return NULL; } -static inline void mntfree(struct vfsmount *mnt) +static inline void mntfree(struct mount *mnt) { - struct super_block *sb = mnt->mnt_sb; + struct vfsmount *m = &mnt->mnt; + struct super_block *sb = m->mnt_sb; /* * This probably indicates that somebody messed @@ -755,18 +757,19 @@ static inline void mntfree(struct vfsmount *mnt) * so mnt_get_writers() below is safe. */ WARN_ON(mnt_get_writers(mnt)); - fsnotify_vfsmount_delete(mnt); - dput(mnt->mnt_root); - free_vfsmnt(real_mount(mnt)); + fsnotify_vfsmount_delete(m); + dput(m->mnt_root); + free_vfsmnt(mnt); deactivate_super(sb); } -static void mntput_no_expire(struct vfsmount *mnt) +static void mntput_no_expire(struct vfsmount *m) { + struct mount *mnt = real_mount(m); put_again: #ifdef CONFIG_SMP br_read_lock(vfsmount_lock); - if (likely(atomic_read(&mnt->mnt_longterm))) { + if (likely(atomic_read(&mnt->mnt.mnt_longterm))) { mnt_add_count(mnt, -1); br_read_unlock(vfsmount_lock); return; @@ -785,11 +788,11 @@ put_again: return; br_write_lock(vfsmount_lock); #endif - if (unlikely(mnt->mnt_pinned)) { - mnt_add_count(mnt, mnt->mnt_pinned + 1); - mnt->mnt_pinned = 0; + if (unlikely(mnt->mnt.mnt_pinned)) { + mnt_add_count(mnt, mnt->mnt.mnt_pinned + 1); + mnt->mnt.mnt_pinned = 0; br_write_unlock(vfsmount_lock); - acct_auto_close_mnt(mnt); + acct_auto_close_mnt(m); goto put_again; } br_write_unlock(vfsmount_lock); @@ -810,7 +813,7 @@ EXPORT_SYMBOL(mntput); struct vfsmount *mntget(struct vfsmount *mnt) { if (mnt) - mnt_add_count(mnt, 1); + mnt_add_count(real_mount(mnt), 1); return mnt; } EXPORT_SYMBOL(mntget); @@ -827,7 +830,7 @@ void mnt_unpin(struct vfsmount *mnt) { br_write_lock(vfsmount_lock); if (mnt->mnt_pinned) { - mnt_add_count(mnt, 1); + mnt_add_count(real_mount(mnt), 1); mnt->mnt_pinned--; } br_write_unlock(vfsmount_lock); @@ -1150,7 +1153,7 @@ int may_umount_tree(struct vfsmount *mnt) /* write lock needed for mnt_get_count */ br_write_lock(vfsmount_lock); for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) { - actual_refs += mnt_get_count(&p->mnt); + actual_refs += mnt_get_count(p); minimum_refs += 2; } br_write_unlock(vfsmount_lock); @@ -1234,7 +1237,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) list_del_init(&p->mnt.mnt_list); __touch_mnt_namespace(p->mnt.mnt_ns); p->mnt.mnt_ns = NULL; - __mnt_make_shortterm(&p->mnt); + __mnt_make_shortterm(p); list_del_init(&p->mnt.mnt_child); if (mnt_has_parent(p)) { p->mnt_parent->mnt.mnt_ghosts++; @@ -1273,7 +1276,7 @@ static int do_umount(struct mount *mnt, int flags) * all race cases, but it's a slowpath. */ br_write_lock(vfsmount_lock); - if (mnt_get_count(&mnt->mnt) != 2) { + if (mnt_get_count(mnt) != 2) { br_write_unlock(vfsmount_lock); return -EBUSY; } @@ -1798,9 +1801,9 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags) return 0; if (readonly_request) - error = mnt_make_readonly(mnt); + error = mnt_make_readonly(real_mount(mnt)); else - __mnt_unmake_readonly(mnt); + __mnt_unmake_readonly(real_mount(mnt)); return error; } @@ -2034,7 +2037,7 @@ int finish_automount(struct vfsmount *m, struct path *path) /* The new mount record should have at least 2 refs to prevent it being * expired before we get a chance to add it */ - BUG_ON(mnt_get_count(m) < 2); + BUG_ON(mnt_get_count(real_mount(m)) < 2); if (m->mnt_sb == path->mnt->mnt_sb && m->mnt_root == path->dentry) { @@ -2365,16 +2368,17 @@ static struct mnt_namespace *alloc_mnt_ns(void) void mnt_make_longterm(struct vfsmount *mnt) { - __mnt_make_longterm(mnt); + __mnt_make_longterm(real_mount(mnt)); } -void mnt_make_shortterm(struct vfsmount *mnt) +void mnt_make_shortterm(struct vfsmount *m) { #ifdef CONFIG_SMP - if (atomic_add_unless(&mnt->mnt_longterm, -1, 1)) + struct mount *mnt = real_mount(m); + if (atomic_add_unless(&mnt->mnt.mnt_longterm, -1, 1)) return; br_write_lock(vfsmount_lock); - atomic_dec(&mnt->mnt_longterm); + atomic_dec(&mnt->mnt.mnt_longterm); br_write_unlock(vfsmount_lock); #endif } @@ -2418,17 +2422,17 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, q = new; while (p) { q->mnt.mnt_ns = new_ns; - __mnt_make_longterm(&q->mnt); + __mnt_make_longterm(q); if (fs) { if (&p->mnt == fs->root.mnt) { fs->root.mnt = mntget(&q->mnt); - __mnt_make_longterm(&q->mnt); + __mnt_make_longterm(q); mnt_make_shortterm(&p->mnt); rootmnt = &p->mnt; } if (&p->mnt == fs->pwd.mnt) { fs->pwd.mnt = mntget(&q->mnt); - __mnt_make_longterm(&q->mnt); + __mnt_make_longterm(q); mnt_make_shortterm(&p->mnt); pwdmnt = &p->mnt; } @@ -2474,7 +2478,7 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) new_ns = alloc_mnt_ns(); if (!IS_ERR(new_ns)) { mnt->mnt_ns = new_ns; - __mnt_make_longterm(mnt); + __mnt_make_longterm(real_mount(mnt)); new_ns->root = mnt; list_add(&new_ns->list, &new_ns->root->mnt_list); } else { -- cgit v1.2.3 From 68e8a9feab251f9d3c8fd9e9893c97843bcd4bd0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 22:53:09 -0500 Subject: vfs: all counters taken to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index a13165c871c2..3fdd30add4f9 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -144,10 +144,10 @@ void mnt_release_group_id(struct mount *mnt) static inline void mnt_add_count(struct mount *mnt, int n) { #ifdef CONFIG_SMP - this_cpu_add(mnt->mnt.mnt_pcp->mnt_count, n); + this_cpu_add(mnt->mnt_pcp->mnt_count, n); #else preempt_disable(); - mnt->mnt.mnt_count += n; + mnt->mnt_count += n; preempt_enable(); #endif } @@ -162,12 +162,12 @@ unsigned int mnt_get_count(struct mount *mnt) int cpu; for_each_possible_cpu(cpu) { - count += per_cpu_ptr(mnt->mnt.mnt_pcp, cpu)->mnt_count; + count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_count; } return count; #else - return mnt->mnt.mnt_count; + return mnt->mnt_count; #endif } @@ -189,14 +189,14 @@ static struct mount *alloc_vfsmnt(const char *name) } #ifdef CONFIG_SMP - mnt->mnt_pcp = alloc_percpu(struct mnt_pcp); - if (!mnt->mnt_pcp) + p->mnt_pcp = alloc_percpu(struct mnt_pcp); + if (!p->mnt_pcp) goto out_free_devname; - this_cpu_add(mnt->mnt_pcp->mnt_count, 1); + this_cpu_add(p->mnt_pcp->mnt_count, 1); #else - mnt->mnt_count = 1; - mnt->mnt_writers = 0; + p->mnt_count = 1; + p->mnt_writers = 0; #endif INIT_LIST_HEAD(&p->mnt_hash); @@ -256,18 +256,18 @@ EXPORT_SYMBOL_GPL(__mnt_is_readonly); static inline void mnt_inc_writers(struct mount *mnt) { #ifdef CONFIG_SMP - this_cpu_inc(mnt->mnt.mnt_pcp->mnt_writers); + this_cpu_inc(mnt->mnt_pcp->mnt_writers); #else - mnt->mnt.mnt_writers++; + mnt->mnt_writers++; #endif } static inline void mnt_dec_writers(struct mount *mnt) { #ifdef CONFIG_SMP - this_cpu_dec(mnt->mnt.mnt_pcp->mnt_writers); + this_cpu_dec(mnt->mnt_pcp->mnt_writers); #else - mnt->mnt.mnt_writers--; + mnt->mnt_writers--; #endif } @@ -278,7 +278,7 @@ static unsigned int mnt_get_writers(struct mount *mnt) int cpu; for_each_possible_cpu(cpu) { - count += per_cpu_ptr(mnt->mnt.mnt_pcp, cpu)->mnt_writers; + count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_writers; } return count; @@ -454,7 +454,7 @@ static void free_vfsmnt(struct mount *mnt) kfree(mnt->mnt.mnt_devname); mnt_free_id(mnt); #ifdef CONFIG_SMP - free_percpu(mnt->mnt.mnt_pcp); + free_percpu(mnt->mnt_pcp); #endif kmem_cache_free(mnt_cache, mnt); } @@ -594,7 +594,7 @@ static void attach_mnt(struct mount *mnt, struct path *path) static inline void __mnt_make_longterm(struct mount *mnt) { #ifdef CONFIG_SMP - atomic_inc(&mnt->mnt.mnt_longterm); + atomic_inc(&mnt->mnt_longterm); #endif } @@ -602,7 +602,7 @@ static inline void __mnt_make_longterm(struct mount *mnt) static inline void __mnt_make_shortterm(struct mount *mnt) { #ifdef CONFIG_SMP - atomic_dec(&mnt->mnt.mnt_longterm); + atomic_dec(&mnt->mnt_longterm); #endif } @@ -769,7 +769,7 @@ static void mntput_no_expire(struct vfsmount *m) put_again: #ifdef CONFIG_SMP br_read_lock(vfsmount_lock); - if (likely(atomic_read(&mnt->mnt.mnt_longterm))) { + if (likely(atomic_read(&mnt->mnt_longterm))) { mnt_add_count(mnt, -1); br_read_unlock(vfsmount_lock); return; @@ -2375,10 +2375,10 @@ void mnt_make_shortterm(struct vfsmount *m) { #ifdef CONFIG_SMP struct mount *mnt = real_mount(m); - if (atomic_add_unless(&mnt->mnt.mnt_longterm, -1, 1)) + if (atomic_add_unless(&mnt->mnt_longterm, -1, 1)) return; br_write_lock(vfsmount_lock); - atomic_dec(&mnt->mnt.mnt_longterm); + atomic_dec(&mnt->mnt_longterm); br_write_unlock(vfsmount_lock); #endif } -- cgit v1.2.3 From 6b41d536f7c84e7cb1c1462073150277e46f6ea8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 23:24:33 -0500 Subject: vfs: take mnt_child/mnt_mounts to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 3fdd30add4f9..9ceb03fe176f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -200,8 +200,8 @@ static struct mount *alloc_vfsmnt(const char *name) #endif INIT_LIST_HEAD(&p->mnt_hash); - INIT_LIST_HEAD(&mnt->mnt_child); - INIT_LIST_HEAD(&mnt->mnt_mounts); + INIT_LIST_HEAD(&p->mnt_child); + INIT_LIST_HEAD(&p->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); INIT_LIST_HEAD(&mnt->mnt_share); @@ -562,7 +562,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) old_path->mnt = &mnt->mnt_parent->mnt; mnt->mnt_parent = mnt; mnt->mnt_mountpoint = mnt->mnt.mnt_root; - list_del_init(&mnt->mnt.mnt_child); + list_del_init(&mnt->mnt_child); list_del_init(&mnt->mnt_hash); dentry_reset_mounted(old_path->dentry); } @@ -588,7 +588,7 @@ static void attach_mnt(struct mount *mnt, struct path *path) mnt_set_mountpoint(path->mnt, path->dentry, mnt); list_add_tail(&mnt->mnt_hash, mount_hashtable + hash(path->mnt, path->dentry)); - list_add_tail(&mnt->mnt.mnt_child, &path->mnt->mnt_mounts); + list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts); } static inline void __mnt_make_longterm(struct mount *mnt) @@ -628,32 +628,32 @@ static void commit_tree(struct mount *mnt) list_add_tail(&mnt->mnt_hash, mount_hashtable + hash(&parent->mnt, mnt->mnt_mountpoint)); - list_add_tail(&mnt->mnt.mnt_child, &parent->mnt.mnt_mounts); + list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); touch_mnt_namespace(n); } static struct mount *next_mnt(struct mount *p, struct vfsmount *root) { - struct list_head *next = p->mnt.mnt_mounts.next; - if (next == &p->mnt.mnt_mounts) { + struct list_head *next = p->mnt_mounts.next; + if (next == &p->mnt_mounts) { while (1) { if (&p->mnt == root) return NULL; - next = p->mnt.mnt_child.next; - if (next != &p->mnt_parent->mnt.mnt_mounts) + next = p->mnt_child.next; + if (next != &p->mnt_parent->mnt_mounts) break; p = p->mnt_parent; } } - return list_entry(next, struct mount, mnt.mnt_child); + return list_entry(next, struct mount, mnt_child); } static struct mount *skip_mnt_tree(struct mount *p) { - struct list_head *prev = p->mnt.mnt_mounts.prev; - while (prev != &p->mnt.mnt_mounts) { - p = list_entry(prev, struct mount, mnt.mnt_child); - prev = p->mnt.mnt_mounts.prev; + struct list_head *prev = p->mnt_mounts.prev; + while (prev != &p->mnt_mounts) { + p = list_entry(prev, struct mount, mnt_child); + prev = p->mnt_mounts.prev; } return p; } @@ -1238,7 +1238,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) __touch_mnt_namespace(p->mnt.mnt_ns); p->mnt.mnt_ns = NULL; __mnt_make_shortterm(p); - list_del_init(&p->mnt.mnt_child); + list_del_init(&p->mnt_child); if (mnt_has_parent(p)) { p->mnt_parent->mnt.mnt_ghosts++; dentry_reset_mounted(p->mnt_mountpoint); @@ -1427,7 +1427,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, q->mnt_mountpoint = mnt->mnt_mountpoint; p = mnt; - list_for_each_entry(r, &mnt->mnt.mnt_mounts, mnt.mnt_child) { + list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { struct mount *s; if (!is_subdir(r->mnt_mountpoint, dentry)) continue; @@ -2134,11 +2134,11 @@ static int select_submounts(struct mount *parent, struct list_head *graveyard) int found = 0; repeat: - next = this_parent->mnt.mnt_mounts.next; + next = this_parent->mnt_mounts.next; resume: - while (next != &this_parent->mnt.mnt_mounts) { + while (next != &this_parent->mnt_mounts) { struct list_head *tmp = next; - struct mount *mnt = list_entry(tmp, struct mount, mnt.mnt_child); + struct mount *mnt = list_entry(tmp, struct mount, mnt_child); next = tmp->next; if (!(mnt->mnt.mnt_flags & MNT_SHRINKABLE)) @@ -2146,7 +2146,7 @@ resume: /* * Descend a level if the d_mounts list is non-empty. */ - if (!list_empty(&mnt->mnt.mnt_mounts)) { + if (!list_empty(&mnt->mnt_mounts)) { this_parent = mnt; goto repeat; } @@ -2160,7 +2160,7 @@ resume: * All done at this level ... ascend and resume the search */ if (this_parent != parent) { - next = this_parent->mnt.mnt_child.next; + next = this_parent->mnt_child.next; this_parent = this_parent->mnt_parent; goto resume; } -- cgit v1.2.3 From 6fc7871fed915914ef441efbe0f9a7c3d0f3bff1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 23:35:54 -0500 Subject: vfs: spread struct mount - get_dominating_id / do_make_slave next pile of horrors, similar to mnt_parent one; this time it's mnt_master. Signed-off-by: Al Viro --- fs/namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 9ceb03fe176f..65d011fe982f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1053,7 +1053,7 @@ static int show_mountinfo(struct seq_file *m, void *v) seq_printf(m, " shared:%i", mnt->mnt_group_id); if (IS_MNT_SLAVE(mnt)) { int master = mnt->mnt_master->mnt_group_id; - int dom = get_dominating_id(mnt, &p->root); + int dom = get_dominating_id(r, &p->root); seq_printf(m, " master:%i", master); if (dom && dom != master) seq_printf(m, " propagate_from:%i", dom); -- cgit v1.2.3 From a8d56d8e4fa0cb9a023834363f8d79415d277a1d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Nov 2011 23:59:29 -0500 Subject: vfs: spread struct mount - propagate_mnt() Signed-off-by: Al Viro --- fs/namespace.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 65d011fe982f..8432344333da 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1595,23 +1595,23 @@ static int attach_recursive_mnt(struct mount *source_mnt, struct path *path, struct path *parent_path) { LIST_HEAD(tree_list); - struct vfsmount *dest_mnt = path->mnt; + struct mount *dest_mnt = real_mount(path->mnt); struct dentry *dest_dentry = path->dentry; struct mount *child, *p; int err; - if (IS_MNT_SHARED(dest_mnt)) { + if (IS_MNT_SHARED(&dest_mnt->mnt)) { err = invent_group_ids(source_mnt, true); if (err) goto out; } - err = propagate_mnt(dest_mnt, dest_dentry, &source_mnt->mnt, &tree_list); + err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list); if (err) goto out_cleanup_ids; br_write_lock(vfsmount_lock); - if (IS_MNT_SHARED(dest_mnt)) { + if (IS_MNT_SHARED(&dest_mnt->mnt)) { for (p = source_mnt; p; p = next_mnt(p, &source_mnt->mnt)) set_mnt_shared(p); } @@ -1620,7 +1620,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, attach_mnt(source_mnt, path); touch_mnt_namespace(parent_path->mnt->mnt_ns); } else { - mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); + mnt_set_mountpoint(&dest_mnt->mnt, dest_dentry, source_mnt); commit_tree(source_mnt); } @@ -1633,7 +1633,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, return 0; out_cleanup_ids: - if (IS_MNT_SHARED(dest_mnt)) + if (IS_MNT_SHARED(&dest_mnt->mnt)) cleanup_group_ids(source_mnt, NULL); out: return err; -- cgit v1.2.3 From 14cf1fa8f54353d9caf6174c1e4280c8c4dcfd7a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 00:01:17 -0500 Subject: vfs: spread struct mount - remaining argument of mnt_set_mountpoint() Signed-off-by: Al Viro --- fs/namespace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 8432344333da..ee42e671afdc 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -570,10 +570,10 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) /* * vfsmount lock must be held for write */ -void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, +void mnt_set_mountpoint(struct mount *mnt, struct dentry *dentry, struct mount *child_mnt) { - child_mnt->mnt_parent = real_mount(mntget(mnt)); + child_mnt->mnt_parent = real_mount(mntget(&mnt->mnt)); child_mnt->mnt_mountpoint = dget(dentry); spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_MOUNTED; @@ -585,7 +585,7 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, */ static void attach_mnt(struct mount *mnt, struct path *path) { - mnt_set_mountpoint(path->mnt, path->dentry, mnt); + mnt_set_mountpoint(real_mount(path->mnt), path->dentry, mnt); list_add_tail(&mnt->mnt_hash, mount_hashtable + hash(path->mnt, path->dentry)); list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts); @@ -1620,7 +1620,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, attach_mnt(source_mnt, path); touch_mnt_namespace(parent_path->mnt->mnt_ns); } else { - mnt_set_mountpoint(&dest_mnt->mnt, dest_dentry, source_mnt); + mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); commit_tree(source_mnt); } -- cgit v1.2.3 From d10e8def07fc87488c396d2eff2c26c43bb541dd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 00:07:16 -0500 Subject: vfs: take mnt_master to struct mount make IS_MNT_SLAVE take struct mount * at the same time Signed-off-by: Al Viro --- fs/namespace.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index ee42e671afdc..3439042fc9f2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -715,14 +715,14 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, if (flag & CL_SLAVE) { list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list); - mnt->mnt.mnt_master = &old->mnt; + mnt->mnt_master = &old->mnt; CLEAR_MNT_SHARED(&mnt->mnt); } else if (!(flag & CL_PRIVATE)) { if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(&old->mnt)) list_add(&mnt->mnt.mnt_share, &old->mnt.mnt_share); - if (IS_MNT_SLAVE(&old->mnt)) + if (IS_MNT_SLAVE(old)) list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave); - mnt->mnt.mnt_master = old->mnt.mnt_master; + mnt->mnt_master = old->mnt_master; } if (flag & CL_MAKE_SHARED) set_mnt_shared(mnt); @@ -1051,8 +1051,8 @@ static int show_mountinfo(struct seq_file *m, void *v) /* Tagged fields ("foo:X" or "bar") */ if (IS_MNT_SHARED(mnt)) seq_printf(m, " shared:%i", mnt->mnt_group_id); - if (IS_MNT_SLAVE(mnt)) { - int master = mnt->mnt_master->mnt_group_id; + if (IS_MNT_SLAVE(r)) { + int master = r->mnt_master->mnt_group_id; int dom = get_dominating_id(r, &p->root); seq_printf(m, " master:%i", master); if (dom && dom != master) -- cgit v1.2.3 From 32301920f44a9334f57dd94bebfc6e593b99ad47 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 00:10:28 -0500 Subject: vfs: and now we can make ->mnt_master point to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 3439042fc9f2..847b7240c512 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -715,7 +715,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, if (flag & CL_SLAVE) { list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list); - mnt->mnt_master = &old->mnt; + mnt->mnt_master = old; CLEAR_MNT_SHARED(&mnt->mnt); } else if (!(flag & CL_PRIVATE)) { if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(&old->mnt)) @@ -1052,7 +1052,7 @@ static int show_mountinfo(struct seq_file *m, void *v) if (IS_MNT_SHARED(mnt)) seq_printf(m, " shared:%i", mnt->mnt_group_id); if (IS_MNT_SLAVE(r)) { - int master = r->mnt_master->mnt_group_id; + int master = r->mnt_master->mnt.mnt_group_id; int dom = get_dominating_id(r, &p->root); seq_printf(m, " master:%i", master); if (dom && dom != master) -- cgit v1.2.3 From 6776db3d32b2a59198ec7ac6d32be0b9fdbd8a68 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 00:22:05 -0500 Subject: vfs: take mnt_share/mnt_slave/mnt_slave_list and mnt_expire to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 847b7240c512..a14750be7a70 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -203,10 +203,10 @@ static struct mount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&p->mnt_child); INIT_LIST_HEAD(&p->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); - INIT_LIST_HEAD(&mnt->mnt_expire); - INIT_LIST_HEAD(&mnt->mnt_share); - INIT_LIST_HEAD(&mnt->mnt_slave_list); - INIT_LIST_HEAD(&mnt->mnt_slave); + INIT_LIST_HEAD(&p->mnt_expire); + INIT_LIST_HEAD(&p->mnt_share); + INIT_LIST_HEAD(&p->mnt_slave_list); + INIT_LIST_HEAD(&p->mnt_slave); #ifdef CONFIG_FSNOTIFY INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); #endif @@ -714,14 +714,14 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, mnt->mnt_parent = mnt; if (flag & CL_SLAVE) { - list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list); + list_add(&mnt->mnt_slave, &old->mnt_slave_list); mnt->mnt_master = old; CLEAR_MNT_SHARED(&mnt->mnt); } else if (!(flag & CL_PRIVATE)) { if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(&old->mnt)) - list_add(&mnt->mnt.mnt_share, &old->mnt.mnt_share); + list_add(&mnt->mnt_share, &old->mnt_share); if (IS_MNT_SLAVE(old)) - list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave); + list_add(&mnt->mnt_slave, &old->mnt_slave); mnt->mnt_master = old->mnt_master; } if (flag & CL_MAKE_SHARED) @@ -730,8 +730,8 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, /* stick the duplicate mount on the same expiry list * as the original if that was on one */ if (flag & CL_EXPIRE) { - if (!list_empty(&old->mnt.mnt_expire)) - list_add(&mnt->mnt.mnt_expire, &old->mnt.mnt_expire); + if (!list_empty(&old->mnt_expire)) + list_add(&mnt->mnt_expire, &old->mnt_expire); } } return mnt; @@ -1233,7 +1233,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) propagate_umount(&tmp_list); list_for_each_entry(p, &tmp_list, mnt_hash) { - list_del_init(&p->mnt.mnt_expire); + list_del_init(&p->mnt_expire); list_del_init(&p->mnt.mnt_list); __touch_mnt_namespace(p->mnt.mnt_ns); p->mnt.mnt_ns = NULL; @@ -1921,7 +1921,7 @@ static int do_move_mount(struct path *path, char *old_name) /* if the mount is moved, it should no longer be expire * automatically */ - list_del_init(&old_path.mnt->mnt_expire); + list_del_init(&old->mnt_expire); out1: unlock_mount(path); out: @@ -2033,11 +2033,12 @@ static int do_new_mount(struct path *path, char *type, int flags, int finish_automount(struct vfsmount *m, struct path *path) { + struct mount *mnt = real_mount(m); int err; /* The new mount record should have at least 2 refs to prevent it being * expired before we get a chance to add it */ - BUG_ON(mnt_get_count(real_mount(m)) < 2); + BUG_ON(mnt_get_count(mnt) < 2); if (m->mnt_sb == path->mnt->mnt_sb && m->mnt_root == path->dentry) { @@ -2050,10 +2051,10 @@ int finish_automount(struct vfsmount *m, struct path *path) return 0; fail: /* remove m from any expiration list it may be on */ - if (!list_empty(&m->mnt_expire)) { + if (!list_empty(&mnt->mnt_expire)) { down_write(&namespace_sem); br_write_lock(vfsmount_lock); - list_del_init(&m->mnt_expire); + list_del_init(&mnt->mnt_expire); br_write_unlock(vfsmount_lock); up_write(&namespace_sem); } @@ -2072,7 +2073,7 @@ void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list) down_write(&namespace_sem); br_write_lock(vfsmount_lock); - list_add_tail(&mnt->mnt_expire, expiry_list); + list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list); br_write_unlock(vfsmount_lock); up_write(&namespace_sem); @@ -2102,14 +2103,14 @@ void mark_mounts_for_expiry(struct list_head *mounts) * - still marked for expiry (marked on the last call here; marks are * cleared by mntput()) */ - list_for_each_entry_safe(mnt, next, mounts, mnt.mnt_expire) { + list_for_each_entry_safe(mnt, next, mounts, mnt_expire) { if (!xchg(&mnt->mnt.mnt_expiry_mark, 1) || propagate_mount_busy(mnt, 1)) continue; - list_move(&mnt->mnt.mnt_expire, &graveyard); + list_move(&mnt->mnt_expire, &graveyard); } while (!list_empty(&graveyard)) { - mnt = list_first_entry(&graveyard, struct mount, mnt.mnt_expire); + mnt = list_first_entry(&graveyard, struct mount, mnt_expire); touch_mnt_namespace(mnt->mnt.mnt_ns); umount_tree(mnt, 1, &umounts); } @@ -2152,7 +2153,7 @@ resume: } if (!propagate_mount_busy(mnt, 1)) { - list_move_tail(&mnt->mnt.mnt_expire, graveyard); + list_move_tail(&mnt->mnt_expire, graveyard); found++; } } @@ -2182,7 +2183,7 @@ static void shrink_submounts(struct mount *mnt, struct list_head *umounts) while (select_submounts(mnt, &graveyard)) { while (!list_empty(&graveyard)) { m = list_first_entry(&graveyard, struct mount, - mnt.mnt_expire); + mnt_expire); touch_mnt_namespace(m->mnt.mnt_ns); umount_tree(m, 1, umounts); } -- cgit v1.2.3 From 95bc5f25c10fcdf02c53af1eda987f58d0bc377c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 00:30:56 -0500 Subject: vfs: spread struct mount - do_add_mount and graft_tree Signed-off-by: Al Viro --- fs/namespace.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index a14750be7a70..6b5e0436acfd 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1666,19 +1666,19 @@ static void unlock_mount(struct path *path) mutex_unlock(&path->dentry->d_inode->i_mutex); } -static int graft_tree(struct vfsmount *mnt, struct path *path) +static int graft_tree(struct mount *mnt, struct path *path) { - if (mnt->mnt_sb->s_flags & MS_NOUSER) + if (mnt->mnt.mnt_sb->s_flags & MS_NOUSER) return -EINVAL; if (S_ISDIR(path->dentry->d_inode->i_mode) != - S_ISDIR(mnt->mnt_root->d_inode->i_mode)) + S_ISDIR(mnt->mnt.mnt_root->d_inode->i_mode)) return -ENOTDIR; if (d_unlinked(path->dentry)) return -ENOENT; - return attach_recursive_mnt(real_mount(mnt), path, NULL); + return attach_recursive_mnt(mnt, path, NULL); } /* @@ -1776,7 +1776,7 @@ static int do_loopback(struct path *path, char *old_name, if (!mnt) goto out2; - err = graft_tree(&mnt->mnt, path); + err = graft_tree(mnt, path); if (err) { br_write_lock(vfsmount_lock); umount_tree(mnt, 0, &umount_list); @@ -1972,7 +1972,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data) /* * add a mount into a namespace's mount tree */ -static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) +static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags) { int err; @@ -1988,15 +1988,15 @@ static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flag /* Refuse the same filesystem on the same mount point */ err = -EBUSY; - if (path->mnt->mnt_sb == newmnt->mnt_sb && + if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb && path->mnt->mnt_root == path->dentry) goto unlock; err = -EINVAL; - if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode)) + if (S_ISLNK(newmnt->mnt.mnt_root->d_inode->i_mode)) goto unlock; - newmnt->mnt_flags = mnt_flags; + newmnt->mnt.mnt_flags = mnt_flags; err = graft_tree(newmnt, path); unlock: @@ -2025,7 +2025,7 @@ static int do_new_mount(struct path *path, char *type, int flags, if (IS_ERR(mnt)) return PTR_ERR(mnt); - err = do_add_mount(mnt, path, mnt_flags); + err = do_add_mount(real_mount(mnt), path, mnt_flags); if (err) mntput(mnt); return err; @@ -2046,7 +2046,7 @@ int finish_automount(struct vfsmount *m, struct path *path) goto fail; } - err = do_add_mount(m, path, path->mnt->mnt_flags | MNT_SHRINKABLE); + err = do_add_mount(mnt, path, path->mnt->mnt_flags | MNT_SHRINKABLE); if (!err) return 0; fail: -- cgit v1.2.3 From 900148dcac6bc93ca688d64a7f9a9f8d706e0d1c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 00:33:11 -0500 Subject: vfs: spread struct mount - mntput_no_expire Signed-off-by: Al Viro --- fs/namespace.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 6b5e0436acfd..3e95cc26dda6 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -763,9 +763,8 @@ static inline void mntfree(struct mount *mnt) deactivate_super(sb); } -static void mntput_no_expire(struct vfsmount *m) +static void mntput_no_expire(struct mount *mnt) { - struct mount *mnt = real_mount(m); put_again: #ifdef CONFIG_SMP br_read_lock(vfsmount_lock); @@ -792,7 +791,7 @@ put_again: mnt_add_count(mnt, mnt->mnt.mnt_pinned + 1); mnt->mnt.mnt_pinned = 0; br_write_unlock(vfsmount_lock); - acct_auto_close_mnt(m); + acct_auto_close_mnt(&mnt->mnt); goto put_again; } br_write_unlock(vfsmount_lock); @@ -805,7 +804,7 @@ void mntput(struct vfsmount *mnt) /* avoid cacheline pingpong, hope gcc doesn't get "smart" */ if (unlikely(mnt->mnt_expiry_mark)) mnt->mnt_expiry_mark = 0; - mntput_no_expire(mnt); + mntput_no_expire(real_mount(mnt)); } } EXPORT_SYMBOL(mntput); @@ -1351,6 +1350,7 @@ static int do_umount(struct mount *mnt, int flags) SYSCALL_DEFINE2(umount, char __user *, name, int, flags) { struct path path; + struct mount *mnt; int retval; int lookup_flags = 0; @@ -1363,6 +1363,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) retval = user_path_at(AT_FDCWD, name, lookup_flags, &path); if (retval) goto out; + mnt = real_mount(path.mnt); retval = -EINVAL; if (path.dentry != path.mnt->mnt_root) goto dput_and_out; @@ -1373,11 +1374,11 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) if (!capable(CAP_SYS_ADMIN)) goto dput_and_out; - retval = do_umount(real_mount(path.mnt), flags); + retval = do_umount(mnt, flags); dput_and_out: /* we mustn't call path_put() as that would clear mnt_expiry_mark */ dput(path.dentry); - mntput_no_expire(path.mnt); + mntput_no_expire(mnt); out: return retval; } -- cgit v1.2.3 From 143c8c91cee7efdd732ec5f61b3471fc46192f20 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 00:46:35 -0500 Subject: vfs: mnt_ns moved to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 3e95cc26dda6..4cdb7f698613 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -505,7 +505,7 @@ struct vfsmount *lookup_mnt(struct path *path) } } -static inline int check_mnt(struct vfsmount *mnt) +static inline int check_mnt(struct mount *mnt) { return mnt->mnt_ns == current->nsproxy->mnt_ns; } @@ -614,13 +614,13 @@ static void commit_tree(struct mount *mnt) struct mount *parent = mnt->mnt_parent; struct mount *m; LIST_HEAD(head); - struct mnt_namespace *n = parent->mnt.mnt_ns; + struct mnt_namespace *n = parent->mnt_ns; BUG_ON(parent == mnt); list_add_tail(&head, &mnt->mnt.mnt_list); list_for_each_entry(m, &head, mnt.mnt_list) { - m->mnt.mnt_ns = n; + m->mnt_ns = n; __mnt_make_longterm(m); } @@ -1234,8 +1234,8 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) list_for_each_entry(p, &tmp_list, mnt_hash) { list_del_init(&p->mnt_expire); list_del_init(&p->mnt.mnt_list); - __touch_mnt_namespace(p->mnt.mnt_ns); - p->mnt.mnt_ns = NULL; + __touch_mnt_namespace(p->mnt_ns); + p->mnt_ns = NULL; __mnt_make_shortterm(p); list_del_init(&p->mnt_child); if (mnt_has_parent(p)) { @@ -1367,7 +1367,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) retval = -EINVAL; if (path.dentry != path.mnt->mnt_root) goto dput_and_out; - if (!check_mnt(path.mnt)) + if (!check_mnt(mnt)) goto dput_and_out; retval = -EPERM; @@ -1619,7 +1619,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, if (parent_path) { detach_mnt(source_mnt, parent_path); attach_mnt(source_mnt, path); - touch_mnt_namespace(parent_path->mnt->mnt_ns); + touch_mnt_namespace(source_mnt->mnt_ns); } else { mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); commit_tree(source_mnt); @@ -1765,7 +1765,7 @@ static int do_loopback(struct path *path, char *old_name, if (IS_MNT_UNBINDABLE(old_path.mnt)) goto out2; - if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) + if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old)) goto out2; err = -ENOMEM; @@ -1818,11 +1818,12 @@ static int do_remount(struct path *path, int flags, int mnt_flags, { int err; struct super_block *sb = path->mnt->mnt_sb; + struct mount *mnt = real_mount(path->mnt); if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!check_mnt(path->mnt)) + if (!check_mnt(mnt)) return -EINVAL; if (path->dentry != path->mnt->mnt_root) @@ -1839,14 +1840,14 @@ static int do_remount(struct path *path, int flags, int mnt_flags, err = do_remount_sb(sb, flags, data, 0); if (!err) { br_write_lock(vfsmount_lock); - mnt_flags |= path->mnt->mnt_flags & MNT_PROPAGATION_MASK; - path->mnt->mnt_flags = mnt_flags; + mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK; + mnt->mnt.mnt_flags = mnt_flags; br_write_unlock(vfsmount_lock); } up_write(&sb->s_umount); if (!err) { br_write_lock(vfsmount_lock); - touch_mnt_namespace(path->mnt->mnt_ns); + touch_mnt_namespace(mnt->mnt_ns); br_write_unlock(vfsmount_lock); } return err; @@ -1880,8 +1881,10 @@ static int do_move_mount(struct path *path, char *old_name) if (err < 0) goto out; + old = real_mount(old_path.mnt); + err = -EINVAL; - if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) + if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old)) goto out1; if (d_unlinked(path->dentry)) @@ -1891,8 +1894,6 @@ static int do_move_mount(struct path *path, char *old_name) if (old_path.dentry != old_path.mnt->mnt_root) goto out1; - old = real_mount(old_path.mnt); - if (!mnt_has_parent(old)) goto out1; @@ -1984,7 +1985,7 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags) return err; err = -EINVAL; - if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt)) + if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(real_mount(path->mnt))) goto unlock; /* Refuse the same filesystem on the same mount point */ @@ -2112,7 +2113,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) } while (!list_empty(&graveyard)) { mnt = list_first_entry(&graveyard, struct mount, mnt_expire); - touch_mnt_namespace(mnt->mnt.mnt_ns); + touch_mnt_namespace(mnt->mnt_ns); umount_tree(mnt, 1, &umounts); } br_write_unlock(vfsmount_lock); @@ -2185,7 +2186,7 @@ static void shrink_submounts(struct mount *mnt, struct list_head *umounts) while (!list_empty(&graveyard)) { m = list_first_entry(&graveyard, struct mount, mnt_expire); - touch_mnt_namespace(m->mnt.mnt_ns); + touch_mnt_namespace(m->mnt_ns); umount_tree(m, 1, umounts); } } @@ -2423,7 +2424,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, p = real_mount(mnt_ns->root); q = new; while (p) { - q->mnt.mnt_ns = new_ns; + q->mnt_ns = new_ns; __mnt_make_longterm(q); if (fs) { if (&p->mnt == fs->root.mnt) { @@ -2479,7 +2480,7 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) new_ns = alloc_mnt_ns(); if (!IS_ERR(new_ns)) { - mnt->mnt_ns = new_ns; + real_mount(mnt)->mnt_ns = new_ns; __mnt_make_longterm(real_mount(mnt)); new_ns->root = mnt; list_add(&new_ns->list, &new_ns->root->mnt_list); @@ -2644,7 +2645,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, IS_MNT_SHARED(&new_mnt->mnt_parent->mnt) || IS_MNT_SHARED(&root_mnt->mnt_parent->mnt)) goto out4; - if (!check_mnt(root.mnt) || !check_mnt(new.mnt)) + if (!check_mnt(root_mnt) || !check_mnt(new_mnt)) goto out4; error = -ENOENT; if (d_unlinked(new.dentry)) @@ -2793,5 +2794,5 @@ EXPORT_SYMBOL(kern_unmount); bool our_mnt(struct vfsmount *mnt) { - return check_mnt(mnt); + return check_mnt(real_mount(mnt)); } -- cgit v1.2.3 From 15169fe784a9846b24cdb0840329d41aebc23249 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 00:50:41 -0500 Subject: vfs: mnt_id/mnt_group_id moved Signed-off-by: Al Viro --- fs/namespace.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 4cdb7f698613..dfed9a25f204 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -85,9 +85,9 @@ static int mnt_alloc_id(struct mount *mnt) retry: ida_pre_get(&mnt_id_ida, GFP_KERNEL); spin_lock(&mnt_id_lock); - res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt.mnt_id); + res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id); if (!res) - mnt_id_start = mnt->mnt.mnt_id + 1; + mnt_id_start = mnt->mnt_id + 1; spin_unlock(&mnt_id_lock); if (res == -EAGAIN) goto retry; @@ -97,7 +97,7 @@ retry: static void mnt_free_id(struct mount *mnt) { - int id = mnt->mnt.mnt_id; + int id = mnt->mnt_id; spin_lock(&mnt_id_lock); ida_remove(&mnt_id_ida, id); if (mnt_id_start > id) @@ -119,9 +119,9 @@ static int mnt_alloc_group_id(struct mount *mnt) res = ida_get_new_above(&mnt_group_ida, mnt_group_start, - &mnt->mnt.mnt_group_id); + &mnt->mnt_group_id); if (!res) - mnt_group_start = mnt->mnt.mnt_group_id + 1; + mnt_group_start = mnt->mnt_group_id + 1; return res; } @@ -131,11 +131,11 @@ static int mnt_alloc_group_id(struct mount *mnt) */ void mnt_release_group_id(struct mount *mnt) { - int id = mnt->mnt.mnt_group_id; + int id = mnt->mnt_group_id; ida_remove(&mnt_group_ida, id); if (mnt_group_start > id) mnt_group_start = id; - mnt->mnt.mnt_group_id = 0; + mnt->mnt_group_id = 0; } /* @@ -696,11 +696,11 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, if (mnt) { if (flag & (CL_SLAVE | CL_PRIVATE)) - mnt->mnt.mnt_group_id = 0; /* not a peer of original */ + mnt->mnt_group_id = 0; /* not a peer of original */ else - mnt->mnt.mnt_group_id = old->mnt.mnt_group_id; + mnt->mnt_group_id = old->mnt_group_id; - if ((flag & CL_MAKE_SHARED) && !mnt->mnt.mnt_group_id) { + if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) { int err = mnt_alloc_group_id(mnt); if (err) goto out_free; @@ -1029,7 +1029,7 @@ static int show_mountinfo(struct seq_file *m, void *v) struct path root = p->root; int err = 0; - seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, r->mnt_parent->mnt.mnt_id, + seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id, MAJOR(sb->s_dev), MINOR(sb->s_dev)); if (sb->s_op->show_path) err = sb->s_op->show_path(m, mnt); @@ -1049,9 +1049,9 @@ static int show_mountinfo(struct seq_file *m, void *v) /* Tagged fields ("foo:X" or "bar") */ if (IS_MNT_SHARED(mnt)) - seq_printf(m, " shared:%i", mnt->mnt_group_id); + seq_printf(m, " shared:%i", r->mnt_group_id); if (IS_MNT_SLAVE(r)) { - int master = r->mnt_master->mnt.mnt_group_id; + int master = r->mnt_master->mnt_group_id; int dom = get_dominating_id(r, &p->root); seq_printf(m, " master:%i", master); if (dom && dom != master) @@ -1507,7 +1507,7 @@ static void cleanup_group_ids(struct mount *mnt, struct mount *end) struct mount *p; for (p = mnt; p != end; p = next_mnt(p, &mnt->mnt)) { - if (p->mnt.mnt_group_id && !IS_MNT_SHARED(&p->mnt)) + if (p->mnt_group_id && !IS_MNT_SHARED(&p->mnt)) mnt_release_group_id(p); } } @@ -1517,7 +1517,7 @@ static int invent_group_ids(struct mount *mnt, bool recurse) struct mount *p; for (p = mnt; p; p = recurse ? next_mnt(p, &mnt->mnt) : NULL) { - if (!p->mnt.mnt_group_id && !IS_MNT_SHARED(&p->mnt)) { + if (!p->mnt_group_id && !IS_MNT_SHARED(&p->mnt)) { int err = mnt_alloc_group_id(p); if (err) { cleanup_group_ids(mnt, p); -- cgit v1.2.3 From 863d684f946eb240c7dd57d265d88315950ca5cc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 00:57:42 -0500 Subject: vfs: move the rest of int fields to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index dfed9a25f204..c7b8dbc88fe5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -787,9 +787,9 @@ put_again: return; br_write_lock(vfsmount_lock); #endif - if (unlikely(mnt->mnt.mnt_pinned)) { - mnt_add_count(mnt, mnt->mnt.mnt_pinned + 1); - mnt->mnt.mnt_pinned = 0; + if (unlikely(mnt->mnt_pinned)) { + mnt_add_count(mnt, mnt->mnt_pinned + 1); + mnt->mnt_pinned = 0; br_write_unlock(vfsmount_lock); acct_auto_close_mnt(&mnt->mnt); goto put_again; @@ -801,10 +801,11 @@ put_again: void mntput(struct vfsmount *mnt) { if (mnt) { + struct mount *m = real_mount(mnt); /* avoid cacheline pingpong, hope gcc doesn't get "smart" */ - if (unlikely(mnt->mnt_expiry_mark)) - mnt->mnt_expiry_mark = 0; - mntput_no_expire(real_mount(mnt)); + if (unlikely(m->mnt_expiry_mark)) + m->mnt_expiry_mark = 0; + mntput_no_expire(m); } } EXPORT_SYMBOL(mntput); @@ -820,16 +821,17 @@ EXPORT_SYMBOL(mntget); void mnt_pin(struct vfsmount *mnt) { br_write_lock(vfsmount_lock); - mnt->mnt_pinned++; + real_mount(mnt)->mnt_pinned++; br_write_unlock(vfsmount_lock); } EXPORT_SYMBOL(mnt_pin); -void mnt_unpin(struct vfsmount *mnt) +void mnt_unpin(struct vfsmount *m) { + struct mount *mnt = real_mount(m); br_write_lock(vfsmount_lock); if (mnt->mnt_pinned) { - mnt_add_count(real_mount(mnt), 1); + mnt_add_count(mnt, 1); mnt->mnt_pinned--; } br_write_unlock(vfsmount_lock); @@ -1200,17 +1202,17 @@ void release_mounts(struct list_head *head) list_del_init(&mnt->mnt_hash); if (mnt_has_parent(mnt)) { struct dentry *dentry; - struct vfsmount *m; + struct mount *m; br_write_lock(vfsmount_lock); dentry = mnt->mnt_mountpoint; - m = &mnt->mnt_parent->mnt; + m = mnt->mnt_parent; mnt->mnt_mountpoint = mnt->mnt.mnt_root; mnt->mnt_parent = mnt; m->mnt_ghosts--; br_write_unlock(vfsmount_lock); dput(dentry); - mntput(m); + mntput(&m->mnt); } mntput(&mnt->mnt); } @@ -1239,7 +1241,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) __mnt_make_shortterm(p); list_del_init(&p->mnt_child); if (mnt_has_parent(p)) { - p->mnt_parent->mnt.mnt_ghosts++; + p->mnt_parent->mnt_ghosts++; dentry_reset_mounted(p->mnt_mountpoint); } change_mnt_propagation(p, MS_PRIVATE); @@ -1281,7 +1283,7 @@ static int do_umount(struct mount *mnt, int flags) } br_write_unlock(vfsmount_lock); - if (!xchg(&mnt->mnt.mnt_expiry_mark, 1)) + if (!xchg(&mnt->mnt_expiry_mark, 1)) return -EAGAIN; } @@ -2106,7 +2108,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) * cleared by mntput()) */ list_for_each_entry_safe(mnt, next, mounts, mnt_expire) { - if (!xchg(&mnt->mnt.mnt_expiry_mark, 1) || + if (!xchg(&mnt->mnt_expiry_mark, 1) || propagate_mount_busy(mnt, 1)) continue; list_move(&mnt->mnt_expire, &graveyard); -- cgit v1.2.3 From fc7be130c7e91cf693d4bc2d9b11f08a5a4893d0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 01:05:37 -0500 Subject: vfs: switch pnode.h macros to struct mount * Signed-off-by: Al Viro --- fs/namespace.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index c7b8dbc88fe5..bbe24defcac7 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -716,9 +716,9 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, if (flag & CL_SLAVE) { list_add(&mnt->mnt_slave, &old->mnt_slave_list); mnt->mnt_master = old; - CLEAR_MNT_SHARED(&mnt->mnt); + CLEAR_MNT_SHARED(mnt); } else if (!(flag & CL_PRIVATE)) { - if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(&old->mnt)) + if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old)) list_add(&mnt->mnt_share, &old->mnt_share); if (IS_MNT_SLAVE(old)) list_add(&mnt->mnt_slave, &old->mnt_slave); @@ -1050,7 +1050,7 @@ static int show_mountinfo(struct seq_file *m, void *v) show_mnt_opts(m, mnt); /* Tagged fields ("foo:X" or "bar") */ - if (IS_MNT_SHARED(mnt)) + if (IS_MNT_SHARED(r)) seq_printf(m, " shared:%i", r->mnt_group_id); if (IS_MNT_SLAVE(r)) { int master = r->mnt_master->mnt_group_id; @@ -1059,7 +1059,7 @@ static int show_mountinfo(struct seq_file *m, void *v) if (dom && dom != master) seq_printf(m, " propagate_from:%i", dom); } - if (IS_MNT_UNBINDABLE(mnt)) + if (IS_MNT_UNBINDABLE(r)) seq_puts(m, " unbindable"); /* Filesystem specific data */ @@ -1421,7 +1421,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, struct mount *res, *p, *q, *r; struct path path; - if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(&mnt->mnt)) + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) return NULL; res = q = clone_mnt(mnt, dentry, flag); @@ -1436,7 +1436,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, continue; for (s = r; s; s = next_mnt(s, &r->mnt)) { - if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(&s->mnt)) { + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(s)) { s = skip_mnt_tree(s); continue; } @@ -1509,7 +1509,7 @@ static void cleanup_group_ids(struct mount *mnt, struct mount *end) struct mount *p; for (p = mnt; p != end; p = next_mnt(p, &mnt->mnt)) { - if (p->mnt_group_id && !IS_MNT_SHARED(&p->mnt)) + if (p->mnt_group_id && !IS_MNT_SHARED(p)) mnt_release_group_id(p); } } @@ -1519,7 +1519,7 @@ static int invent_group_ids(struct mount *mnt, bool recurse) struct mount *p; for (p = mnt; p; p = recurse ? next_mnt(p, &mnt->mnt) : NULL) { - if (!p->mnt_group_id && !IS_MNT_SHARED(&p->mnt)) { + if (!p->mnt_group_id && !IS_MNT_SHARED(p)) { int err = mnt_alloc_group_id(p); if (err) { cleanup_group_ids(mnt, p); @@ -1603,7 +1603,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, struct mount *child, *p; int err; - if (IS_MNT_SHARED(&dest_mnt->mnt)) { + if (IS_MNT_SHARED(dest_mnt)) { err = invent_group_ids(source_mnt, true); if (err) goto out; @@ -1614,7 +1614,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, br_write_lock(vfsmount_lock); - if (IS_MNT_SHARED(&dest_mnt->mnt)) { + if (IS_MNT_SHARED(dest_mnt)) { for (p = source_mnt; p; p = next_mnt(p, &source_mnt->mnt)) set_mnt_shared(p); } @@ -1636,7 +1636,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, return 0; out_cleanup_ids: - if (IS_MNT_SHARED(&dest_mnt->mnt)) + if (IS_MNT_SHARED(dest_mnt)) cleanup_group_ids(source_mnt, NULL); out: return err; @@ -1764,7 +1764,7 @@ static int do_loopback(struct path *path, char *old_name, old = real_mount(old_path.mnt); err = -EINVAL; - if (IS_MNT_UNBINDABLE(old_path.mnt)) + if (IS_MNT_UNBINDABLE(old)) goto out2; if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old)) @@ -1859,7 +1859,7 @@ static inline int tree_contains_unbindable(struct mount *mnt) { struct mount *p; for (p = mnt; p; p = next_mnt(p, &mnt->mnt)) { - if (IS_MNT_UNBINDABLE(&p->mnt)) + if (IS_MNT_UNBINDABLE(p)) return 1; } return 0; @@ -1884,9 +1884,10 @@ static int do_move_mount(struct path *path, char *old_name) goto out; old = real_mount(old_path.mnt); + p = real_mount(path->mnt); err = -EINVAL; - if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old)) + if (!check_mnt(p) || !check_mnt(old)) goto out1; if (d_unlinked(path->dentry)) @@ -1905,17 +1906,16 @@ static int do_move_mount(struct path *path, char *old_name) /* * Don't move a mount residing in a shared parent. */ - if (IS_MNT_SHARED(&old->mnt_parent->mnt)) + if (IS_MNT_SHARED(old->mnt_parent)) goto out1; /* * Don't move a mount tree containing unbindable mounts to a destination * mount which is shared. */ - if (IS_MNT_SHARED(path->mnt) && - tree_contains_unbindable(old)) + if (IS_MNT_SHARED(p) && tree_contains_unbindable(old)) goto out1; err = -ELOOP; - for (p = real_mount(path->mnt); mnt_has_parent(p); p = p->mnt_parent) + for (; mnt_has_parent(p); p = p->mnt_parent) if (p == old) goto out1; @@ -2643,9 +2643,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, error = -EINVAL; new_mnt = real_mount(new.mnt); root_mnt = real_mount(root.mnt); - if (IS_MNT_SHARED(old.mnt) || - IS_MNT_SHARED(&new_mnt->mnt_parent->mnt) || - IS_MNT_SHARED(&root_mnt->mnt_parent->mnt)) + if (IS_MNT_SHARED(real_mount(old.mnt)) || + IS_MNT_SHARED(new_mnt->mnt_parent) || + IS_MNT_SHARED(root_mnt->mnt_parent)) goto out4; if (!check_mnt(root_mnt) || !check_mnt(new_mnt)) goto out4; -- cgit v1.2.3 From 1a4eeaf2a8c07404e2d1c3ff99b393fd4c207170 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 02:19:55 -0500 Subject: vfs: move mnt_list to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index bbe24defcac7..e15125356ac1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -202,7 +202,7 @@ static struct mount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&p->mnt_hash); INIT_LIST_HEAD(&p->mnt_child); INIT_LIST_HEAD(&p->mnt_mounts); - INIT_LIST_HEAD(&mnt->mnt_list); + INIT_LIST_HEAD(&p->mnt_list); INIT_LIST_HEAD(&p->mnt_expire); INIT_LIST_HEAD(&p->mnt_share); INIT_LIST_HEAD(&p->mnt_slave_list); @@ -618,8 +618,8 @@ static void commit_tree(struct mount *mnt) BUG_ON(parent == mnt); - list_add_tail(&head, &mnt->mnt.mnt_list); - list_for_each_entry(m, &head, mnt.mnt_list) { + list_add_tail(&head, &mnt->mnt_list); + list_for_each_entry(m, &head, mnt_list) { m->mnt_ns = n; __mnt_make_longterm(m); } @@ -987,7 +987,8 @@ static void show_type(struct seq_file *m, struct super_block *sb) static int show_vfsmnt(struct seq_file *m, void *v) { - struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); + struct mount *r = list_entry(v, struct mount, mnt_list); + struct vfsmount *mnt = &r->mnt; int err = 0; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; @@ -1024,8 +1025,8 @@ const struct seq_operations mounts_op = { static int show_mountinfo(struct seq_file *m, void *v) { struct proc_mounts *p = m->private; - struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); - struct mount *r = real_mount(mnt); + struct mount *r = list_entry(v, struct mount, mnt_list); + struct vfsmount *mnt = &r->mnt; struct super_block *sb = mnt->mnt_sb; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; struct path root = p->root; @@ -1092,7 +1093,8 @@ const struct seq_operations mountinfo_op = { static int show_vfsstat(struct seq_file *m, void *v) { - struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); + struct mount *r = list_entry(v, struct mount, mnt_list); + struct vfsmount *mnt = &r->mnt; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; int err = 0; @@ -1235,7 +1237,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) list_for_each_entry(p, &tmp_list, mnt_hash) { list_del_init(&p->mnt_expire); - list_del_init(&p->mnt.mnt_list); + list_del_init(&p->mnt_list); __touch_mnt_namespace(p->mnt_ns); p->mnt_ns = NULL; __mnt_make_shortterm(p); @@ -1331,7 +1333,7 @@ static int do_umount(struct mount *mnt, int flags) retval = -EBUSY; if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { - if (!list_empty(&mnt->mnt.mnt_list)) + if (!list_empty(&mnt->mnt_list)) umount_tree(mnt, 1, &umount_list); retval = 0; } @@ -1451,7 +1453,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, if (!q) goto Enomem; br_write_lock(vfsmount_lock); - list_add_tail(&q->mnt.mnt_list, &res->mnt.mnt_list); + list_add_tail(&q->mnt_list, &res->mnt_list); attach_mnt(q, &path); br_write_unlock(vfsmount_lock); } @@ -1492,12 +1494,12 @@ void drop_collected_mounts(struct vfsmount *mnt) int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, struct vfsmount *root) { - struct vfsmount *mnt; + struct mount *mnt; int res = f(root, arg); if (res) return res; - list_for_each_entry(mnt, &root->mnt_list, mnt_list) { - res = f(mnt, arg); + list_for_each_entry(mnt, &real_mount(root)->mnt_list, mnt_list) { + res = f(&mnt->mnt, arg); if (res) return res; } @@ -2415,7 +2417,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, } new_ns->root = &new->mnt; br_write_lock(vfsmount_lock); - list_add_tail(&new_ns->list, &new_ns->root->mnt_list); + list_add_tail(&new_ns->list, &new->mnt_list); br_write_unlock(vfsmount_lock); /* @@ -2476,18 +2478,17 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, * create_mnt_ns - creates a private namespace and adds a root filesystem * @mnt: pointer to the new root filesystem mountpoint */ -static struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) +static struct mnt_namespace *create_mnt_ns(struct vfsmount *m) { - struct mnt_namespace *new_ns; - - new_ns = alloc_mnt_ns(); + struct mnt_namespace *new_ns = alloc_mnt_ns(); if (!IS_ERR(new_ns)) { - real_mount(mnt)->mnt_ns = new_ns; - __mnt_make_longterm(real_mount(mnt)); - new_ns->root = mnt; - list_add(&new_ns->list, &new_ns->root->mnt_list); + struct mount *mnt = real_mount(m); + mnt->mnt_ns = new_ns; + __mnt_make_longterm(mnt); + new_ns->root = m; + list_add(&new_ns->list, &mnt->mnt_list); } else { - mntput(mnt); + mntput(m); } return new_ns; } -- cgit v1.2.3 From 52ba1621de1479ce7e52b6d167860462e483313c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 02:25:17 -0500 Subject: vfs: move mnt_devname Signed-off-by: Al Viro --- fs/namespace.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index e15125356ac1..b8a30928d0c1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -183,8 +183,8 @@ static struct mount *alloc_vfsmnt(const char *name) goto out_free_cache; if (name) { - mnt->mnt_devname = kstrdup(name, GFP_KERNEL); - if (!mnt->mnt_devname) + p->mnt_devname = kstrdup(name, GFP_KERNEL); + if (!p->mnt_devname) goto out_free_id; } @@ -215,7 +215,7 @@ static struct mount *alloc_vfsmnt(const char *name) #ifdef CONFIG_SMP out_free_devname: - kfree(p->mnt.mnt_devname); + kfree(p->mnt_devname); #endif out_free_id: mnt_free_id(p); @@ -451,7 +451,7 @@ static void __mnt_unmake_readonly(struct mount *mnt) static void free_vfsmnt(struct mount *mnt) { - kfree(mnt->mnt.mnt_devname); + kfree(mnt->mnt_devname); mnt_free_id(mnt); #ifdef CONFIG_SMP free_percpu(mnt->mnt_pcp); @@ -692,7 +692,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, int flag) { struct super_block *sb = old->mnt.mnt_sb; - struct mount *mnt = alloc_vfsmnt(old->mnt.mnt_devname); + struct mount *mnt = alloc_vfsmnt(old->mnt_devname); if (mnt) { if (flag & (CL_SLAVE | CL_PRIVATE)) @@ -997,7 +997,7 @@ static int show_vfsmnt(struct seq_file *m, void *v) if (err) goto out; } else { - mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); + mangle(m, r->mnt_devname ? r->mnt_devname : "none"); } seq_putc(m, ' '); seq_path(m, &mnt_path, " \t\n\\"); @@ -1070,7 +1070,7 @@ static int show_mountinfo(struct seq_file *m, void *v) if (sb->s_op->show_devname) err = sb->s_op->show_devname(m, mnt); else - mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); + mangle(m, r->mnt_devname ? r->mnt_devname : "none"); if (err) goto out; seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); @@ -1103,9 +1103,9 @@ static int show_vfsstat(struct seq_file *m, void *v) seq_puts(m, "device "); err = mnt->mnt_sb->s_op->show_devname(m, mnt); } else { - if (mnt->mnt_devname) { + if (r->mnt_devname) { seq_puts(m, "device "); - mangle(m, mnt->mnt_devname); + mangle(m, r->mnt_devname); } else seq_puts(m, "no device"); } -- cgit v1.2.3 From c63181e6b6df89176b3984c6977bb5ec03d0df23 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 02:35:16 -0500 Subject: vfs: move fsnotify junk to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index b8a30928d0c1..124a12555fe4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -173,54 +173,53 @@ unsigned int mnt_get_count(struct mount *mnt) static struct mount *alloc_vfsmnt(const char *name) { - struct mount *p = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); - if (p) { - struct vfsmount *mnt = &p->mnt; + struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); + if (mnt) { int err; - err = mnt_alloc_id(p); + err = mnt_alloc_id(mnt); if (err) goto out_free_cache; if (name) { - p->mnt_devname = kstrdup(name, GFP_KERNEL); - if (!p->mnt_devname) + mnt->mnt_devname = kstrdup(name, GFP_KERNEL); + if (!mnt->mnt_devname) goto out_free_id; } #ifdef CONFIG_SMP - p->mnt_pcp = alloc_percpu(struct mnt_pcp); - if (!p->mnt_pcp) + mnt->mnt_pcp = alloc_percpu(struct mnt_pcp); + if (!mnt->mnt_pcp) goto out_free_devname; - this_cpu_add(p->mnt_pcp->mnt_count, 1); + this_cpu_add(mnt->mnt_pcp->mnt_count, 1); #else - p->mnt_count = 1; - p->mnt_writers = 0; + mnt->mnt_count = 1; + mnt->mnt_writers = 0; #endif - INIT_LIST_HEAD(&p->mnt_hash); - INIT_LIST_HEAD(&p->mnt_child); - INIT_LIST_HEAD(&p->mnt_mounts); - INIT_LIST_HEAD(&p->mnt_list); - INIT_LIST_HEAD(&p->mnt_expire); - INIT_LIST_HEAD(&p->mnt_share); - INIT_LIST_HEAD(&p->mnt_slave_list); - INIT_LIST_HEAD(&p->mnt_slave); + INIT_LIST_HEAD(&mnt->mnt_hash); + INIT_LIST_HEAD(&mnt->mnt_child); + INIT_LIST_HEAD(&mnt->mnt_mounts); + INIT_LIST_HEAD(&mnt->mnt_list); + INIT_LIST_HEAD(&mnt->mnt_expire); + INIT_LIST_HEAD(&mnt->mnt_share); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + INIT_LIST_HEAD(&mnt->mnt_slave); #ifdef CONFIG_FSNOTIFY INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks); #endif } - return p; + return mnt; #ifdef CONFIG_SMP out_free_devname: - kfree(p->mnt_devname); + kfree(mnt->mnt_devname); #endif out_free_id: - mnt_free_id(p); + mnt_free_id(mnt); out_free_cache: - kmem_cache_free(mnt_cache, p); + kmem_cache_free(mnt_cache, mnt); return NULL; } -- cgit v1.2.3 From 909b0a88ef2dc86bd5d2223edf48eb30c865cb69 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 03:06:56 -0500 Subject: vfs: spread struct mount - remaining argument of next_mnt() Signed-off-by: Al Viro --- fs/namespace.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 124a12555fe4..24e845671ad3 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -631,12 +631,12 @@ static void commit_tree(struct mount *mnt) touch_mnt_namespace(n); } -static struct mount *next_mnt(struct mount *p, struct vfsmount *root) +static struct mount *next_mnt(struct mount *p, struct mount *root) { struct list_head *next = p->mnt_mounts.next; if (next == &p->mnt_mounts) { while (1) { - if (&p->mnt == root) + if (p == root) return NULL; next = p->mnt_child.next; if (next != &p->mnt_parent->mnt_mounts) @@ -1145,16 +1145,17 @@ const struct seq_operations mountstats_op = { * open files, pwds, chroots or sub mounts that are * busy. */ -int may_umount_tree(struct vfsmount *mnt) +int may_umount_tree(struct vfsmount *m) { + struct mount *mnt = real_mount(m); int actual_refs = 0; int minimum_refs = 0; struct mount *p; - BUG_ON(!mnt); + BUG_ON(!m); /* write lock needed for mnt_get_count */ br_write_lock(vfsmount_lock); - for (p = real_mount(mnt); p; p = next_mnt(p, mnt)) { + for (p = mnt; p; p = next_mnt(p, mnt)) { actual_refs += mnt_get_count(p); minimum_refs += 2; } @@ -1228,7 +1229,7 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) LIST_HEAD(tmp_list); struct mount *p; - for (p = mnt; p; p = next_mnt(p, &mnt->mnt)) + for (p = mnt; p; p = next_mnt(p, mnt)) list_move(&p->mnt_hash, &tmp_list); if (propagate) @@ -1436,7 +1437,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, if (!is_subdir(r->mnt_mountpoint, dentry)) continue; - for (s = r; s; s = next_mnt(s, &r->mnt)) { + for (s = r; s; s = next_mnt(s, r)) { if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(s)) { s = skip_mnt_tree(s); continue; @@ -1509,7 +1510,7 @@ static void cleanup_group_ids(struct mount *mnt, struct mount *end) { struct mount *p; - for (p = mnt; p != end; p = next_mnt(p, &mnt->mnt)) { + for (p = mnt; p != end; p = next_mnt(p, mnt)) { if (p->mnt_group_id && !IS_MNT_SHARED(p)) mnt_release_group_id(p); } @@ -1519,7 +1520,7 @@ static int invent_group_ids(struct mount *mnt, bool recurse) { struct mount *p; - for (p = mnt; p; p = recurse ? next_mnt(p, &mnt->mnt) : NULL) { + for (p = mnt; p; p = recurse ? next_mnt(p, mnt) : NULL) { if (!p->mnt_group_id && !IS_MNT_SHARED(p)) { int err = mnt_alloc_group_id(p); if (err) { @@ -1616,7 +1617,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, br_write_lock(vfsmount_lock); if (IS_MNT_SHARED(dest_mnt)) { - for (p = source_mnt; p; p = next_mnt(p, &source_mnt->mnt)) + for (p = source_mnt; p; p = next_mnt(p, source_mnt)) set_mnt_shared(p); } if (parent_path) { @@ -1731,7 +1732,7 @@ static int do_change_type(struct path *path, int flag) } br_write_lock(vfsmount_lock); - for (m = mnt; m; m = (recurse ? next_mnt(m, &mnt->mnt) : NULL)) + for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) change_mnt_propagation(m, type); br_write_unlock(vfsmount_lock); @@ -1859,7 +1860,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags, static inline int tree_contains_unbindable(struct mount *mnt) { struct mount *p; - for (p = mnt; p; p = next_mnt(p, &mnt->mnt)) { + for (p = mnt; p; p = next_mnt(p, mnt)) { if (IS_MNT_UNBINDABLE(p)) return 1; } @@ -2399,6 +2400,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, struct mnt_namespace *new_ns; struct vfsmount *rootmnt = NULL, *pwdmnt = NULL; struct mount *p, *q; + struct mount *old = real_mount(mnt_ns->root); struct mount *new; new_ns = alloc_mnt_ns(); @@ -2407,8 +2409,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, down_write(&namespace_sem); /* First pass: copy the tree topology */ - new = copy_tree(real_mount(mnt_ns->root), mnt_ns->root->mnt_root, - CL_COPY_ALL | CL_EXPIRE); + new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE); if (!new) { up_write(&namespace_sem); kfree(new_ns); @@ -2424,7 +2425,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, * as belonging to new namespace. We have already acquired a private * fs_struct, so tsk->fs->lock is not needed. */ - p = real_mount(mnt_ns->root); + p = old; q = new; while (p) { q->mnt_ns = new_ns; @@ -2443,8 +2444,8 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, pwdmnt = &p->mnt; } } - p = next_mnt(p, mnt_ns->root); - q = next_mnt(q, new_ns->root); + p = next_mnt(p, old); + q = next_mnt(q, new); } up_write(&namespace_sem); -- cgit v1.2.3 From 3a2393d71d77b034669d495b49c212a87e04abdc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 25 Nov 2011 03:19:09 -0500 Subject: vfs: opencode mntget() mnt_set_mountpoint() Signed-off-by: Al Viro --- fs/namespace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 24e845671ad3..cd6389387d1f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -572,8 +572,9 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) void mnt_set_mountpoint(struct mount *mnt, struct dentry *dentry, struct mount *child_mnt) { - child_mnt->mnt_parent = real_mount(mntget(&mnt->mnt)); + mnt_add_count(mnt, 1); /* essentially, that's mntget */ child_mnt->mnt_mountpoint = dget(dentry); + child_mnt->mnt_parent = mnt; spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_MOUNTED; spin_unlock(&dentry->d_lock); -- cgit v1.2.3 From 0226f4923f6c9b40cfa1c1c1b19a6ac6b3924ead Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 6 Dec 2011 12:21:54 -0500 Subject: vfs: take /proc/*/mounts and friends to fs/proc_namespace.c rationale: that stuff is far tighter bound to fs/namespace.c than to the guts of procfs proper. Signed-off-by: Al Viro --- fs/namespace.c | 218 ++------------------------------------------------------- 1 file changed, 7 insertions(+), 211 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index cd6389387d1f..21a8261256dd 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -898,10 +898,10 @@ void replace_mount_options(struct super_block *sb, char *options) EXPORT_SYMBOL(replace_mount_options); #ifdef CONFIG_PROC_FS -/* iterator */ +/* iterator; we want it to have access to namespace_sem, thus here... */ static void *m_start(struct seq_file *m, loff_t *pos) { - struct proc_mounts *p = m->private; + struct proc_mounts *p = container_of(m, struct proc_mounts, m); down_read(&namespace_sem); return seq_list_start(&p->ns->list, *pos); @@ -909,7 +909,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) static void *m_next(struct seq_file *m, void *v, loff_t *pos) { - struct proc_mounts *p = m->private; + struct proc_mounts *p = container_of(m, struct proc_mounts, m); return seq_list_next(v, &p->ns->list, pos); } @@ -919,222 +919,18 @@ static void m_stop(struct seq_file *m, void *v) up_read(&namespace_sem); } -int mnt_had_events(struct proc_mounts *p) -{ - struct mnt_namespace *ns = p->ns; - int res = 0; - - br_read_lock(vfsmount_lock); - if (p->m.poll_event != ns->event) { - p->m.poll_event = ns->event; - res = 1; - } - br_read_unlock(vfsmount_lock); - - return res; -} - -struct proc_fs_info { - int flag; - const char *str; -}; - -static int show_sb_opts(struct seq_file *m, struct super_block *sb) -{ - static const struct proc_fs_info fs_info[] = { - { MS_SYNCHRONOUS, ",sync" }, - { MS_DIRSYNC, ",dirsync" }, - { MS_MANDLOCK, ",mand" }, - { 0, NULL } - }; - const struct proc_fs_info *fs_infop; - - for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { - if (sb->s_flags & fs_infop->flag) - seq_puts(m, fs_infop->str); - } - - return security_sb_show_options(m, sb); -} - -static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt) -{ - static const struct proc_fs_info mnt_info[] = { - { MNT_NOSUID, ",nosuid" }, - { MNT_NODEV, ",nodev" }, - { MNT_NOEXEC, ",noexec" }, - { MNT_NOATIME, ",noatime" }, - { MNT_NODIRATIME, ",nodiratime" }, - { MNT_RELATIME, ",relatime" }, - { 0, NULL } - }; - const struct proc_fs_info *fs_infop; - - for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) { - if (mnt->mnt_flags & fs_infop->flag) - seq_puts(m, fs_infop->str); - } -} - -static void show_type(struct seq_file *m, struct super_block *sb) -{ - mangle(m, sb->s_type->name); - if (sb->s_subtype && sb->s_subtype[0]) { - seq_putc(m, '.'); - mangle(m, sb->s_subtype); - } -} - -static int show_vfsmnt(struct seq_file *m, void *v) +static int m_show(struct seq_file *m, void *v) { + struct proc_mounts *p = container_of(m, struct proc_mounts, m); struct mount *r = list_entry(v, struct mount, mnt_list); - struct vfsmount *mnt = &r->mnt; - int err = 0; - struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; - - if (mnt->mnt_sb->s_op->show_devname) { - err = mnt->mnt_sb->s_op->show_devname(m, mnt); - if (err) - goto out; - } else { - mangle(m, r->mnt_devname ? r->mnt_devname : "none"); - } - seq_putc(m, ' '); - seq_path(m, &mnt_path, " \t\n\\"); - seq_putc(m, ' '); - show_type(m, mnt->mnt_sb); - seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw"); - err = show_sb_opts(m, mnt->mnt_sb); - if (err) - goto out; - show_mnt_opts(m, mnt); - if (mnt->mnt_sb->s_op->show_options) - err = mnt->mnt_sb->s_op->show_options(m, mnt); - seq_puts(m, " 0 0\n"); -out: - return err; + return p->show(m, &r->mnt); } const struct seq_operations mounts_op = { .start = m_start, .next = m_next, .stop = m_stop, - .show = show_vfsmnt -}; - -static int show_mountinfo(struct seq_file *m, void *v) -{ - struct proc_mounts *p = m->private; - struct mount *r = list_entry(v, struct mount, mnt_list); - struct vfsmount *mnt = &r->mnt; - struct super_block *sb = mnt->mnt_sb; - struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; - struct path root = p->root; - int err = 0; - - seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id, - MAJOR(sb->s_dev), MINOR(sb->s_dev)); - if (sb->s_op->show_path) - err = sb->s_op->show_path(m, mnt); - else - seq_dentry(m, mnt->mnt_root, " \t\n\\"); - if (err) - goto out; - seq_putc(m, ' '); - - /* mountpoints outside of chroot jail will give SEQ_SKIP on this */ - err = seq_path_root(m, &mnt_path, &root, " \t\n\\"); - if (err) - goto out; - - seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); - show_mnt_opts(m, mnt); - - /* Tagged fields ("foo:X" or "bar") */ - if (IS_MNT_SHARED(r)) - seq_printf(m, " shared:%i", r->mnt_group_id); - if (IS_MNT_SLAVE(r)) { - int master = r->mnt_master->mnt_group_id; - int dom = get_dominating_id(r, &p->root); - seq_printf(m, " master:%i", master); - if (dom && dom != master) - seq_printf(m, " propagate_from:%i", dom); - } - if (IS_MNT_UNBINDABLE(r)) - seq_puts(m, " unbindable"); - - /* Filesystem specific data */ - seq_puts(m, " - "); - show_type(m, sb); - seq_putc(m, ' '); - if (sb->s_op->show_devname) - err = sb->s_op->show_devname(m, mnt); - else - mangle(m, r->mnt_devname ? r->mnt_devname : "none"); - if (err) - goto out; - seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); - err = show_sb_opts(m, sb); - if (err) - goto out; - if (sb->s_op->show_options) - err = sb->s_op->show_options(m, mnt); - seq_putc(m, '\n'); -out: - return err; -} - -const struct seq_operations mountinfo_op = { - .start = m_start, - .next = m_next, - .stop = m_stop, - .show = show_mountinfo, -}; - -static int show_vfsstat(struct seq_file *m, void *v) -{ - struct mount *r = list_entry(v, struct mount, mnt_list); - struct vfsmount *mnt = &r->mnt; - struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; - int err = 0; - - /* device */ - if (mnt->mnt_sb->s_op->show_devname) { - seq_puts(m, "device "); - err = mnt->mnt_sb->s_op->show_devname(m, mnt); - } else { - if (r->mnt_devname) { - seq_puts(m, "device "); - mangle(m, r->mnt_devname); - } else - seq_puts(m, "no device"); - } - - /* mount point */ - seq_puts(m, " mounted on "); - seq_path(m, &mnt_path, " \t\n\\"); - seq_putc(m, ' '); - - /* file system type */ - seq_puts(m, "with fstype "); - show_type(m, mnt->mnt_sb); - - /* optional statistics */ - if (mnt->mnt_sb->s_op->show_stats) { - seq_putc(m, ' '); - if (!err) - err = mnt->mnt_sb->s_op->show_stats(m, mnt); - } - - seq_putc(m, '\n'); - return err; -} - -const struct seq_operations mountstats_op = { - .start = m_start, - .next = m_next, - .stop = m_stop, - .show = show_vfsstat, + .show = m_show, }; #endif /* CONFIG_PROC_FS */ -- cgit v1.2.3 From be08d6d260b6e7eb346162a1081cdf5f94fda569 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 6 Dec 2011 13:32:36 -0500 Subject: switch mnt_namespace ->root to struct mount Signed-off-by: Al Viro --- fs/namespace.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 21a8261256dd..d4016f911ef9 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2197,7 +2197,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, struct mnt_namespace *new_ns; struct vfsmount *rootmnt = NULL, *pwdmnt = NULL; struct mount *p, *q; - struct mount *old = real_mount(mnt_ns->root); + struct mount *old = mnt_ns->root; struct mount *new; new_ns = alloc_mnt_ns(); @@ -2212,7 +2212,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, kfree(new_ns); return ERR_PTR(-ENOMEM); } - new_ns->root = &new->mnt; + new_ns->root = new; br_write_lock(vfsmount_lock); list_add_tail(&new_ns->list, &new->mnt_list); br_write_unlock(vfsmount_lock); @@ -2282,7 +2282,7 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m) struct mount *mnt = real_mount(m); mnt->mnt_ns = new_ns; __mnt_make_longterm(mnt); - new_ns->root = m; + new_ns->root = mnt; list_add(&new_ns->list, &mnt->mnt_list); } else { mntput(m); @@ -2512,8 +2512,8 @@ static void __init init_mount_tree(void) init_task.nsproxy->mnt_ns = ns; get_mnt_ns(ns); - root.mnt = ns->root; - root.dentry = ns->root->mnt_root; + root.mnt = mnt; + root.dentry = mnt->mnt_root; set_fs_pwd(current->fs, &root); set_fs_root(current->fs, &root); @@ -2560,7 +2560,7 @@ void put_mnt_ns(struct mnt_namespace *ns) return; down_write(&namespace_sem); br_write_lock(vfsmount_lock); - umount_tree(real_mount(ns->root), 0, &umount_list); + umount_tree(ns->root, 0, &umount_list); br_write_unlock(vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); -- cgit v1.2.3 From d10577a8d86a0c735488d66d32289a6d66bcfa20 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 7 Dec 2011 13:06:11 -0500 Subject: vfs: trim includes a bit [folded fix for missing magic.h from Tetsuo Handa] Signed-off-by: Al Viro --- fs/namespace.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index d4016f911ef9..773435ca300d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -9,30 +9,17 @@ */ #include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include -#include -#include #include #include -#include #include -#include -#include -#include #include -#include -#include -#include -#include +#include /* acct_auto_close_mnt */ +#include /* init_rootfs */ +#include /* get_fs_root et.al. */ +#include /* fsnotify_vfsmount_delete */ +#include #include "pnode.h" #include "internal.h" -- cgit v1.2.3 From 34c80b1d93e6e20ca9dea0baf583a5b5510d92d4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 8 Dec 2011 21:32:45 -0500 Subject: vfs: switch ->show_options() to struct dentry * Signed-off-by: Al Viro --- fs/namespace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 773435ca300d..db65e2e4921f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -836,12 +836,12 @@ static inline void mangle(struct seq_file *m, const char *s) * * See also save_mount_options(). */ -int generic_show_options(struct seq_file *m, struct vfsmount *mnt) +int generic_show_options(struct seq_file *m, struct dentry *root) { const char *options; rcu_read_lock(); - options = rcu_dereference(mnt->mnt_sb->s_options); + options = rcu_dereference(root->d_sb->s_options); if (options != NULL && options[0]) { seq_putc(m, ','); -- cgit v1.2.3 From 39f7c4db1d2d9e2e2a90abdf34811783089d217d Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 21 Nov 2011 12:11:30 +0100 Subject: vfs: keep list of mounts for each superblock Keep track of vfsmounts belonging to a superblock. List is protected by vfsmount_lock. Signed-off-by: Miklos Szeredi Tested-by: Toshiyuki Okajima Signed-off-by: Al Viro --- fs/namespace.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index db65e2e4921f..145217b088d1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -671,6 +671,9 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void mnt->mnt.mnt_sb = root->d_sb; mnt->mnt_mountpoint = mnt->mnt.mnt_root; mnt->mnt_parent = mnt; + br_write_lock(vfsmount_lock); + list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts); + br_write_unlock(vfsmount_lock); return &mnt->mnt; } EXPORT_SYMBOL_GPL(vfs_kern_mount); @@ -699,6 +702,9 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, mnt->mnt.mnt_root = dget(root); mnt->mnt_mountpoint = mnt->mnt.mnt_root; mnt->mnt_parent = mnt; + br_write_lock(vfsmount_lock); + list_add_tail(&mnt->mnt_instance, &sb->s_mounts); + br_write_unlock(vfsmount_lock); if (flag & CL_SLAVE) { list_add(&mnt->mnt_slave, &old->mnt_slave_list); @@ -781,6 +787,7 @@ put_again: acct_auto_close_mnt(&mnt->mnt); goto put_again; } + list_del(&mnt->mnt_instance); br_write_unlock(vfsmount_lock); mntfree(mnt); } -- cgit v1.2.3 From 4ed5e82fe77f4147cf386327c9a63a2dd7eff518 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 21 Nov 2011 12:11:31 +0100 Subject: vfs: protect remounting superblock read-only Currently remouting superblock read-only is racy in a major way. With the per mount read-only infrastructure it is now possible to prevent most races, which this patch attempts. Before starting the remount read-only, iterate through all mounts belonging to the superblock and if none of them have any pending writes, set sb->s_readonly_remount. This indicates that remount is in progress and no further write requests are allowed. If the remount succeeds set MS_RDONLY and reset s_readonly_remount. If the remounting is unsuccessful just reset s_readonly_remount. This can result in transient EROFS errors, despite the fact the remount failed. Unfortunately hodling off writes is difficult as remount itself may touch the filesystem (e.g. through load_nls()) which would deadlock. A later patch deals with delayed writes due to nlink going to zero. Signed-off-by: Miklos Szeredi Tested-by: Toshiyuki Okajima Signed-off-by: Al Viro --- fs/namespace.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 145217b088d1..98ebc78b21ab 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -273,6 +273,15 @@ static unsigned int mnt_get_writers(struct mount *mnt) #endif } +static int mnt_is_readonly(struct vfsmount *mnt) +{ + if (mnt->mnt_sb->s_readonly_remount) + return 1; + /* Order wrt setting s_flags/s_readonly_remount in do_remount() */ + smp_rmb(); + return __mnt_is_readonly(mnt); +} + /* * Most r/o checks on a fs are for operations that take * discrete amounts of time, like a write() or unlink(). @@ -312,7 +321,7 @@ int mnt_want_write(struct vfsmount *m) * MNT_WRITE_HOLD is cleared. */ smp_rmb(); - if (__mnt_is_readonly(m)) { + if (mnt_is_readonly(m)) { mnt_dec_writers(mnt); ret = -EROFS; goto out; @@ -435,6 +444,35 @@ static void __mnt_unmake_readonly(struct mount *mnt) br_write_unlock(vfsmount_lock); } +int sb_prepare_remount_readonly(struct super_block *sb) +{ + struct mount *mnt; + int err = 0; + + br_write_lock(vfsmount_lock); + list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { + if (!(mnt->mnt.mnt_flags & MNT_READONLY)) { + mnt->mnt.mnt_flags |= MNT_WRITE_HOLD; + smp_mb(); + if (mnt_get_writers(mnt) > 0) { + err = -EBUSY; + break; + } + } + } + if (!err) { + sb->s_readonly_remount = 1; + smp_wmb(); + } + list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { + if (mnt->mnt.mnt_flags & MNT_WRITE_HOLD) + mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD; + } + br_write_unlock(vfsmount_lock); + + return err; +} + static void free_vfsmnt(struct mount *mnt) { kfree(mnt->mnt_devname); -- cgit v1.2.3 From 8e8b87964bc8dc5c14b6543fc933b7725f07d3ac Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 21 Nov 2011 12:11:33 +0100 Subject: vfs: prevent remount read-only if pending removes If there are any inodes on the super block that have been unlinked (i_nlink == 0) but have not yet been deleted then prevent the remounting the super block read-only. Reported-by: Toshiyuki Okajima Signed-off-by: Miklos Szeredi Tested-by: Toshiyuki Okajima Signed-off-by: Al Viro --- fs/namespace.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs/namespace.c') diff --git a/fs/namespace.c b/fs/namespace.c index 98ebc78b21ab..7e6f2c9dc7c4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -449,6 +449,10 @@ int sb_prepare_remount_readonly(struct super_block *sb) struct mount *mnt; int err = 0; + /* Racy optimization. Recheck the counter under MNT_WRITE_HOLD */ + if (atomic_long_read(&sb->s_remove_count)) + return -EBUSY; + br_write_lock(vfsmount_lock); list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { if (!(mnt->mnt.mnt_flags & MNT_READONLY)) { @@ -460,6 +464,9 @@ int sb_prepare_remount_readonly(struct super_block *sb) } } } + if (!err && atomic_long_read(&sb->s_remove_count)) + err = -EBUSY; + if (!err) { sb->s_readonly_remount = 1; smp_wmb(); -- cgit v1.2.3