aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2011-06-28 06:11:18 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2011-07-23 10:32:52 -0400
commit48e370ff93769ee6e592ddef3bb38686b8147c67 (patch)
tree045a8b0c905be07df33ae06d776e972448a6e447
parent9e8fb38e7d7a00e5f63bbb331f0ea4c02286d5e6 (diff)
fs/9p: add 9P2000.L unlinkat operation
unlinkat - Remove a directory entry size[4] Tunlinkat tag[2] dirfid[4] name[s] flag[4] size[4] Runlinkat tag[2] older Tremove have the below request format size[4] Tremove tag[2] fid[4] The remove message is used to remove a directory entry either file or directory The remove opreation is actually a directory opertation and should ideally have dirfid, if not we cannot represent the fid on server with anything other than name. We will have to derive the directory name from fid in the Tremove request. NOTE: The operation doesn't clunk the unlink fid. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--fs/9p/vfs_inode.c48
-rw-r--r--include/net/9p/9p.h2
-rw-r--r--include/net/9p/client.h1
-rw-r--r--net/9p/client.c23
4 files changed, 56 insertions, 18 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index bce66f56c62c..8bb5507e822f 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -534,38 +534,50 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
534/** 534/**
535 * v9fs_remove - helper function to remove files and directories 535 * v9fs_remove - helper function to remove files and directories
536 * @dir: directory inode that is being deleted 536 * @dir: directory inode that is being deleted
537 * @file: dentry that is being deleted 537 * @dentry: dentry that is being deleted
538 * @rmdir: removing a directory 538 * @rmdir: removing a directory
539 * 539 *
540 */ 540 */
541 541
542static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) 542static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
543{ 543{
544 int retval; 544 struct inode *inode;
545 struct p9_fid *v9fid; 545 int retval = -EOPNOTSUPP;
546 struct inode *file_inode; 546 struct p9_fid *v9fid, *dfid;
547 547 struct v9fs_session_info *v9ses;
548 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
549 rmdir);
550 548
551 file_inode = file->d_inode; 549 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
552 v9fid = v9fs_fid_clone(file); 550 dir, dentry, flags);
553 if (IS_ERR(v9fid))
554 return PTR_ERR(v9fid);
555 551
556 retval = p9_client_remove(v9fid); 552 v9ses = v9fs_inode2v9ses(dir);
553 inode = dentry->d_inode;
554 dfid = v9fs_fid_lookup(dentry->d_parent);
555 if (IS_ERR(dfid)) {
556 retval = PTR_ERR(dfid);
557 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
558 return retval;
559 }
560 if (v9fs_proto_dotl(v9ses))
561 retval = p9_client_unlinkat(dfid, dentry->d_name.name, flags);
562 if (retval == -EOPNOTSUPP) {
563 /* Try the one based on path */
564 v9fid = v9fs_fid_clone(dentry);
565 if (IS_ERR(v9fid))
566 return PTR_ERR(v9fid);
567 retval = p9_client_remove(v9fid);
568 }
557 if (!retval) { 569 if (!retval) {
558 /* 570 /*
559 * directories on unlink should have zero 571 * directories on unlink should have zero
560 * link count 572 * link count
561 */ 573 */
562 if (rmdir) { 574 if (flags & AT_REMOVEDIR) {
563 clear_nlink(file_inode); 575 clear_nlink(inode);
564 drop_nlink(dir); 576 drop_nlink(dir);
565 } else 577 } else
566 drop_nlink(file_inode); 578 drop_nlink(inode);
567 579
568 v9fs_invalidate_inode_attr(file_inode); 580 v9fs_invalidate_inode_attr(inode);
569 v9fs_invalidate_inode_attr(dir); 581 v9fs_invalidate_inode_attr(dir);
570 } 582 }
571 return retval; 583 return retval;
@@ -856,7 +868,7 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
856 868
857int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) 869int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
858{ 870{
859 return v9fs_remove(i, d, 1); 871 return v9fs_remove(i, d, AT_REMOVEDIR);
860} 872}
861 873
862/** 874/**
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 61156207c98c..342dcf13d039 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -183,6 +183,8 @@ enum p9_msg_t {
183 P9_RMKDIR, 183 P9_RMKDIR,
184 P9_TRENAMEAT = 74, 184 P9_TRENAMEAT = 74,
185 P9_RRENAMEAT, 185 P9_RRENAMEAT,
186 P9_TUNLINKAT = 76,
187 P9_RUNLINKAT,
186 P9_TVERSION = 100, 188 P9_TVERSION = 100,
187 P9_RVERSION, 189 P9_RVERSION,
188 P9_TAUTH = 102, 190 P9_TAUTH = 102,
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 62ceddf9994a..55ce72ce9861 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -234,6 +234,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
234int p9_client_clunk(struct p9_fid *fid); 234int p9_client_clunk(struct p9_fid *fid);
235int p9_client_fsync(struct p9_fid *fid, int datasync); 235int p9_client_fsync(struct p9_fid *fid, int datasync);
236int p9_client_remove(struct p9_fid *fid); 236int p9_client_remove(struct p9_fid *fid);
237int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
237int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, 238int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
238 u64 offset, u32 count); 239 u64 offset, u32 count);
239int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, 240int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
diff --git a/net/9p/client.c b/net/9p/client.c
index c4b77f383582..a953baa3624e 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1303,6 +1303,29 @@ error:
1303} 1303}
1304EXPORT_SYMBOL(p9_client_remove); 1304EXPORT_SYMBOL(p9_client_remove);
1305 1305
1306int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags)
1307{
1308 int err = 0;
1309 struct p9_req_t *req;
1310 struct p9_client *clnt;
1311
1312 P9_DPRINTK(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n",
1313 dfid->fid, name, flags);
1314
1315 clnt = dfid->clnt;
1316 req = p9_client_rpc(clnt, P9_TUNLINKAT, "dsd", dfid->fid, name, flags);
1317 if (IS_ERR(req)) {
1318 err = PTR_ERR(req);
1319 goto error;
1320 }
1321 P9_DPRINTK(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name);
1322
1323 p9_free_req(clnt, req);
1324error:
1325 return err;
1326}
1327EXPORT_SYMBOL(p9_client_unlinkat);
1328
1306int 1329int
1307p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, 1330p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1308 u32 count) 1331 u32 count)