aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
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 /fs/9p
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>
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/vfs_inode.c101
1 files changed, 97 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,