7f4c2a
From 86318073e0c3c9747badf26733b66d070b67064e Mon Sep 17 00:00:00 2001
7f4c2a
From: vmallika <vmallika@redhat.com>
7f4c2a
Date: Thu, 27 Aug 2015 11:31:01 +0530
7f4c2a
Subject: [PATCH 309/320] posix: xattrop 'GF_XATTROP_GET_AND_SET' implementation
7f4c2a
7f4c2a
This is a backport of http://review.gluster.org/#/c/11995
7f4c2a
7f4c2a
GF_XATTROP_GET_AND_SET stores the existing xattr
7f4c2a
value in xdata and sets the new value
7f4c2a
7f4c2a
xattrop was reusing input xattr dict to set the results
7f4c2a
instead of creating new dict.
7f4c2a
This can be problem for server side xlators as the inout dict
7f4c2a
will have the value changed.
7f4c2a
7f4c2a
> Change-Id: I43369082e1d0090d211381181e9f3b9075b8e771
7f4c2a
> BUG: 1251454
7f4c2a
> Signed-off-by: vmallika <vmallika@redhat.com>
7f4c2a
7f4c2a
Change-Id: I2033c5bde803f9fd0c1cd39192d51003d22776d3
7f4c2a
BUG: 1251457
7f4c2a
Signed-off-by: vmallika <vmallika@redhat.com>
7f4c2a
Reviewed-on: https://code.engineering.redhat.com/gerrit/56467
7f4c2a
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
7f4c2a
Tested-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
7f4c2a
---
7f4c2a
 libglusterfs/src/glusterfs.h      |    3 +-
7f4c2a
 xlators/storage/posix/src/posix.c |   38 +++++++++++++++++++++++++++++++-----
7f4c2a
 2 files changed, 34 insertions(+), 7 deletions(-)
7f4c2a
7f4c2a
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h
7f4c2a
index 97965ab..87a63db 100644
7f4c2a
--- a/libglusterfs/src/glusterfs.h
7f4c2a
+++ b/libglusterfs/src/glusterfs.h
7f4c2a
@@ -376,7 +376,8 @@ typedef enum {
7f4c2a
         GF_XATTROP_ADD_ARRAY,
7f4c2a
         GF_XATTROP_ADD_ARRAY64,
7f4c2a
         GF_XATTROP_OR_ARRAY,
7f4c2a
-        GF_XATTROP_AND_ARRAY
7f4c2a
+        GF_XATTROP_AND_ARRAY,
7f4c2a
+        GF_XATTROP_GET_AND_SET
7f4c2a
 } gf_xattrop_flags_t;
7f4c2a
 
7f4c2a
 #define GF_SET_IF_NOT_PRESENT 0x1 /* default behaviour */
7f4c2a
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
7f4c2a
index 535e5ff..f1ebcc6 100644
7f4c2a
--- a/xlators/storage/posix/src/posix.c
7f4c2a
+++ b/xlators/storage/posix/src/posix.c
7f4c2a
@@ -4820,6 +4820,7 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
7f4c2a
         int                   op_errno = 0;
7f4c2a
         gf_xattrop_flags_t    optype   = 0;
7f4c2a
         char                 *array    = NULL;
7f4c2a
+        char                 *dst_data = NULL;
7f4c2a
         inode_t              *inode    = NULL;
7f4c2a
         xlator_t             *this     = NULL;
7f4c2a
         posix_xattr_filler_t *filler   = NULL;
7f4c2a
@@ -4883,6 +4884,11 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
7f4c2a
                         goto unlock;
7f4c2a
                 }
7f4c2a
 
7f4c2a
+                if (size == -1 && optype == GF_XATTROP_GET_AND_SET) {
7f4c2a
+                        GF_FREE (array);
7f4c2a
+                        array = NULL;
7f4c2a
+                }
7f4c2a
+
7f4c2a
                 /* We only write back the xattr if it has been really modified
7f4c2a
                  * (i.e. v->data is not all 0's). Otherwise we return its value
7f4c2a
                  * but we don't update anything.
7f4c2a
@@ -4890,7 +4896,8 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
7f4c2a
                  * If the xattr does not exist, a value of all 0's is returned
7f4c2a
                  * without creating it. */
7f4c2a
                 size = v->len;
7f4c2a
-                if (mem_0filled(v->data, v->len) == 0)
7f4c2a
+                if (optype != GF_XATTROP_GET_AND_SET &&
7f4c2a
+                    mem_0filled(v->data, v->len) == 0)
7f4c2a
                         goto unlock;
7f4c2a
 
7f4c2a
                 switch (optype) {
7f4c2a
@@ -4898,12 +4905,18 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
7f4c2a
                 case GF_XATTROP_ADD_ARRAY:
7f4c2a
                         __add_array ((int32_t *) array,
7f4c2a
                                      (int32_t *) v->data, v->len / 4);
7f4c2a
+                        dst_data = array;
7f4c2a
                         break;
7f4c2a
 
7f4c2a
                 case GF_XATTROP_ADD_ARRAY64:
7f4c2a
                         __add_long_array ((int64_t *) array,
7f4c2a
                                           (int64_t *) v->data,
7f4c2a
                                           v->len / 8);
7f4c2a
+                        dst_data = array;
7f4c2a
+                        break;
7f4c2a
+
7f4c2a
+                case GF_XATTROP_GET_AND_SET:
7f4c2a
+                        dst_data = v->data;
7f4c2a
                         break;
7f4c2a
 
7f4c2a
                 default:
7f4c2a
@@ -4919,10 +4932,10 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
7f4c2a
 
7f4c2a
                 if (filler->real_path) {
7f4c2a
                         size = sys_lsetxattr (filler->real_path, k,
7f4c2a
-                                              array, v->len, 0);
7f4c2a
+                                              dst_data, v->len, 0);
7f4c2a
                 } else {
7f4c2a
                         size = sys_fsetxattr (filler->fdnum, k,
7f4c2a
-                                              (char *)array,
7f4c2a
+                                              (char *)dst_data,
7f4c2a
                                               v->len, 0);
7f4c2a
                 }
7f4c2a
                 op_errno = errno;
7f4c2a
@@ -4948,8 +4961,8 @@ unlock:
7f4c2a
                                 k, strerror (op_errno));
7f4c2a
                 op_ret = -1;
7f4c2a
                 goto out;
7f4c2a
-        } else {
7f4c2a
-                size = dict_set_bin (d, k, array, v->len);
7f4c2a
+        } else if (array) {
7f4c2a
+                size = dict_set_bin (filler->xattr, k, array, v->len);
7f4c2a
 
7f4c2a
                 if (size != 0) {
7f4c2a
                         if (filler->real_path)
7f4c2a
@@ -4999,6 +5012,7 @@ do_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd,
7f4c2a
         struct posix_fd      *pfd       = NULL;
7f4c2a
         inode_t              *inode     = NULL;
7f4c2a
         posix_xattr_filler_t  filler    = {0,};
7f4c2a
+        dict_t               *xdata     = NULL;
7f4c2a
 
7f4c2a
         VALIDATE_OR_GOTO (frame, out);
7f4c2a
         VALIDATE_OR_GOTO (xattr, out);
7f4c2a
@@ -5031,11 +5045,19 @@ do_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd,
7f4c2a
                 inode = fd->inode;
7f4c2a
         }
7f4c2a
 
7f4c2a
+        xdata = dict_new ();
7f4c2a
+        if (xdata == NULL) {
7f4c2a
+                op_ret = -1;
7f4c2a
+                op_errno = ENOMEM;
7f4c2a
+                goto out;
7f4c2a
+        }
7f4c2a
+
7f4c2a
         filler.this = this;
7f4c2a
         filler.fdnum = _fd;
7f4c2a
         filler.real_path = real_path;
7f4c2a
         filler.flags = (int)optype;
7f4c2a
         filler.inode = inode;
7f4c2a
+        filler.xattr = xdata;
7f4c2a
 
7f4c2a
         op_ret = dict_foreach (xattr, _posix_handle_xattr_keyvalue_pair,
7f4c2a
                                &filler);
7f4c2a
@@ -5043,7 +5065,11 @@ do_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd,
7f4c2a
 
7f4c2a
 out:
7f4c2a
 
7f4c2a
-        STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, xattr, NULL);
7f4c2a
+        STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, xdata, xdata);
7f4c2a
+
7f4c2a
+        if (xdata)
7f4c2a
+                dict_unref (xdata);
7f4c2a
+
7f4c2a
         return 0;
7f4c2a
 }
7f4c2a
 
7f4c2a
-- 
7f4c2a
1.7.1
7f4c2a