aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/9p/vfs_inode.c60
-rw-r--r--include/net/9p/9p.h2
-rw-r--r--include/net/9p/client.h1
-rw-r--r--net/9p/client.c26
4 files changed, 86 insertions, 3 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 68f02973c338..88419073c654 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1527,7 +1527,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1527 if (IS_ERR(fid)) 1527 if (IS_ERR(fid))
1528 return PTR_ERR(fid); 1528 return PTR_ERR(fid);
1529 1529
1530 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) 1530 if (!v9fs_proto_dotu(v9ses))
1531 return -EBADF; 1531 return -EBADF;
1532 1532
1533 st = p9_client_stat(fid); 1533 st = p9_client_stat(fid);
@@ -1995,6 +1995,60 @@ error:
1995 return err; 1995 return err;
1996} 1996}
1997 1997
1998static int
1999v9fs_vfs_readlink_dotl(struct dentry *dentry, char *buffer, int buflen)
2000{
2001 int retval;
2002 struct p9_fid *fid;
2003 char *target = NULL;
2004
2005 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
2006 retval = -EPERM;
2007 fid = v9fs_fid_lookup(dentry);
2008 if (IS_ERR(fid))
2009 return PTR_ERR(fid);
2010
2011 retval = p9_client_readlink(fid, &target);
2012 if (retval < 0)
2013 return retval;
2014
2015 strncpy(buffer, target, buflen);
2016 P9_DPRINTK(P9_DEBUG_VFS, "%s -> %s\n", dentry->d_name.name, buffer);
2017
2018 retval = strnlen(buffer, buflen);
2019 return retval;
2020}
2021
2022/**
2023 * v9fs_vfs_follow_link_dotl - follow a symlink path
2024 * @dentry: dentry for symlink
2025 * @nd: nameidata
2026 *
2027 */
2028
2029static void *
2030v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
2031{
2032 int len = 0;
2033 char *link = __getname();
2034
2035 P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
2036
2037 if (!link)
2038 link = ERR_PTR(-ENOMEM);
2039 else {
2040 len = v9fs_vfs_readlink_dotl(dentry, link, PATH_MAX);
2041 if (len < 0) {
2042 __putname(link);
2043 link = ERR_PTR(len);
2044 } else
2045 link[min(len, PATH_MAX-1)] = 0;
2046 }
2047 nd_set_link(nd, link);
2048
2049 return NULL;
2050}
2051
1998static const struct inode_operations v9fs_dir_inode_operations_dotu = { 2052static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1999 .create = v9fs_vfs_create, 2053 .create = v9fs_vfs_create,
2000 .lookup = v9fs_vfs_lookup, 2054 .lookup = v9fs_vfs_lookup,
@@ -2064,8 +2118,8 @@ static const struct inode_operations v9fs_symlink_inode_operations = {
2064}; 2118};
2065 2119
2066static const struct inode_operations v9fs_symlink_inode_operations_dotl = { 2120static const struct inode_operations v9fs_symlink_inode_operations_dotl = {
2067 .readlink = generic_readlink, 2121 .readlink = v9fs_vfs_readlink_dotl,
2068 .follow_link = v9fs_vfs_follow_link, 2122 .follow_link = v9fs_vfs_follow_link_dotl,
2069 .put_link = v9fs_vfs_put_link, 2123 .put_link = v9fs_vfs_put_link,
2070 .getattr = v9fs_vfs_getattr_dotl, 2124 .getattr = v9fs_vfs_getattr_dotl,
2071 .setattr = v9fs_vfs_setattr_dotl, 2125 .setattr = v9fs_vfs_setattr_dotl,
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 6367a71d84fc..071fd7a8d781 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -153,6 +153,8 @@ enum p9_msg_t {
153 P9_RMKNOD, 153 P9_RMKNOD,
154 P9_TRENAME = 20, 154 P9_TRENAME = 20,
155 P9_RRENAME, 155 P9_RRENAME,
156 P9_TREADLINK = 22,
157 P9_RREADLINK,
156 P9_TGETATTR = 24, 158 P9_TGETATTR = 24,
157 P9_RGETATTR, 159 P9_RGETATTR,
158 P9_TSETATTR = 26, 160 P9_TSETATTR = 26,
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 127c9f2a9cb8..335b088e7672 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -262,5 +262,6 @@ int p9_is_proto_dotu(struct p9_client *clnt);
262int p9_is_proto_dotl(struct p9_client *clnt); 262int p9_is_proto_dotl(struct p9_client *clnt);
263struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *); 263struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *);
264int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int); 264int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int);
265int p9_client_readlink(struct p9_fid *fid, char **target);
265 266
266#endif /* NET_9P_CLIENT_H */ 267#endif /* NET_9P_CLIENT_H */
diff --git a/net/9p/client.c b/net/9p/client.c
index fc1b0579016a..2bc99e9031e7 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1870,3 +1870,29 @@ error:
1870 return err; 1870 return err;
1871} 1871}
1872EXPORT_SYMBOL(p9_client_getlock_dotl); 1872EXPORT_SYMBOL(p9_client_getlock_dotl);
1873
1874int p9_client_readlink(struct p9_fid *fid, char **target)
1875{
1876 int err;
1877 struct p9_client *clnt;
1878 struct p9_req_t *req;
1879
1880 err = 0;
1881 clnt = fid->clnt;
1882 P9_DPRINTK(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid);
1883
1884 req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid);
1885 if (IS_ERR(req))
1886 return PTR_ERR(req);
1887
1888 err = p9pdu_readf(req->rc, clnt->proto_version, "s", target);
1889 if (err) {
1890 p9pdu_dump(1, req->rc);
1891 goto error;
1892 }
1893 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target);
1894error:
1895 p9_free_req(clnt, req);
1896 return err;
1897}
1898EXPORT_SYMBOL(p9_client_readlink);