aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:57 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:29 -0500
commit34286d6662308d82aed891852d04c7c3a2649b16 (patch)
treec4b7311404d302e7cb94df7a4690298e1059910a /fs
parent44a7d7a878c9cbb74f236ea755b25b6b2e26a9a9 (diff)
fs: rcu-walk aware d_revalidate method
Require filesystems be aware of .d_revalidate being called in rcu-walk mode (nd->flags & LOOKUP_RCU). For now do a simple push down, returning -ECHILD from all implementations. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs')
-rw-r--r--fs/afs/dir.c4
-rw-r--r--fs/autofs4/root.c13
-rw-r--r--fs/ceph/dir.c7
-rw-r--r--fs/cifs/dir.c3
-rw-r--r--fs/coda/dir.c7
-rw-r--r--fs/ecryptfs/dentry.c9
-rw-r--r--fs/fat/namei_vfat.c6
-rw-r--r--fs/fuse/dir.c6
-rw-r--r--fs/gfs2/dentry.c17
-rw-r--r--fs/hfs/sysdep.c7
-rw-r--r--fs/jfs/namei.c2
-rw-r--r--fs/namei.c54
-rw-r--r--fs/ncpfs/dir.c4
-rw-r--r--fs/ncpfs/inode.c1
-rw-r--r--fs/nfs/dir.c8
-rw-r--r--fs/ocfs2/dcache.c10
-rw-r--r--fs/proc/base.c33
-rw-r--r--fs/proc/proc_sysctl.c3
-rw-r--r--fs/reiserfs/xattr.c2
-rw-r--r--fs/sysfs/dir.c6
20 files changed, 159 insertions, 43 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index b8bb7e7148d0..34a3263d60a4 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/fs.h> 15#include <linux/fs.h>
16#include <linux/namei.h>
16#include <linux/pagemap.h> 17#include <linux/pagemap.h>
17#include <linux/ctype.h> 18#include <linux/ctype.h>
18#include <linux/sched.h> 19#include <linux/sched.h>
@@ -607,6 +608,9 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
607 void *dir_version; 608 void *dir_version;
608 int ret; 609 int ret;
609 610
611 if (nd->flags & LOOKUP_RCU)
612 return -ECHILD;
613
610 vnode = AFS_FS_I(dentry->d_inode); 614 vnode = AFS_FS_I(dentry->d_inode);
611 615
612 if (dentry->d_inode) 616 if (dentry->d_inode)
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index bfe3f2eb684d..651e4ef563b1 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -315,12 +315,19 @@ out_error:
315 */ 315 */
316static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) 316static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
317{ 317{
318 struct inode *dir = dentry->d_parent->d_inode; 318 struct inode *dir;
319 struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); 319 struct autofs_sb_info *sbi;
320 int oz_mode = autofs4_oz_mode(sbi); 320 int oz_mode;
321 int flags = nd ? nd->flags : 0; 321 int flags = nd ? nd->flags : 0;
322 int status = 1; 322 int status = 1;
323 323
324 if (flags & LOOKUP_RCU)
325 return -ECHILD;
326
327 dir = dentry->d_parent->d_inode;
328 sbi = autofs4_sbi(dir->i_sb);
329 oz_mode = autofs4_oz_mode(sbi);
330
324 /* Pending dentry */ 331 /* Pending dentry */
325 spin_lock(&sbi->fs_lock); 332 spin_lock(&sbi->fs_lock);
326 if (autofs4_ispending(dentry)) { 333 if (autofs4_ispending(dentry)) {
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index cc01cf826769..fa7ca04ee816 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -990,7 +990,12 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
990 */ 990 */
991static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) 991static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
992{ 992{
993 struct inode *dir = dentry->d_parent->d_inode; 993 struct inode *dir;
994
995 if (nd->flags & LOOKUP_RCU)
996 return -ECHILD;
997
998 dir = dentry->d_parent->d_inode;
994 999
995 dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, 1000 dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
996 dentry->d_name.len, dentry->d_name.name, dentry->d_inode, 1001 dentry->d_name.len, dentry->d_name.name, dentry->d_inode,
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e3b10ca6d453..db2a58c00f7b 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -656,6 +656,9 @@ lookup_out:
656static int 656static int
657cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) 657cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
658{ 658{
659 if (nd->flags & LOOKUP_RCU)
660 return -ECHILD;
661
659 if (direntry->d_inode) { 662 if (direntry->d_inode) {
660 if (cifs_revalidate_dentry(direntry)) 663 if (cifs_revalidate_dentry(direntry))
661 return 0; 664 return 0;
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index aa40c811f8d2..619a8303766e 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -18,6 +18,7 @@
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/spinlock.h> 20#include <linux/spinlock.h>
21#include <linux/namei.h>
21 22
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23 24
@@ -541,9 +542,13 @@ out:
541/* called when a cache lookup succeeds */ 542/* called when a cache lookup succeeds */
542static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) 543static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
543{ 544{
544 struct inode *inode = de->d_inode; 545 struct inode *inode;
545 struct coda_inode_info *cii; 546 struct coda_inode_info *cii;
546 547
548 if (nd->flags & LOOKUP_RCU)
549 return -ECHILD;
550
551 inode = de->d_inode;
547 if (!inode || coda_isroot(inode)) 552 if (!inode || coda_isroot(inode))
548 goto out; 553 goto out;
549 if (is_bad_inode(inode)) 554 if (is_bad_inode(inode))
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
index 906e803f7f79..6fc4f319b550 100644
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -44,12 +44,17 @@
44 */ 44 */
45static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) 45static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
46{ 46{
47 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); 47 struct dentry *lower_dentry;
48 struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); 48 struct vfsmount *lower_mnt;
49 struct dentry *dentry_save; 49 struct dentry *dentry_save;
50 struct vfsmount *vfsmount_save; 50 struct vfsmount *vfsmount_save;
51 int rc = 1; 51 int rc = 1;
52 52
53 if (nd->flags & LOOKUP_RCU)
54 return -ECHILD;
55
56 lower_dentry = ecryptfs_dentry_to_lower(dentry);
57 lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
53 if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) 58 if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
54 goto out; 59 goto out;
55 dentry_save = nd->path.dentry; 60 dentry_save = nd->path.dentry;
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 3be5ed7d859f..e3ffc5e12332 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -43,6 +43,9 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
43 43
44static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) 44static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
45{ 45{
46 if (nd->flags & LOOKUP_RCU)
47 return -ECHILD;
48
46 /* This is not negative dentry. Always valid. */ 49 /* This is not negative dentry. Always valid. */
47 if (dentry->d_inode) 50 if (dentry->d_inode)
48 return 1; 51 return 1;
@@ -51,6 +54,9 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
51 54
52static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) 55static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
53{ 56{
57 if (nd->flags & LOOKUP_RCU)
58 return -ECHILD;
59
54 /* 60 /*
55 * This is not negative dentry. Always valid. 61 * This is not negative dentry. Always valid.
56 * 62 *
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index c9a8a426a395..07f4b5e675fc 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -156,8 +156,12 @@ u64 fuse_get_attr_version(struct fuse_conn *fc)
156 */ 156 */
157static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) 157static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
158{ 158{
159 struct inode *inode = entry->d_inode; 159 struct inode *inode;
160
161 if (nd->flags & LOOKUP_RCU)
162 return -ECHILD;
160 163
164 inode = entry->d_inode;
161 if (inode && is_bad_inode(inode)) 165 if (inode && is_bad_inode(inode))
162 return 0; 166 return 0;
163 else if (fuse_dentry_time(entry) < get_jiffies_64()) { 167 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c
index 50497f65763b..4a456338b873 100644
--- a/fs/gfs2/dentry.c
+++ b/fs/gfs2/dentry.c
@@ -11,6 +11,7 @@
11#include <linux/completion.h> 11#include <linux/completion.h>
12#include <linux/buffer_head.h> 12#include <linux/buffer_head.h>
13#include <linux/gfs2_ondisk.h> 13#include <linux/gfs2_ondisk.h>
14#include <linux/namei.h>
14#include <linux/crc32.h> 15#include <linux/crc32.h>
15 16
16#include "gfs2.h" 17#include "gfs2.h"
@@ -34,15 +35,23 @@
34 35
35static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) 36static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
36{ 37{
37 struct dentry *parent = dget_parent(dentry); 38 struct dentry *parent;
38 struct gfs2_sbd *sdp = GFS2_SB(parent->d_inode); 39 struct gfs2_sbd *sdp;
39 struct gfs2_inode *dip = GFS2_I(parent->d_inode); 40 struct gfs2_inode *dip;
40 struct inode *inode = dentry->d_inode; 41 struct inode *inode;
41 struct gfs2_holder d_gh; 42 struct gfs2_holder d_gh;
42 struct gfs2_inode *ip = NULL; 43 struct gfs2_inode *ip = NULL;
43 int error; 44 int error;
44 int had_lock = 0; 45 int had_lock = 0;
45 46
47 if (nd->flags & LOOKUP_RCU)
48 return -ECHILD;
49
50 parent = dget_parent(dentry);
51 sdp = GFS2_SB(parent->d_inode);
52 dip = GFS2_I(parent->d_inode);
53 inode = dentry->d_inode;
54
46 if (inode) { 55 if (inode) {
47 if (is_bad_inode(inode)) 56 if (is_bad_inode(inode))
48 goto invalid; 57 goto invalid;
diff --git a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c
index 7478f5c219aa..19cf291eb91f 100644
--- a/fs/hfs/sysdep.c
+++ b/fs/hfs/sysdep.c
@@ -8,15 +8,20 @@
8 * This file contains the code to do various system dependent things. 8 * This file contains the code to do various system dependent things.
9 */ 9 */
10 10
11#include <linux/namei.h>
11#include "hfs_fs.h" 12#include "hfs_fs.h"
12 13
13/* dentry case-handling: just lowercase everything */ 14/* dentry case-handling: just lowercase everything */
14 15
15static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) 16static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
16{ 17{
17 struct inode *inode = dentry->d_inode; 18 struct inode *inode;
18 int diff; 19 int diff;
19 20
21 if (nd->flags & LOOKUP_RCU)
22 return -ECHILD;
23
24 inode = dentry->d_inode;
20 if(!inode) 25 if(!inode)
21 return 1; 26 return 1;
22 27
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index a151cbdec626..4414e3a42264 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1608,6 +1608,8 @@ out:
1608 1608
1609static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd) 1609static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
1610{ 1610{
1611 if (nd->flags & LOOKUP_RCU)
1612 return -ECHILD;
1611 /* 1613 /*
1612 * This is not negative dentry. Always valid. 1614 * This is not negative dentry. Always valid.
1613 * 1615 *
diff --git a/fs/namei.c b/fs/namei.c
index 90bd2873e117..6e275363e89d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -563,10 +563,26 @@ void release_open_intent(struct nameidata *nd)
563 fput(nd->intent.open.file); 563 fput(nd->intent.open.file);
564} 564}
565 565
566static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
567{
568 int status;
569
570 status = dentry->d_op->d_revalidate(dentry, nd);
571 if (status == -ECHILD) {
572 if (nameidata_dentry_drop_rcu(nd, dentry))
573 return status;
574 status = dentry->d_op->d_revalidate(dentry, nd);
575 }
576
577 return status;
578}
579
566static inline struct dentry * 580static inline struct dentry *
567do_revalidate(struct dentry *dentry, struct nameidata *nd) 581do_revalidate(struct dentry *dentry, struct nameidata *nd)
568{ 582{
569 int status = dentry->d_op->d_revalidate(dentry, nd); 583 int status;
584
585 status = d_revalidate(dentry, nd);
570 if (unlikely(status <= 0)) { 586 if (unlikely(status <= 0)) {
571 /* 587 /*
572 * The dentry failed validation. 588 * The dentry failed validation.
@@ -574,14 +590,20 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd)
574 * the dentry otherwise d_revalidate is asking us 590 * the dentry otherwise d_revalidate is asking us
575 * to return a fail status. 591 * to return a fail status.
576 */ 592 */
577 if (!status) { 593 if (status < 0) {
594 /* If we're in rcu-walk, we don't have a ref */
595 if (!(nd->flags & LOOKUP_RCU))
596 dput(dentry);
597 dentry = ERR_PTR(status);
598
599 } else {
600 /* Don't d_invalidate in rcu-walk mode */
601 if (nameidata_dentry_drop_rcu_maybe(nd, dentry))
602 return ERR_PTR(-ECHILD);
578 if (!d_invalidate(dentry)) { 603 if (!d_invalidate(dentry)) {
579 dput(dentry); 604 dput(dentry);
580 dentry = NULL; 605 dentry = NULL;
581 } 606 }
582 } else {
583 dput(dentry);
584 dentry = ERR_PTR(status);
585 } 607 }
586 } 608 }
587 return dentry; 609 return dentry;
@@ -626,7 +648,7 @@ force_reval_path(struct path *path, struct nameidata *nd)
626 if (!need_reval_dot(dentry)) 648 if (!need_reval_dot(dentry))
627 return 0; 649 return 0;
628 650
629 status = dentry->d_op->d_revalidate(dentry, nd); 651 status = d_revalidate(dentry, nd);
630 if (status > 0) 652 if (status > 0)
631 return 0; 653 return 0;
632 654
@@ -1039,12 +1061,8 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
1039 return -ECHILD; 1061 return -ECHILD;
1040 1062
1041 nd->seq = seq; 1063 nd->seq = seq;
1042 if (dentry->d_flags & DCACHE_OP_REVALIDATE) { 1064 if (dentry->d_flags & DCACHE_OP_REVALIDATE)
1043 /* We commonly drop rcu-walk here */
1044 if (nameidata_dentry_drop_rcu(nd, dentry))
1045 return -ECHILD;
1046 goto need_revalidate; 1065 goto need_revalidate;
1047 }
1048 path->mnt = mnt; 1066 path->mnt = mnt;
1049 path->dentry = dentry; 1067 path->dentry = dentry;
1050 __follow_mount_rcu(nd, path, inode); 1068 __follow_mount_rcu(nd, path, inode);
@@ -1292,12 +1310,11 @@ return_reval:
1292 * We may need to check the cached dentry for staleness. 1310 * We may need to check the cached dentry for staleness.
1293 */ 1311 */
1294 if (need_reval_dot(nd->path.dentry)) { 1312 if (need_reval_dot(nd->path.dentry)) {
1295 if (nameidata_drop_rcu_maybe(nd))
1296 return -ECHILD;
1297 err = -ESTALE;
1298 /* Note: we do not d_invalidate() */ 1313 /* Note: we do not d_invalidate() */
1299 if (!nd->path.dentry->d_op->d_revalidate( 1314 err = d_revalidate(nd->path.dentry, nd);
1300 nd->path.dentry, nd)) 1315 if (!err)
1316 err = -ESTALE;
1317 if (err < 0)
1301 break; 1318 break;
1302 } 1319 }
1303return_base: 1320return_base:
@@ -2080,10 +2097,11 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2080 dir = nd->path.dentry; 2097 dir = nd->path.dentry;
2081 case LAST_DOT: 2098 case LAST_DOT:
2082 if (need_reval_dot(dir)) { 2099 if (need_reval_dot(dir)) {
2083 if (!dir->d_op->d_revalidate(dir, nd)) { 2100 error = d_revalidate(nd->path.dentry, nd);
2101 if (!error)
2084 error = -ESTALE; 2102 error = -ESTALE;
2103 if (error < 0)
2085 goto exit; 2104 goto exit;
2086 }
2087 } 2105 }
2088 /* fallthrough */ 2106 /* fallthrough */
2089 case LAST_ROOT: 2107 case LAST_ROOT:
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 4b9cbb28d7fa..28f136d4aaec 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -17,6 +17,7 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/vmalloc.h> 18#include <linux/vmalloc.h>
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/namei.h>
20#include <asm/uaccess.h> 21#include <asm/uaccess.h>
21#include <asm/byteorder.h> 22#include <asm/byteorder.h>
22 23
@@ -308,6 +309,9 @@ ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
308 int res, val = 0, len; 309 int res, val = 0, len;
309 __u8 __name[NCP_MAXPATHLEN + 1]; 310 __u8 __name[NCP_MAXPATHLEN + 1];
310 311
312 if (nd->flags & LOOKUP_RCU)
313 return -ECHILD;
314
311 parent = dget_parent(dentry); 315 parent = dget_parent(dentry);
312 dir = parent->d_inode; 316 dir = parent->d_inode;
313 317
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 0c75a5f3cafd..9531c052d7a4 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -29,6 +29,7 @@
29#include <linux/vfs.h> 29#include <linux/vfs.h>
30#include <linux/mount.h> 30#include <linux/mount.h>
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <linux/namei.h>
32 33
33#include <linux/ncp_fs.h> 34#include <linux/ncp_fs.h>
34 35
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 37e0a8bb077e..58beace14b19 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -938,7 +938,8 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
938 * component of the path. 938 * component of the path.
939 * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT. 939 * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
940 */ 940 */
941static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask) 941static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
942 unsigned int mask)
942{ 943{
943 if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT)) 944 if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
944 return 0; 945 return 0;
@@ -1018,7 +1019,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
1018 * If the parent directory is seen to have changed, we throw out the 1019 * If the parent directory is seen to have changed, we throw out the
1019 * cached dentry and do a new lookup. 1020 * cached dentry and do a new lookup.
1020 */ 1021 */
1021static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) 1022static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
1022{ 1023{
1023 struct inode *dir; 1024 struct inode *dir;
1024 struct inode *inode; 1025 struct inode *inode;
@@ -1027,6 +1028,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
1027 struct nfs_fattr *fattr = NULL; 1028 struct nfs_fattr *fattr = NULL;
1028 int error; 1029 int error;
1029 1030
1031 if (nd->flags & LOOKUP_RCU)
1032 return -ECHILD;
1033
1030 parent = dget_parent(dentry); 1034 parent = dget_parent(dentry);
1031 dir = parent->d_inode; 1035 dir = parent->d_inode;
1032 nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); 1036 nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE);
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index 4d54c60ceee4..0310b16a7238 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -52,9 +52,15 @@ void ocfs2_dentry_attach_gen(struct dentry *dentry)
52static int ocfs2_dentry_revalidate(struct dentry *dentry, 52static int ocfs2_dentry_revalidate(struct dentry *dentry,
53 struct nameidata *nd) 53 struct nameidata *nd)
54{ 54{
55 struct inode *inode = dentry->d_inode; 55 struct inode *inode;
56 int ret = 0; /* if all else fails, just return false */ 56 int ret = 0; /* if all else fails, just return false */
57 struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); 57 struct ocfs2_super *osb;
58
59 if (nd->flags & LOOKUP_RCU)
60 return -ECHILD;
61
62 inode = dentry->d_inode;
63 osb = OCFS2_SB(dentry->d_sb);
58 64
59 mlog_entry("(0x%p, '%.*s')\n", dentry, 65 mlog_entry("(0x%p, '%.*s')\n", dentry,
60 dentry->d_name.len, dentry->d_name.name); 66 dentry->d_name.len, dentry->d_name.name);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 85f0a80912aa..dc5b2fcadc3b 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1719,10 +1719,16 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
1719 */ 1719 */
1720static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) 1720static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
1721{ 1721{
1722 struct inode *inode = dentry->d_inode; 1722 struct inode *inode;
1723 struct task_struct *task = get_proc_task(inode); 1723 struct task_struct *task;
1724 const struct cred *cred; 1724 const struct cred *cred;
1725 1725
1726 if (nd && nd->flags & LOOKUP_RCU)
1727 return -ECHILD;
1728
1729 inode = dentry->d_inode;
1730 task = get_proc_task(inode);
1731
1726 if (task) { 1732 if (task) {
1727 if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || 1733 if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
1728 task_dumpable(task)) { 1734 task_dumpable(task)) {
@@ -1888,12 +1894,19 @@ static int proc_fd_link(struct inode *inode, struct path *path)
1888 1894
1889static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) 1895static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1890{ 1896{
1891 struct inode *inode = dentry->d_inode; 1897 struct inode *inode;
1892 struct task_struct *task = get_proc_task(inode); 1898 struct task_struct *task;
1893 int fd = proc_fd(inode); 1899 int fd;
1894 struct files_struct *files; 1900 struct files_struct *files;
1895 const struct cred *cred; 1901 const struct cred *cred;
1896 1902
1903 if (nd && nd->flags & LOOKUP_RCU)
1904 return -ECHILD;
1905
1906 inode = dentry->d_inode;
1907 task = get_proc_task(inode);
1908 fd = proc_fd(inode);
1909
1897 if (task) { 1910 if (task) {
1898 files = get_files_struct(task); 1911 files = get_files_struct(task);
1899 if (files) { 1912 if (files) {
@@ -2563,8 +2576,14 @@ static const struct pid_entry proc_base_stuff[] = {
2563 */ 2576 */
2564static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd) 2577static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
2565{ 2578{
2566 struct inode *inode = dentry->d_inode; 2579 struct inode *inode;
2567 struct task_struct *task = get_proc_task(inode); 2580 struct task_struct *task;
2581
2582 if (nd->flags & LOOKUP_RCU)
2583 return -ECHILD;
2584
2585 inode = dentry->d_inode;
2586 task = get_proc_task(inode);
2568 if (task) { 2587 if (task) {
2569 put_task_struct(task); 2588 put_task_struct(task);
2570 return 1; 2589 return 1;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 35efd85a4d32..c9097f43b425 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;
@@ -389,6 +390,8 @@ static const struct inode_operations proc_sys_dir_operations = {
389 390
390static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd) 391static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
391{ 392{
393 if (nd->flags & LOOKUP_RCU)
394 return -ECHILD;
392 return !PROC_I(dentry->d_inode)->sysctl->unregistering; 395 return !PROC_I(dentry->d_inode)->sysctl->unregistering;
393} 396}
394 397
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index e0f0d7ea10a1..9ea22a56cdf1 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -972,6 +972,8 @@ int reiserfs_permission(struct inode *inode, int mask)
972 972
973static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) 973static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd)
974{ 974{
975 if (nd->flags & LOOKUP_RCU)
976 return -ECHILD;
975 return -EPERM; 977 return -EPERM;
976} 978}
977 979
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 3e076caa8daf..ea9120a830d8 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -239,9 +239,13 @@ static int sysfs_dentry_delete(const struct dentry *dentry)
239 239
240static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd) 240static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
241{ 241{
242 struct sysfs_dirent *sd = dentry->d_fsdata; 242 struct sysfs_dirent *sd;
243 int is_dir; 243 int is_dir;
244 244
245 if (nd->flags & LOOKUP_RCU)
246 return -ECHILD;
247
248 sd = dentry->d_fsdata;
245 mutex_lock(&sysfs_mutex); 249 mutex_lock(&sysfs_mutex);
246 250
247 /* The sysfs dirent has been deleted */ 251 /* The sysfs dirent has been deleted */