diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/fs/namei.c b/fs/namei.c index 98dc2e134362..22f6e8d16aa8 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -546,6 +546,22 @@ struct path { | |||
546 | struct dentry *dentry; | 546 | struct dentry *dentry; |
547 | }; | 547 | }; |
548 | 548 | ||
549 | static inline void dput_path(struct path *path, struct nameidata *nd) | ||
550 | { | ||
551 | dput(path->dentry); | ||
552 | if (path->mnt != nd->mnt) | ||
553 | mntput(path->mnt); | ||
554 | } | ||
555 | |||
556 | static inline void path_to_nameidata(struct path *path, struct nameidata *nd) | ||
557 | { | ||
558 | dput(nd->dentry); | ||
559 | if (nd->mnt != path->mnt) | ||
560 | mntput(nd->mnt); | ||
561 | nd->mnt = path->mnt; | ||
562 | nd->dentry = path->dentry; | ||
563 | } | ||
564 | |||
549 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) | 565 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) |
550 | { | 566 | { |
551 | int error; | 567 | int error; |
@@ -555,8 +571,11 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata | |||
555 | touch_atime(path->mnt, dentry); | 571 | touch_atime(path->mnt, dentry); |
556 | nd_set_link(nd, NULL); | 572 | nd_set_link(nd, NULL); |
557 | 573 | ||
558 | if (path->mnt == nd->mnt) | 574 | if (path->mnt != nd->mnt) { |
559 | mntget(path->mnt); | 575 | path_to_nameidata(path, nd); |
576 | dget(dentry); | ||
577 | } | ||
578 | mntget(path->mnt); | ||
560 | cookie = dentry->d_inode->i_op->follow_link(dentry, nd); | 579 | cookie = dentry->d_inode->i_op->follow_link(dentry, nd); |
561 | error = PTR_ERR(cookie); | 580 | error = PTR_ERR(cookie); |
562 | if (!IS_ERR(cookie)) { | 581 | if (!IS_ERR(cookie)) { |
@@ -573,22 +592,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata | |||
573 | return error; | 592 | return error; |
574 | } | 593 | } |
575 | 594 | ||
576 | static inline void dput_path(struct path *path, struct nameidata *nd) | ||
577 | { | ||
578 | dput(path->dentry); | ||
579 | if (path->mnt != nd->mnt) | ||
580 | mntput(path->mnt); | ||
581 | } | ||
582 | |||
583 | static inline void path_to_nameidata(struct path *path, struct nameidata *nd) | ||
584 | { | ||
585 | dput(nd->dentry); | ||
586 | if (nd->mnt != path->mnt) | ||
587 | mntput(nd->mnt); | ||
588 | nd->mnt = path->mnt; | ||
589 | nd->dentry = path->dentry; | ||
590 | } | ||
591 | |||
592 | /* | 595 | /* |
593 | * This limits recursive symlink follows to 8, while | 596 | * This limits recursive symlink follows to 8, while |
594 | * limiting consecutive symlinks to 40. | 597 | * limiting consecutive symlinks to 40. |