aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-02-15 11:06:36 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-02-15 11:06:36 -0500
commit055d219441cc23f631240335fd369b6b5852681a (patch)
tree4b9edd925dcda0b72a4ca3ec146f516f52e51bee
parent007a14af2649c9ac77f38cd23469518ffb8b355a (diff)
parent4e924a4f53a0e1ea060bd50695a12a238b250322 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: get rid of nameidata_dentry_drop_rcu() calling nameidata_drop_rcu() drop out of RCU in return_reval split do_revalidate() into RCU and non-RCU cases in do_lookup() split RCU and non-RCU cases of need_revalidate nothing in do_follow_link() is going to see RCU
-rw-r--r--fs/namei.c122
1 files changed, 57 insertions, 65 deletions
diff --git a/fs/namei.c b/fs/namei.c
index ec4b2d0190a..9e701e28a32 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -455,14 +455,6 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry
455 struct fs_struct *fs = current->fs; 455 struct fs_struct *fs = current->fs;
456 struct dentry *parent = nd->path.dentry; 456 struct dentry *parent = nd->path.dentry;
457 457
458 /*
459 * It can be possible to revalidate the dentry that we started
460 * the path walk with. force_reval_path may also revalidate the
461 * dentry already committed to the nameidata.
462 */
463 if (unlikely(parent == dentry))
464 return nameidata_drop_rcu(nd);
465
466 BUG_ON(!(nd->flags & LOOKUP_RCU)); 458 BUG_ON(!(nd->flags & LOOKUP_RCU));
467 if (nd->root.mnt) { 459 if (nd->root.mnt) {
468 spin_lock(&fs->lock); 460 spin_lock(&fs->lock);
@@ -571,33 +563,15 @@ void release_open_intent(struct nameidata *nd)
571 } 563 }
572} 564}
573 565
574/* 566static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd)
575 * Call d_revalidate and handle filesystems that request rcu-walk
576 * to be dropped. This may be called and return in rcu-walk mode,
577 * regardless of success or error. If -ECHILD is returned, the caller
578 * must return -ECHILD back up the path walk stack so path walk may
579 * be restarted in ref-walk mode.
580 */
581static int d_revalidate(struct dentry *dentry, struct nameidata *nd)
582{ 567{
583 int status; 568 return dentry->d_op->d_revalidate(dentry, nd);
584
585 status = dentry->d_op->d_revalidate(dentry, nd);
586 if (status == -ECHILD) {
587 if (nameidata_dentry_drop_rcu(nd, dentry))
588 return status;
589 status = dentry->d_op->d_revalidate(dentry, nd);
590 }
591
592 return status;
593} 569}
594 570
595static inline struct dentry * 571static struct dentry *
596do_revalidate(struct dentry *dentry, struct nameidata *nd) 572do_revalidate(struct dentry *dentry, struct nameidata *nd)
597{ 573{
598 int status; 574 int status = d_revalidate(dentry, nd);
599
600 status = d_revalidate(dentry, nd);
601 if (unlikely(status <= 0)) { 575 if (unlikely(status <= 0)) {
602 /* 576 /*
603 * The dentry failed validation. 577 * The dentry failed validation.
@@ -606,24 +580,39 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd)
606 * to return a fail status. 580 * to return a fail status.
607 */ 581 */
608 if (status < 0) { 582 if (status < 0) {
609 /* If we're in rcu-walk, we don't have a ref */ 583 dput(dentry);
610 if (!(nd->flags & LOOKUP_RCU))
611 dput(dentry);
612 dentry = ERR_PTR(status); 584 dentry = ERR_PTR(status);
613 585 } else if (!d_invalidate(dentry)) {
614 } else { 586 dput(dentry);
615 /* Don't d_invalidate in rcu-walk mode */ 587 dentry = NULL;
616 if (nameidata_dentry_drop_rcu_maybe(nd, dentry))
617 return ERR_PTR(-ECHILD);
618 if (!d_invalidate(dentry)) {
619 dput(dentry);
620 dentry = NULL;
621 }
622 } 588 }
623 } 589 }
624 return dentry; 590 return dentry;
625} 591}
626 592
593static inline struct dentry *
594do_revalidate_rcu(struct dentry *dentry, struct nameidata *nd)
595{
596 int status = d_revalidate(dentry, nd);
597 if (likely(status > 0))
598 return dentry;
599 if (status == -ECHILD) {
600 if (nameidata_dentry_drop_rcu(nd, dentry))
601 return ERR_PTR(-ECHILD);
602 return do_revalidate(dentry, nd);
603 }
604 if (status < 0)
605 return ERR_PTR(status);
606 /* Don't d_invalidate in rcu-walk mode */
607 if (nameidata_dentry_drop_rcu(nd, dentry))
608 return ERR_PTR(-ECHILD);
609 if (!d_invalidate(dentry)) {
610 dput(dentry);
611 dentry = NULL;
612 }
613 return dentry;
614}
615
627static inline int need_reval_dot(struct dentry *dentry) 616static inline int need_reval_dot(struct dentry *dentry)
628{ 617{
629 if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE))) 618 if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE)))
@@ -668,9 +657,6 @@ force_reval_path(struct path *path, struct nameidata *nd)
668 return 0; 657 return 0;
669 658
670 if (!status) { 659 if (!status) {
671 /* Don't d_invalidate in rcu-walk mode */
672 if (nameidata_drop_rcu(nd))
673 return -ECHILD;
674 d_invalidate(dentry); 660 d_invalidate(dentry);
675 status = -ESTALE; 661 status = -ESTALE;
676 } 662 }
@@ -777,6 +763,8 @@ __do_follow_link(const struct path *link, struct nameidata *nd, void **p)
777 int error; 763 int error;
778 struct dentry *dentry = link->dentry; 764 struct dentry *dentry = link->dentry;
779 765
766 BUG_ON(nd->flags & LOOKUP_RCU);
767
780 touch_atime(link->mnt, dentry); 768 touch_atime(link->mnt, dentry);
781 nd_set_link(nd, NULL); 769 nd_set_link(nd, NULL);
782 770
@@ -811,6 +799,11 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd)
811{ 799{
812 void *cookie; 800 void *cookie;
813 int err = -ELOOP; 801 int err = -ELOOP;
802
803 /* We drop rcu-walk here */
804 if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry))
805 return -ECHILD;
806
814 if (current->link_count >= MAX_NESTED_LINKS) 807 if (current->link_count >= MAX_NESTED_LINKS)
815 goto loop; 808 goto loop;
816 if (current->total_link_count >= 40) 809 if (current->total_link_count >= 40)
@@ -1255,9 +1248,15 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
1255 return -ECHILD; 1248 return -ECHILD;
1256 1249
1257 nd->seq = seq; 1250 nd->seq = seq;
1258 if (dentry->d_flags & DCACHE_OP_REVALIDATE) 1251 if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
1259 goto need_revalidate; 1252 dentry = do_revalidate_rcu(dentry, nd);
1260done2: 1253 if (!dentry)
1254 goto need_lookup;
1255 if (IS_ERR(dentry))
1256 goto fail;
1257 if (!(nd->flags & LOOKUP_RCU))
1258 goto done;
1259 }
1261 path->mnt = mnt; 1260 path->mnt = mnt;
1262 path->dentry = dentry; 1261 path->dentry = dentry;
1263 if (likely(__follow_mount_rcu(nd, path, inode, false))) 1262 if (likely(__follow_mount_rcu(nd, path, inode, false)))
@@ -1270,8 +1269,13 @@ done2:
1270 if (!dentry) 1269 if (!dentry)
1271 goto need_lookup; 1270 goto need_lookup;
1272found: 1271found:
1273 if (dentry->d_flags & DCACHE_OP_REVALIDATE) 1272 if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
1274 goto need_revalidate; 1273 dentry = do_revalidate(dentry, nd);
1274 if (!dentry)
1275 goto need_lookup;
1276 if (IS_ERR(dentry))
1277 goto fail;
1278 }
1275done: 1279done:
1276 path->mnt = mnt; 1280 path->mnt = mnt;
1277 path->dentry = dentry; 1281 path->dentry = dentry;
@@ -1313,16 +1317,6 @@ need_lookup:
1313 mutex_unlock(&dir->i_mutex); 1317 mutex_unlock(&dir->i_mutex);
1314 goto found; 1318 goto found;
1315 1319
1316need_revalidate:
1317 dentry = do_revalidate(dentry, nd);
1318 if (!dentry)
1319 goto need_lookup;
1320 if (IS_ERR(dentry))
1321 goto fail;
1322 if (nd->flags & LOOKUP_RCU)
1323 goto done2;
1324 goto done;
1325
1326fail: 1320fail:
1327 return PTR_ERR(dentry); 1321 return PTR_ERR(dentry);
1328} 1322}
@@ -1419,9 +1413,6 @@ exec_again:
1419 goto out_dput; 1413 goto out_dput;
1420 1414
1421 if (inode->i_op->follow_link) { 1415 if (inode->i_op->follow_link) {
1422 /* We commonly drop rcu-walk here */
1423 if (nameidata_dentry_drop_rcu_maybe(nd, next.dentry))
1424 return -ECHILD;
1425 BUG_ON(inode != next.dentry->d_inode); 1416 BUG_ON(inode != next.dentry->d_inode);
1426 err = do_follow_link(&next, nd); 1417 err = do_follow_link(&next, nd);
1427 if (err) 1418 if (err)
@@ -1467,8 +1458,6 @@ last_component:
1467 break; 1458 break;
1468 if (inode && unlikely(inode->i_op->follow_link) && 1459 if (inode && unlikely(inode->i_op->follow_link) &&
1469 (lookup_flags & LOOKUP_FOLLOW)) { 1460 (lookup_flags & LOOKUP_FOLLOW)) {
1470 if (nameidata_dentry_drop_rcu_maybe(nd, next.dentry))
1471 return -ECHILD;
1472 BUG_ON(inode != next.dentry->d_inode); 1461 BUG_ON(inode != next.dentry->d_inode);
1473 err = do_follow_link(&next, nd); 1462 err = do_follow_link(&next, nd);
1474 if (err) 1463 if (err)
@@ -1504,12 +1493,15 @@ return_reval:
1504 * We may need to check the cached dentry for staleness. 1493 * We may need to check the cached dentry for staleness.
1505 */ 1494 */
1506 if (need_reval_dot(nd->path.dentry)) { 1495 if (need_reval_dot(nd->path.dentry)) {
1496 if (nameidata_drop_rcu_last_maybe(nd))
1497 return -ECHILD;
1507 /* Note: we do not d_invalidate() */ 1498 /* Note: we do not d_invalidate() */
1508 err = d_revalidate(nd->path.dentry, nd); 1499 err = d_revalidate(nd->path.dentry, nd);
1509 if (!err) 1500 if (!err)
1510 err = -ESTALE; 1501 err = -ESTALE;
1511 if (err < 0) 1502 if (err < 0)
1512 break; 1503 break;
1504 return 0;
1513 } 1505 }
1514return_base: 1506return_base:
1515 if (nameidata_drop_rcu_last_maybe(nd)) 1507 if (nameidata_drop_rcu_last_maybe(nd))