aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 11:56:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-07 11:56:33 -0500
commitb4a45f5fe8078bfc10837dbd5b98735058bc4698 (patch)
treedf6f13a27610a3ec7eb4a661448cd779a8f84c79 /fs/proc
parent01539ba2a706ab7d35fc0667dff919ade7f87d63 (diff)
parentb3e19d924b6eaf2ca7d22cba99a517c5171007b6 (diff)
Merge branch 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin
* 'vfs-scale-working' of git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin: (57 commits) fs: scale mntget/mntput fs: rename vfsmount counter helpers fs: implement faster dentry memcmp fs: prefetch inode data in dcache lookup fs: improve scalability of pseudo filesystems fs: dcache per-inode inode alias locking fs: dcache per-bucket dcache hash locking bit_spinlock: add required includes kernel: add bl_list xfs: provide simple rcu-walk ACL implementation btrfs: provide simple rcu-walk ACL implementation ext2,3,4: provide simple rcu-walk ACL implementation fs: provide simple rcu-walk generic_check_acl implementation fs: provide rcu-walk aware permission i_ops fs: rcu-walk aware d_revalidate method fs: cache optimise dentry and inode for rcu-walk fs: dcache reduce branches in lookup path fs: dcache remove d_mounted fs: fs_struct use seqlock fs: rcu-walk for path lookup ...
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c53
-rw-r--r--fs/proc/generic.c4
-rw-r--r--fs/proc/inode.c9
-rw-r--r--fs/proc/proc_sysctl.c31
4 files changed, 68 insertions, 29 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 08cba2c3b612..b20962c71a52 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1795,10 +1795,16 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
1795 */ 1795 */
1796static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) 1796static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
1797{ 1797{
1798 struct inode *inode = dentry->d_inode; 1798 struct inode *inode;
1799 struct task_struct *task = get_proc_task(inode); 1799 struct task_struct *task;
1800 const struct cred *cred; 1800 const struct cred *cred;
1801 1801
1802 if (nd && nd->flags & LOOKUP_RCU)
1803 return -ECHILD;
1804
1805 inode = dentry->d_inode;
1806 task = get_proc_task(inode);
1807
1802 if (task) { 1808 if (task) {
1803 if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || 1809 if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
1804 task_dumpable(task)) { 1810 task_dumpable(task)) {
@@ -1820,7 +1826,7 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
1820 return 0; 1826 return 0;
1821} 1827}
1822 1828
1823static int pid_delete_dentry(struct dentry * dentry) 1829static int pid_delete_dentry(const struct dentry * dentry)
1824{ 1830{
1825 /* Is the task we represent dead? 1831 /* Is the task we represent dead?
1826 * If so, then don't put the dentry on the lru list, 1832 * If so, then don't put the dentry on the lru list,
@@ -1964,12 +1970,19 @@ static int proc_fd_link(struct inode *inode, struct path *path)
1964 1970
1965static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) 1971static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1966{ 1972{
1967 struct inode *inode = dentry->d_inode; 1973 struct inode *inode;
1968 struct task_struct *task = get_proc_task(inode); 1974 struct task_struct *task;
1969 int fd = proc_fd(inode); 1975 int fd;
1970 struct files_struct *files; 1976 struct files_struct *files;
1971 const struct cred *cred; 1977 const struct cred *cred;
1972 1978
1979 if (nd && nd->flags & LOOKUP_RCU)
1980 return -ECHILD;
1981
1982 inode = dentry->d_inode;
1983 task = get_proc_task(inode);
1984 fd = proc_fd(inode);
1985
1973 if (task) { 1986 if (task) {
1974 files = get_files_struct(task); 1987 files = get_files_struct(task);
1975 if (files) { 1988 if (files) {
@@ -2045,7 +2058,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
2045 inode->i_op = &proc_pid_link_inode_operations; 2058 inode->i_op = &proc_pid_link_inode_operations;
2046 inode->i_size = 64; 2059 inode->i_size = 64;
2047 ei->op.proc_get_link = proc_fd_link; 2060 ei->op.proc_get_link = proc_fd_link;
2048 dentry->d_op = &tid_fd_dentry_operations; 2061 d_set_d_op(dentry, &tid_fd_dentry_operations);
2049 d_add(dentry, inode); 2062 d_add(dentry, inode);
2050 /* Close the race of the process dying before we return the dentry */ 2063 /* Close the race of the process dying before we return the dentry */
2051 if (tid_fd_revalidate(dentry, NULL)) 2064 if (tid_fd_revalidate(dentry, NULL))
@@ -2177,11 +2190,13 @@ static const struct file_operations proc_fd_operations = {
2177 * /proc/pid/fd needs a special permission handler so that a process can still 2190 * /proc/pid/fd needs a special permission handler so that a process can still
2178 * access /proc/self/fd after it has executed a setuid(). 2191 * access /proc/self/fd after it has executed a setuid().
2179 */ 2192 */
2180static int proc_fd_permission(struct inode *inode, int mask) 2193static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags)
2181{ 2194{
2182 int rv; 2195 int rv;
2183 2196
2184 rv = generic_permission(inode, mask, NULL); 2197 if (flags & IPERM_FLAG_RCU)
2198 return -ECHILD;
2199 rv = generic_permission(inode, mask, flags, NULL);
2185 if (rv == 0) 2200 if (rv == 0)
2186 return 0; 2201 return 0;
2187 if (task_pid(current) == proc_pid(inode)) 2202 if (task_pid(current) == proc_pid(inode))
@@ -2213,7 +2228,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
2213 ei->fd = fd; 2228 ei->fd = fd;
2214 inode->i_mode = S_IFREG | S_IRUSR; 2229 inode->i_mode = S_IFREG | S_IRUSR;
2215 inode->i_fop = &proc_fdinfo_file_operations; 2230 inode->i_fop = &proc_fdinfo_file_operations;
2216 dentry->d_op = &tid_fd_dentry_operations; 2231 d_set_d_op(dentry, &tid_fd_dentry_operations);
2217 d_add(dentry, inode); 2232 d_add(dentry, inode);
2218 /* Close the race of the process dying before we return the dentry */ 2233 /* Close the race of the process dying before we return the dentry */
2219 if (tid_fd_revalidate(dentry, NULL)) 2234 if (tid_fd_revalidate(dentry, NULL))
@@ -2272,7 +2287,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir,
2272 if (p->fop) 2287 if (p->fop)
2273 inode->i_fop = p->fop; 2288 inode->i_fop = p->fop;
2274 ei->op = p->op; 2289 ei->op = p->op;
2275 dentry->d_op = &pid_dentry_operations; 2290 d_set_d_op(dentry, &pid_dentry_operations);
2276 d_add(dentry, inode); 2291 d_add(dentry, inode);
2277 /* Close the race of the process dying before we return the dentry */ 2292 /* Close the race of the process dying before we return the dentry */
2278 if (pid_revalidate(dentry, NULL)) 2293 if (pid_revalidate(dentry, NULL))
@@ -2639,8 +2654,14 @@ static const struct pid_entry proc_base_stuff[] = {
2639 */ 2654 */
2640static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd) 2655static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
2641{ 2656{
2642 struct inode *inode = dentry->d_inode; 2657 struct inode *inode;
2643 struct task_struct *task = get_proc_task(inode); 2658 struct task_struct *task;
2659
2660 if (nd->flags & LOOKUP_RCU)
2661 return -ECHILD;
2662
2663 inode = dentry->d_inode;
2664 task = get_proc_task(inode);
2644 if (task) { 2665 if (task) {
2645 put_task_struct(task); 2666 put_task_struct(task);
2646 return 1; 2667 return 1;
@@ -2691,7 +2712,7 @@ static struct dentry *proc_base_instantiate(struct inode *dir,
2691 if (p->fop) 2712 if (p->fop)
2692 inode->i_fop = p->fop; 2713 inode->i_fop = p->fop;
2693 ei->op = p->op; 2714 ei->op = p->op;
2694 dentry->d_op = &proc_base_dentry_operations; 2715 d_set_d_op(dentry, &proc_base_dentry_operations);
2695 d_add(dentry, inode); 2716 d_add(dentry, inode);
2696 error = NULL; 2717 error = NULL;
2697out: 2718out:
@@ -3005,7 +3026,7 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
3005 inode->i_nlink = 2 + pid_entry_count_dirs(tgid_base_stuff, 3026 inode->i_nlink = 2 + pid_entry_count_dirs(tgid_base_stuff,
3006 ARRAY_SIZE(tgid_base_stuff)); 3027 ARRAY_SIZE(tgid_base_stuff));
3007 3028
3008 dentry->d_op = &pid_dentry_operations; 3029 d_set_d_op(dentry, &pid_dentry_operations);
3009 3030
3010 d_add(dentry, inode); 3031 d_add(dentry, inode);
3011 /* Close the race of the process dying before we return the dentry */ 3032 /* Close the race of the process dying before we return the dentry */
@@ -3248,7 +3269,7 @@ static struct dentry *proc_task_instantiate(struct inode *dir,
3248 inode->i_nlink = 2 + pid_entry_count_dirs(tid_base_stuff, 3269 inode->i_nlink = 2 + pid_entry_count_dirs(tid_base_stuff,
3249 ARRAY_SIZE(tid_base_stuff)); 3270 ARRAY_SIZE(tid_base_stuff));
3250 3271
3251 dentry->d_op = &pid_dentry_operations; 3272 d_set_d_op(dentry, &pid_dentry_operations);
3252 3273
3253 d_add(dentry, inode); 3274 d_add(dentry, inode);
3254 /* Close the race of the process dying before we return the dentry */ 3275 /* Close the race of the process dying before we return the dentry */
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index dd29f0337661..f766be29d2c7 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -400,7 +400,7 @@ static const struct inode_operations proc_link_inode_operations = {
400 * smarter: we could keep a "volatile" flag in the 400 * smarter: we could keep a "volatile" flag in the
401 * inode to indicate which ones to keep. 401 * inode to indicate which ones to keep.
402 */ 402 */
403static int proc_delete_dentry(struct dentry * dentry) 403static int proc_delete_dentry(const struct dentry * dentry)
404{ 404{
405 return 1; 405 return 1;
406} 406}
@@ -439,7 +439,7 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
439out_unlock: 439out_unlock:
440 440
441 if (inode) { 441 if (inode) {
442 dentry->d_op = &proc_dentry_operations; 442 d_set_d_op(dentry, &proc_dentry_operations);
443 d_add(dentry, inode); 443 d_add(dentry, inode);
444 return NULL; 444 return NULL;
445 } 445 }
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 3ddb6068177c..6bcb926b101b 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -65,11 +65,18 @@ static struct inode *proc_alloc_inode(struct super_block *sb)
65 return inode; 65 return inode;
66} 66}
67 67
68static void proc_destroy_inode(struct inode *inode) 68static void proc_i_callback(struct rcu_head *head)
69{ 69{
70 struct inode *inode = container_of(head, struct inode, i_rcu);
71 INIT_LIST_HEAD(&inode->i_dentry);
70 kmem_cache_free(proc_inode_cachep, PROC_I(inode)); 72 kmem_cache_free(proc_inode_cachep, PROC_I(inode));
71} 73}
72 74
75static void proc_destroy_inode(struct inode *inode)
76{
77 call_rcu(&inode->i_rcu, proc_i_callback);
78}
79
73static void init_once(void *foo) 80static void init_once(void *foo)
74{ 81{
75 struct proc_inode *ei = (struct proc_inode *) foo; 82 struct proc_inode *ei = (struct proc_inode *) foo;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index b652cb00906b..09a1f92a34ef 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -5,6 +5,7 @@
5#include <linux/sysctl.h> 5#include <linux/sysctl.h>
6#include <linux/proc_fs.h> 6#include <linux/proc_fs.h>
7#include <linux/security.h> 7#include <linux/security.h>
8#include <linux/namei.h>
8#include "internal.h" 9#include "internal.h"
9 10
10static const struct dentry_operations proc_sys_dentry_operations; 11static const struct dentry_operations proc_sys_dentry_operations;
@@ -120,7 +121,7 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
120 goto out; 121 goto out;
121 122
122 err = NULL; 123 err = NULL;
123 dentry->d_op = &proc_sys_dentry_operations; 124 d_set_d_op(dentry, &proc_sys_dentry_operations);
124 d_add(dentry, inode); 125 d_add(dentry, inode);
125 126
126out: 127out:
@@ -201,7 +202,7 @@ static int proc_sys_fill_cache(struct file *filp, void *dirent,
201 dput(child); 202 dput(child);
202 return -ENOMEM; 203 return -ENOMEM;
203 } else { 204 } else {
204 child->d_op = &proc_sys_dentry_operations; 205 d_set_d_op(child, &proc_sys_dentry_operations);
205 d_add(child, inode); 206 d_add(child, inode);
206 } 207 }
207 } else { 208 } else {
@@ -294,7 +295,7 @@ out:
294 return ret; 295 return ret;
295} 296}
296 297
297static int proc_sys_permission(struct inode *inode, int mask) 298static int proc_sys_permission(struct inode *inode, int mask,unsigned int flags)
298{ 299{
299 /* 300 /*
300 * sysctl entries that are not writeable, 301 * sysctl entries that are not writeable,
@@ -304,6 +305,9 @@ static int proc_sys_permission(struct inode *inode, int mask)
304 struct ctl_table *table; 305 struct ctl_table *table;
305 int error; 306 int error;
306 307
308 if (flags & IPERM_FLAG_RCU)
309 return -ECHILD;
310
307 /* Executable files are not allowed under /proc/sys/ */ 311 /* Executable files are not allowed under /proc/sys/ */
308 if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) 312 if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))
309 return -EACCES; 313 return -EACCES;
@@ -389,23 +393,30 @@ static const struct inode_operations proc_sys_dir_operations = {
389 393
390static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd) 394static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
391{ 395{
396 if (nd->flags & LOOKUP_RCU)
397 return -ECHILD;
392 return !PROC_I(dentry->d_inode)->sysctl->unregistering; 398 return !PROC_I(dentry->d_inode)->sysctl->unregistering;
393} 399}
394 400
395static int proc_sys_delete(struct dentry *dentry) 401static int proc_sys_delete(const struct dentry *dentry)
396{ 402{
397 return !!PROC_I(dentry->d_inode)->sysctl->unregistering; 403 return !!PROC_I(dentry->d_inode)->sysctl->unregistering;
398} 404}
399 405
400static int proc_sys_compare(struct dentry *dir, struct qstr *qstr, 406static int proc_sys_compare(const struct dentry *parent,
401 struct qstr *name) 407 const struct inode *pinode,
408 const struct dentry *dentry, const struct inode *inode,
409 unsigned int len, const char *str, const struct qstr *name)
402{ 410{
403 struct dentry *dentry = container_of(qstr, struct dentry, d_name); 411 /* Although proc doesn't have negative dentries, rcu-walk means
404 if (qstr->len != name->len) 412 * that inode here can be NULL */
413 if (!inode)
414 return 0;
415 if (name->len != len)
405 return 1; 416 return 1;
406 if (memcmp(qstr->name, name->name, name->len)) 417 if (memcmp(name->name, str, len))
407 return 1; 418 return 1;
408 return !sysctl_is_seen(PROC_I(dentry->d_inode)->sysctl); 419 return !sysctl_is_seen(PROC_I(inode)->sysctl);
409} 420}
410 421
411static const struct dentry_operations proc_sys_dentry_operations = { 422static const struct dentry_operations proc_sys_dentry_operations = {