From: Cyrill Gorcunov <gorcunov@openvz.org>
To: Al Viro <viro@ZenIV.linux.org.uk>,
LINUXFS-ML <linux-fsdevel@vger.kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Christoph Hellwig <hch@infradead.org>,
James Bottomley <jbottomley@parallels.com>,
xemul@openvz.org, Cyrill Gorcunov <gorcunov@openvz.org>
Subject: [patch 3/3] vfs: Make the rename_lock per-sb
Date: Thu, 28 Jul 2011 17:12:22 +0400 [thread overview]
Message-ID: <20110728132139.661808096@openvz.org> (raw)
In-Reply-To: 20110728131219.146414619@openvz.org
[-- Attachment #1: dcache-3-13.patch --]
[-- Type: text/plain, Size: 13762 bytes --]
From: Pavel Emelyanov <xemul@openvz.org>
There are two things I try to get with this patch.
The first one -- renames on different sb-s will not depend on each other.
The second one -- I plan to factor out the dcache shrinking code (in
further patches). In order to make the srink_dcache_for_umount work OK
on a dying SB it's better to have this lock non-global.
There's some trickery in the prepend_path -- this one has to relock
the rename lock as it ascends the vfsmount tree. This relock seems OK,
as the dentry path of each mount renames solid, and even if we "race"
with the rename on some of the super blocks, the overall path we get
will be either the one we had before rename or them one we had after
one, i.e. -- some existing one.
v2: Use a pointer s_rename_lock in nfs_path() instead of
dereferences in cycle.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
drivers/staging/pohmelfs/path_entry.c | 4 +-
fs/autofs4/waitq.c | 6 +--
fs/dcache.c | 66 +++++++++++++++++-----------------
fs/nfs/namespace.c | 7 ++-
fs/super.c | 1
include/linux/dcache.h | 2 -
include/linux/fs.h | 2 +
kernel/auditsc.c | 4 +-
8 files changed, 47 insertions(+), 45 deletions(-)
Index: linux-2.6.git/drivers/staging/pohmelfs/path_entry.c
===================================================================
--- linux-2.6.git.orig/drivers/staging/pohmelfs/path_entry.c
+++ linux-2.6.git/drivers/staging/pohmelfs/path_entry.c
@@ -99,7 +99,7 @@ int pohmelfs_path_length(struct pohmelfs
rename_retry:
len = 1; /* Root slash */
d = first;
- seq = read_seqbegin(&rename_lock);
+ seq = read_seqbegin(&root->d_sb->s_rename_lock);
rcu_read_lock();
if (!IS_ROOT(d) && d_unhashed(d))
@@ -110,7 +110,7 @@ rename_retry:
d = d->d_parent;
}
rcu_read_unlock();
- if (read_seqretry(&rename_lock, seq))
+ if (read_seqretry(&root->d_sb->s_rename_lock, seq))
goto rename_retry;
dput(root);
Index: linux-2.6.git/fs/autofs4/waitq.c
===================================================================
--- linux-2.6.git.orig/fs/autofs4/waitq.c
+++ linux-2.6.git/fs/autofs4/waitq.c
@@ -195,7 +195,7 @@ rename_retry:
buf = *name;
len = 0;
- seq = read_seqbegin(&rename_lock);
+ seq = read_seqbegin(&sbi->sb->s_rename_lock);
rcu_read_lock();
spin_lock(&sbi->fs_lock);
for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent)
@@ -204,7 +204,7 @@ rename_retry:
if (!len || --len > NAME_MAX) {
spin_unlock(&sbi->fs_lock);
rcu_read_unlock();
- if (read_seqretry(&rename_lock, seq))
+ if (read_seqretry(&sbi->sb->s_rename_lock, seq))
goto rename_retry;
return 0;
}
@@ -220,7 +220,7 @@ rename_retry:
}
spin_unlock(&sbi->fs_lock);
rcu_read_unlock();
- if (read_seqretry(&rename_lock, seq))
+ if (read_seqretry(&sbi->sb->s_rename_lock, seq))
goto rename_retry;
return len;
Index: linux-2.6.git/fs/dcache.c
===================================================================
--- linux-2.6.git.orig/fs/dcache.c
+++ linux-2.6.git/fs/dcache.c
@@ -80,10 +80,6 @@ int sysctl_vfs_cache_pressure __read_mos
EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lru_lock);
-__cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock);
-
-EXPORT_SYMBOL(rename_lock);
-
static struct kmem_cache *dentry_cache __read_mostly;
/*
@@ -1014,7 +1010,7 @@ static struct dentry *try_to_ascend(stru
*/
if (new != old->d_parent ||
(old->d_flags & DCACHE_DISCONNECTED) ||
- (!locked && read_seqretry(&rename_lock, seq))) {
+ (!locked && read_seqretry(&old->d_sb->s_rename_lock, seq))) {
spin_unlock(&new->d_lock);
new = NULL;
}
@@ -1043,7 +1039,7 @@ int have_submounts(struct dentry *parent
unsigned seq;
int locked = 0;
- seq = read_seqbegin(&rename_lock);
+ seq = read_seqbegin(&parent->d_sb->s_rename_lock);
again:
this_parent = parent;
@@ -1086,21 +1082,21 @@ resume:
goto resume;
}
spin_unlock(&this_parent->d_lock);
- if (!locked && read_seqretry(&rename_lock, seq))
+ if (!locked && read_seqretry(&parent->d_sb->s_rename_lock, seq))
goto rename_retry;
if (locked)
- read_sequnlock(&rename_lock);
+ read_sequnlock(&parent->d_sb->s_rename_lock);
return 0; /* No mount points found in tree */
positive:
- if (!locked && read_seqretry(&rename_lock, seq))
+ if (!locked && read_seqretry(&parent->d_sb->s_rename_lock, seq))
goto rename_retry;
if (locked)
- read_sequnlock(&rename_lock);
+ read_sequnlock(&parent->d_sb->s_rename_lock);
return 1;
rename_retry:
locked = 1;
- read_seqlock(&rename_lock);
+ read_seqlock(&parent->d_sb->s_rename_lock);
goto again;
}
EXPORT_SYMBOL(have_submounts);
@@ -1127,7 +1123,7 @@ static int select_parent(struct dentry *
int found = 0;
int locked = 0;
- seq = read_seqbegin(&rename_lock);
+ seq = read_seqbegin(&parent->d_sb->s_rename_lock);
again:
this_parent = parent;
spin_lock(&this_parent->d_lock);
@@ -1188,17 +1184,17 @@ resume:
}
out:
spin_unlock(&this_parent->d_lock);
- if (!locked && read_seqretry(&rename_lock, seq))
+ if (!locked && read_seqretry(&parent->d_sb->s_rename_lock, seq))
goto rename_retry;
if (locked)
- read_sequnlock(&rename_lock);
+ read_sequnlock(&parent->d_sb->s_rename_lock);
return found;
rename_retry:
if (found)
return found;
locked = 1;
- read_seqlock(&rename_lock);
+ read_seqlock(&parent->d_sb->s_rename_lock);
goto again;
}
@@ -1859,11 +1855,11 @@ struct dentry *d_lookup(struct dentry *p
unsigned seq;
do {
- seq = read_seqbegin(&rename_lock);
+ seq = read_seqbegin(&parent->d_sb->s_rename_lock);
dentry = __d_lookup(parent, name);
if (dentry)
break;
- } while (read_seqretry(&rename_lock, seq));
+ } while (read_seqretry(&parent->d_sb->s_rename_lock, seq));
return dentry;
}
EXPORT_SYMBOL(d_lookup);
@@ -2226,6 +2222,7 @@ static void __d_move(struct dentry * den
BUG_ON(d_ancestor(dentry, target));
BUG_ON(d_ancestor(target, dentry));
+ BUG_ON(dentry->d_sb != target->d_sb);
dentry_lock_for_move(dentry, target);
@@ -2284,9 +2281,9 @@ static void __d_move(struct dentry * den
*/
void d_move(struct dentry *dentry, struct dentry *target)
{
- write_seqlock(&rename_lock);
+ write_seqlock(&dentry->d_sb->s_rename_lock);
__d_move(dentry, target);
- write_sequnlock(&rename_lock);
+ write_sequnlock(&dentry->d_sb->s_rename_lock);
}
EXPORT_SYMBOL(d_move);
@@ -2422,7 +2419,7 @@ struct dentry *d_materialise_unique(stru
alias = __d_find_alias(inode, 0);
if (alias) {
actual = alias;
- write_seqlock(&rename_lock);
+ write_seqlock(&dentry->d_sb->s_rename_lock);
if (d_ancestor(alias, dentry)) {
/* Check for loops */
@@ -2431,7 +2428,7 @@ struct dentry *d_materialise_unique(stru
/* Is this an anonymous mountpoint that we
* could splice into our tree? */
__d_materialise_dentry(dentry, alias);
- write_sequnlock(&rename_lock);
+ write_sequnlock(&dentry->d_sb->s_rename_lock);
__d_drop(alias);
goto found;
} else {
@@ -2439,7 +2436,7 @@ struct dentry *d_materialise_unique(stru
* aliasing */
actual = __d_unalias(inode, dentry, alias);
}
- write_sequnlock(&rename_lock);
+ write_sequnlock(&dentry->d_sb->s_rename_lock);
if (IS_ERR(actual))
dput(alias);
goto out_nolock;
@@ -2504,8 +2501,8 @@ static int prepend_path(const struct pat
bool slash = false;
int error = 0;
- read_seqlock(&rename_lock);
br_read_lock(vfsmount_lock);
+ read_seqlock(&vfsmnt->mnt_sb->s_rename_lock);
while (dentry != root->dentry || vfsmnt != root->mnt) {
struct dentry * parent;
@@ -2515,7 +2512,9 @@ static int prepend_path(const struct pat
goto global_root;
}
dentry = vfsmnt->mnt_mountpoint;
+ read_sequnlock(&vfsmnt->mnt_sb->s_rename_lock);
vfsmnt = vfsmnt->mnt_parent;
+ read_seqlock(&vfsmnt->mnt_sb->s_rename_lock);
continue;
}
parent = dentry->d_parent;
@@ -2536,8 +2535,8 @@ out:
if (!error && !slash)
error = prepend(buffer, buflen, "/", 1);
+ read_sequnlock(&vfsmnt->mnt_sb->s_rename_lock);
br_read_unlock(vfsmount_lock);
- read_sequnlock(&rename_lock);
return error;
global_root:
@@ -2708,6 +2707,7 @@ static char *__dentry_path(struct dentry
{
char *end = buf + buflen;
char *retval;
+ struct super_block *sb = dentry->d_sb;
prepend(&end, &buflen, "\0", 1);
if (buflen < 1)
@@ -2716,7 +2716,7 @@ static char *__dentry_path(struct dentry
retval = end-1;
*retval = '/';
- read_seqlock(&rename_lock);
+ read_seqlock(&sb->s_rename_lock);
while (!IS_ROOT(dentry)) {
struct dentry *parent = dentry->d_parent;
int error;
@@ -2731,10 +2731,10 @@ static char *__dentry_path(struct dentry
retval = end;
dentry = parent;
}
- read_sequnlock(&rename_lock);
+ read_sequnlock(&sb->s_rename_lock);
return retval;
Elong:
- read_sequnlock(&rename_lock);
+ read_sequnlock(&sb->s_rename_lock);
return ERR_PTR(-ENAMETOOLONG);
}
@@ -2853,7 +2853,7 @@ int is_subdir(struct dentry *new_dentry,
do {
/* for restarting inner loop in case of seq retry */
- seq = read_seqbegin(&rename_lock);
+ seq = read_seqbegin(&old_dentry->d_sb->s_rename_lock);
/*
* Need rcu_readlock to protect against the d_parent trashing
* due to d_move
@@ -2864,7 +2864,7 @@ int is_subdir(struct dentry *new_dentry,
else
result = 0;
rcu_read_unlock();
- } while (read_seqretry(&rename_lock, seq));
+ } while (read_seqretry(&old_dentry->d_sb->s_rename_lock, seq));
return result;
}
@@ -2901,7 +2901,7 @@ void d_genocide(struct dentry *root)
unsigned seq;
int locked = 0;
- seq = read_seqbegin(&rename_lock);
+ seq = read_seqbegin(&root->d_sb->s_rename_lock);
again:
this_parent = root;
spin_lock(&this_parent->d_lock);
@@ -2944,15 +2944,15 @@ resume:
goto resume;
}
spin_unlock(&this_parent->d_lock);
- if (!locked && read_seqretry(&rename_lock, seq))
+ if (!locked && read_seqretry(&root->d_sb->s_rename_lock, seq))
goto rename_retry;
if (locked)
- read_sequnlock(&rename_lock);
+ read_sequnlock(&root->d_sb->s_rename_lock);
return;
rename_retry:
locked = 1;
- read_seqlock(&rename_lock);
+ read_seqlock(&root->d_sb->s_rename_lock);
goto again;
}
Index: linux-2.6.git/fs/nfs/namespace.c
===================================================================
--- linux-2.6.git.orig/fs/nfs/namespace.c
+++ linux-2.6.git/fs/nfs/namespace.c
@@ -47,6 +47,7 @@ static struct vfsmount *nfs_do_submount(
*/
char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
{
+ seqlock_t *p_rename_lock = &dentry->d_sb->s_rename_lock;
char *end;
int namelen;
unsigned seq;
@@ -57,7 +58,7 @@ rename_retry:
*--end = '\0';
buflen--;
- seq = read_seqbegin(&rename_lock);
+ seq = read_seqbegin(p_rename_lock);
rcu_read_lock();
while (1) {
spin_lock(&dentry->d_lock);
@@ -73,7 +74,7 @@ rename_retry:
spin_unlock(&dentry->d_lock);
dentry = dentry->d_parent;
}
- if (read_seqretry(&rename_lock, seq)) {
+ if (read_seqretry(p_rename_lock, seq)) {
spin_unlock(&dentry->d_lock);
rcu_read_unlock();
goto rename_retry;
@@ -112,7 +113,7 @@ rename_retry:
Elong_unlock:
spin_unlock(&dentry->d_lock);
rcu_read_unlock();
- if (read_seqretry(&rename_lock, seq))
+ if (read_seqretry(p_rename_lock, seq))
goto rename_retry;
Elong:
return ERR_PTR(-ENAMETOOLONG);
Index: linux-2.6.git/fs/super.c
===================================================================
--- linux-2.6.git.orig/fs/super.c
+++ linux-2.6.git/fs/super.c
@@ -105,6 +105,7 @@ static struct super_block *alloc_super(s
s->s_count = 1;
atomic_set(&s->s_active, 1);
mutex_init(&s->s_vfs_rename_mutex);
+ seqlock_init(&s->s_rename_lock);
lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
mutex_init(&s->s_dquot.dqio_mutex);
mutex_init(&s->s_dquot.dqonoff_mutex);
Index: linux-2.6.git/include/linux/dcache.h
===================================================================
--- linux-2.6.git.orig/include/linux/dcache.h
+++ linux-2.6.git/include/linux/dcache.h
@@ -219,8 +219,6 @@ struct dentry_operations {
#define DCACHE_MANAGED_DENTRY \
(DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
-extern seqlock_t rename_lock;
-
static inline int dname_external(struct dentry *dentry)
{
return dentry->d_name.name != dentry->d_iname;
Index: linux-2.6.git/include/linux/fs.h
===================================================================
--- linux-2.6.git.orig/include/linux/fs.h
+++ linux-2.6.git/include/linux/fs.h
@@ -1421,6 +1421,8 @@ struct super_block {
*/
struct mutex s_vfs_rename_mutex; /* Kludge */
+ seqlock_t s_rename_lock;
+
/*
* Filesystem subtype. If non-empty the filesystem type field
* in /proc/mounts will be "type.subtype"
Index: linux-2.6.git/kernel/auditsc.c
===================================================================
--- linux-2.6.git.orig/kernel/auditsc.c
+++ linux-2.6.git/kernel/auditsc.c
@@ -1779,7 +1779,7 @@ retry:
drop = NULL;
d = dentry;
rcu_read_lock();
- seq = read_seqbegin(&rename_lock);
+ seq = read_seqbegin(&dentry->d_sb->s_rename_lock);
for(;;) {
struct inode *inode = d->d_inode;
if (inode && unlikely(!hlist_empty(&inode->i_fsnotify_marks))) {
@@ -1797,7 +1797,7 @@ retry:
break;
d = parent;
}
- if (unlikely(read_seqretry(&rename_lock, seq) || drop)) { /* in this order */
+ if (unlikely(read_seqretry(&dentry->d_sb->s_rename_lock, seq) || drop)) { /* in this order */
rcu_read_unlock();
if (!drop) {
/* just a race with rename */
next prev parent reply other threads:[~2011-07-28 13:21 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-28 13:12 [patch 0/3] A few patches for dcache Cyrill Gorcunov
2011-07-28 13:12 ` [patch 1/3] vfs, dcache: Introduce lighten r/o rename_lock lockers Cyrill Gorcunov
2011-07-28 13:12 ` [patch 2/3] vfs, dcache: Factor out rename_lock locking Cyrill Gorcunov
2011-07-28 13:12 ` Cyrill Gorcunov [this message]
2011-07-29 3:25 ` [patch 0/3] A few patches for dcache Dave Chinner
2011-07-29 5:59 ` Cyrill Gorcunov
2011-07-29 6:59 ` Dave Chinner
2011-07-29 7:01 ` Cyrill Gorcunov
2011-07-29 7:24 ` Al Viro
2011-07-29 7:50 ` Cyrill Gorcunov
2011-08-15 7:42 ` Cyrill Gorcunov
2011-08-24 6:31 ` Pavel Emelyanov
-- strict thread matches above, loose matches on Subject: below --
2011-07-14 22:35 [patch 0/3] A few preparation patches for dcache further dcache shrinker rework Cyrill Gorcunov
2011-07-14 22:35 ` [patch 3/3] vfs: Make the rename_lock per-sb Cyrill Gorcunov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110728132139.661808096@openvz.org \
--to=gorcunov@openvz.org \
--cc=akpm@linux-foundation.org \
--cc=hch@infradead.org \
--cc=jbottomley@parallels.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=viro@ZenIV.linux.org.uk \
--cc=xemul@openvz.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).