aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c66
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
716void nd_set_link(struct nameidata *nd, char *path)
717{
718 nd->saved_names[nd->depth] = path;
719}
720EXPORT_SYMBOL(nd_set_link);
721
722char *nd_get_link(struct nameidata *nd)
723{
724 return nd->saved_names[nd->depth];
725}
726EXPORT_SYMBOL(nd_get_link);
727
728static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) 715static 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
908out_put_nd_path: 889out_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 */
4431int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) 4411int 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}
4447EXPORT_SYMBOL(generic_readlink); 4424EXPORT_SYMBOL(generic_readlink);
@@ -4473,22 +4450,21 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
4473} 4450}
4474EXPORT_SYMBOL(page_readlink); 4451EXPORT_SYMBOL(page_readlink);
4475 4452
4476void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd) 4453const 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}
4482EXPORT_SYMBOL(page_follow_link_light); 4461EXPORT_SYMBOL(page_follow_link_light);
4483 4462
4484void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) 4463void 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}
4493EXPORT_SYMBOL(page_put_link); 4469EXPORT_SYMBOL(page_put_link);
4494 4470