Commit 719ea2fb authored by Al Viro's avatar Al Viro

new helpers: lock_mount_hash/unlock_mount_hash

aka br_write_{lock,unlock} of vfsmount_lock.  Inlines in fs/mount.h,
vfsmount_lock extern moved over there as well.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent aab407fc
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <linux/device.h>
#include "internal.h" #include "internal.h"
/* /*
......
...@@ -9,8 +9,6 @@ ...@@ -9,8 +9,6 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/lglock.h>
struct super_block; struct super_block;
struct file_system_type; struct file_system_type;
struct linux_binprm; struct linux_binprm;
...@@ -62,8 +60,6 @@ extern int sb_prepare_remount_readonly(struct super_block *); ...@@ -62,8 +60,6 @@ extern int sb_prepare_remount_readonly(struct super_block *);
extern void __init mnt_init(void); extern void __init mnt_init(void);
extern struct lglock vfsmount_lock;
extern int __mnt_want_write(struct vfsmount *); extern int __mnt_want_write(struct vfsmount *);
extern int __mnt_want_write_file(struct file *); extern int __mnt_want_write_file(struct file *);
extern void __mnt_drop_write(struct vfsmount *); extern void __mnt_drop_write(struct vfsmount *);
......
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/lglock.h>
struct mnt_namespace { struct mnt_namespace {
atomic_t count; atomic_t count;
...@@ -83,6 +84,18 @@ static inline void get_mnt_ns(struct mnt_namespace *ns) ...@@ -83,6 +84,18 @@ static inline void get_mnt_ns(struct mnt_namespace *ns)
atomic_inc(&ns->count); atomic_inc(&ns->count);
} }
extern struct lglock vfsmount_lock;
static inline void lock_mount_hash(void)
{
br_write_lock(&vfsmount_lock);
}
static inline void unlock_mount_hash(void)
{
br_write_unlock(&vfsmount_lock);
}
struct proc_mounts { struct proc_mounts {
struct seq_file m; struct seq_file m;
struct mnt_namespace *ns; struct mnt_namespace *ns;
......
...@@ -456,7 +456,7 @@ static int mnt_make_readonly(struct mount *mnt) ...@@ -456,7 +456,7 @@ static int mnt_make_readonly(struct mount *mnt)
{ {
int ret = 0; int ret = 0;
br_write_lock(&vfsmount_lock); lock_mount_hash();
mnt->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 * After storing MNT_WRITE_HOLD, we'll read the counters. This store
...@@ -490,15 +490,15 @@ static int mnt_make_readonly(struct mount *mnt) ...@@ -490,15 +490,15 @@ static int mnt_make_readonly(struct mount *mnt)
*/ */
smp_wmb(); smp_wmb();
mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD; mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
return ret; return ret;
} }
static void __mnt_unmake_readonly(struct mount *mnt) static void __mnt_unmake_readonly(struct mount *mnt)
{ {
br_write_lock(&vfsmount_lock); lock_mount_hash();
mnt->mnt.mnt_flags &= ~MNT_READONLY; mnt->mnt.mnt_flags &= ~MNT_READONLY;
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
} }
int sb_prepare_remount_readonly(struct super_block *sb) int sb_prepare_remount_readonly(struct super_block *sb)
...@@ -510,7 +510,7 @@ int sb_prepare_remount_readonly(struct super_block *sb) ...@@ -510,7 +510,7 @@ int sb_prepare_remount_readonly(struct super_block *sb)
if (atomic_long_read(&sb->s_remove_count)) if (atomic_long_read(&sb->s_remove_count))
return -EBUSY; return -EBUSY;
br_write_lock(&vfsmount_lock); lock_mount_hash();
list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
if (!(mnt->mnt.mnt_flags & MNT_READONLY)) { if (!(mnt->mnt.mnt_flags & MNT_READONLY)) {
mnt->mnt.mnt_flags |= MNT_WRITE_HOLD; mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
...@@ -532,7 +532,7 @@ int sb_prepare_remount_readonly(struct super_block *sb) ...@@ -532,7 +532,7 @@ int sb_prepare_remount_readonly(struct super_block *sb)
if (mnt->mnt.mnt_flags & MNT_WRITE_HOLD) if (mnt->mnt.mnt_flags & MNT_WRITE_HOLD)
mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD; mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
} }
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
return err; return err;
} }
...@@ -794,9 +794,9 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void ...@@ -794,9 +794,9 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
mnt->mnt.mnt_sb = root->d_sb; mnt->mnt.mnt_sb = root->d_sb;
mnt->mnt_mountpoint = mnt->mnt.mnt_root; mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt; mnt->mnt_parent = mnt;
br_write_lock(&vfsmount_lock); lock_mount_hash();
list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts); list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
return &mnt->mnt; return &mnt->mnt;
} }
EXPORT_SYMBOL_GPL(vfs_kern_mount); EXPORT_SYMBOL_GPL(vfs_kern_mount);
...@@ -837,9 +837,9 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, ...@@ -837,9 +837,9 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
mnt->mnt.mnt_root = dget(root); mnt->mnt.mnt_root = dget(root);
mnt->mnt_mountpoint = mnt->mnt.mnt_root; mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt; mnt->mnt_parent = mnt;
br_write_lock(&vfsmount_lock); lock_mount_hash();
list_add_tail(&mnt->mnt_instance, &sb->s_mounts); list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
if ((flag & CL_SLAVE) || if ((flag & CL_SLAVE) ||
((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) { ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
...@@ -883,28 +883,28 @@ static void mntput_no_expire(struct mount *mnt) ...@@ -883,28 +883,28 @@ static void mntput_no_expire(struct mount *mnt)
} }
br_read_unlock(&vfsmount_lock); br_read_unlock(&vfsmount_lock);
br_write_lock(&vfsmount_lock); lock_mount_hash();
mnt_add_count(mnt, -1); mnt_add_count(mnt, -1);
if (mnt_get_count(mnt)) { if (mnt_get_count(mnt)) {
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
return; return;
} }
#else #else
mnt_add_count(mnt, -1); mnt_add_count(mnt, -1);
if (likely(mnt_get_count(mnt))) if (likely(mnt_get_count(mnt)))
return; return;
br_write_lock(&vfsmount_lock); lock_mount_hash();
#endif #endif
if (unlikely(mnt->mnt_pinned)) { if (unlikely(mnt->mnt_pinned)) {
mnt_add_count(mnt, mnt->mnt_pinned + 1); mnt_add_count(mnt, mnt->mnt_pinned + 1);
mnt->mnt_pinned = 0; mnt->mnt_pinned = 0;
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
acct_auto_close_mnt(&mnt->mnt); acct_auto_close_mnt(&mnt->mnt);
goto put_again; goto put_again;
} }
list_del(&mnt->mnt_instance); list_del(&mnt->mnt_instance);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
/* /*
* This probably indicates that somebody messed * This probably indicates that somebody messed
...@@ -945,21 +945,21 @@ EXPORT_SYMBOL(mntget); ...@@ -945,21 +945,21 @@ EXPORT_SYMBOL(mntget);
void mnt_pin(struct vfsmount *mnt) void mnt_pin(struct vfsmount *mnt)
{ {
br_write_lock(&vfsmount_lock); lock_mount_hash();
real_mount(mnt)->mnt_pinned++; real_mount(mnt)->mnt_pinned++;
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
} }
EXPORT_SYMBOL(mnt_pin); EXPORT_SYMBOL(mnt_pin);
void mnt_unpin(struct vfsmount *m) void mnt_unpin(struct vfsmount *m)
{ {
struct mount *mnt = real_mount(m); struct mount *mnt = real_mount(m);
br_write_lock(&vfsmount_lock); lock_mount_hash();
if (mnt->mnt_pinned) { if (mnt->mnt_pinned) {
mnt_add_count(mnt, 1); mnt_add_count(mnt, 1);
mnt->mnt_pinned--; mnt->mnt_pinned--;
} }
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
} }
EXPORT_SYMBOL(mnt_unpin); EXPORT_SYMBOL(mnt_unpin);
...@@ -1076,12 +1076,12 @@ int may_umount_tree(struct vfsmount *m) ...@@ -1076,12 +1076,12 @@ int may_umount_tree(struct vfsmount *m)
BUG_ON(!m); BUG_ON(!m);
/* write lock needed for mnt_get_count */ /* write lock needed for mnt_get_count */
br_write_lock(&vfsmount_lock); lock_mount_hash();
for (p = mnt; p; p = next_mnt(p, mnt)) { for (p = mnt; p; p = next_mnt(p, mnt)) {
actual_refs += mnt_get_count(p); actual_refs += mnt_get_count(p);
minimum_refs += 2; minimum_refs += 2;
} }
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
if (actual_refs > minimum_refs) if (actual_refs > minimum_refs)
return 0; return 0;
...@@ -1108,10 +1108,10 @@ int may_umount(struct vfsmount *mnt) ...@@ -1108,10 +1108,10 @@ int may_umount(struct vfsmount *mnt)
{ {
int ret = 1; int ret = 1;
down_read(&namespace_sem); down_read(&namespace_sem);
br_write_lock(&vfsmount_lock); lock_mount_hash();
if (propagate_mount_busy(real_mount(mnt), 2)) if (propagate_mount_busy(real_mount(mnt), 2))
ret = 0; ret = 0;
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
up_read(&namespace_sem); up_read(&namespace_sem);
return ret; return ret;
} }
...@@ -1208,12 +1208,12 @@ static int do_umount(struct mount *mnt, int flags) ...@@ -1208,12 +1208,12 @@ static int do_umount(struct mount *mnt, int flags)
* probably don't strictly need the lock here if we examined * probably don't strictly need the lock here if we examined
* all race cases, but it's a slowpath. * all race cases, but it's a slowpath.
*/ */
br_write_lock(&vfsmount_lock); lock_mount_hash();
if (mnt_get_count(mnt) != 2) { if (mnt_get_count(mnt) != 2) {
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
return -EBUSY; return -EBUSY;
} }
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
if (!xchg(&mnt->mnt_expiry_mark, 1)) if (!xchg(&mnt->mnt_expiry_mark, 1))
return -EAGAIN; return -EAGAIN;
...@@ -1255,7 +1255,7 @@ static int do_umount(struct mount *mnt, int flags) ...@@ -1255,7 +1255,7 @@ static int do_umount(struct mount *mnt, int flags)
} }
namespace_lock(); namespace_lock();
br_write_lock(&vfsmount_lock); lock_mount_hash();
event++; event++;
if (!(flags & MNT_DETACH)) if (!(flags & MNT_DETACH))
...@@ -1267,7 +1267,7 @@ static int do_umount(struct mount *mnt, int flags) ...@@ -1267,7 +1267,7 @@ static int do_umount(struct mount *mnt, int flags)
umount_tree(mnt, 1); umount_tree(mnt, 1);
retval = 0; retval = 0;
} }
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
namespace_unlock(); namespace_unlock();
return retval; return retval;
} }
...@@ -1410,18 +1410,18 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, ...@@ -1410,18 +1410,18 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
q = clone_mnt(p, p->mnt.mnt_root, flag); q = clone_mnt(p, p->mnt.mnt_root, flag);
if (IS_ERR(q)) if (IS_ERR(q))
goto out; goto out;
br_write_lock(&vfsmount_lock); lock_mount_hash();
list_add_tail(&q->mnt_list, &res->mnt_list); list_add_tail(&q->mnt_list, &res->mnt_list);
attach_mnt(q, parent, p->mnt_mp); attach_mnt(q, parent, p->mnt_mp);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
} }
} }
return res; return res;
out: out:
if (res) { if (res) {
br_write_lock(&vfsmount_lock); lock_mount_hash();
umount_tree(res, 0); umount_tree(res, 0);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
} }
return q; return q;
} }
...@@ -1443,9 +1443,9 @@ struct vfsmount *collect_mounts(struct path *path) ...@@ -1443,9 +1443,9 @@ struct vfsmount *collect_mounts(struct path *path)
void drop_collected_mounts(struct vfsmount *mnt) void drop_collected_mounts(struct vfsmount *mnt)
{ {
namespace_lock(); namespace_lock();
br_write_lock(&vfsmount_lock); lock_mount_hash();
umount_tree(real_mount(mnt), 0); umount_tree(real_mount(mnt), 0);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
namespace_unlock(); namespace_unlock();
} }
...@@ -1572,7 +1572,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, ...@@ -1572,7 +1572,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
if (err) if (err)
goto out_cleanup_ids; goto out_cleanup_ids;
br_write_lock(&vfsmount_lock); lock_mount_hash();
if (IS_MNT_SHARED(dest_mnt)) { if (IS_MNT_SHARED(dest_mnt)) {
for (p = source_mnt; p; p = next_mnt(p, source_mnt)) for (p = source_mnt; p; p = next_mnt(p, source_mnt))
...@@ -1591,7 +1591,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, ...@@ -1591,7 +1591,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
list_del_init(&child->mnt_hash); list_del_init(&child->mnt_hash);
commit_tree(child); commit_tree(child);
} }
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
return 0; return 0;
...@@ -1693,10 +1693,10 @@ static int do_change_type(struct path *path, int flag) ...@@ -1693,10 +1693,10 @@ static int do_change_type(struct path *path, int flag)
goto out_unlock; goto out_unlock;
} }
br_write_lock(&vfsmount_lock); lock_mount_hash();
for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
change_mnt_propagation(m, type); change_mnt_propagation(m, type);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
out_unlock: out_unlock:
namespace_unlock(); namespace_unlock();
...@@ -1768,9 +1768,9 @@ static int do_loopback(struct path *path, const char *old_name, ...@@ -1768,9 +1768,9 @@ static int do_loopback(struct path *path, const char *old_name,
err = graft_tree(mnt, parent, mp); err = graft_tree(mnt, parent, mp);
if (err) { if (err) {
br_write_lock(&vfsmount_lock); lock_mount_hash();
umount_tree(mnt, 0); umount_tree(mnt, 0);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
} }
out2: out2:
unlock_mount(mp); unlock_mount(mp);
...@@ -1829,11 +1829,11 @@ static int do_remount(struct path *path, int flags, int mnt_flags, ...@@ -1829,11 +1829,11 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
else else
err = do_remount_sb(sb, flags, data, 0); err = do_remount_sb(sb, flags, data, 0);
if (!err) { if (!err) {
br_write_lock(&vfsmount_lock); lock_mount_hash();
mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK; mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
mnt->mnt.mnt_flags = mnt_flags; mnt->mnt.mnt_flags = mnt_flags;
touch_mnt_namespace(mnt->mnt_ns); touch_mnt_namespace(mnt->mnt_ns);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
} }
up_write(&sb->s_umount); up_write(&sb->s_umount);
return err; return err;
...@@ -2093,7 +2093,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) ...@@ -2093,7 +2093,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
return; return;
namespace_lock(); namespace_lock();
br_write_lock(&vfsmount_lock); lock_mount_hash();
/* extract from the expiration list every vfsmount that matches the /* extract from the expiration list every vfsmount that matches the
* following criteria: * following criteria:
...@@ -2112,7 +2112,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) ...@@ -2112,7 +2112,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
touch_mnt_namespace(mnt->mnt_ns); touch_mnt_namespace(mnt->mnt_ns);
umount_tree(mnt, 1); umount_tree(mnt, 1);
} }
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
namespace_unlock(); namespace_unlock();
} }
...@@ -2662,7 +2662,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, ...@@ -2662,7 +2662,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
if (!is_path_reachable(old_mnt, old.dentry, &new)) if (!is_path_reachable(old_mnt, old.dentry, &new))
goto out4; goto out4;
root_mp->m_count++; /* pin it so it won't go away */ root_mp->m_count++; /* pin it so it won't go away */
br_write_lock(&vfsmount_lock); lock_mount_hash();
detach_mnt(new_mnt, &parent_path); detach_mnt(new_mnt, &parent_path);
detach_mnt(root_mnt, &root_parent); detach_mnt(root_mnt, &root_parent);
if (root_mnt->mnt.mnt_flags & MNT_LOCKED) { if (root_mnt->mnt.mnt_flags & MNT_LOCKED) {
...@@ -2674,7 +2674,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, ...@@ -2674,7 +2674,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
/* mount new_root on / */ /* mount new_root on / */
attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp); attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp);
touch_mnt_namespace(current->nsproxy->mnt_ns); touch_mnt_namespace(current->nsproxy->mnt_ns);
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
chroot_fs_refs(&root, &new); chroot_fs_refs(&root, &new);
put_mountpoint(root_mp); put_mountpoint(root_mp);
error = 0; error = 0;
...@@ -2784,9 +2784,9 @@ void kern_unmount(struct vfsmount *mnt) ...@@ -2784,9 +2784,9 @@ void kern_unmount(struct vfsmount *mnt)
{ {
/* release long term mount so mount point can be released */ /* release long term mount so mount point can be released */
if (!IS_ERR_OR_NULL(mnt)) { if (!IS_ERR_OR_NULL(mnt)) {
br_write_lock(&vfsmount_lock); lock_mount_hash();
real_mount(mnt)->mnt_ns = NULL; real_mount(mnt)->mnt_ns = NULL;
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
mntput(mnt); mntput(mnt);
} }
} }
......
...@@ -264,12 +264,12 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, ...@@ -264,12 +264,12 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
prev_src_mnt = child; prev_src_mnt = child;
} }
out: out:
br_write_lock(&vfsmount_lock); lock_mount_hash();
while (!list_empty(&tmp_list)) { while (!list_empty(&tmp_list)) {
child = list_first_entry(&tmp_list, struct mount, mnt_hash); child = list_first_entry(&tmp_list, struct mount, mnt_hash);
umount_tree(child, 0); umount_tree(child, 0);
} }
br_write_unlock(&vfsmount_lock); unlock_mount_hash();
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment