From mboxrd@z Thu Jan 1 00:00:00 1970 From: Cyrill Gorcunov Subject: [patch 1/3] vfs, dcache: Introduce lighten r/o rename_lock lockers Date: Fri, 15 Jul 2011 02:35:07 +0400 Message-ID: <20110714223730.024481927@openvz.org> References: <20110714223506.678350552@openvz.org> Cc: akpm@linux-foundation.org, xemul@openvz.org, Cyrill Gorcunov To: linux-fsdevel@vger.kernel.org Return-path: Received: from mail-fx0-f52.google.com ([209.85.161.52]:33268 "EHLO mail-fx0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932279Ab1GNWkZ (ORCPT ); Thu, 14 Jul 2011 18:40:25 -0400 Received: by mail-fx0-f52.google.com with SMTP id 18so1695061fxd.11 for ; Thu, 14 Jul 2011 15:40:25 -0700 (PDT) Content-Disposition: inline; filename=dcache-1-13.patch Sender: linux-fsdevel-owner@vger.kernel.org List-ID: From: Pavel Emelyanov Subject: [patch 1/3] vfs, dcache: Introduce lighten r/o rename_lock lockers There are some places, that need to _lock_ the rename_lock, but they do it for reading the dentry tree. When doing the write_seqlock they force the existing "willing to restart" readers do the restart, which is not actually required. Introduce two more seqlock helpers, that lock the lock, but do not update the seq count. Signed-off-by: Pavel Emelyanov Signed-off-by: Cyrill Gorcunov --- fs/dcache.c | 40 ++++++++++++++++++++-------------------- include/linux/seqlock.h | 16 ++++++++++++++++ 2 files changed, 36 insertions(+), 20 deletions(-) Index: linux-2.6.git/fs/dcache.c =================================================================== --- linux-2.6.git.orig/fs/dcache.c +++ linux-2.6.git/fs/dcache.c @@ -1089,18 +1089,18 @@ resume: if (!locked && read_seqretry(&rename_lock, seq)) goto rename_retry; if (locked) - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); return 0; /* No mount points found in tree */ positive: if (!locked && read_seqretry(&rename_lock, seq)) goto rename_retry; if (locked) - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); return 1; rename_retry: locked = 1; - write_seqlock(&rename_lock); + read_seqlock(&rename_lock); goto again; } EXPORT_SYMBOL(have_submounts); @@ -1191,14 +1191,14 @@ out: if (!locked && read_seqretry(&rename_lock, seq)) goto rename_retry; if (locked) - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); return found; rename_retry: if (found) return found; locked = 1; - write_seqlock(&rename_lock); + read_seqlock(&rename_lock); goto again; } @@ -2562,9 +2562,9 @@ char *__d_path(const struct path *path, int error; prepend(&res, &buflen, "\0", 1); - write_seqlock(&rename_lock); + read_seqlock(&rename_lock); error = prepend_path(path, root, &res, &buflen); - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); if (error) return ERR_PTR(error); @@ -2626,12 +2626,12 @@ char *d_path(const struct path *path, ch return path->dentry->d_op->d_dname(path->dentry, buf, buflen); get_fs_root(current->fs, &root); - write_seqlock(&rename_lock); + read_seqlock(&rename_lock); tmp = root; error = path_with_deleted(path, &tmp, &res, &buflen); if (error) res = ERR_PTR(error); - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); path_put(&root); return res; } @@ -2657,12 +2657,12 @@ char *d_path_with_unreachable(const stru return path->dentry->d_op->d_dname(path->dentry, buf, buflen); get_fs_root(current->fs, &root); - write_seqlock(&rename_lock); + read_seqlock(&rename_lock); tmp = root; error = path_with_deleted(path, &tmp, &res, &buflen); if (!error && !path_equal(&tmp, &root)) error = prepend_unreachable(&res, &buflen); - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); path_put(&root); if (error) res = ERR_PTR(error); @@ -2729,9 +2729,9 @@ char *dentry_path_raw(struct dentry *den { char *retval; - write_seqlock(&rename_lock); + read_seqlock(&rename_lock); retval = __dentry_path(dentry, buf, buflen); - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); return retval; } @@ -2742,7 +2742,7 @@ char *dentry_path(struct dentry *dentry, char *p = NULL; char *retval; - write_seqlock(&rename_lock); + read_seqlock(&rename_lock); if (d_unlinked(dentry)) { p = buf + buflen; if (prepend(&p, &buflen, "//deleted", 10) != 0) @@ -2750,7 +2750,7 @@ char *dentry_path(struct dentry *dentry, buflen++; } retval = __dentry_path(dentry, buf, buflen); - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); if (!IS_ERR(retval) && p) *p = '/'; /* restore '/' overriden with '\0' */ return retval; @@ -2788,7 +2788,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, b get_fs_root_and_pwd(current->fs, &root, &pwd); error = -ENOENT; - write_seqlock(&rename_lock); + read_seqlock(&rename_lock); if (!d_unlinked(pwd.dentry)) { unsigned long len; struct path tmp = root; @@ -2797,7 +2797,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, b prepend(&cwd, &buflen, "\0", 1); error = prepend_path(&pwd, &tmp, &cwd, &buflen); - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); if (error) goto out; @@ -2817,7 +2817,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, b error = -EFAULT; } } else { - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); } out: @@ -2947,12 +2947,12 @@ resume: if (!locked && read_seqretry(&rename_lock, seq)) goto rename_retry; if (locked) - write_sequnlock(&rename_lock); + read_sequnlock(&rename_lock); return; rename_retry: locked = 1; - write_seqlock(&rename_lock); + read_seqlock(&rename_lock); goto again; } Index: linux-2.6.git/include/linux/seqlock.h =================================================================== --- linux-2.6.git.orig/include/linux/seqlock.h +++ linux-2.6.git/include/linux/seqlock.h @@ -108,6 +108,22 @@ static __always_inline int read_seqretry return unlikely(sl->sequence != start); } +/* + * Lock/unlock the critical section against updates but + * no sequence counter altering, so the other lockless + * readers will not have to restart reading data if + * read-only-lock occured. + */ + +static __always_inline void read_seqlock(seqlock_t *sl) +{ + spin_lock(&sl->lock); +} + +static __always_inline void read_sequnlock(seqlock_t *sl) +{ + spin_unlock(&sl->lock); +} /* * Version using sequence counter only.