aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-05-10 11:01:00 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-05-10 22:20:17 -0400
commitfab51e8ab25e1ad661ef8da42077de78477fba83 (patch)
tree172e315fc3d3fec020327a9878e522f8efec0e0d /fs/namei.c
parent4f697a5e173023a4f566339452a9d6f2cc7bd7dc (diff)
namei: take the treatment of absolute symlinks to get_link()
rather than letting the callers handle the jump-to-root part of semantics, do it right in get_link() and return the rest of the body for the caller to deal with - at that point it's treated the same way as relative symlinks would be. And return NULL when there's no "rest of the body" - those are treated the same as pure jump symlink would be. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c49
1 files changed, 20 insertions, 29 deletions
diff --git a/fs/namei.c b/fs/namei.c
index c5eb77a57974..c6ff9da69cec 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -918,9 +918,24 @@ const char *get_link(struct nameidata *nd)
918 res = inode->i_link; 918 res = inode->i_link;
919 if (!res) { 919 if (!res) {
920 res = inode->i_op->follow_link(dentry, &last->cookie); 920 res = inode->i_op->follow_link(dentry, &last->cookie);
921 if (IS_ERR_OR_NULL(res)) 921 if (IS_ERR_OR_NULL(res)) {
922 last->cookie = NULL; 922 last->cookie = NULL;
923 return res;
924 }
925 }
926 if (*res == '/') {
927 if (!nd->root.mnt)
928 set_root(nd);
929 path_put(&nd->path);
930 nd->path = nd->root;
931 path_get(&nd->root);
932 nd->inode = nd->path.dentry->d_inode;
933 nd->flags |= LOOKUP_JUMPED;
934 while (unlikely(*++res == '/'))
935 ;
923 } 936 }
937 if (!*res)
938 res = NULL;
924 return res; 939 return res;
925} 940}
926 941
@@ -1854,24 +1869,9 @@ OK:
1854 /* jumped */ 1869 /* jumped */
1855 put_link(nd); 1870 put_link(nd);
1856 } else { 1871 } else {
1857 if (*s == '/') { 1872 nd->stack[nd->depth - 1].name = name;
1858 if (!nd->root.mnt) 1873 name = s;
1859 set_root(nd); 1874 continue;
1860 path_put(&nd->path);
1861 nd->path = nd->root;
1862 path_get(&nd->root);
1863 nd->flags |= LOOKUP_JUMPED;
1864 while (unlikely(*++s == '/'))
1865 ;
1866 }
1867 nd->inode = nd->path.dentry->d_inode;
1868 if (unlikely(!*s)) {
1869 put_link(nd);
1870 } else {
1871 nd->stack[nd->depth - 1].name = name;
1872 name = s;
1873 continue;
1874 }
1875 } 1875 }
1876 } 1876 }
1877 if (!d_can_lookup(nd->path.dentry)) { 1877 if (!d_can_lookup(nd->path.dentry)) {
@@ -2002,6 +2002,7 @@ static int trailing_symlink(struct nameidata *nd)
2002 if (unlikely(error)) 2002 if (unlikely(error))
2003 return error; 2003 return error;
2004 nd->flags |= LOOKUP_PARENT; 2004 nd->flags |= LOOKUP_PARENT;
2005 nd->stack[0].name = NULL;
2005 s = get_link(nd); 2006 s = get_link(nd);
2006 if (unlikely(IS_ERR(s))) { 2007 if (unlikely(IS_ERR(s))) {
2007 terminate_walk(nd); 2008 terminate_walk(nd);
@@ -2009,16 +2010,6 @@ static int trailing_symlink(struct nameidata *nd)
2009 } 2010 }
2010 if (unlikely(!s)) 2011 if (unlikely(!s))
2011 return 0; 2012 return 0;
2012 if (*s == '/') {
2013 if (!nd->root.mnt)
2014 set_root(nd);
2015 path_put(&nd->path);
2016 nd->path = nd->root;
2017 path_get(&nd->root);
2018 nd->flags |= LOOKUP_JUMPED;
2019 }
2020 nd->inode = nd->path.dentry->d_inode;
2021 nd->stack[0].name = NULL;
2022 return link_path_walk(s, nd); 2013 return link_path_walk(s, nd);
2023} 2014}
2024 2015