aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-06-10 04:15:17 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-07-14 08:32:56 -0400
commit6d7b5aaed7d887b34f29f900244cdbd17a86637c (patch)
treee94341bc903a57e1c92c03c4953ae041b87f9807 /fs/namei.c
parent1d674107ea4b68669e012e654d64369b7f2bb250 (diff)
namei.c: let follow_link() do put_link() on failure
no need for kludgy "set cookie to ERR_PTR(...) because we failed before we did actual ->follow_link() and want to suppress put_link()", no pointless check in put_link() itself. Callers checked if follow_link() has failed anyway; might as well break out of their loops if that happened, without bothering to call put_link() first. [AV: folded fixes from hch] Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c74
1 files changed, 41 insertions, 33 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 7d694194024a..6135a14d5a84 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -605,7 +605,7 @@ static inline void path_to_nameidata(const struct path *path,
605static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) 605static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
606{ 606{
607 struct inode *inode = link->dentry->d_inode; 607 struct inode *inode = link->dentry->d_inode;
608 if (!IS_ERR(cookie) && inode->i_op->put_link) 608 if (inode->i_op->put_link)
609 inode->i_op->put_link(link->dentry, nd, cookie); 609 inode->i_op->put_link(link->dentry, nd, cookie);
610 path_put(link); 610 path_put(link);
611} 611}
@@ -613,19 +613,19 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
613static __always_inline int 613static __always_inline int
614follow_link(struct path *link, struct nameidata *nd, void **p) 614follow_link(struct path *link, struct nameidata *nd, void **p)
615{ 615{
616 int error;
617 struct dentry *dentry = link->dentry; 616 struct dentry *dentry = link->dentry;
617 int error;
618 char *s;
618 619
619 BUG_ON(nd->flags & LOOKUP_RCU); 620 BUG_ON(nd->flags & LOOKUP_RCU);
620 621
621 if (link->mnt == nd->path.mnt) 622 if (link->mnt == nd->path.mnt)
622 mntget(link->mnt); 623 mntget(link->mnt);
623 624
624 if (unlikely(current->total_link_count >= 40)) { 625 error = -ELOOP;
625 *p = ERR_PTR(-ELOOP); /* no ->put_link(), please */ 626 if (unlikely(current->total_link_count >= 40))
626 path_put(&nd->path); 627 goto out_put_nd_path;
627 return -ELOOP; 628
628 }
629 cond_resched(); 629 cond_resched();
630 current->total_link_count++; 630 current->total_link_count++;
631 631
@@ -633,30 +633,37 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
633 nd_set_link(nd, NULL); 633 nd_set_link(nd, NULL);
634 634
635 error = security_inode_follow_link(link->dentry, nd); 635 error = security_inode_follow_link(link->dentry, nd);
636 if (error) { 636 if (error)
637 *p = ERR_PTR(error); /* no ->put_link(), please */ 637 goto out_put_nd_path;
638 path_put(&nd->path);
639 return error;
640 }
641 638
642 nd->last_type = LAST_BIND; 639 nd->last_type = LAST_BIND;
643 *p = dentry->d_inode->i_op->follow_link(dentry, nd); 640 *p = dentry->d_inode->i_op->follow_link(dentry, nd);
644 error = PTR_ERR(*p); 641 error = PTR_ERR(*p);
645 if (!IS_ERR(*p)) { 642 if (IS_ERR(*p))
646 char *s = nd_get_link(nd); 643 goto out_put_link;
647 error = 0; 644
648 if (s) 645 error = 0;
649 error = __vfs_follow_link(nd, s); 646 s = nd_get_link(nd);
650 else if (nd->last_type == LAST_BIND) { 647 if (s) {
651 nd->flags |= LOOKUP_JUMPED; 648 error = __vfs_follow_link(nd, s);
652 nd->inode = nd->path.dentry->d_inode; 649 } else if (nd->last_type == LAST_BIND) {
653 if (nd->inode->i_op->follow_link) { 650 nd->flags |= LOOKUP_JUMPED;
654 /* stepped on a _really_ weird one */ 651 nd->inode = nd->path.dentry->d_inode;
655 path_put(&nd->path); 652 if (nd->inode->i_op->follow_link) {
656 error = -ELOOP; 653 /* stepped on a _really_ weird one */
657 } 654 path_put(&nd->path);
655 error = -ELOOP;
658 } 656 }
659 } 657 }
658 if (unlikely(error))
659 put_link(nd, link, *p);
660
661 return error;
662
663out_put_nd_path:
664 path_put(&nd->path);
665out_put_link:
666 path_put(link);
660 return error; 667 return error;
661} 668}
662 669
@@ -1383,9 +1390,10 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
1383 void *cookie; 1390 void *cookie;
1384 1391
1385 res = follow_link(&link, nd, &cookie); 1392 res = follow_link(&link, nd, &cookie);
1386 if (!res) 1393 if (res)
1387 res = walk_component(nd, path, &nd->last, 1394 break;
1388 nd->last_type, LOOKUP_FOLLOW); 1395 res = walk_component(nd, path, &nd->last,
1396 nd->last_type, LOOKUP_FOLLOW);
1389 put_link(nd, &link, cookie); 1397 put_link(nd, &link, cookie);
1390 } while (res > 0); 1398 } while (res > 0);
1391 1399
@@ -1777,8 +1785,9 @@ static int path_lookupat(int dfd, const char *name,
1777 struct path link = path; 1785 struct path link = path;
1778 nd->flags |= LOOKUP_PARENT; 1786 nd->flags |= LOOKUP_PARENT;
1779 err = follow_link(&link, nd, &cookie); 1787 err = follow_link(&link, nd, &cookie);
1780 if (!err) 1788 if (err)
1781 err = lookup_last(nd, &path); 1789 break;
1790 err = lookup_last(nd, &path);
1782 put_link(nd, &link, cookie); 1791 put_link(nd, &link, cookie);
1783 } 1792 }
1784 } 1793 }
@@ -2475,9 +2484,8 @@ static struct file *path_openat(int dfd, const char *pathname,
2475 nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); 2484 nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
2476 error = follow_link(&link, nd, &cookie); 2485 error = follow_link(&link, nd, &cookie);
2477 if (unlikely(error)) 2486 if (unlikely(error))
2478 filp = ERR_PTR(error); 2487 goto out_filp;
2479 else 2488 filp = do_last(nd, &path, op, pathname);
2480 filp = do_last(nd, &path, op, pathname);
2481 put_link(nd, &link, cookie); 2489 put_link(nd, &link, cookie);
2482 } 2490 }
2483out: 2491out: