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>
This commit is contained in:
parent
368c09d2a3
commit
329176cc2c
4 changed files with 86 additions and 3 deletions
|
@ -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);
|
||||
|
@ -1995,6 +1995,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,
|
||||
|
@ -2064,8 +2118,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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -262,5 +262,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 */
|
||||
|
|
|
@ -1870,3 +1870,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);
|
||||
|
|
Loading…
Reference in a new issue