diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-06-18 10:47:04 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-14 08:35:40 -0400 |
commit | b5fb63c18315c5510c1d0636179c057e0c761c77 (patch) | |
tree | 19e42c9aa285eb64c277ece4083d4834351b3d5b /fs/namei.c | |
parent | 408ef013cc9e2f94a14f7ccbbe52ddfb18437a99 (diff) |
fs: add nd_jump_link
Add a helper that abstracts out the jump to an already parsed struct path
from ->follow_link operation from procfs. Not only does this clean up
the code by moving the two sides of this game into a single helper, but
it also prepares for making struct nameidata private to namei.c
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/fs/namei.c b/fs/namei.c index a9b94c62c303..0e1b9c3eb36d 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -586,6 +586,21 @@ static inline void path_to_nameidata(const struct path *path, | |||
586 | nd->path.dentry = path->dentry; | 586 | nd->path.dentry = path->dentry; |
587 | } | 587 | } |
588 | 588 | ||
589 | /* | ||
590 | * Helper to directly jump to a known parsed path from ->follow_link, | ||
591 | * caller must have taken a reference to path beforehand. | ||
592 | */ | ||
593 | void nd_jump_link(struct nameidata *nd, struct path *path) | ||
594 | { | ||
595 | path_put(&nd->path); | ||
596 | |||
597 | nd->path = *path; | ||
598 | nd->inode = nd->path.dentry->d_inode; | ||
599 | nd->flags |= LOOKUP_JUMPED; | ||
600 | |||
601 | BUG_ON(nd->inode->i_op->follow_link); | ||
602 | } | ||
603 | |||
589 | static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) | 604 | static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) |
590 | { | 605 | { |
591 | struct inode *inode = link->dentry->d_inode; | 606 | struct inode *inode = link->dentry->d_inode; |
@@ -630,17 +645,9 @@ follow_link(struct path *link, struct nameidata *nd, void **p) | |||
630 | s = nd_get_link(nd); | 645 | s = nd_get_link(nd); |
631 | if (s) { | 646 | if (s) { |
632 | error = __vfs_follow_link(nd, s); | 647 | error = __vfs_follow_link(nd, s); |
633 | } else if (nd->last_type == LAST_BIND) { | 648 | if (unlikely(error)) |
634 | nd->flags |= LOOKUP_JUMPED; | 649 | put_link(nd, link, *p); |
635 | nd->inode = nd->path.dentry->d_inode; | ||
636 | if (nd->inode->i_op->follow_link) { | ||
637 | /* stepped on a _really_ weird one */ | ||
638 | path_put(&nd->path); | ||
639 | error = -ELOOP; | ||
640 | } | ||
641 | } | 650 | } |
642 | if (unlikely(error)) | ||
643 | put_link(nd, link, *p); | ||
644 | 651 | ||
645 | return error; | 652 | return error; |
646 | 653 | ||