aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-03-25 11:00:12 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-05-26 07:26:32 -0400
commit9f1fafee9e42b73beb3aa51ab2d6a19bfddeb5fe (patch)
tree0c0251b271371e572daf29d2a2282c323c557e8c /fs/namei.c
parent19660af736ba00e1620970601dd313efedbbcfd2 (diff)
merge handle_reval_dot and nameidata_drop_rcu_last
new helper: complete_walk(). Done on successful completion of walk, drops out of RCU mode, does d_revalidate of final result if that hadn't been done already. handle_reval_dot() and nameidata_drop_rcu_last() subsumed into that one; callers converted to use of complete_walk(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c121
1 files changed, 40 insertions, 81 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 1039cbae0c12..9f594312d486 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -469,43 +469,6 @@ err_root:
469} 469}
470 470
471/** 471/**
472 * nameidata_drop_rcu_last - drop nameidata ending path walk out of rcu-walk
473 * @nd: nameidata pathwalk data to drop
474 * Returns: 0 on success, -ECHILD on failure
475 *
476 * nameidata_drop_rcu_last attempts to drop the current nd->path into ref-walk.
477 * nd->path should be the final element of the lookup, so nd->root is discarded.
478 * Must be called from rcu-walk context.
479 */
480static int nameidata_drop_rcu_last(struct nameidata *nd)
481{
482 struct dentry *dentry = nd->path.dentry;
483
484 BUG_ON(!(nd->flags & LOOKUP_RCU));
485 nd->flags &= ~LOOKUP_RCU;
486 if (!(nd->flags & LOOKUP_ROOT))
487 nd->root.mnt = NULL;
488 spin_lock(&dentry->d_lock);
489 if (!__d_rcu_to_refcount(dentry, nd->seq))
490 goto err_unlock;
491 BUG_ON(nd->inode != dentry->d_inode);
492 spin_unlock(&dentry->d_lock);
493
494 mntget(nd->path.mnt);
495
496 rcu_read_unlock();
497 br_read_unlock(vfsmount_lock);
498
499 return 0;
500
501err_unlock:
502 spin_unlock(&dentry->d_lock);
503 rcu_read_unlock();
504 br_read_unlock(vfsmount_lock);
505 return -ECHILD;
506}
507
508/**
509 * release_open_intent - free up open intent resources 472 * release_open_intent - free up open intent resources
510 * @nd: pointer to nameidata 473 * @nd: pointer to nameidata
511 */ 474 */
@@ -548,26 +511,39 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd)
548 return dentry; 511 return dentry;
549} 512}
550 513
551/* 514/**
552 * handle_reval_path - force revalidation of a dentry 515 * complete_walk - successful completion of path walk
553 * 516 * @nd: pointer nameidata
554 * In some situations the path walking code will trust dentries without
555 * revalidating them. This causes problems for filesystems that depend on
556 * d_revalidate to handle file opens (e.g. NFSv4). When FS_REVAL_DOT is set
557 * (which indicates that it's possible for the dentry to go stale), force
558 * a d_revalidate call before proceeding.
559 * 517 *
560 * Returns 0 if the revalidation was successful. If the revalidation fails, 518 * If we had been in RCU mode, drop out of it and legitimize nd->path.
561 * either return the error returned by d_revalidate or -ESTALE if the 519 * Revalidate the final result, unless we'd already done that during
562 * revalidation it just returned 0. If d_revalidate returns 0, we attempt to 520 * the path walk or the filesystem doesn't ask for it. Return 0 on
563 * invalidate the dentry. It's up to the caller to handle putting references 521 * success, -error on failure. In case of failure caller does not
564 * to the path if necessary. 522 * need to drop nd->path.
565 */ 523 */
566static inline int handle_reval_path(struct nameidata *nd) 524static int complete_walk(struct nameidata *nd)
567{ 525{
568 struct dentry *dentry = nd->path.dentry; 526 struct dentry *dentry = nd->path.dentry;
569 int status; 527 int status;
570 528
529 if (nd->flags & LOOKUP_RCU) {
530 nd->flags &= ~LOOKUP_RCU;
531 if (!(nd->flags & LOOKUP_ROOT))
532 nd->root.mnt = NULL;
533 spin_lock(&dentry->d_lock);
534 if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) {
535 spin_unlock(&dentry->d_lock);
536 rcu_read_unlock();
537 br_read_unlock(vfsmount_lock);
538 return -ECHILD;
539 }
540 BUG_ON(nd->inode != dentry->d_inode);
541 spin_unlock(&dentry->d_lock);
542 mntget(nd->path.mnt);
543 rcu_read_unlock();
544 br_read_unlock(vfsmount_lock);
545 }
546
571 if (likely(!(nd->flags & LOOKUP_JUMPED))) 547 if (likely(!(nd->flags & LOOKUP_JUMPED)))
572 return 0; 548 return 0;
573 549
@@ -585,6 +561,7 @@ static inline int handle_reval_path(struct nameidata *nd)
585 if (!status) 561 if (!status)
586 status = -ESTALE; 562 status = -ESTALE;
587 563
564 path_put(&nd->path);
588 return status; 565 return status;
589} 566}
590 567
@@ -1598,18 +1575,8 @@ static int path_lookupat(int dfd, const char *name,
1598 } 1575 }
1599 } 1576 }
1600 1577
1601 if (nd->flags & LOOKUP_RCU) { 1578 if (!err)
1602 /* went all way through without dropping RCU */ 1579 err = complete_walk(nd);
1603 BUG_ON(err);
1604 if (nameidata_drop_rcu_last(nd))
1605 err = -ECHILD;
1606 }
1607
1608 if (!err) {
1609 err = handle_reval_path(nd);
1610 if (err)
1611 path_put(&nd->path);
1612 }
1613 1580
1614 if (!err && nd->flags & LOOKUP_DIRECTORY) { 1581 if (!err && nd->flags & LOOKUP_DIRECTORY) {
1615 if (!nd->inode->i_op->lookup) { 1582 if (!nd->inode->i_op->lookup) {
@@ -2075,13 +2042,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2075 return ERR_PTR(error); 2042 return ERR_PTR(error);
2076 /* fallthrough */ 2043 /* fallthrough */
2077 case LAST_ROOT: 2044 case LAST_ROOT:
2078 if (nd->flags & LOOKUP_RCU) { 2045 error = complete_walk(nd);
2079 if (nameidata_drop_rcu_last(nd))
2080 return ERR_PTR(-ECHILD);
2081 }
2082 error = handle_reval_path(nd);
2083 if (error) 2046 if (error)
2084 goto exit; 2047 return ERR_PTR(error);
2085 audit_inode(pathname, nd->path.dentry); 2048 audit_inode(pathname, nd->path.dentry);
2086 if (open_flag & O_CREAT) { 2049 if (open_flag & O_CREAT) {
2087 error = -EISDIR; 2050 error = -EISDIR;
@@ -2089,10 +2052,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2089 } 2052 }
2090 goto ok; 2053 goto ok;
2091 case LAST_BIND: 2054 case LAST_BIND:
2092 /* can't be RCU mode here */ 2055 error = complete_walk(nd);
2093 error = handle_reval_path(nd);
2094 if (error) 2056 if (error)
2095 goto exit; 2057 return ERR_PTR(error);
2096 audit_inode(pathname, dir); 2058 audit_inode(pathname, dir);
2097 goto ok; 2059 goto ok;
2098 } 2060 }
@@ -2111,10 +2073,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2111 if (error) /* symlink */ 2073 if (error) /* symlink */
2112 return NULL; 2074 return NULL;
2113 /* sayonara */ 2075 /* sayonara */
2114 if (nd->flags & LOOKUP_RCU) { 2076 error = complete_walk(nd);
2115 if (nameidata_drop_rcu_last(nd)) 2077 if (error)
2116 return ERR_PTR(-ECHILD); 2078 return ERR_PTR(-ECHILD);
2117 }
2118 2079
2119 error = -ENOTDIR; 2080 error = -ENOTDIR;
2120 if (nd->flags & LOOKUP_DIRECTORY) { 2081 if (nd->flags & LOOKUP_DIRECTORY) {
@@ -2126,11 +2087,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2126 } 2087 }
2127 2088
2128 /* create side of things */ 2089 /* create side of things */
2129 2090 error = complete_walk(nd);
2130 if (nd->flags & LOOKUP_RCU) { 2091 if (error)
2131 if (nameidata_drop_rcu_last(nd)) 2092 return ERR_PTR(error);
2132 return ERR_PTR(-ECHILD);
2133 }
2134 2093
2135 audit_inode(pathname, dir); 2094 audit_inode(pathname, dir);
2136 error = -EISDIR; 2095 error = -EISDIR;