ceph: use CEPH_MDS_OP_RMXATTR request to remove xattr
authorYan, Zheng <zyan@redhat.com>
Thu, 21 Apr 2016 04:11:54 +0000 (12:11 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Wed, 25 May 2016 23:15:33 +0000 (01:15 +0200)
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>
fs/ceph/xattr.c

index 5afabc4bf4c7137fdba4410dc136f8e182398266..426c83cc683a324368556de34bfc978b290f7096 100644 (file)
@@ -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);