From: Valerie Aurora <vaurora@redhat.com>
To: Nick Piggin <npiggin@kernel.dk>
Cc: Al Viro <viro@zeniv.linux.org.uk>, linux-fsdevel@vger.kernel.org
Subject: Re: [patch 04/10] fs: fs_struct rwlock to spinlock
Date: Tue, 17 Aug 2010 19:14:42 -0400 [thread overview]
Message-ID: <20100817231442.GN5556@shell> (raw)
In-Reply-To: <20100817184120.870235320@kernel.dk>
On Wed, Aug 18, 2010 at 04:37:33AM +1000, Nick Piggin wrote:
> fs: fs_struct rwlock to spinlock
>
> struct fs_struct.lock is an rwlock with the read-side used to protect root and
> pwd members while taking references to them. Taking a reference to a path
> typically requires just 2 atomic ops, so the critical section is very small.
> Parallel read-side operations would have cacheline contention on the lock, the
> dentry, and the vfsmount cachelines, so the rwlock is unlikely to ever give a
> real parallelism increase.
>
> Replace it with a spinlock to avoid one or two atomic operations in typical
> path lookup fastpath.
>
> Signed-off-by: Nick Piggin <npiggin@kernel.dk>
>
> ---
> drivers/staging/pohmelfs/path_entry.c | 8 ++++----
> fs/exec.c | 4 ++--
> fs/fs_struct.c | 32 ++++++++++++++++----------------
> include/linux/fs_struct.h | 14 +++++++-------
> kernel/fork.c | 10 +++++-----
> 5 files changed, 34 insertions(+), 34 deletions(-)
>
> Index: linux-2.6/fs/fs_struct.c
> ===================================================================
> --- linux-2.6.orig/fs/fs_struct.c 2010-08-18 04:04:01.000000000 +1000
> +++ linux-2.6/fs/fs_struct.c 2010-08-18 04:04:29.000000000 +1000
> @@ -13,11 +13,11 @@ void set_fs_root(struct fs_struct *fs, s
> {
> struct path old_root;
>
> - write_lock(&fs->lock);
> + spin_lock(&fs->lock);
> old_root = fs->root;
> fs->root = *path;
> path_get(path);
> - write_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> if (old_root.dentry)
> path_put(&old_root);
> }
> @@ -30,11 +30,11 @@ void set_fs_pwd(struct fs_struct *fs, st
> {
> struct path old_pwd;
>
> - write_lock(&fs->lock);
> + spin_lock(&fs->lock);
> old_pwd = fs->pwd;
> fs->pwd = *path;
> path_get(path);
> - write_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
>
> if (old_pwd.dentry)
> path_put(&old_pwd);
> @@ -51,7 +51,7 @@ void chroot_fs_refs(struct path *old_roo
> task_lock(p);
> fs = p->fs;
> if (fs) {
> - write_lock(&fs->lock);
> + spin_lock(&fs->lock);
> if (fs->root.dentry == old_root->dentry
> && fs->root.mnt == old_root->mnt) {
> path_get(new_root);
> @@ -64,7 +64,7 @@ void chroot_fs_refs(struct path *old_roo
> fs->pwd = *new_root;
> count++;
> }
> - write_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> }
> task_unlock(p);
> } while_each_thread(g, p);
> @@ -87,10 +87,10 @@ void exit_fs(struct task_struct *tsk)
> if (fs) {
> int kill;
> task_lock(tsk);
> - write_lock(&fs->lock);
> + spin_lock(&fs->lock);
> tsk->fs = NULL;
> kill = !--fs->users;
> - write_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> task_unlock(tsk);
> if (kill)
> free_fs_struct(fs);
> @@ -104,7 +104,7 @@ struct fs_struct *copy_fs_struct(struct
> if (fs) {
> fs->users = 1;
> fs->in_exec = 0;
> - rwlock_init(&fs->lock);
> + spin_lock_init(&fs->lock);
> fs->umask = old->umask;
> get_fs_root_and_pwd(old, &fs->root, &fs->pwd);
> }
> @@ -121,10 +121,10 @@ int unshare_fs_struct(void)
> return -ENOMEM;
>
> task_lock(current);
> - write_lock(&fs->lock);
> + spin_lock(&fs->lock);
> kill = !--fs->users;
> current->fs = new_fs;
> - write_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> task_unlock(current);
>
> if (kill)
> @@ -143,7 +143,7 @@ EXPORT_SYMBOL(current_umask);
> /* to be mentioned only in INIT_TASK */
> struct fs_struct init_fs = {
> .users = 1,
> - .lock = __RW_LOCK_UNLOCKED(init_fs.lock),
> + .lock = __SPIN_LOCK_UNLOCKED(init_fs.lock),
> .umask = 0022,
> };
>
> @@ -156,14 +156,14 @@ void daemonize_fs_struct(void)
>
> task_lock(current);
>
> - write_lock(&init_fs.lock);
> + spin_lock(&init_fs.lock);
> init_fs.users++;
> - write_unlock(&init_fs.lock);
> + spin_unlock(&init_fs.lock);
>
> - write_lock(&fs->lock);
> + spin_lock(&fs->lock);
> current->fs = &init_fs;
> kill = !--fs->users;
> - write_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
>
> task_unlock(current);
> if (kill)
> Index: linux-2.6/include/linux/fs_struct.h
> ===================================================================
> --- linux-2.6.orig/include/linux/fs_struct.h 2010-08-18 04:04:01.000000000 +1000
> +++ linux-2.6/include/linux/fs_struct.h 2010-08-18 04:04:29.000000000 +1000
> @@ -5,7 +5,7 @@
>
> struct fs_struct {
> int users;
> - rwlock_t lock;
> + spinlock_t lock;
> int umask;
> int in_exec;
> struct path root, pwd;
> @@ -23,29 +23,29 @@ extern int unshare_fs_struct(void);
>
> static inline void get_fs_root(struct fs_struct *fs, struct path *root)
> {
> - read_lock(&fs->lock);
> + spin_lock(&fs->lock);
> *root = fs->root;
> path_get(root);
> - read_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> }
>
> static inline void get_fs_pwd(struct fs_struct *fs, struct path *pwd)
> {
> - read_lock(&fs->lock);
> + spin_lock(&fs->lock);
> *pwd = fs->pwd;
> path_get(pwd);
> - read_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> }
>
> static inline void get_fs_root_and_pwd(struct fs_struct *fs, struct path *root,
> struct path *pwd)
> {
> - read_lock(&fs->lock);
> + spin_lock(&fs->lock);
> *root = fs->root;
> path_get(root);
> *pwd = fs->pwd;
> path_get(pwd);
> - read_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> }
>
> #endif /* _LINUX_FS_STRUCT_H */
> Index: linux-2.6/fs/exec.c
> ===================================================================
> --- linux-2.6.orig/fs/exec.c 2010-08-18 04:04:01.000000000 +1000
> +++ linux-2.6/fs/exec.c 2010-08-18 04:04:29.000000000 +1000
> @@ -1117,7 +1117,7 @@ int check_unsafe_exec(struct linux_binpr
> bprm->unsafe = tracehook_unsafe_exec(p);
>
> n_fs = 1;
> - write_lock(&p->fs->lock);
> + spin_lock(&p->fs->lock);
> rcu_read_lock();
> for (t = next_thread(p); t != p; t = next_thread(t)) {
> if (t->fs == p->fs)
> @@ -1134,7 +1134,7 @@ int check_unsafe_exec(struct linux_binpr
> res = 1;
> }
> }
> - write_unlock(&p->fs->lock);
> + spin_unlock(&p->fs->lock);
>
> return res;
> }
> Index: linux-2.6/kernel/fork.c
> ===================================================================
> --- linux-2.6.orig/kernel/fork.c 2010-08-18 04:04:01.000000000 +1000
> +++ linux-2.6/kernel/fork.c 2010-08-18 04:04:29.000000000 +1000
> @@ -752,13 +752,13 @@ static int copy_fs(unsigned long clone_f
> struct fs_struct *fs = current->fs;
> if (clone_flags & CLONE_FS) {
> /* tsk->fs is already what we want */
> - write_lock(&fs->lock);
> + spin_lock(&fs->lock);
> if (fs->in_exec) {
> - write_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> return -EAGAIN;
> }
> fs->users++;
> - write_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> return 0;
> }
> tsk->fs = copy_fs_struct(fs);
> @@ -1676,13 +1676,13 @@ SYSCALL_DEFINE1(unshare, unsigned long,
>
> if (new_fs) {
> fs = current->fs;
> - write_lock(&fs->lock);
> + spin_lock(&fs->lock);
> current->fs = new_fs;
> if (--fs->users)
> new_fs = NULL;
> else
> new_fs = fs;
> - write_unlock(&fs->lock);
> + spin_unlock(&fs->lock);
> }
>
> if (new_mm) {
> Index: linux-2.6/drivers/staging/pohmelfs/path_entry.c
> ===================================================================
> --- linux-2.6.orig/drivers/staging/pohmelfs/path_entry.c 2010-08-18 04:04:01.000000000 +1000
> +++ linux-2.6/drivers/staging/pohmelfs/path_entry.c 2010-08-18 04:04:29.000000000 +1000
> @@ -44,9 +44,9 @@ int pohmelfs_construct_path_string(struc
> return -ENOENT;
> }
>
> - read_lock(¤t->fs->lock);
> + spin_lock(¤t->fs->lock);
> path.mnt = mntget(current->fs->root.mnt);
> - read_unlock(¤t->fs->lock);
> + spin_unlock(¤t->fs->lock);
>
> path.dentry = d;
>
> @@ -91,9 +91,9 @@ int pohmelfs_path_length(struct pohmelfs
> return -ENOENT;
> }
>
> - read_lock(¤t->fs->lock);
> + spin_lock(¤t->fs->lock);
> root = dget(current->fs->root.dentry);
> - read_unlock(¤t->fs->lock);
> + spin_unlock(¤t->fs->lock);
>
> spin_lock(&dcache_lock);
Your reasoning makes sense to me. Shared reader access seems very
unlikely whereas the cost of taking the lock is certain.
Reviewed-by: Valerie Aurora <vaurora@redhat.com>
-VAL
next prev parent reply other threads:[~2010-08-17 23:14 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-17 18:37 [patch 00/10] first set of vfs scale patches Nick Piggin
2010-08-17 18:37 ` [patch 01/10] fs: fix do_lookup false negative Nick Piggin
2010-08-17 22:45 ` Valerie Aurora
2010-08-17 23:04 ` Sage Weil
2010-08-18 13:41 ` Andi Kleen
2010-08-17 18:37 ` [patch 02/10] fs: dentry allocation consolidation Nick Piggin
2010-08-17 22:45 ` Valerie Aurora
2010-08-17 18:37 ` [patch 03/10] apparmor: use task path helpers Nick Piggin
2010-08-17 22:59 ` Valerie Aurora
2010-08-17 18:37 ` [patch 04/10] fs: fs_struct rwlock to spinlock Nick Piggin
2010-08-17 23:14 ` Valerie Aurora [this message]
2010-08-20 10:05 ` Nick Piggin
2010-08-17 18:37 ` [patch 05/10] fs: remove extra lookup in __lookup_hash Nick Piggin
2010-08-18 13:57 ` Andi Kleen
2010-08-18 21:13 ` Andi Kleen
2010-08-18 19:34 ` Valerie Aurora
2010-08-17 18:37 ` [patch 06/10] fs: cleanup files_lock locking Nick Piggin
2010-08-18 19:46 ` Valerie Aurora
2010-08-17 18:37 ` [patch 07/10] tty: fix fu_list abuse Nick Piggin
2010-08-17 18:37 ` [patch 08/10] lglock: introduce special lglock and brlock spin locks Nick Piggin
2010-08-17 18:37 ` [patch 09/10] fs: scale files_lock Nick Piggin
2010-08-17 18:37 ` [patch 10/10] fs: brlock vfsmount_lock Nick Piggin
2010-08-18 14:05 ` Andi Kleen
2010-08-20 10:09 ` Nick Piggin
2010-08-17 21:14 ` [patch 00/10] first set of vfs scale patches Al Viro
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=20100817231442.GN5556@shell \
--to=vaurora@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=npiggin@kernel.dk \
--cc=viro@zeniv.linux.org.uk \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.