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@xxxxxxxxxx> Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@xxxxxxxxxxxxxxxxxx> --- fs/9p/vfs_inode.c | 60 ++++++++++++++++++++++++++++++++++++++++++++-- include/net/9p/9p.h | 2 + include/net/9p/client.h | 1 + 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 2f904a8..2ce3668 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) if (IS_ERR(fid)) return PTR_ERR(fid); - if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) + if (!v9fs_proto_dotu(v9ses)) return -EBADF; st = p9_client_stat(fid); @@ -1994,6 +1994,60 @@ error: return err; } +static int +v9fs_vfs_readlink_dotl(struct dentry *dentry, char *buffer, int buflen) +{ + int retval; + struct p9_fid *fid; + char *target = NULL; + + P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); + retval = -EPERM; + fid = v9fs_fid_lookup(dentry); + if (IS_ERR(fid)) + return PTR_ERR(fid); + + retval = p9_client_readlink(fid, &target); + if (retval < 0) + return retval; + + strncpy(buffer, target, buflen); + P9_DPRINTK(P9_DEBUG_VFS, "%s -> %s\n", dentry->d_name.name, buffer); + + retval = strnlen(buffer, buflen); + return retval; +} + +/** + * v9fs_vfs_follow_link_dotl - follow a symlink path + * @dentry: dentry for symlink + * @nd: nameidata + * + */ + +static void * +v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) +{ + int len = 0; + char *link = __getname(); + + P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); + + if (!link) + link = ERR_PTR(-ENOMEM); + else { + len = v9fs_vfs_readlink_dotl(dentry, link, PATH_MAX); + if (len < 0) { + __putname(link); + link = ERR_PTR(len); + } else + link[min(len, PATH_MAX-1)] = 0; + } + nd_set_link(nd, link); + + return NULL; +} + static const struct inode_operations v9fs_dir_inode_operations_dotu = { .create = v9fs_vfs_create, .lookup = v9fs_vfs_lookup, @@ -2063,8 +2117,8 @@ static const struct inode_operations v9fs_symlink_inode_operations = { }; static const struct inode_operations v9fs_symlink_inode_operations_dotl = { - .readlink = generic_readlink, - .follow_link = v9fs_vfs_follow_link, + .readlink = v9fs_vfs_readlink_dotl, + .follow_link = v9fs_vfs_follow_link_dotl, .put_link = v9fs_vfs_put_link, .getattr = v9fs_vfs_getattr_dotl, .setattr = v9fs_vfs_setattr_dotl, diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 0c9ad95..bce81bc 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -153,6 +153,8 @@ enum p9_msg_t { P9_RMKNOD, P9_TRENAME = 20, P9_RRENAME, + P9_TREADLINK = 22, + P9_RREADLINK, P9_TGETATTR = 24, P9_RGETATTR, P9_TSETATTR = 26, diff --git a/include/net/9p/client.h b/include/net/9p/client.h index fb358f5..fa91c5e 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -264,5 +264,6 @@ int p9_is_proto_dotu(struct p9_client *clnt); int p9_is_proto_dotl(struct p9_client *clnt); struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *); int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int); +int p9_client_readlink(struct p9_fid *fid, char **target); #endif /* NET_9P_CLIENT_H */ diff --git a/net/9p/client.c b/net/9p/client.c index 4b90b82..9274981 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1894,3 +1894,29 @@ error: return err; } EXPORT_SYMBOL(p9_client_getlock_dotl); + +int p9_client_readlink(struct p9_fid *fid, char **target) +{ + int err; + struct p9_client *clnt; + struct p9_req_t *req; + + err = 0; + clnt = fid->clnt; + P9_DPRINTK(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid); + + req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid); + if (IS_ERR(req)) + return PTR_ERR(req); + + err = p9pdu_readf(req->rc, clnt->proto_version, "s", target); + if (err) { + p9pdu_dump(1, req->rc); + goto error; + } + P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target); +error: + p9_free_req(clnt, req); + return err; +} +EXPORT_SYMBOL(p9_client_readlink); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html