aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)