Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 329176cc authored by M. Mohan Kumar's avatar M. Mohan Kumar Committed by Eric Van Hensbergen
Browse files

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: default avatarM. Mohan Kumar <mohan@in.ibm.com>
Reviewed-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarVenkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: default avatarEric Van Hensbergen <ericvh@gmail.com>
parent 368c09d2
Loading
Loading
Loading
Loading
+57 −3
Original line number Diff line number Diff line
@@ -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 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
	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,
+2 −0
Original line number Diff line number Diff line
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+26 −0
Original line number Diff line number Diff line
@@ -1870,3 +1870,29 @@ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
	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);