diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 66 |
1 files changed, 21 insertions, 45 deletions
diff --git a/fs/namei.c b/fs/namei.c index ab2bcbdbd683..aeca44877371 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -502,7 +502,6 @@ struct nameidata { | |||
502 | int last_type; | 502 | int last_type; |
503 | unsigned depth; | 503 | unsigned depth; |
504 | struct file *base; | 504 | struct file *base; |
505 | char *saved_names[MAX_NESTED_LINKS + 1]; | ||
506 | }; | 505 | }; |
507 | 506 | ||
508 | /* | 507 | /* |
@@ -713,23 +712,11 @@ void nd_jump_link(struct nameidata *nd, struct path *path) | |||
713 | nd->flags |= LOOKUP_JUMPED; | 712 | nd->flags |= LOOKUP_JUMPED; |
714 | } | 713 | } |
715 | 714 | ||
716 | void nd_set_link(struct nameidata *nd, char *path) | ||
717 | { | ||
718 | nd->saved_names[nd->depth] = path; | ||
719 | } | ||
720 | EXPORT_SYMBOL(nd_set_link); | ||
721 | |||
722 | char *nd_get_link(struct nameidata *nd) | ||
723 | { | ||
724 | return nd->saved_names[nd->depth]; | ||
725 | } | ||
726 | EXPORT_SYMBOL(nd_get_link); | ||
727 | |||
728 | static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) | 715 | static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) |
729 | { | 716 | { |
730 | struct inode *inode = link->dentry->d_inode; | 717 | struct inode *inode = link->dentry->d_inode; |
731 | if (inode->i_op->put_link) | 718 | if (cookie && inode->i_op->put_link) |
732 | inode->i_op->put_link(link->dentry, nd, cookie); | 719 | inode->i_op->put_link(link->dentry, cookie); |
733 | path_put(link); | 720 | path_put(link); |
734 | } | 721 | } |
735 | 722 | ||
@@ -854,7 +841,7 @@ follow_link(struct path *link, struct nameidata *nd, void **p) | |||
854 | { | 841 | { |
855 | struct dentry *dentry = link->dentry; | 842 | struct dentry *dentry = link->dentry; |
856 | int error; | 843 | int error; |
857 | char *s; | 844 | const char *s; |
858 | 845 | ||
859 | BUG_ON(nd->flags & LOOKUP_RCU); | 846 | BUG_ON(nd->flags & LOOKUP_RCU); |
860 | 847 | ||
@@ -869,26 +856,20 @@ follow_link(struct path *link, struct nameidata *nd, void **p) | |||
869 | current->total_link_count++; | 856 | current->total_link_count++; |
870 | 857 | ||
871 | touch_atime(link); | 858 | touch_atime(link); |
872 | nd_set_link(nd, NULL); | ||
873 | 859 | ||
874 | error = security_inode_follow_link(dentry); | 860 | error = security_inode_follow_link(dentry); |
875 | if (error) | 861 | if (error) |
876 | goto out_put_nd_path; | 862 | goto out_put_nd_path; |
877 | 863 | ||
878 | nd->last_type = LAST_BIND; | 864 | nd->last_type = LAST_BIND; |
879 | *p = dentry->d_inode->i_op->follow_link(dentry, nd); | 865 | *p = NULL; |
880 | error = PTR_ERR(*p); | 866 | s = dentry->d_inode->i_op->follow_link(dentry, p, nd); |
881 | if (IS_ERR(*p)) | 867 | error = PTR_ERR(s); |
868 | if (IS_ERR(s)) | ||
882 | goto out_put_nd_path; | 869 | goto out_put_nd_path; |
883 | 870 | ||
884 | error = 0; | 871 | error = 0; |
885 | s = nd_get_link(nd); | ||
886 | if (s) { | 872 | if (s) { |
887 | if (unlikely(IS_ERR(s))) { | ||
888 | path_put(&nd->path); | ||
889 | put_link(nd, link, *p); | ||
890 | return PTR_ERR(s); | ||
891 | } | ||
892 | if (*s == '/') { | 873 | if (*s == '/') { |
893 | if (!nd->root.mnt) | 874 | if (!nd->root.mnt) |
894 | set_root(nd); | 875 | set_root(nd); |
@@ -906,7 +887,6 @@ follow_link(struct path *link, struct nameidata *nd, void **p) | |||
906 | return error; | 887 | return error; |
907 | 888 | ||
908 | out_put_nd_path: | 889 | out_put_nd_path: |
909 | *p = NULL; | ||
910 | path_put(&nd->path); | 890 | path_put(&nd->path); |
911 | path_put(link); | 891 | path_put(link); |
912 | return error; | 892 | return error; |
@@ -4430,18 +4410,15 @@ EXPORT_SYMBOL(readlink_copy); | |||
4430 | */ | 4410 | */ |
4431 | int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 4411 | int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
4432 | { | 4412 | { |
4433 | struct nameidata nd; | ||
4434 | void *cookie; | 4413 | void *cookie; |
4414 | const char *link = dentry->d_inode->i_op->follow_link(dentry, &cookie, NULL); | ||
4435 | int res; | 4415 | int res; |
4436 | 4416 | ||
4437 | nd.depth = 0; | 4417 | if (IS_ERR(link)) |
4438 | cookie = dentry->d_inode->i_op->follow_link(dentry, &nd); | 4418 | return PTR_ERR(link); |
4439 | if (IS_ERR(cookie)) | 4419 | res = readlink_copy(buffer, buflen, link); |
4440 | return PTR_ERR(cookie); | 4420 | if (cookie && dentry->d_inode->i_op->put_link) |
4441 | 4421 | dentry->d_inode->i_op->put_link(dentry, cookie); | |
4442 | res = readlink_copy(buffer, buflen, nd_get_link(&nd)); | ||
4443 | if (dentry->d_inode->i_op->put_link) | ||
4444 | dentry->d_inode->i_op->put_link(dentry, &nd, cookie); | ||
4445 | return res; | 4422 | return res; |
4446 | } | 4423 | } |
4447 | EXPORT_SYMBOL(generic_readlink); | 4424 | EXPORT_SYMBOL(generic_readlink); |
@@ -4473,22 +4450,21 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) | |||
4473 | } | 4450 | } |
4474 | EXPORT_SYMBOL(page_readlink); | 4451 | EXPORT_SYMBOL(page_readlink); |
4475 | 4452 | ||
4476 | void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd) | 4453 | const char *page_follow_link_light(struct dentry *dentry, void **cookie, struct nameidata *nd) |
4477 | { | 4454 | { |
4478 | struct page *page = NULL; | 4455 | struct page *page = NULL; |
4479 | nd_set_link(nd, page_getlink(dentry, &page)); | 4456 | char *res = page_getlink(dentry, &page); |
4480 | return page; | 4457 | if (!IS_ERR(res)) |
4458 | *cookie = page; | ||
4459 | return res; | ||
4481 | } | 4460 | } |
4482 | EXPORT_SYMBOL(page_follow_link_light); | 4461 | EXPORT_SYMBOL(page_follow_link_light); |
4483 | 4462 | ||
4484 | void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) | 4463 | void page_put_link(struct dentry *dentry, void *cookie) |
4485 | { | 4464 | { |
4486 | struct page *page = cookie; | 4465 | struct page *page = cookie; |
4487 | 4466 | kunmap(page); | |
4488 | if (page) { | 4467 | page_cache_release(page); |
4489 | kunmap(page); | ||
4490 | page_cache_release(page); | ||
4491 | } | ||
4492 | } | 4468 | } |
4493 | EXPORT_SYMBOL(page_put_link); | 4469 | EXPORT_SYMBOL(page_put_link); |
4494 | 4470 | ||