Skip to content

Commit

Permalink
fs: brlock vfsmount_lock
Browse files Browse the repository at this point in the history
fs: brlock vfsmount_lock

Use a brlock for the vfsmount lock. It must be taken for write whenever
modifying the mount hash or associated fields, and may be taken for read when
performing mount hash lookups.

A new lock is added for the mnt-id allocator, so it doesn't need to take
the heavy vfsmount write-lock.

The number of atomics should remain the same for fastpath rlock cases, though
code would be slightly slower due to per-cpu access. Scalability is not not be
much improved in common cases yet, due to other locks (ie. dcache_lock) getting
in the way. However path lookups crossing mountpoints should be one case where
scalability is improved (currently requiring the global lock).

The slowpath is slower due to use of brlock. On a 64 core, 64 socket, 32 node
Altix system (high latency to remote nodes), a simple umount microbenchmark
(mount --bind mnt mnt2 ; umount mnt2 loop 1000 times), before this patch it
took 6.8s, afterwards took 7.1s, about 5% slower.

Cc: Al Viro <[email protected]>
Signed-off-by: Nick Piggin <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
Nick Piggin authored and Al Viro committed Aug 18, 2010
1 parent 6416ccb commit 99b7db7
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 77 deletions.
11 changes: 6 additions & 5 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1935,7 +1935,7 @@ static int prepend_path(const struct path *path, struct path *root,
bool slash = false;
int error = 0;

spin_lock(&vfsmount_lock);
br_read_lock(vfsmount_lock);
while (dentry != root->dentry || vfsmnt != root->mnt) {
struct dentry * parent;

Expand Down Expand Up @@ -1964,7 +1964,7 @@ static int prepend_path(const struct path *path, struct path *root,
if (!error && !slash)
error = prepend(buffer, buflen, "/", 1);

spin_unlock(&vfsmount_lock);
br_read_unlock(vfsmount_lock);
return error;

global_root:
Expand Down Expand Up @@ -2302,11 +2302,12 @@ int path_is_under(struct path *path1, struct path *path2)
struct vfsmount *mnt = path1->mnt;
struct dentry *dentry = path1->dentry;
int res;
spin_lock(&vfsmount_lock);

br_read_lock(vfsmount_lock);
if (mnt != path2->mnt) {
for (;;) {
if (mnt->mnt_parent == mnt) {
spin_unlock(&vfsmount_lock);
br_read_unlock(vfsmount_lock);
return 0;
}
if (mnt->mnt_parent == path2->mnt)
Expand All @@ -2316,7 +2317,7 @@ int path_is_under(struct path *path1, struct path *path2)
dentry = mnt->mnt_mountpoint;
}
res = is_subdir(dentry, path2->dentry);
spin_unlock(&vfsmount_lock);
br_read_unlock(vfsmount_lock);
return res;
}
EXPORT_SYMBOL(path_is_under);
Expand Down
5 changes: 4 additions & 1 deletion fs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* 2 of the License, or (at your option) any later version.
*/

#include <linux/lglock.h>

struct super_block;
struct linux_binprm;
struct path;
Expand Down Expand Up @@ -70,7 +72,8 @@ extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);

extern void __init mnt_init(void);

extern spinlock_t vfsmount_lock;
DECLARE_BRLOCK(vfsmount_lock);


/*
* fs_struct.c
Expand Down
7 changes: 4 additions & 3 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,15 +595,16 @@ int follow_up(struct path *path)
{
struct vfsmount *parent;
struct dentry *mountpoint;
spin_lock(&vfsmount_lock);

br_read_lock(vfsmount_lock);
parent = path->mnt->mnt_parent;
if (parent == path->mnt) {
spin_unlock(&vfsmount_lock);
br_read_unlock(vfsmount_lock);
return 0;
}
mntget(parent);
mountpoint = dget(path->mnt->mnt_mountpoint);
spin_unlock(&vfsmount_lock);
br_read_unlock(vfsmount_lock);
dput(path->dentry);
path->dentry = mountpoint;
mntput(path->mnt);
Expand Down
Loading

0 comments on commit 99b7db7

Please sign in to comment.