aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDipankar Sarma <dipankar@in.ibm.com>2005-09-09 16:04:14 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 16:57:55 -0400
commitb835996f628eadb55c5fb222ba46fe9395bf73c7 (patch)
treed63d80585d197e1ffc299af4a0034049790fb197 /fs
parentab2af1f5005069321c5d130f09cce577b03f43ef (diff)
[PATCH] files: lock-free fd look-up
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 <maneesh@in.ibm.com> Signed-off-by: Ravikiran Thirumalai <kiran_th@gmail.com> Signed-off-by: Dipankar Sarma <dipankar@in.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/fcntl.c4
-rw-r--r--fs/proc/base.c29
-rw-r--r--fs/select.c13
3 files changed, 27 insertions, 19 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index d2f3ed8acd93..863b46e0d78a 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -40,10 +40,10 @@ static inline int get_close_on_exec(unsigned int fd)
40 struct files_struct *files = current->files; 40 struct files_struct *files = current->files;
41 struct fdtable *fdt; 41 struct fdtable *fdt;
42 int res; 42 int res;
43 spin_lock(&files->file_lock); 43 rcu_read_lock();
44 fdt = files_fdtable(files); 44 fdt = files_fdtable(files);
45 res = FD_ISSET(fd, fdt->close_on_exec); 45 res = FD_ISSET(fd, fdt->close_on_exec);
46 spin_unlock(&files->file_lock); 46 rcu_read_unlock();
47 return res; 47 return res;
48} 48}
49 49
diff --git a/fs/proc/base.c b/fs/proc/base.c
index d0087a0b024b..23db452ab428 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -62,6 +62,7 @@
62#include <linux/namespace.h> 62#include <linux/namespace.h>
63#include <linux/mm.h> 63#include <linux/mm.h>
64#include <linux/smp_lock.h> 64#include <linux/smp_lock.h>
65#include <linux/rcupdate.h>
65#include <linux/kallsyms.h> 66#include <linux/kallsyms.h>
66#include <linux/mount.h> 67#include <linux/mount.h>
67#include <linux/security.h> 68#include <linux/security.h>
@@ -283,16 +284,16 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
283 284
284 files = get_files_struct(task); 285 files = get_files_struct(task);
285 if (files) { 286 if (files) {
286 spin_lock(&files->file_lock); 287 rcu_read_lock();
287 file = fcheck_files(files, fd); 288 file = fcheck_files(files, fd);
288 if (file) { 289 if (file) {
289 *mnt = mntget(file->f_vfsmnt); 290 *mnt = mntget(file->f_vfsmnt);
290 *dentry = dget(file->f_dentry); 291 *dentry = dget(file->f_dentry);
291 spin_unlock(&files->file_lock); 292 rcu_read_unlock();
292 put_files_struct(files); 293 put_files_struct(files);
293 return 0; 294 return 0;
294 } 295 }
295 spin_unlock(&files->file_lock); 296 rcu_read_unlock();
296 put_files_struct(files); 297 put_files_struct(files);
297 } 298 }
298 return -ENOENT; 299 return -ENOENT;
@@ -1062,7 +1063,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
1062 files = get_files_struct(p); 1063 files = get_files_struct(p);
1063 if (!files) 1064 if (!files)
1064 goto out; 1065 goto out;
1065 spin_lock(&files->file_lock); 1066 rcu_read_lock();
1066 fdt = files_fdtable(files); 1067 fdt = files_fdtable(files);
1067 for (fd = filp->f_pos-2; 1068 for (fd = filp->f_pos-2;
1068 fd < fdt->max_fds; 1069 fd < fdt->max_fds;
@@ -1071,7 +1072,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
1071 1072
1072 if (!fcheck_files(files, fd)) 1073 if (!fcheck_files(files, fd))
1073 continue; 1074 continue;
1074 spin_unlock(&files->file_lock); 1075 rcu_read_unlock();
1075 1076
1076 j = NUMBUF; 1077 j = NUMBUF;
1077 i = fd; 1078 i = fd;
@@ -1083,12 +1084,12 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
1083 1084
1084 ino = fake_ino(tid, PROC_TID_FD_DIR + fd); 1085 ino = fake_ino(tid, PROC_TID_FD_DIR + fd);
1085 if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) { 1086 if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) {
1086 spin_lock(&files->file_lock); 1087 rcu_read_lock();
1087 break; 1088 break;
1088 } 1089 }
1089 spin_lock(&files->file_lock); 1090 rcu_read_lock();
1090 } 1091 }
1091 spin_unlock(&files->file_lock); 1092 rcu_read_unlock();
1092 put_files_struct(files); 1093 put_files_struct(files);
1093 } 1094 }
1094out: 1095out:
@@ -1263,9 +1264,9 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1263 1264
1264 files = get_files_struct(task); 1265 files = get_files_struct(task);
1265 if (files) { 1266 if (files) {
1266 spin_lock(&files->file_lock); 1267 rcu_read_lock();
1267 if (fcheck_files(files, fd)) { 1268 if (fcheck_files(files, fd)) {
1268 spin_unlock(&files->file_lock); 1269 rcu_read_unlock();
1269 put_files_struct(files); 1270 put_files_struct(files);
1270 if (task_dumpable(task)) { 1271 if (task_dumpable(task)) {
1271 inode->i_uid = task->euid; 1272 inode->i_uid = task->euid;
@@ -1277,7 +1278,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1277 security_task_to_inode(task, inode); 1278 security_task_to_inode(task, inode);
1278 return 1; 1279 return 1;
1279 } 1280 }
1280 spin_unlock(&files->file_lock); 1281 rcu_read_unlock();
1281 put_files_struct(files); 1282 put_files_struct(files);
1282 } 1283 }
1283 d_drop(dentry); 1284 d_drop(dentry);
@@ -1369,7 +1370,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
1369 if (!files) 1370 if (!files)
1370 goto out_unlock; 1371 goto out_unlock;
1371 inode->i_mode = S_IFLNK; 1372 inode->i_mode = S_IFLNK;
1372 spin_lock(&files->file_lock); 1373 rcu_read_lock();
1373 file = fcheck_files(files, fd); 1374 file = fcheck_files(files, fd);
1374 if (!file) 1375 if (!file)
1375 goto out_unlock2; 1376 goto out_unlock2;
@@ -1377,7 +1378,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
1377 inode->i_mode |= S_IRUSR | S_IXUSR; 1378 inode->i_mode |= S_IRUSR | S_IXUSR;
1378 if (file->f_mode & 2) 1379 if (file->f_mode & 2)
1379 inode->i_mode |= S_IWUSR | S_IXUSR; 1380 inode->i_mode |= S_IWUSR | S_IXUSR;
1380 spin_unlock(&files->file_lock); 1381 rcu_read_unlock();
1381 put_files_struct(files); 1382 put_files_struct(files);
1382 inode->i_op = &proc_pid_link_inode_operations; 1383 inode->i_op = &proc_pid_link_inode_operations;
1383 inode->i_size = 64; 1384 inode->i_size = 64;
@@ -1387,7 +1388,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
1387 return NULL; 1388 return NULL;
1388 1389
1389out_unlock2: 1390out_unlock2:
1390 spin_unlock(&files->file_lock); 1391 rcu_read_unlock();
1391 put_files_struct(files); 1392 put_files_struct(files);
1392out_unlock: 1393out_unlock:
1393 iput(inode); 1394 iput(inode);
diff --git a/fs/select.c b/fs/select.c
index 2e56325c73c4..f10a10317d54 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -22,6 +22,7 @@
22#include <linux/personality.h> /* for STICKY_TIMEOUTS */ 22#include <linux/personality.h> /* for STICKY_TIMEOUTS */
23#include <linux/file.h> 23#include <linux/file.h>
24#include <linux/fs.h> 24#include <linux/fs.h>
25#include <linux/rcupdate.h>
25 26
26#include <asm/uaccess.h> 27#include <asm/uaccess.h>
27 28
@@ -185,9 +186,9 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
185 int retval, i; 186 int retval, i;
186 long __timeout = *timeout; 187 long __timeout = *timeout;
187 188
188 spin_lock(&current->files->file_lock); 189 rcu_read_lock();
189 retval = max_select_fd(n, fds); 190 retval = max_select_fd(n, fds);
190 spin_unlock(&current->files->file_lock); 191 rcu_read_unlock();
191 192
192 if (retval < 0) 193 if (retval < 0)
193 return retval; 194 return retval;
@@ -329,8 +330,10 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
329 goto out_nofds; 330 goto out_nofds;
330 331
331 /* max_fdset can increase, so grab it once to avoid race */ 332 /* max_fdset can increase, so grab it once to avoid race */
333 rcu_read_lock();
332 fdt = files_fdtable(current->files); 334 fdt = files_fdtable(current->files);
333 max_fdset = fdt->max_fdset; 335 max_fdset = fdt->max_fdset;
336 rcu_read_unlock();
334 if (n > max_fdset) 337 if (n > max_fdset)
335 n = max_fdset; 338 n = max_fdset;
336 339
@@ -469,10 +472,14 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti
469 struct poll_list *head; 472 struct poll_list *head;
470 struct poll_list *walk; 473 struct poll_list *walk;
471 struct fdtable *fdt; 474 struct fdtable *fdt;
475 int max_fdset;
472 476
473 /* Do a sanity check on nfds ... */ 477 /* Do a sanity check on nfds ... */
478 rcu_read_lock();
474 fdt = files_fdtable(current->files); 479 fdt = files_fdtable(current->files);
475 if (nfds > fdt->max_fdset && nfds > OPEN_MAX) 480 max_fdset = fdt->max_fdset;
481 rcu_read_unlock();
482 if (nfds > max_fdset && nfds > OPEN_MAX)
476 return -EINVAL; 483 return -EINVAL;
477 484
478 if (timeout) { 485 if (timeout) {