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 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).