Blob Blame History Raw
From 86318073e0c3c9747badf26733b66d070b67064e Mon Sep 17 00:00:00 2001
From: vmallika <vmallika@redhat.com>
Date: Thu, 27 Aug 2015 11:31:01 +0530
Subject: [PATCH 309/320] posix: xattrop 'GF_XATTROP_GET_AND_SET' implementation

This is a backport of http://review.gluster.org/#/c/11995

GF_XATTROP_GET_AND_SET stores the existing xattr
value in xdata and sets the new value

xattrop was reusing input xattr dict to set the results
instead of creating new dict.
This can be problem for server side xlators as the inout dict
will have the value changed.

> Change-Id: I43369082e1d0090d211381181e9f3b9075b8e771
> BUG: 1251454
> Signed-off-by: vmallika <vmallika@redhat.com>

Change-Id: I2033c5bde803f9fd0c1cd39192d51003d22776d3
BUG: 1251457
Signed-off-by: vmallika <vmallika@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/56467
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
Tested-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
---
 libglusterfs/src/glusterfs.h      |    3 +-
 xlators/storage/posix/src/posix.c |   38 +++++++++++++++++++++++++++++++-----
 2 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h
index 97965ab..87a63db 100644
--- a/libglusterfs/src/glusterfs.h
+++ b/libglusterfs/src/glusterfs.h
@@ -376,7 +376,8 @@ typedef enum {
         GF_XATTROP_ADD_ARRAY,
         GF_XATTROP_ADD_ARRAY64,
         GF_XATTROP_OR_ARRAY,
-        GF_XATTROP_AND_ARRAY
+        GF_XATTROP_AND_ARRAY,
+        GF_XATTROP_GET_AND_SET
 } gf_xattrop_flags_t;
 
 #define GF_SET_IF_NOT_PRESENT 0x1 /* default behaviour */
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 535e5ff..f1ebcc6 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -4820,6 +4820,7 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
         int                   op_errno = 0;
         gf_xattrop_flags_t    optype   = 0;
         char                 *array    = NULL;
+        char                 *dst_data = NULL;
         inode_t              *inode    = NULL;
         xlator_t             *this     = NULL;
         posix_xattr_filler_t *filler   = NULL;
@@ -4883,6 +4884,11 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
                         goto unlock;
                 }
 
+                if (size == -1 && optype == GF_XATTROP_GET_AND_SET) {
+                        GF_FREE (array);
+                        array = NULL;
+                }
+
                 /* We only write back the xattr if it has been really modified
                  * (i.e. v->data is not all 0's). Otherwise we return its value
                  * but we don't update anything.
@@ -4890,7 +4896,8 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
                  * If the xattr does not exist, a value of all 0's is returned
                  * without creating it. */
                 size = v->len;
-                if (mem_0filled(v->data, v->len) == 0)
+                if (optype != GF_XATTROP_GET_AND_SET &&
+                    mem_0filled(v->data, v->len) == 0)
                         goto unlock;
 
                 switch (optype) {
@@ -4898,12 +4905,18 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
                 case GF_XATTROP_ADD_ARRAY:
                         __add_array ((int32_t *) array,
                                      (int32_t *) v->data, v->len / 4);
+                        dst_data = array;
                         break;
 
                 case GF_XATTROP_ADD_ARRAY64:
                         __add_long_array ((int64_t *) array,
                                           (int64_t *) v->data,
                                           v->len / 8);
+                        dst_data = array;
+                        break;
+
+                case GF_XATTROP_GET_AND_SET:
+                        dst_data = v->data;
                         break;
 
                 default:
@@ -4919,10 +4932,10 @@ _posix_handle_xattr_keyvalue_pair (dict_t *d, char *k, data_t *v,
 
                 if (filler->real_path) {
                         size = sys_lsetxattr (filler->real_path, k,
-                                              array, v->len, 0);
+                                              dst_data, v->len, 0);
                 } else {
                         size = sys_fsetxattr (filler->fdnum, k,
-                                              (char *)array,
+                                              (char *)dst_data,
                                               v->len, 0);
                 }
                 op_errno = errno;
@@ -4948,8 +4961,8 @@ unlock:
                                 k, strerror (op_errno));
                 op_ret = -1;
                 goto out;
-        } else {
-                size = dict_set_bin (d, k, array, v->len);
+        } else if (array) {
+                size = dict_set_bin (filler->xattr, k, array, v->len);
 
                 if (size != 0) {
                         if (filler->real_path)
@@ -4999,6 +5012,7 @@ do_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd,
         struct posix_fd      *pfd       = NULL;
         inode_t              *inode     = NULL;
         posix_xattr_filler_t  filler    = {0,};
+        dict_t               *xdata     = NULL;
 
         VALIDATE_OR_GOTO (frame, out);
         VALIDATE_OR_GOTO (xattr, out);
@@ -5031,11 +5045,19 @@ do_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd,
                 inode = fd->inode;
         }
 
+        xdata = dict_new ();
+        if (xdata == NULL) {
+                op_ret = -1;
+                op_errno = ENOMEM;
+                goto out;
+        }
+
         filler.this = this;
         filler.fdnum = _fd;
         filler.real_path = real_path;
         filler.flags = (int)optype;
         filler.inode = inode;
+        filler.xattr = xdata;
 
         op_ret = dict_foreach (xattr, _posix_handle_xattr_keyvalue_pair,
                                &filler);
@@ -5043,7 +5065,11 @@ do_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd,
 
 out:
 
-        STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, xattr, NULL);
+        STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, xdata, xdata);
+
+        if (xdata)
+                dict_unref (xdata);
+
         return 0;
 }
 
-- 
1.7.1