Linux filesystem development
 help / color / mirror / Atom feed
From: Dave Hansen <hansendc@us.ibm.com>
To: containers@lists.osdl.org
Cc: linux-fsdevel@vger.kernel.org, hch@infradead.org,
	viro@ftp.linux.org.uk, dgc@sgi.com, clameter@sgi.com,
	Dave Hansen <hansendc@us.ibm.com>
Subject: [RFC][PATCH 2/2] record cpu hint for future fput()
Date: Tue, 20 Feb 2007 18:03:53 -0800	[thread overview]
Message-ID: <20070221020352.42A2383B@localhost.localdomain> (raw)
In-Reply-To: <20070221020352.4EE9C66E@localhost.localdomain>


Most mnt_want/drop_write() pairs are really close in
the code; they aren't held for very long.  So, in
practice is hard to get bounced between cpus between
when you mnt_want_write() and mnt_drop_write().

The exception to this is the pair in may_open() and
__fput().  Between those two it is pretty common to
move between cpus.  During a kernel compile of around
900 files on a 4-way, I saw it happen ~400 times.

This patch assumes that the cpu doing the allocating of
the 'struct file' is also the one doing the
mnt_want_write().  It is OK that it is wrong sometimes,
it just means that we regress back to the
spinlock-protected search of all of the cpus' counts.

My kernel compile from before went from 400 misses
during a compile to just 20 with this patch.

It might also be helpful to do the writer count per-node
which would _greatly_ decrease the number of migrations
that we see.


---

 lxc-dave/fs/file_table.c       |    2 +-
 lxc-dave/fs/namespace.c        |   17 +++++++++--------
 lxc-dave/fs/open.c             |    4 ++++
 lxc-dave/include/linux/fs.h    |    1 +
 lxc-dave/include/linux/mount.h |    1 +
 5 files changed, 16 insertions(+), 9 deletions(-)

diff -puN fs/file_table.c~fput-cpu fs/file_table.c
--- lxc/fs/file_table.c~fput-cpu	2007-02-20 17:59:48.000000000 -0800
+++ lxc-dave/fs/file_table.c	2007-02-20 17:59:49.000000000 -0800
@@ -215,7 +215,7 @@ void fastcall __fput(struct file *file)
 	if (file->f_mode & FMODE_WRITE) {
 		put_write_access(inode);
 		if(!special_file(inode->i_mode))
-			mnt_drop_write(mnt);
+			__mnt_drop_write(mnt, file->f_write_cpu);
 	}
 	put_pid(file->f_owner.pid);
 	file_kill(file);
diff -puN fs/namespace.c~fput-cpu fs/namespace.c
--- lxc/fs/namespace.c~fput-cpu	2007-02-20 17:59:48.000000000 -0800
+++ lxc-dave/fs/namespace.c	2007-02-20 18:00:27.000000000 -0800
@@ -89,8 +89,8 @@ struct vfsmount *alloc_vfsmnt(const char
 int mnt_want_write(struct vfsmount *mnt)
 {
 	int ret = 0;
-	atomic_t *cpu_writecount;
 	int cpu = get_cpu();
+	atomic_t *cpu_writecount;
 retry:
 	/*
 	 * Not strictly required, but quick and cheap
@@ -122,22 +122,17 @@ out:
 	put_cpu();
 	return ret;
 }
-EXPORT_SYMBOL_GPL(mnt_want_write);
 
-void mnt_drop_write(struct vfsmount *mnt)
+void __mnt_drop_write(struct vfsmount *mnt, int cpu)
 {
 	static int miss = 0;
 	atomic_t *cpu_writecount;
-	int cpu;
 	int borrowed = 0;
 	int retries = 0;
 retry:
-	cpu = get_cpu();
 	cpu_writecount = per_cpu_ptr(mnt->writers, cpu);
-	if (atomic_add_unless(cpu_writecount, -1, 0)) {
-		put_cpu();
+	if (atomic_add_unless(cpu_writecount, -1, 0))
 		return;
-	}
 	spin_lock(&vfsmount_lock);
 	/*
 	 * Holding the spinlock, and only checking cpus that
@@ -167,6 +162,12 @@ retry:
 	if (!borrowed)
 		goto retry;
 }
+void mnt_drop_write(struct vfsmount *mnt)
+{
+	int cpu = get_cpu();
+	__mnt_drop_write(mnt, cpu);
+	put_cpu();
+}
 EXPORT_SYMBOL_GPL(mnt_drop_write);
 
 /*
diff -puN fs/open.c~fput-cpu fs/open.c
--- lxc/fs/open.c~fput-cpu	2007-02-20 17:59:48.000000000 -0800
+++ lxc-dave/fs/open.c	2007-02-20 17:59:49.000000000 -0800
@@ -715,6 +715,10 @@ static struct file *__dentry_open(struct
 	f->f_path.mnt = mnt;
 	f->f_pos = 0;
 	f->f_op = fops_get(inode->i_fop);
+	/*
+	 * This is OK to race because it is just a hint
+	 */
+	f->f_write_cpu = smp_processor_id();
 	file_move(f, &inode->i_sb->s_files);
 
 	if (!open && f->f_op)
diff -puN include/linux/fs.h~fput-cpu include/linux/fs.h
--- lxc/include/linux/fs.h~fput-cpu	2007-02-20 17:59:48.000000000 -0800
+++ lxc-dave/include/linux/fs.h	2007-02-20 17:59:49.000000000 -0800
@@ -766,6 +766,7 @@ struct file {
 	struct fown_struct	f_owner;
 	unsigned int		f_uid, f_gid;
 	struct file_ra_state	f_ra;
+	int f_write_cpu;
 
 	unsigned long		f_version;
 #ifdef CONFIG_SECURITY
diff -puN include/linux/mount.h~fput-cpu include/linux/mount.h
--- lxc/include/linux/mount.h~fput-cpu	2007-02-20 17:59:49.000000000 -0800
+++ lxc-dave/include/linux/mount.h	2007-02-20 17:59:49.000000000 -0800
@@ -94,6 +94,7 @@ static inline int __mnt_is_readonly(stru
 
 extern int mnt_want_write(struct vfsmount *mnt);
 extern void mnt_drop_write(struct vfsmount *mnt);
+extern void __mnt_drop_write(struct vfsmount *mnt, int cpu);
 extern void mntput_no_expire(struct vfsmount *mnt);
 extern void mnt_pin(struct vfsmount *mnt);
 extern void mnt_unpin(struct vfsmount *mnt);
_

      reply	other threads:[~2007-02-21  2:03 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-02-21  2:03 [RFC][PATCH 1/2] r/o bind mounts: NUMA-friendly writer count Dave Hansen
2007-02-21  2:03 ` Dave Hansen [this message]

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=20070221020352.42A2383B@localhost.localdomain \
    --to=hansendc@us.ibm.com \
    --cc=clameter@sgi.com \
    --cc=containers@lists.osdl.org \
    --cc=dgc@sgi.com \
    --cc=hch@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=viro@ftp.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