aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenkateswararao Jujjuri (JV) <jvrao@linux.vnet.ibm.com>2010-06-09 18:59:31 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2010-08-02 15:28:29 -0400
commit50cc42ff3d7bc48a436c5a0413459ca7841b505f (patch)
tree7209ab2807e3a284c1fbd36dd885e34b81809b0d
parent652df9a7fd03cb47a3f663f0c08a2bd086505e9b (diff)
9p: Define and implement TSYMLINK for 9P2000.L
Create a symbolic link SYNOPSIS size[4] Tsymlink tag[2] fid[4] name[s] symtgt[s] gid[4] size[4] Rsymlink tag[2] qid[13] DESCRIPTION Create a symbolic link named 'name' pointing to 'symtgt'. gid represents the effective group id of the caller. The permissions of a symbolic link are irrelevant hence it is omitted from the protocol. Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Reviewed-by: Sripathi Kodi <sripathik@in.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--fs/9p/vfs_inode.c101
-rw-r--r--include/net/9p/9p.h4
-rw-r--r--include/net/9p/client.h2
-rw-r--r--net/9p/client.c34
4 files changed, 137 insertions, 4 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index e6ece237241f..a7319364544b 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1245,7 +1245,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1245 if (IS_ERR(fid)) 1245 if (IS_ERR(fid))
1246 return PTR_ERR(fid); 1246 return PTR_ERR(fid);
1247 1247
1248 if (!v9fs_proto_dotu(v9ses)) 1248 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses))
1249 return -EBADF; 1249 return -EBADF;
1250 1250
1251 st = p9_client_stat(fid); 1251 st = p9_client_stat(fid);
@@ -1351,6 +1351,99 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1351} 1351}
1352 1352
1353/** 1353/**
1354 * v9fs_vfs_symlink_dotl - helper function to create symlinks
1355 * @dir: directory inode containing symlink
1356 * @dentry: dentry for symlink
1357 * @symname: symlink data
1358 *
1359 * See Also: 9P2000.L RFC for more information
1360 *
1361 */
1362
1363static int
1364v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
1365 const char *symname)
1366{
1367 struct v9fs_session_info *v9ses;
1368 struct p9_fid *dfid;
1369 struct p9_fid *fid = NULL;
1370 struct inode *inode;
1371 struct p9_qid qid;
1372 char *name;
1373 int err;
1374 gid_t gid;
1375
1376 name = (char *) dentry->d_name.name;
1377 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_symlink_dotl : %lu,%s,%s\n",
1378 dir->i_ino, name, symname);
1379 v9ses = v9fs_inode2v9ses(dir);
1380
1381 dfid = v9fs_fid_lookup(dentry->d_parent);
1382 if (IS_ERR(dfid)) {
1383 err = PTR_ERR(dfid);
1384 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
1385 return err;
1386 }
1387
1388 gid = v9fs_get_fsgid_for_create(dir);
1389
1390 if (gid < 0) {
1391 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_egid failed %d\n", gid);
1392 goto error;
1393 }
1394
1395 /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */
1396 err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid);
1397
1398 if (err < 0) {
1399 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err);
1400 goto error;
1401 }
1402
1403 if (v9ses->cache) {
1404 /* Now walk from the parent so we can get an unopened fid. */
1405 fid = p9_client_walk(dfid, 1, &name, 1);
1406 if (IS_ERR(fid)) {
1407 err = PTR_ERR(fid);
1408 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
1409 err);
1410 fid = NULL;
1411 goto error;
1412 }
1413
1414 /* instantiate inode and assign the unopened fid to dentry */
1415 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
1416 if (IS_ERR(inode)) {
1417 err = PTR_ERR(inode);
1418 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
1419 err);
1420 goto error;
1421 }
1422 dentry->d_op = &v9fs_cached_dentry_operations;
1423 d_instantiate(dentry, inode);
1424 err = v9fs_fid_add(dentry, fid);
1425 if (err < 0)
1426 goto error;
1427 fid = NULL;
1428 } else {
1429 /* Not in cached mode. No need to populate inode with stat */
1430 inode = v9fs_get_inode(dir->i_sb, S_IFLNK);
1431 if (IS_ERR(inode)) {
1432 err = PTR_ERR(inode);
1433 goto error;
1434 }
1435 dentry->d_op = &v9fs_dentry_operations;
1436 d_instantiate(dentry, inode);
1437 }
1438
1439error:
1440 if (fid)
1441 p9_client_clunk(fid);
1442
1443 return err;
1444}
1445
1446/**
1354 * v9fs_vfs_symlink - helper function to create symlinks 1447 * v9fs_vfs_symlink - helper function to create symlinks
1355 * @dir: directory inode containing symlink 1448 * @dir: directory inode containing symlink
1356 * @dentry: dentry for symlink 1449 * @dentry: dentry for symlink
@@ -1527,7 +1620,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1527 .create = v9fs_vfs_create, 1620 .create = v9fs_vfs_create,
1528 .lookup = v9fs_vfs_lookup, 1621 .lookup = v9fs_vfs_lookup,
1529 .symlink = v9fs_vfs_symlink, 1622 .symlink = v9fs_vfs_symlink,
1530 .link = v9fs_vfs_link_dotl, 1623 .link = v9fs_vfs_link,
1531 .unlink = v9fs_vfs_unlink, 1624 .unlink = v9fs_vfs_unlink,
1532 .mkdir = v9fs_vfs_mkdir, 1625 .mkdir = v9fs_vfs_mkdir,
1533 .rmdir = v9fs_vfs_rmdir, 1626 .rmdir = v9fs_vfs_rmdir,
@@ -1540,8 +1633,8 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1540static const struct inode_operations v9fs_dir_inode_operations_dotl = { 1633static const struct inode_operations v9fs_dir_inode_operations_dotl = {
1541 .create = v9fs_vfs_create, 1634 .create = v9fs_vfs_create,
1542 .lookup = v9fs_vfs_lookup, 1635 .lookup = v9fs_vfs_lookup,
1543 .symlink = v9fs_vfs_symlink, 1636 .link = v9fs_vfs_link_dotl,
1544 .link = v9fs_vfs_link, 1637 .symlink = v9fs_vfs_symlink_dotl,
1545 .unlink = v9fs_vfs_unlink, 1638 .unlink = v9fs_vfs_unlink,
1546 .mkdir = v9fs_vfs_mkdir, 1639 .mkdir = v9fs_vfs_mkdir,
1547 .rmdir = v9fs_vfs_rmdir, 1640 .rmdir = v9fs_vfs_rmdir,
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 5985c0f83db3..44a6883d7144 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -88,6 +88,8 @@ do { \
88 * enum p9_msg_t - 9P message types 88 * enum p9_msg_t - 9P message types
89 * @P9_TSTATFS: file system status request 89 * @P9_TSTATFS: file system status request
90 * @P9_RSTATFS: file system status response 90 * @P9_RSTATFS: file system status response
91 * @P9_TSYMLINK: make symlink request
92 * @P9_RSYMLINK: make symlink response
91 * @P9_TRENAME: rename request 93 * @P9_TRENAME: rename request
92 * @P9_RRENAME: rename response 94 * @P9_RRENAME: rename response
93 * @P9_TVERSION: version handshake request 95 * @P9_TVERSION: version handshake request
@@ -131,6 +133,8 @@ do { \
131enum p9_msg_t { 133enum p9_msg_t {
132 P9_TSTATFS = 8, 134 P9_TSTATFS = 8,
133 P9_RSTATFS, 135 P9_RSTATFS,
136 P9_TSYMLINK = 16,
137 P9_RSYMLINK,
134 P9_TRENAME = 20, 138 P9_TRENAME = 20,
135 P9_RRENAME, 139 P9_RRENAME,
136 P9_TGETATTR = 24, 140 P9_TGETATTR = 24,
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index e36f11650e99..2e039730920e 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -227,6 +227,8 @@ int p9_client_open(struct p9_fid *fid, int mode);
227int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, 227int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
228 char *extension); 228 char *extension);
229int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, char *newname); 229int p9_client_link(struct p9_fid *fid, struct p9_fid *oldfid, char *newname);
230int p9_client_symlink(struct p9_fid *fid, char *name, char *symname, gid_t gid,
231 struct p9_qid *qid);
230int p9_client_clunk(struct p9_fid *fid); 232int p9_client_clunk(struct p9_fid *fid);
231int p9_client_remove(struct p9_fid *fid); 233int p9_client_remove(struct p9_fid *fid);
232int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, 234int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
diff --git a/net/9p/client.c b/net/9p/client.c
index ad1c4489ab4d..e37e64cb9394 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1095,6 +1095,40 @@ error:
1095} 1095}
1096EXPORT_SYMBOL(p9_client_fcreate); 1096EXPORT_SYMBOL(p9_client_fcreate);
1097 1097
1098int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid,
1099 struct p9_qid *qid)
1100{
1101 int err = 0;
1102 struct p9_client *clnt;
1103 struct p9_req_t *req;
1104
1105 P9_DPRINTK(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s symtgt %s\n",
1106 dfid->fid, name, symtgt);
1107 clnt = dfid->clnt;
1108
1109 req = p9_client_rpc(clnt, P9_TSYMLINK, "dssd", dfid->fid, name, symtgt,
1110 gid);
1111 if (IS_ERR(req)) {
1112 err = PTR_ERR(req);
1113 goto error;
1114 }
1115
1116 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
1117 if (err) {
1118 p9pdu_dump(1, req->rc);
1119 goto free_and_error;
1120 }
1121
1122 P9_DPRINTK(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n",
1123 qid->type, (unsigned long long)qid->path, qid->version);
1124
1125free_and_error:
1126 p9_free_req(clnt, req);
1127error:
1128 return err;
1129}
1130EXPORT_SYMBOL(p9_client_symlink);
1131
1098int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname) 1132int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname)
1099{ 1133{
1100 struct p9_client *clnt; 1134 struct p9_client *clnt;