diff options
| -rw-r--r-- | fs/9p/vfs_inode.c | 48 | ||||
| -rw-r--r-- | include/net/9p/9p.h | 2 | ||||
| -rw-r--r-- | include/net/9p/client.h | 1 | ||||
| -rw-r--r-- | net/9p/client.c | 23 | 
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,  /**   * v9fs_remove - helper function to remove files and directories   * @dir: directory inode that is being deleted - * @file:  dentry that is being deleted + * @dentry:  dentry that is being deleted   * @rmdir: removing a directory   *   */ -static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) +static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)  { -	int retval; -	struct p9_fid *v9fid; -	struct inode *file_inode; - -	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, -		rmdir); +	struct inode *inode; +	int retval = -EOPNOTSUPP; +	struct p9_fid *v9fid, *dfid; +	struct v9fs_session_info *v9ses; -	file_inode = file->d_inode; -	v9fid = v9fs_fid_clone(file); -	if (IS_ERR(v9fid)) -		return PTR_ERR(v9fid); +	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n", +		   dir, dentry, flags); -	retval = p9_client_remove(v9fid); +	v9ses = v9fs_inode2v9ses(dir); +	inode = dentry->d_inode; +	dfid = v9fs_fid_lookup(dentry->d_parent); +	if (IS_ERR(dfid)) { +		retval = PTR_ERR(dfid); +		P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", retval); +		return retval; +	} +	if (v9fs_proto_dotl(v9ses)) +		retval = p9_client_unlinkat(dfid, dentry->d_name.name, flags); +	if (retval == -EOPNOTSUPP) { +		/* Try the one based on path */ +		v9fid = v9fs_fid_clone(dentry); +		if (IS_ERR(v9fid)) +			return PTR_ERR(v9fid); +		retval = p9_client_remove(v9fid); +	}  	if (!retval) {  		/*  		 * directories on unlink should have zero  		 * link count  		 */ -		if (rmdir) { -			clear_nlink(file_inode); +		if (flags & AT_REMOVEDIR) { +			clear_nlink(inode);  			drop_nlink(dir);  		} else -			drop_nlink(file_inode); +			drop_nlink(inode); -		v9fs_invalidate_inode_attr(file_inode); +		v9fs_invalidate_inode_attr(inode);  		v9fs_invalidate_inode_attr(dir);  	}  	return retval; @@ -856,7 +868,7 @@ int v9fs_vfs_unlink(struct inode *i, struct dentry *d)  int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)  { -	return v9fs_remove(i, d, 1); +	return v9fs_remove(i, d, AT_REMOVEDIR);  }  /** 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 {  	P9_RMKDIR,  	P9_TRENAMEAT = 74,  	P9_RRENAMEAT, +	P9_TUNLINKAT = 76, +	P9_RUNLINKAT,  	P9_TVERSION = 100,  	P9_RVERSION,  	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,  int p9_client_clunk(struct p9_fid *fid);  int p9_client_fsync(struct p9_fid *fid, int datasync);  int p9_client_remove(struct p9_fid *fid); +int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);  int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,  							u64 offset, u32 count);  int 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:  }  EXPORT_SYMBOL(p9_client_remove); +int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags) +{ +	int err = 0; +	struct p9_req_t *req; +	struct p9_client *clnt; + +	P9_DPRINTK(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n", +		   dfid->fid, name, flags); + +	clnt = dfid->clnt; +	req = p9_client_rpc(clnt, P9_TUNLINKAT, "dsd", dfid->fid, name, flags); +	if (IS_ERR(req)) { +		err = PTR_ERR(req); +		goto error; +	} +	P9_DPRINTK(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name); + +	p9_free_req(clnt, req); +error: +	return err; +} +EXPORT_SYMBOL(p9_client_unlinkat); +  int  p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,  								u32 count) | 
