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. |
