<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
From: Dipankar Sarma &lt;dipankar@in.ibm.com&gt;

With the use of RCU in files structure, the look-up of files using fds can now
be lock-free.  The lookup is protected by rcu_read_lock()/rcu_read_unlock(). 
This patch changes the readers to use lock-free lookup.

Signed-off-by: Maneesh Soni &lt;maneesh@in.ibm.com&gt;
Signed-off-by: Ravikiran Thirumalai &lt;kiran_th@gmail.com&gt;
Signed-off-by: Dipankar Sarma &lt;dipankar@in.ibm.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@osdl.org&gt;
---

 arch/mips/kernel/irixioctl.c    |    5 +++--
 arch/sparc64/solaris/ioctl.c    |    7 ++++---
 drivers/char/tty_io.c           |    4 ++--
 fs/fcntl.c                      |    4 ++--
 fs/proc/base.c                  |   29 +++++++++++++++--------------
 fs/select.c                     |   13 ++++++++++---
 net/ipv4/netfilter/ipt_owner.c  |    1 +
 net/ipv6/netfilter/ip6t_owner.c |    1 +
 security/selinux/hooks.c        |    2 +-
 9 files changed, 39 insertions(+), 27 deletions(-)

diff -puN arch/mips/kernel/irixioctl.c~files-lock-free-fd-look-up arch/mips/kernel/irixioctl.c
--- devel/arch/mips/kernel/irixioctl.c~files-lock-free-fd-look-up	2005-08-30 18:46:01.000000000 -0700
+++ devel-akpm/arch/mips/kernel/irixioctl.c	2005-08-30 18:46:01.000000000 -0700
@@ -14,6 +14,7 @@
 #include &lt;linux/syscalls.h&gt;
 #include &lt;linux/tty.h&gt;
 #include &lt;linux/file.h&gt;
+#include &lt;linux/rcupdate.h&gt;
 
 #include &lt;asm/uaccess.h&gt;
 #include &lt;asm/ioctl.h&gt;
@@ -33,7 +34,7 @@ static struct tty_struct *get_tty(int fd
 	struct file *filp;
 	struct tty_struct *ttyp = NULL;
 
-	spin_lock(&amp;current-&gt;files-&gt;file_lock);
+	rcu_read_lock();
 	filp = fcheck(fd);
 	if(filp &amp;&amp; filp-&gt;private_data) {
 		ttyp = (struct tty_struct *) filp-&gt;private_data;
@@ -41,7 +42,7 @@ static struct tty_struct *get_tty(int fd
 		if(ttyp-&gt;magic != TTY_MAGIC)
 			ttyp =NULL;
 	}
-	spin_unlock(&amp;current-&gt;files-&gt;file_lock);
+	rcu_read_unlock();
 	return ttyp;
 }
 
diff -puN arch/sparc64/solaris/ioctl.c~files-lock-free-fd-look-up arch/sparc64/solaris/ioctl.c
--- devel/arch/sparc64/solaris/ioctl.c~files-lock-free-fd-look-up	2005-08-30 18:46:01.000000000 -0700
+++ devel-akpm/arch/sparc64/solaris/ioctl.c	2005-08-30 18:46:01.000000000 -0700
@@ -24,6 +24,7 @@
 #include &lt;linux/netdevice.h&gt;
 #include &lt;linux/mtio.h&gt;
 #include &lt;linux/time.h&gt;
+#include &lt;linux/rcupdate.h&gt;
 #include &lt;linux/compat.h&gt;
 
 #include &lt;net/sock.h&gt;
@@ -295,16 +296,16 @@ static inline int solaris_sockmod(unsign
 	struct inode *ino;
 	struct fdtable *fdt;
 	/* I wonder which of these tests are superfluous... --patrik */
-	spin_lock(&amp;current-&gt;files-&gt;file_lock);
+	rcu_read_lock();
 	fdt = files_fdtable(current-&gt;files);
 	if (! fdt-&gt;fd[fd] ||
 	    ! fdt-&gt;fd[fd]-&gt;f_dentry ||
 	    ! (ino = fdt-&gt;fd[fd]-&gt;f_dentry-&gt;d_inode) ||
 	    ! S_ISSOCK(ino-&gt;i_mode)) {
-		spin_unlock(&amp;current-&gt;files-&gt;file_lock);
+		rcu_read_unlock();
 		return TBADF;
 	}
-	spin_unlock(&amp;current-&gt;files-&gt;file_lock);
+	rcu_read_unlock();
 	
 	switch (cmd &amp; 0xff) {
 	case 109: /* SI_SOCKPARAMS */
diff -puN drivers/char/tty_io.c~files-lock-free-fd-look-up drivers/char/tty_io.c
--- devel/drivers/char/tty_io.c~files-lock-free-fd-look-up	2005-08-30 18:46:01.000000000 -0700
+++ devel-akpm/drivers/char/tty_io.c	2005-08-30 18:46:01.000000000 -0700
@@ -2689,7 +2689,7 @@ static void __do_SAK(void *arg)
 		}
 		task_lock(p);
 		if (p-&gt;files) {
-			spin_lock(&amp;p-&gt;files-&gt;file_lock);
+			rcu_read_lock();
 			fdt = files_fdtable(p-&gt;files);
 			for (i=0; i &lt; fdt-&gt;max_fds; i++) {
 				filp = fcheck_files(p-&gt;files, i);
@@ -2704,7 +2704,7 @@ static void __do_SAK(void *arg)
 					break;
 				}
 			}
-			spin_unlock(&amp;p-&gt;files-&gt;file_lock);
+			rcu_read_unlock();
 		}
 		task_unlock(p);
 	} while_each_task_pid(session, PIDTYPE_SID, p);
diff -puN fs/fcntl.c~files-lock-free-fd-look-up fs/fcntl.c
--- devel/fs/fcntl.c~files-lock-free-fd-look-up	2005-08-30 18:46:01.000000000 -0700
+++ devel-akpm/fs/fcntl.c	2005-08-30 18:46:01.000000000 -0700
@@ -40,10 +40,10 @@ static inline int get_close_on_exec(unsi
 	struct files_struct *files = current-&gt;files;
 	struct fdtable *fdt;
 	int res;
-	spin_lock(&amp;files-&gt;file_lock);
+	rcu_read_lock();
 	fdt = files_fdtable(files);
 	res = FD_ISSET(fd, fdt-&gt;close_on_exec);
-	spin_unlock(&amp;files-&gt;file_lock);
+	rcu_read_unlock();
 	return res;
 }
 
diff -puN fs/proc/base.c~files-lock-free-fd-look-up fs/proc/base.c
--- devel/fs/proc/base.c~files-lock-free-fd-look-up	2005-08-30 18:46:01.000000000 -0700
+++ devel-akpm/fs/proc/base.c	2005-08-30 18:46:01.000000000 -0700
@@ -62,6 +62,7 @@
 #include &lt;linux/namespace.h&gt;
 #include &lt;linux/mm.h&gt;
 #include &lt;linux/smp_lock.h&gt;
+#include &lt;linux/rcupdate.h&gt;
 #include &lt;linux/kallsyms.h&gt;
 #include &lt;linux/mount.h&gt;
 #include &lt;linux/security.h&gt;
@@ -283,16 +284,16 @@ static int proc_fd_link(struct inode *in
 
 	files = get_files_struct(task);
 	if (files) {
-		spin_lock(&amp;files-&gt;file_lock);
+		rcu_read_lock();
 		file = fcheck_files(files, fd);
 		if (file) {
 			*mnt = mntget(file-&gt;f_vfsmnt);
 			*dentry = dget(file-&gt;f_dentry);
-			spin_unlock(&amp;files-&gt;file_lock);
+			rcu_read_unlock();
 			put_files_struct(files);
 			return 0;
 		}
-		spin_unlock(&amp;files-&gt;file_lock);
+		rcu_read_unlock();
 		put_files_struct(files);
 	}
 	return -ENOENT;
@@ -1062,7 +1063,7 @@ static int proc_readfd(struct file * fil
 			files = get_files_struct(p);
 			if (!files)
 				goto out;
-			spin_lock(&amp;files-&gt;file_lock);
+			rcu_read_lock();
 			fdt = files_fdtable(files);
 			for (fd = filp-&gt;f_pos-2;
 			     fd &lt; fdt-&gt;max_fds;
@@ -1071,7 +1072,7 @@ static int proc_readfd(struct file * fil
 
 				if (!fcheck_files(files, fd))
 					continue;
-				spin_unlock(&amp;files-&gt;file_lock);
+				rcu_read_unlock();
 
 				j = NUMBUF;
 				i = fd;
@@ -1083,12 +1084,12 @@ static int proc_readfd(struct file * fil
 
 				ino = fake_ino(tid, PROC_TID_FD_DIR + fd);
 				if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) &lt; 0) {
-					spin_lock(&amp;files-&gt;file_lock);
+					rcu_read_lock();
 					break;
 				}
-				spin_lock(&amp;files-&gt;file_lock);
+				rcu_read_lock();
 			}
-			spin_unlock(&amp;files-&gt;file_lock);
+			rcu_read_unlock();
 			put_files_struct(files);
 	}
 out:
@@ -1263,9 +1264,9 @@ static int tid_fd_revalidate(struct dent
 
 	files = get_files_struct(task);
 	if (files) {
-		spin_lock(&amp;files-&gt;file_lock);
+		rcu_read_lock();
 		if (fcheck_files(files, fd)) {
-			spin_unlock(&amp;files-&gt;file_lock);
+			rcu_read_unlock();
 			put_files_struct(files);
 			if (task_dumpable(task)) {
 				inode-&gt;i_uid = task-&gt;euid;
@@ -1277,7 +1278,7 @@ static int tid_fd_revalidate(struct dent
 			security_task_to_inode(task, inode);
 			return 1;
 		}
-		spin_unlock(&amp;files-&gt;file_lock);
+		rcu_read_unlock();
 		put_files_struct(files);
 	}
 	d_drop(dentry);
@@ -1369,7 +1370,7 @@ static struct dentry *proc_lookupfd(stru
 	if (!files)
 		goto out_unlock;
 	inode-&gt;i_mode = S_IFLNK;
-	spin_lock(&amp;files-&gt;file_lock);
+	rcu_read_lock();
 	file = fcheck_files(files, fd);
 	if (!file)
 		goto out_unlock2;
@@ -1377,7 +1378,7 @@ static struct dentry *proc_lookupfd(stru
 		inode-&gt;i_mode |= S_IRUSR | S_IXUSR;
 	if (file-&gt;f_mode &amp; 2)
 		inode-&gt;i_mode |= S_IWUSR | S_IXUSR;
-	spin_unlock(&amp;files-&gt;file_lock);
+	rcu_read_unlock();
 	put_files_struct(files);
 	inode-&gt;i_op = &amp;proc_pid_link_inode_operations;
 	inode-&gt;i_size = 64;
@@ -1387,7 +1388,7 @@ static struct dentry *proc_lookupfd(stru
 	return NULL;
 
 out_unlock2:
-	spin_unlock(&amp;files-&gt;file_lock);
+	rcu_read_unlock();
 	put_files_struct(files);
 out_unlock:
 	iput(inode);
diff -puN fs/select.c~files-lock-free-fd-look-up fs/select.c
--- devel/fs/select.c~files-lock-free-fd-look-up	2005-08-30 18:46:01.000000000 -0700
+++ devel-akpm/fs/select.c	2005-08-30 18:46:01.000000000 -0700
@@ -22,6 +22,7 @@
 #include &lt;linux/personality.h&gt; /* for STICKY_TIMEOUTS */
 #include &lt;linux/file.h&gt;
 #include &lt;linux/fs.h&gt;
+#include &lt;linux/rcupdate.h&gt;
 
 #include &lt;asm/uaccess.h&gt;
 
@@ -185,9 +186,9 @@ int do_select(int n, fd_set_bits *fds, l
 	int retval, i;
 	long __timeout = *timeout;
 
- 	spin_lock(&amp;current-&gt;files-&gt;file_lock);
+	rcu_read_lock();
 	retval = max_select_fd(n, fds);
-	spin_unlock(&amp;current-&gt;files-&gt;file_lock);
+	rcu_read_unlock();
 
 	if (retval &lt; 0)
 		return retval;
@@ -307,8 +308,10 @@ static int core_sys_select(int n, fd_set
 		goto out_nofds;
 
 	/* max_fdset can increase, so grab it once to avoid race */
+	rcu_read_lock();
 	fdt = files_fdtable(current-&gt;files);
 	max_fdset = fdt-&gt;max_fdset;
+	rcu_read_unlock();
 	if (n &gt; max_fdset)
 		n = max_fdset;
 
@@ -579,10 +582,14 @@ int do_sys_poll(struct pollfd __user *uf
 	struct poll_list *head;
  	struct poll_list *walk;
 	struct fdtable *fdt;
+	int max_fdset;
 
 	/* Do a sanity check on nfds ... */
+	rcu_read_lock();
 	fdt = files_fdtable(current-&gt;files);
-	if (nfds &gt; fdt-&gt;max_fdset &amp;&amp; nfds &gt; OPEN_MAX)
+	max_fdset = fdt-&gt;max_fdset;
+	rcu_read_unlock();
+	if (nfds &gt; max_fdset &amp;&amp; nfds &gt; OPEN_MAX)
 		return -EINVAL;
 
 	poll_initwait(&amp;table);
diff -puN net/ipv4/netfilter/ipt_owner.c~files-lock-free-fd-look-up net/ipv4/netfilter/ipt_owner.c
--- devel/net/ipv4/netfilter/ipt_owner.c~files-lock-free-fd-look-up	2005-08-30 18:46:01.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ipt_owner.c	2005-08-30 18:46:01.000000000 -0700
@@ -11,6 +11,7 @@
 #include &lt;linux/module.h&gt;
 #include &lt;linux/skbuff.h&gt;
 #include &lt;linux/file.h&gt;
+#include &lt;linux/rcupdate.h&gt;
 #include &lt;net/sock.h&gt;
 
 #include &lt;linux/netfilter_ipv4/ipt_owner.h&gt;
diff -puN net/ipv6/netfilter/ip6t_owner.c~files-lock-free-fd-look-up net/ipv6/netfilter/ip6t_owner.c
--- devel/net/ipv6/netfilter/ip6t_owner.c~files-lock-free-fd-look-up	2005-08-30 18:46:01.000000000 -0700
+++ devel-akpm/net/ipv6/netfilter/ip6t_owner.c	2005-08-30 18:46:01.000000000 -0700
@@ -11,6 +11,7 @@
 #include &lt;linux/module.h&gt;
 #include &lt;linux/skbuff.h&gt;
 #include &lt;linux/file.h&gt;
+#include &lt;linux/rcupdate.h&gt;
 #include &lt;net/sock.h&gt;
 
 #include &lt;linux/netfilter_ipv6/ip6t_owner.h&gt;
diff -puN security/selinux/hooks.c~files-lock-free-fd-look-up security/selinux/hooks.c
--- devel/security/selinux/hooks.c~files-lock-free-fd-look-up	2005-08-30 18:46:01.000000000 -0700
+++ devel-akpm/security/selinux/hooks.c	2005-08-30 18:46:01.000000000 -0700
@@ -1652,7 +1652,7 @@ static inline void flush_unauthorized_fi
 						continue;
 					}
 					if (devnull) {
-						atomic_inc(&amp;devnull-&gt;f_count);
+						rcuref_inc(&amp;devnull-&gt;f_count);
 					} else {
 						devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
 						if (!devnull) {
_
</pre></body></html>