Commit 34286d6662308d82aed891852d04c7c3a2649b16

Authored by Nick Piggin
1 parent 44a7d7a878

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>

Showing 27 changed files with 215 additions and 61 deletions Side-by-side Diff

Documentation/filesystems/Locking
... ... @@ -9,7 +9,7 @@
9 9  
10 10 --------------------------- dentry_operations --------------------------
11 11 prototypes:
12   - int (*d_revalidate)(struct dentry *, int);
  12 + int (*d_revalidate)(struct dentry *, struct nameidata *);
13 13 int (*d_hash)(const struct dentry *, const struct inode *,
14 14 struct qstr *);
15 15 int (*d_compare)(const struct dentry *, const struct inode *,
... ... @@ -21,14 +21,14 @@
21 21 char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
22 22  
23 23 locking rules:
24   - rename_lock ->d_lock may block
25   -d_revalidate: no no yes
26   -d_hash no no no
27   -d_compare: yes no no
28   -d_delete: no yes no
29   -d_release: no no yes
30   -d_iput: no no yes
31   -d_dname: no no no
  24 + rename_lock ->d_lock may block rcu-walk
  25 +d_revalidate: no no yes (ref-walk) maybe
  26 +d_hash no no no maybe
  27 +d_compare: yes no no maybe
  28 +d_delete: no yes no no
  29 +d_release: no no yes no
  30 +d_iput: no no yes no
  31 +d_dname: no no no no
32 32  
33 33 --------------------------- inode_operations ---------------------------
34 34 prototypes:
Documentation/filesystems/path-lookup.txt
... ... @@ -317,11 +317,10 @@
317 317 The cases where rcu-walk cannot continue are:
318 318 * NULL dentry (ie. any uncached path element)
319 319 * parent with d_inode->i_op->permission or ACLs
320   -* dentries with d_revalidate
321 320 * Following links
322 321  
323   -In future patches, permission checks and d_revalidate become rcu-walk aware. It
324   -may be possible eventually to make following links rcu-walk aware.
  322 +In future patches, permission checks become rcu-walk aware. It may be possible
  323 +eventually to make following links rcu-walk aware.
325 324  
326 325 Uncached path elements will always require dropping to ref-walk mode, at the
327 326 very least because i_mutex needs to be grabbed, and objects allocated.
Documentation/filesystems/porting
... ... @@ -360,4 +360,24 @@
360 360 INIT_LIST_HEAD(&inode->i_dentry);
361 361  
362 362 must be done in the RCU callback.
  363 +
  364 +--
  365 +[recommended]
  366 + vfs now tries to do path walking in "rcu-walk mode", which avoids
  367 +atomic operations and scalability hazards on dentries and inodes (see
  368 +Documentation/filesystems/path-walk.txt). d_hash and d_compare changes (above)
  369 +are examples of the changes required to support this. For more complex
  370 +filesystem callbacks, the vfs drops out of rcu-walk mode before the fs call, so
  371 +no changes are required to the filesystem. However, this is costly and loses
  372 +the benefits of rcu-walk mode. We will begin to add filesystem callbacks that
  373 +are rcu-walk aware, shown below. Filesystems should take advantage of this
  374 +where possible.
  375 +
  376 +--
  377 +[mandatory]
  378 + d_revalidate is a callback that is made on every path element (if
  379 +the filesystem provides it), which requires dropping out of rcu-walk mode. This
  380 +may now be called in rcu-walk mode (nd->flags & LOOKUP_RCU). -ECHILD should be
  381 +returned if the filesystem cannot handle rcu-walk. See
  382 +Documentation/filesystems/vfs.txt for more details.
Documentation/filesystems/vfs.txt
... ... @@ -863,6 +863,15 @@
863 863 dcache. Most filesystems leave this as NULL, because all their
864 864 dentries in the dcache are valid
865 865  
  866 + d_revalidate may be called in rcu-walk mode (nd->flags & LOOKUP_RCU).
  867 + If in rcu-walk mode, the filesystem must revalidate the dentry without
  868 + blocking or storing to the dentry, d_parent and d_inode should not be
  869 + used without care (because they can go NULL), instead nd->inode should
  870 + be used.
  871 +
  872 + If a situation is encountered that rcu-walk cannot handle, return
  873 + -ECHILD and it will be called again in ref-walk mode.
  874 +
866 875 d_hash: called when the VFS adds a dentry to the hash table. The first
867 876 dentry passed to d_hash is the parent directory that the name is
868 877 to be hashed into. The inode is the dentry's inode.
drivers/staging/autofs/root.c
... ... @@ -154,12 +154,15 @@
154 154 * yet completely filled in, and revalidate has to delay such
155 155 * lookups..
156 156 */
157   -static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd)
  157 +static int autofs_revalidate(struct dentry *dentry, struct nameidata *nd)
158 158 {
159 159 struct inode * dir;
160 160 struct autofs_sb_info *sbi;
161 161 struct autofs_dir_ent *ent;
162 162 int res;
  163 +
  164 + if (nd->flags & LOOKUP_RCU)
  165 + return -ECHILD;
163 166  
164 167 lock_kernel();
165 168 dir = dentry->d_parent->d_inode;
drivers/staging/smbfs/dir.c
... ... @@ -14,6 +14,7 @@
14 14 #include <linux/ctype.h>
15 15 #include <linux/net.h>
16 16 #include <linux/sched.h>
  17 +#include <linux/namei.h>
17 18  
18 19 #include "smb_fs.h"
19 20 #include "smb_mount.h"
20 21  
21 22  
... ... @@ -301,12 +302,19 @@
301 302 * This is the callback when the dcache has a lookup hit.
302 303 */
303 304 static int
304   -smb_lookup_validate(struct dentry * dentry, struct nameidata *nd)
  305 +smb_lookup_validate(struct dentry *dentry, struct nameidata *nd)
305 306 {
306   - struct smb_sb_info *server = server_from_dentry(dentry);
307   - struct inode * inode = dentry->d_inode;
308   - unsigned long age = jiffies - dentry->d_time;
  307 + struct smb_sb_info *server;
  308 + struct inode *inode;
  309 + unsigned long age;
309 310 int valid;
  311 +
  312 + if (nd->flags & LOOKUP_RCU)
  313 + return -ECHILD;
  314 +
  315 + server = server_from_dentry(dentry);
  316 + inode = dentry->d_inode;
  317 + age = jiffies - dentry->d_time;
310 318  
311 319 /*
312 320 * The default validation is based on dentry age:
... ... @@ -13,6 +13,7 @@
13 13 #include <linux/module.h>
14 14 #include <linux/init.h>
15 15 #include <linux/fs.h>
  16 +#include <linux/namei.h>
16 17 #include <linux/pagemap.h>
17 18 #include <linux/ctype.h>
18 19 #include <linux/sched.h>
... ... @@ -606,6 +607,9 @@
606 607 struct key *key;
607 608 void *dir_version;
608 609 int ret;
  610 +
  611 + if (nd->flags & LOOKUP_RCU)
  612 + return -ECHILD;
609 613  
610 614 vnode = AFS_FS_I(dentry->d_inode);
611 615  
... ... @@ -315,11 +315,18 @@
315 315 */
316 316 static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
317 317 {
318   - struct inode *dir = dentry->d_parent->d_inode;
319   - struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
320   - int oz_mode = autofs4_oz_mode(sbi);
  318 + struct inode *dir;
  319 + struct autofs_sb_info *sbi;
  320 + int oz_mode;
321 321 int flags = nd ? nd->flags : 0;
322 322 int status = 1;
  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);
323 330  
324 331 /* Pending dentry */
325 332 spin_lock(&sbi->fs_lock);
... ... @@ -990,7 +990,12 @@
990 990 */
991 991 static 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 1000 dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
996 1001 dentry->d_name.len, dentry->d_name.name, dentry->d_inode,
... ... @@ -656,6 +656,9 @@
656 656 static int
657 657 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
658 658 {
  659 + if (nd->flags & LOOKUP_RCU)
  660 + return -ECHILD;
  661 +
659 662 if (direntry->d_inode) {
660 663 if (cifs_revalidate_dentry(direntry))
661 664 return 0;
... ... @@ -18,6 +18,7 @@
18 18 #include <linux/errno.h>
19 19 #include <linux/string.h>
20 20 #include <linux/spinlock.h>
  21 +#include <linux/namei.h>
21 22  
22 23 #include <asm/uaccess.h>
23 24  
24 25  
... ... @@ -541,9 +542,13 @@
541 542 /* called when a cache lookup succeeds */
542 543 static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
543 544 {
544   - struct inode *inode = de->d_inode;
  545 + struct inode *inode;
545 546 struct coda_inode_info *cii;
546 547  
  548 + if (nd->flags & LOOKUP_RCU)
  549 + return -ECHILD;
  550 +
  551 + inode = de->d_inode;
547 552 if (!inode || coda_isroot(inode))
548 553 goto out;
549 554 if (is_bad_inode(inode))
fs/ecryptfs/dentry.c
... ... @@ -44,12 +44,17 @@
44 44 */
45 45 static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
46 46 {
47   - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
48   - struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
  47 + struct dentry *lower_dentry;
  48 + struct vfsmount *lower_mnt;
49 49 struct dentry *dentry_save;
50 50 struct vfsmount *vfsmount_save;
51 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 58 if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
54 59 goto out;
55 60 dentry_save = nd->path.dentry;
... ... @@ -43,6 +43,9 @@
43 43  
44 44 static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
45 45 {
  46 + if (nd->flags & LOOKUP_RCU)
  47 + return -ECHILD;
  48 +
46 49 /* This is not negative dentry. Always valid. */
47 50 if (dentry->d_inode)
48 51 return 1;
... ... @@ -51,6 +54,9 @@
51 54  
52 55 static 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 61 * This is not negative dentry. Always valid.
56 62 *
... ... @@ -156,8 +156,12 @@
156 156 */
157 157 static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
158 158 {
159   - struct inode *inode = entry->d_inode;
  159 + struct inode *inode;
160 160  
  161 + if (nd->flags & LOOKUP_RCU)
  162 + return -ECHILD;
  163 +
  164 + inode = entry->d_inode;
161 165 if (inode && is_bad_inode(inode))
162 166 return 0;
163 167 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
... ... @@ -11,6 +11,7 @@
11 11 #include <linux/completion.h>
12 12 #include <linux/buffer_head.h>
13 13 #include <linux/gfs2_ondisk.h>
  14 +#include <linux/namei.h>
14 15 #include <linux/crc32.h>
15 16  
16 17 #include "gfs2.h"
17 18  
... ... @@ -34,14 +35,22 @@
34 35  
35 36 static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
36 37 {
37   - struct dentry *parent = dget_parent(dentry);
38   - struct gfs2_sbd *sdp = GFS2_SB(parent->d_inode);
39   - struct gfs2_inode *dip = GFS2_I(parent->d_inode);
40   - struct inode *inode = dentry->d_inode;
  38 + struct dentry *parent;
  39 + struct gfs2_sbd *sdp;
  40 + struct gfs2_inode *dip;
  41 + struct inode *inode;
41 42 struct gfs2_holder d_gh;
42 43 struct gfs2_inode *ip = NULL;
43 44 int error;
44 45 int had_lock = 0;
  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;
45 54  
46 55 if (inode) {
47 56 if (is_bad_inode(inode))
... ... @@ -8,15 +8,20 @@
8 8 * This file contains the code to do various system dependent things.
9 9 */
10 10  
  11 +#include <linux/namei.h>
11 12 #include "hfs_fs.h"
12 13  
13 14 /* dentry case-handling: just lowercase everything */
14 15  
15 16 static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
16 17 {
17   - struct inode *inode = dentry->d_inode;
  18 + struct inode *inode;
18 19 int diff;
19 20  
  21 + if (nd->flags & LOOKUP_RCU)
  22 + return -ECHILD;
  23 +
  24 + inode = dentry->d_inode;
20 25 if(!inode)
21 26 return 1;
22 27  
... ... @@ -1608,6 +1608,8 @@
1608 1608  
1609 1609 static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
1610 1610 {
  1611 + if (nd->flags & LOOKUP_RCU)
  1612 + return -ECHILD;
1611 1613 /*
1612 1614 * This is not negative dentry. Always valid.
1613 1615 *
... ... @@ -563,10 +563,26 @@
563 563 fput(nd->intent.open.file);
564 564 }
565 565  
  566 +static 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 +
566 580 static inline struct dentry *
567 581 do_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 586 if (unlikely(status <= 0)) {
571 587 /*
572 588 * The dentry failed validation.
573 589  
... ... @@ -574,14 +590,20 @@
574 590 * the dentry otherwise d_revalidate is asking us
575 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 603 if (!d_invalidate(dentry)) {
579 604 dput(dentry);
580 605 dentry = NULL;
581 606 }
582   - } else {
583   - dput(dentry);
584   - dentry = ERR_PTR(status);
585 607 }
586 608 }
587 609 return dentry;
... ... @@ -626,7 +648,7 @@
626 648 if (!need_reval_dot(dentry))
627 649 return 0;
628 650  
629   - status = dentry->d_op->d_revalidate(dentry, nd);
  651 + status = d_revalidate(dentry, nd);
630 652 if (status > 0)
631 653 return 0;
632 654  
633 655  
... ... @@ -1039,12 +1061,8 @@
1039 1061 return -ECHILD;
1040 1062  
1041 1063 nd->seq = seq;
1042   - 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;
  1064 + if (dentry->d_flags & DCACHE_OP_REVALIDATE)
1046 1065 goto need_revalidate;
1047   - }
1048 1066 path->mnt = mnt;
1049 1067 path->dentry = dentry;
1050 1068 __follow_mount_rcu(nd, path, inode);
1051 1069  
... ... @@ -1292,12 +1310,11 @@
1292 1310 * We may need to check the cached dentry for staleness.
1293 1311 */
1294 1312 if (need_reval_dot(nd->path.dentry)) {
1295   - if (nameidata_drop_rcu_maybe(nd))
1296   - return -ECHILD;
1297   - err = -ESTALE;
1298 1313 /* Note: we do not d_invalidate() */
1299   - if (!nd->path.dentry->d_op->d_revalidate(
1300   - nd->path.dentry, nd))
  1314 + err = d_revalidate(nd->path.dentry, nd);
  1315 + if (!err)
  1316 + err = -ESTALE;
  1317 + if (err < 0)
1301 1318 break;
1302 1319 }
1303 1320 return_base:
1304 1321  
1305 1322  
... ... @@ -2080,10 +2097,11 @@
2080 2097 dir = nd->path.dentry;
2081 2098 case LAST_DOT:
2082 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 2102 error = -ESTALE;
  2103 + if (error < 0)
2085 2104 goto exit;
2086   - }
2087 2105 }
2088 2106 /* fallthrough */
2089 2107 case LAST_ROOT:
... ... @@ -17,6 +17,7 @@
17 17 #include <linux/kernel.h>
18 18 #include <linux/vmalloc.h>
19 19 #include <linux/mm.h>
  20 +#include <linux/namei.h>
20 21 #include <asm/uaccess.h>
21 22 #include <asm/byteorder.h>
22 23  
... ... @@ -307,6 +308,9 @@
307 308 struct ncp_entry_info finfo;
308 309 int res, val = 0, len;
309 310 __u8 __name[NCP_MAXPATHLEN + 1];
  311 +
  312 + if (nd->flags & LOOKUP_RCU)
  313 + return -ECHILD;
310 314  
311 315 parent = dget_parent(dentry);
312 316 dir = parent->d_inode;
... ... @@ -29,6 +29,7 @@
29 29 #include <linux/vfs.h>
30 30 #include <linux/mount.h>
31 31 #include <linux/seq_file.h>
  32 +#include <linux/namei.h>
32 33  
33 34 #include <linux/ncp_fs.h>
34 35  
... ... @@ -938,7 +938,8 @@
938 938 * component of the path.
939 939 * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
940 940 */
941   -static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask)
  941 +static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
  942 + unsigned int mask)
942 943 {
943 944 if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
944 945 return 0;
... ... @@ -1018,7 +1019,7 @@
1018 1019 * If the parent directory is seen to have changed, we throw out the
1019 1020 * cached dentry and do a new lookup.
1020 1021 */
1021   -static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
  1022 +static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
1022 1023 {
1023 1024 struct inode *dir;
1024 1025 struct inode *inode;
... ... @@ -1026,6 +1027,9 @@
1026 1027 struct nfs_fh *fhandle = NULL;
1027 1028 struct nfs_fattr *fattr = NULL;
1028 1029 int error;
  1030 +
  1031 + if (nd->flags & LOOKUP_RCU)
  1032 + return -ECHILD;
1029 1033  
1030 1034 parent = dget_parent(dentry);
1031 1035 dir = parent->d_inode;
... ... @@ -52,9 +52,15 @@
52 52 static int ocfs2_dentry_revalidate(struct dentry *dentry,
53 53 struct nameidata *nd)
54 54 {
55   - struct inode *inode = dentry->d_inode;
  55 + struct inode *inode;
56 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 65 mlog_entry("(0x%p, '%.*s')\n", dentry,
60 66 dentry->d_name.len, dentry->d_name.name);
... ... @@ -1719,10 +1719,16 @@
1719 1719 */
1720 1720 static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
1721 1721 {
1722   - struct inode *inode = dentry->d_inode;
1723   - struct task_struct *task = get_proc_task(inode);
  1722 + struct inode *inode;
  1723 + struct task_struct *task;
1724 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 1732 if (task) {
1727 1733 if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
1728 1734 task_dumpable(task)) {
1729 1735  
... ... @@ -1888,12 +1894,19 @@
1888 1894  
1889 1895 static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
1890 1896 {
1891   - struct inode *inode = dentry->d_inode;
1892   - struct task_struct *task = get_proc_task(inode);
1893   - int fd = proc_fd(inode);
  1897 + struct inode *inode;
  1898 + struct task_struct *task;
  1899 + int fd;
1894 1900 struct files_struct *files;
1895 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 1910 if (task) {
1898 1911 files = get_files_struct(task);
1899 1912 if (files) {
... ... @@ -2563,8 +2576,14 @@
2563 2576 */
2564 2577 static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
2565 2578 {
2566   - struct inode *inode = dentry->d_inode;
2567   - struct task_struct *task = get_proc_task(inode);
  2579 + struct inode *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 2587 if (task) {
2569 2588 put_task_struct(task);
2570 2589 return 1;
fs/proc/proc_sysctl.c
... ... @@ -5,6 +5,7 @@
5 5 #include <linux/sysctl.h>
6 6 #include <linux/proc_fs.h>
7 7 #include <linux/security.h>
  8 +#include <linux/namei.h>
8 9 #include "internal.h"
9 10  
10 11 static const struct dentry_operations proc_sys_dentry_operations;
... ... @@ -389,6 +390,8 @@
389 390  
390 391 static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
391 392 {
  393 + if (nd->flags & LOOKUP_RCU)
  394 + return -ECHILD;
392 395 return !PROC_I(dentry->d_inode)->sysctl->unregistering;
393 396 }
394 397  
... ... @@ -972,6 +972,8 @@
972 972  
973 973 static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd)
974 974 {
  975 + if (nd->flags & LOOKUP_RCU)
  976 + return -ECHILD;
975 977 return -EPERM;
976 978 }
977 979  
... ... @@ -239,9 +239,13 @@
239 239  
240 240 static 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 243 int is_dir;
244 244  
  245 + if (nd->flags & LOOKUP_RCU)
  246 + return -ECHILD;
  247 +
  248 + sd = dentry->d_fsdata;
245 249 mutex_lock(&sysfs_mutex);
246 250  
247 251 /* The sysfs dirent has been deleted */
include/linux/dcache.h
... ... @@ -190,7 +190,6 @@
190 190 #define DCACHE_OP_REVALIDATE 0x4000
191 191 #define DCACHE_OP_DELETE 0x8000
192 192  
193   -
194 193 extern spinlock_t dcache_inode_lock;
195 194 extern seqlock_t rename_lock;
196 195