diff options
author | Eric Van Hensbergen <ericvh@gmail.com> | 2010-08-02 15:28:09 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2010-08-02 15:28:09 -0400 |
commit | 09d34ee5f93b2e53b64ffba27bc18731e31154e1 (patch) | |
tree | 6a1abd891731247c270d42ba8d7c3b4e8b9fd4b3 /fs | |
parent | 87d7845aa0b157a62448dd3e339856f28befe1f4 (diff) |
9p: Define and implement TLINK for 9P2000.L
This patch adds a helper function to get the dentry from inode and
uses it in creating a Hardlink
SYNOPSIS
size[4] Tlink tag[2] dfid[4] oldfid[4] newpath[s]
size[4] Rlink tag[2]
DESCRIPTION
Create a link 'newpath' in directory pointed by dfid linking to oldfid path.
[sripathik@in.ibm.com : p9_client_link should not free req structure
if p9_client_rpc has returned an error.]
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/9p/vfs_inode.c | 107 |
1 files changed, 106 insertions, 1 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index a90324f4546a..e6ece237241f 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -236,6 +236,41 @@ void v9fs_destroy_inode(struct inode *inode) | |||
236 | #endif | 236 | #endif |
237 | 237 | ||
238 | /** | 238 | /** |
239 | * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a | ||
240 | * new file system object. This checks the S_ISGID to determine the owning | ||
241 | * group of the new file system object. | ||
242 | */ | ||
243 | |||
244 | static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) | ||
245 | { | ||
246 | BUG_ON(dir_inode == NULL); | ||
247 | |||
248 | if (dir_inode->i_mode & S_ISGID) { | ||
249 | /* set_gid bit is set.*/ | ||
250 | return dir_inode->i_gid; | ||
251 | } | ||
252 | return current_fsgid(); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * v9fs_dentry_from_dir_inode - helper function to get the dentry from | ||
257 | * dir inode. | ||
258 | * | ||
259 | */ | ||
260 | |||
261 | struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode) | ||
262 | { | ||
263 | struct dentry *dentry; | ||
264 | |||
265 | spin_lock(&dcache_lock); | ||
266 | /* Directory should have only one entry. */ | ||
267 | BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry)); | ||
268 | dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); | ||
269 | spin_unlock(&dcache_lock); | ||
270 | return dentry; | ||
271 | } | ||
272 | |||
273 | /** | ||
239 | * v9fs_get_inode - helper function to setup an inode | 274 | * v9fs_get_inode - helper function to setup an inode |
240 | * @sb: superblock | 275 | * @sb: superblock |
241 | * @mode: mode to setup inode with | 276 | * @mode: mode to setup inode with |
@@ -1374,6 +1409,76 @@ clunk_fid: | |||
1374 | } | 1409 | } |
1375 | 1410 | ||
1376 | /** | 1411 | /** |
1412 | * v9fs_vfs_link_dotl - create a hardlink for dotl | ||
1413 | * @old_dentry: dentry for file to link to | ||
1414 | * @dir: inode destination for new link | ||
1415 | * @dentry: dentry for link | ||
1416 | * | ||
1417 | */ | ||
1418 | |||
1419 | static int | ||
1420 | v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, | ||
1421 | struct dentry *dentry) | ||
1422 | { | ||
1423 | int err; | ||
1424 | struct p9_fid *dfid, *oldfid; | ||
1425 | char *name; | ||
1426 | struct v9fs_session_info *v9ses; | ||
1427 | struct dentry *dir_dentry; | ||
1428 | |||
1429 | P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n", | ||
1430 | dir->i_ino, old_dentry->d_name.name, | ||
1431 | dentry->d_name.name); | ||
1432 | |||
1433 | v9ses = v9fs_inode2v9ses(dir); | ||
1434 | dir_dentry = v9fs_dentry_from_dir_inode(dir); | ||
1435 | dfid = v9fs_fid_lookup(dir_dentry); | ||
1436 | if (IS_ERR(dfid)) | ||
1437 | return PTR_ERR(dfid); | ||
1438 | |||
1439 | oldfid = v9fs_fid_lookup(old_dentry); | ||
1440 | if (IS_ERR(oldfid)) | ||
1441 | return PTR_ERR(oldfid); | ||
1442 | |||
1443 | name = (char *) dentry->d_name.name; | ||
1444 | |||
1445 | err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name); | ||
1446 | |||
1447 | if (err < 0) { | ||
1448 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); | ||
1449 | return err; | ||
1450 | } | ||
1451 | |||
1452 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { | ||
1453 | /* Get the latest stat info from server. */ | ||
1454 | struct p9_fid *fid; | ||
1455 | struct p9_stat_dotl *st; | ||
1456 | |||
1457 | fid = v9fs_fid_lookup(old_dentry); | ||
1458 | if (IS_ERR(fid)) | ||
1459 | return PTR_ERR(fid); | ||
1460 | |||
1461 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | ||
1462 | if (IS_ERR(st)) | ||
1463 | return PTR_ERR(st); | ||
1464 | |||
1465 | v9fs_stat2inode_dotl(st, old_dentry->d_inode); | ||
1466 | |||
1467 | kfree(st); | ||
1468 | } else { | ||
1469 | /* Caching disabled. No need to get upto date stat info. | ||
1470 | * This dentry will be released immediately. So, just i_count++ | ||
1471 | */ | ||
1472 | atomic_inc(&old_dentry->d_inode->i_count); | ||
1473 | } | ||
1474 | |||
1475 | dentry->d_op = old_dentry->d_op; | ||
1476 | d_instantiate(dentry, old_dentry->d_inode); | ||
1477 | |||
1478 | return err; | ||
1479 | } | ||
1480 | |||
1481 | /** | ||
1377 | * v9fs_vfs_mknod - create a special file | 1482 | * v9fs_vfs_mknod - create a special file |
1378 | * @dir: inode destination for new link | 1483 | * @dir: inode destination for new link |
1379 | * @dentry: dentry for file | 1484 | * @dentry: dentry for file |
@@ -1422,7 +1527,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = { | |||
1422 | .create = v9fs_vfs_create, | 1527 | .create = v9fs_vfs_create, |
1423 | .lookup = v9fs_vfs_lookup, | 1528 | .lookup = v9fs_vfs_lookup, |
1424 | .symlink = v9fs_vfs_symlink, | 1529 | .symlink = v9fs_vfs_symlink, |
1425 | .link = v9fs_vfs_link, | 1530 | .link = v9fs_vfs_link_dotl, |
1426 | .unlink = v9fs_vfs_unlink, | 1531 | .unlink = v9fs_vfs_unlink, |
1427 | .mkdir = v9fs_vfs_mkdir, | 1532 | .mkdir = v9fs_vfs_mkdir, |
1428 | .rmdir = v9fs_vfs_rmdir, | 1533 | .rmdir = v9fs_vfs_rmdir, |