diff options
author | M. Mohan Kumar <mohan@in.ibm.com> | 2010-09-28 10:29:25 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2010-10-28 10:08:48 -0400 |
commit | 329176cc2c50e63c580ddaabb385876db5af1360 (patch) | |
tree | c7a95364c6339f75d37e1b63890d94114cd1935e | |
parent | 368c09d2a303c39e9f37193b23e945e6754cf0a7 (diff) |
9p: Implement TREADLINK operation for 9p2000.L
Synopsis
size[4] TReadlink tag[2] fid[4]
size[4] RReadlink tag[2] target[s]
Description
Readlink is used to return the contents of the symoblic link
referred by fid. Contents of symboic link is returned as a
response.
target[s] - Contents of the symbolic link referred by fid.
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r-- | fs/9p/vfs_inode.c | 60 | ||||
-rw-r--r-- | include/net/9p/9p.h | 2 | ||||
-rw-r--r-- | include/net/9p/client.h | 1 | ||||
-rw-r--r-- | net/9p/client.c | 26 |
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 | ||
1998 | static int | ||
1999 | v9fs_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 | |||
2029 | static void * | ||
2030 | v9fs_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 | |||
1998 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { | 2052 | static 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 | ||
2066 | static const struct inode_operations v9fs_symlink_inode_operations_dotl = { | 2120 | static 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); | |||
262 | int p9_is_proto_dotl(struct p9_client *clnt); | 262 | int p9_is_proto_dotl(struct p9_client *clnt); |
263 | struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *); | 263 | struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *); |
264 | int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int); | 264 | int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int); |
265 | int 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 | } |
1872 | EXPORT_SYMBOL(p9_client_getlock_dotl); | 1872 | EXPORT_SYMBOL(p9_client_getlock_dotl); |
1873 | |||
1874 | int 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); | ||
1894 | error: | ||
1895 | p9_free_req(clnt, req); | ||
1896 | return err; | ||
1897 | } | ||
1898 | EXPORT_SYMBOL(p9_client_readlink); | ||