aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
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/namei.c
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/namei.c')
-rw-r--r--fs/namei.c54
1 files changed, 36 insertions, 18 deletions
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: