diff options
-rw-r--r-- | libglusterfs/src/glusterfs.h | 3 | ||||
-rw-r--r-- | 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 3e3d0b02dd1..18ffbb1f2b1 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -372,7 +372,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 ffb9f764c99..9da1cda3411 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -4841,6 +4841,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; @@ -4904,6 +4905,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. @@ -4911,7 +4917,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) { @@ -4919,12 +4926,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: @@ -4940,10 +4953,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; @@ -4969,8 +4982,8 @@ unlock: k, strerror (op_errno)); op_ret = -1; goto out; - } else { - op_ret = dict_set_bin (d, k, array, v->len); + } else if (array) { + op_ret = dict_set_bin (filler->xattr, k, array, v->len); if (op_ret) { if (filler->real_path) gf_msg_debug (this->name, 0, @@ -5020,6 +5033,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); @@ -5052,11 +5066,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); @@ -5064,7 +5086,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; } |