summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2016-04-21 12:11:54 +0800
committerIlya Dryomov <idryomov@gmail.com>2016-05-26 01:15:33 +0200
commit04303d8ad06985bed4ea4f46018fc8f55a0962a8 (patch)
tree1d0c59cb25abf8882c3d8d084f28cb04bd2125fe
parent3f38495409b613071021fca86629df7ae81820ad (diff)
ceph: use CEPH_MDS_OP_RMXATTR request to remove xattr
Setxattr with NULL value and XATTR_REPLACE flag should be equivalent to removexattr. But current MDS does not support deleting vxattrs through MDS_OP_SETXATTR request. The workaround is sending MDS_OP_RMXATTR request if setxattr actually removs xattr. Signed-off-by: Yan, Zheng <zyan@redhat.com>
-rw-r--r--fs/ceph/xattr.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 5afabc4bf4c7..426c83cc683a 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -886,6 +886,7 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
struct ceph_mds_request *req;
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_pagelist *pagelist = NULL;
+ int op = CEPH_MDS_OP_SETXATTR;
int err;
if (size > 0) {
@@ -899,20 +900,21 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
if (err)
goto out;
} else if (!value) {
- flags |= CEPH_XATTR_REMOVE;
+ if (flags & CEPH_XATTR_REPLACE)
+ op = CEPH_MDS_OP_RMXATTR;
+ else
+ flags |= CEPH_XATTR_REMOVE;
}
dout("setxattr value=%.*s\n", (int)size, value);
/* do request */
- req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SETXATTR,
- USE_AUTH_MDS);
+ req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
if (IS_ERR(req)) {
err = PTR_ERR(req);
goto out;
}
- req->r_args.setxattr.flags = cpu_to_le32(flags);
req->r_path2 = kstrdup(name, GFP_NOFS);
if (!req->r_path2) {
ceph_mdsc_put_request(req);
@@ -920,8 +922,11 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
goto out;
}
- req->r_pagelist = pagelist;
- pagelist = NULL;
+ if (op == CEPH_MDS_OP_SETXATTR) {
+ req->r_args.setxattr.flags = cpu_to_le32(flags);
+ req->r_pagelist = pagelist;
+ pagelist = NULL;
+ }
req->r_inode = inode;
ihold(inode);