md-cache: Do not invalidate cache post set/remove xattr
Since setxattr and removexattr fops cbk do not carry poststat, the stat cache was being invalidated in setxatr/remoxattr cbk. Hence the further lookup wouldn't be served from cache. To prevent this invalidation, md-cache is modified to get the poststat in set/removexattr_cbk in dict. Co-authored with Xavi Hernandez. Change-Id: I6b946be2d20b807e2578825743c25ba5927a60b4 fixes: bz#1586018 Signed-off-by: Xavi Hernandez <xhernandez@redhat.com> Signed-off-by: Poornima G <pgurusid@redhat.com>
This commit is contained in:
committed by
Amar Tumballi
parent
af6c6429f9
commit
69f77d28c3
@ -132,6 +132,8 @@ int32_t
|
||||
is_data_equal (data_t *one,
|
||||
data_t *two)
|
||||
{
|
||||
struct iatt *iatt1, *iatt2;
|
||||
|
||||
if (!one || !two || !one->data || !two->data) {
|
||||
gf_msg_callingfn ("dict", GF_LOG_ERROR, EINVAL,
|
||||
LG_MSG_INVALID_ARG,
|
||||
@ -143,12 +145,64 @@ is_data_equal (data_t *one,
|
||||
if (one == two)
|
||||
return 1;
|
||||
|
||||
if (one->len != two->len)
|
||||
return 0;
|
||||
|
||||
if (one->data == two->data)
|
||||
return 1;
|
||||
|
||||
if (one->data_type != two->data_type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (one->data_type == GF_DATA_TYPE_IATT) {
|
||||
if ((one->len < sizeof(struct iatt)) ||
|
||||
(two->len < sizeof(struct iatt))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
iatt1 = (struct iatt *)one->data;
|
||||
iatt2 = (struct iatt *)two->data;
|
||||
|
||||
/* Two iatt structs are considered equal if main fields are
|
||||
* equal, even if times differ.
|
||||
* TODO: maybe when ctime if fully operational we could
|
||||
* enforce time matching. */
|
||||
if (iatt1->ia_ino != iatt2->ia_ino) {
|
||||
return 0;
|
||||
}
|
||||
if (iatt1->ia_type != iatt2->ia_type) {
|
||||
return 0;
|
||||
}
|
||||
if ((iatt1->ia_type == IA_IFBLK) ||
|
||||
(iatt1->ia_type == IA_IFCHR)) {
|
||||
if (iatt1->ia_rdev != iatt2->ia_rdev) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (gf_uuid_compare(iatt1->ia_gfid, iatt2->ia_gfid) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: ia_uid, ia_gid, ia_prot and ia_size can be changed
|
||||
* with some commands. Here we don't have enough
|
||||
* information to decide if they should match or not. */
|
||||
/*
|
||||
if ((iatt1->ia_uid != iatt2->ia_uid) ||
|
||||
(iatt1->ia_gid != iatt2->ia_gid) ||
|
||||
(st_mode_from_ia(iatt1->ia_prot, iatt1->ia_type) !=
|
||||
st_mode_from_ia(iatt2->ia_prot, iatt2->ia_type))) {
|
||||
return 0;
|
||||
}
|
||||
if (iatt1->ia_type == IA_IFREG) {
|
||||
if (iatt1->ia_size != iatt2->ia_size) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (one->len != two->len)
|
||||
return 0;
|
||||
|
||||
if (memcmp (one->data, two->data, one->len) == 0)
|
||||
return 1;
|
||||
|
||||
@ -1196,6 +1250,25 @@ data_to_bin (data_t *data)
|
||||
return data->data;
|
||||
}
|
||||
|
||||
struct iatt *
|
||||
data_to_iatt (data_t *data, char *key)
|
||||
{
|
||||
VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_IATT, key, NULL);
|
||||
|
||||
/* We only check for smaller size. If it's bigger we simply ignore
|
||||
* the extra data. This way it's easy to do changes in the future that
|
||||
* pass more data but are backward compatible (if the initial contents
|
||||
* of the struct are maintained, of course). */
|
||||
if (data->len < sizeof(struct iatt)) {
|
||||
gf_msg("glusterfs", GF_LOG_ERROR, ENOBUFS,
|
||||
LG_MSG_UNDERSIZED_BUF,
|
||||
"data value for '%s' is smaller than expected", key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (struct iatt *)data->data;
|
||||
}
|
||||
|
||||
int
|
||||
dict_null_foreach_fn (dict_t *d, char *k,
|
||||
data_t *v, void *tmp)
|
||||
|
@ -166,6 +166,7 @@ char *data_to_str (data_t *data);
|
||||
void *data_to_bin (data_t *data);
|
||||
void *data_to_ptr (data_t *data);
|
||||
data_t * data_copy (data_t *old);
|
||||
struct iatt *data_to_iatt (data_t *data, char *key);
|
||||
|
||||
int dict_foreach (dict_t *this,
|
||||
int (*fn)(dict_t *this,
|
||||
|
@ -321,6 +321,8 @@ enum gf_internal_fop_indicator {
|
||||
#define DHT_MODE_IN_XDATA_KEY "dht-get-mode-in-xattr"
|
||||
#define GET_LINK_COUNT "get-link-count"
|
||||
#define GF_GET_SIZE "get-size"
|
||||
#define GF_PRESTAT "virt-gf-prestat"
|
||||
#define GF_POSTSTAT "virt-gf-poststat"
|
||||
|
||||
/*CTR and Marker requires inode dentry link count from posix*/
|
||||
#define GF_RESPONSE_LINK_COUNT_XDATA "gf_response_link_count"
|
||||
|
@ -147,6 +147,7 @@ data_to_uint16
|
||||
data_to_uint32
|
||||
data_to_uint64
|
||||
data_to_uint8
|
||||
data_to_iatt
|
||||
data_unref
|
||||
default_access
|
||||
default_access_cbk
|
||||
|
38
tests/bugs/md-cache/setxattr-prepoststat.t
Executable file
38
tests/bugs/md-cache/setxattr-prepoststat.t
Executable file
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
. $(dirname $0)/../../include.rc
|
||||
. $(dirname $0)/../../volume.rc
|
||||
|
||||
cleanup;
|
||||
|
||||
## 1. Start glusterd
|
||||
TEST glusterd;
|
||||
|
||||
## 2. Lets create volume
|
||||
TEST $CLI volume create $V0 disperse 6 redundancy 2 $H0:$B0/${V0}{0..5}
|
||||
|
||||
TEST $CLI volume set $V0 group metadata-cache
|
||||
TEST $CLI volume set $V0 performance.xattr-cache-list "user.*"
|
||||
TEST $CLI volume start $V0
|
||||
|
||||
TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0
|
||||
TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M1
|
||||
|
||||
TEST touch $M0/file1
|
||||
TEST `echo "abakjshdjahskjdhakjhdskjac" >> $M0/file1`
|
||||
size=`stat -c '%s' $M0/file1`
|
||||
|
||||
## Setxattr from mount-0
|
||||
TEST "setfattr -n user.DOSATTRIB -v "abc" $M0/file1"
|
||||
EXPECT $size stat -c '%s' $M0/file1
|
||||
|
||||
## Getxattr from mount-1, this should return the correct value
|
||||
TEST "getfattr -n user.DOSATTRIB $M1/file1 | grep -q abc"
|
||||
|
||||
TEST "setfattr -x user.DOSATTRIB $M1/file1"
|
||||
EXPECT $size stat -c '%s' $M1/file1
|
||||
|
||||
EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
|
||||
EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M1
|
||||
|
||||
cleanup;
|
@ -5558,9 +5558,9 @@ dht_file_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
out:
|
||||
|
||||
if (local->fop == GF_FOP_SETXATTR) {
|
||||
DHT_STACK_UNWIND (setxattr, frame, op_ret, op_errno, NULL);
|
||||
DHT_STACK_UNWIND (setxattr, frame, op_ret, op_errno, xdata);
|
||||
} else {
|
||||
DHT_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno, NULL);
|
||||
DHT_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno, xdata);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -259,6 +259,7 @@ ec_value_ignore (char *key)
|
||||
(XATTR_IS_NODE_UUID(key))) {
|
||||
return _gf_true;
|
||||
}
|
||||
|
||||
return _gf_false;
|
||||
}
|
||||
|
||||
@ -554,6 +555,64 @@ int32_t ec_dict_data_uuid(ec_cbk_data_t * cbk, int32_t which, char * key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ec_dict_data_iatt(ec_cbk_data_t *cbk, int32_t which, char *key)
|
||||
{
|
||||
ec_t *ec = cbk->fop->xl->private;
|
||||
data_t *data[ec->nodes];
|
||||
dict_t *dict;
|
||||
struct iatt *stbuf, *tmp;
|
||||
int32_t i, ret;
|
||||
|
||||
ec_dict_list(data, cbk, which, key, _gf_false);
|
||||
|
||||
stbuf = NULL;
|
||||
for (i = 0; i < ec->nodes; i++) {
|
||||
if ((data[i] == NULL) || (data[i] == EC_MISSING_DATA)) {
|
||||
continue;
|
||||
}
|
||||
tmp = data_to_iatt(data[i], key);
|
||||
if (tmp == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (stbuf == NULL) {
|
||||
stbuf = GF_MALLOC(sizeof(struct iatt), gf_common_mt_char);
|
||||
if (stbuf == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
*stbuf = *tmp;
|
||||
} else {
|
||||
if (!ec_iatt_combine (cbk->fop, stbuf, tmp, 1)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stbuf->ia_type == IA_IFREG) {
|
||||
ec_iatt_rebuild(ec, stbuf, 1, cbk->count);
|
||||
/* TODO: not sure if an iatt could come in xdata from a fop that takes
|
||||
* no locks. */
|
||||
if (!ec_get_inode_size(cbk->fop, cbk->fop->locks[0].lock->loc.inode,
|
||||
&stbuf->ia_size)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict;
|
||||
ret = dict_set_iatt(dict, key, stbuf, false);
|
||||
if (ret >= 0) {
|
||||
stbuf = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
GF_FREE(stbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t ec_dict_data_max32(ec_cbk_data_t *cbk, int32_t which, char *key)
|
||||
{
|
||||
ec_t *ec = cbk->fop->xl->private;
|
||||
@ -736,6 +795,10 @@ int32_t ec_dict_data_combine(dict_t * dict, char * key, data_t * value,
|
||||
return ec_dict_data_max64(data->cbk, data->which, key);
|
||||
}
|
||||
|
||||
if (strcmp (key, GF_PRESTAT) == 0 || strcmp (key, GF_POSTSTAT) == 0) {
|
||||
return ec_dict_data_iatt(data->cbk, data->which, key);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "common-utils.h"
|
||||
|
||||
#include "statedump.h"
|
||||
#include "syncop.h"
|
||||
|
||||
#include "upcall.h"
|
||||
#include "upcall-mem-types.h"
|
||||
@ -1697,8 +1696,7 @@ up_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
if (!up_invalidate_needed (local->xattr))
|
||||
goto out;
|
||||
|
||||
ret = syncop_stat (FIRST_CHILD(frame->this), &local->loc, &stbuf,
|
||||
NULL, NULL);
|
||||
ret = dict_get_iatt (xdata, GF_POSTSTAT, &stbuf);
|
||||
if (ret == 0)
|
||||
flags |= UP_TIMES;
|
||||
|
||||
@ -1774,8 +1772,7 @@ up_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
if (!up_invalidate_needed (local->xattr))
|
||||
goto out;
|
||||
|
||||
ret = syncop_fstat (FIRST_CHILD(frame->this), local->fd, &stbuf, NULL,
|
||||
NULL);
|
||||
ret = dict_get_iatt (xdata, GF_POSTSTAT, &stbuf);
|
||||
if (ret == 0)
|
||||
flags |= UP_TIMES;
|
||||
|
||||
@ -1850,8 +1847,7 @@ up_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
if (!up_invalidate_needed (local->xattr))
|
||||
goto out;
|
||||
|
||||
ret = syncop_fstat (FIRST_CHILD(frame->this), local->fd, &stbuf, NULL,
|
||||
NULL);
|
||||
ret = dict_get_iatt (xdata, GF_POSTSTAT, &stbuf);
|
||||
if (ret == 0)
|
||||
flags |= UP_TIMES;
|
||||
|
||||
@ -1938,8 +1934,7 @@ up_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
if (!up_invalidate_needed (local->xattr))
|
||||
goto out;
|
||||
|
||||
ret = syncop_stat (FIRST_CHILD(frame->this), &local->loc, &stbuf, NULL,
|
||||
NULL);
|
||||
ret = dict_get_iatt (xdata, GF_POSTSTAT, &stbuf);
|
||||
if (ret == 0)
|
||||
flags |= UP_TIMES;
|
||||
|
||||
|
@ -2157,6 +2157,9 @@ mdc_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, dict_t *xdata)
|
||||
{
|
||||
mdc_local_t *local = NULL;
|
||||
struct iatt prestat = {0,};
|
||||
struct iatt poststat = {0,};
|
||||
int ret = 0;
|
||||
|
||||
local = frame->local;
|
||||
if (!local)
|
||||
@ -2170,7 +2173,15 @@ mdc_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
|
||||
mdc_inode_xatt_update (this, local->loc.inode, local->xattr);
|
||||
|
||||
mdc_inode_iatt_invalidate (this, local->loc.inode);
|
||||
ret = dict_get_iatt (xdata, GF_PRESTAT, &prestat);
|
||||
if (ret >= 0) {
|
||||
ret = dict_get_iatt (xdata, GF_POSTSTAT, &poststat);
|
||||
mdc_inode_iatt_set_validate (this, local->loc.inode, &prestat,
|
||||
&poststat, _gf_true);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
mdc_inode_iatt_invalidate (this, local->loc.inode);
|
||||
|
||||
out:
|
||||
MDC_STACK_UNWIND (setxattr, frame, op_ret, op_errno, xdata);
|
||||
@ -2193,6 +2204,7 @@ mdc_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
|
||||
STACK_WIND (frame, mdc_setxattr_cbk,
|
||||
FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr,
|
||||
loc, xattr, flags, xdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2202,6 +2214,9 @@ mdc_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, dict_t *xdata)
|
||||
{
|
||||
mdc_local_t *local = NULL;
|
||||
struct iatt prestat = {0,};
|
||||
struct iatt poststat = {0,};
|
||||
int ret = 0;
|
||||
|
||||
local = frame->local;
|
||||
if (!local)
|
||||
@ -2215,7 +2230,16 @@ mdc_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
|
||||
mdc_inode_xatt_update (this, local->fd->inode, local->xattr);
|
||||
|
||||
mdc_inode_iatt_invalidate (this, local->fd->inode);
|
||||
ret = dict_get_iatt (xdata, GF_PRESTAT, &prestat);
|
||||
if (ret >= 0) {
|
||||
ret = dict_get_iatt (xdata, GF_POSTSTAT, &poststat);
|
||||
mdc_inode_iatt_set_validate (this, local->fd->inode, &prestat,
|
||||
&poststat, _gf_true);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
mdc_inode_iatt_invalidate (this, local->fd->inode);
|
||||
|
||||
out:
|
||||
MDC_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno, xdata);
|
||||
|
||||
@ -2237,6 +2261,7 @@ mdc_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd,
|
||||
STACK_WIND (frame, mdc_fsetxattr_cbk,
|
||||
FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsetxattr,
|
||||
fd, xattr, flags, xdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2380,6 +2405,9 @@ mdc_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, dict_t *xdata)
|
||||
{
|
||||
mdc_local_t *local = NULL;
|
||||
struct iatt prestat = {0,};
|
||||
struct iatt poststat = {0,};
|
||||
int ret = 0;
|
||||
|
||||
local = frame->local;
|
||||
if (!local)
|
||||
@ -2396,7 +2424,15 @@ mdc_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
else
|
||||
mdc_inode_xatt_invalidate (this, local->loc.inode);
|
||||
|
||||
mdc_inode_iatt_invalidate (this, local->loc.inode);
|
||||
ret = dict_get_iatt (xdata, GF_PRESTAT, &prestat);
|
||||
if (ret >= 0) {
|
||||
ret = dict_get_iatt (xdata, GF_POSTSTAT, &poststat);
|
||||
mdc_inode_iatt_set_validate (this, local->loc.inode, &prestat,
|
||||
&poststat, _gf_true);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
mdc_inode_iatt_invalidate (this, local->loc.inode);
|
||||
out:
|
||||
MDC_STACK_UNWIND (removexattr, frame, op_ret, op_errno, xdata);
|
||||
|
||||
@ -2451,6 +2487,9 @@ mdc_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, dict_t *xdata)
|
||||
{
|
||||
mdc_local_t *local = NULL;
|
||||
struct iatt prestat = {0,};
|
||||
struct iatt poststat = {0,};
|
||||
int ret = 0;
|
||||
|
||||
local = frame->local;
|
||||
if (!local)
|
||||
@ -2467,7 +2506,16 @@ mdc_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
else
|
||||
mdc_inode_xatt_invalidate (this, local->fd->inode);
|
||||
|
||||
mdc_inode_iatt_invalidate (this, local->fd->inode);
|
||||
ret = dict_get_iatt (xdata, GF_PRESTAT, &prestat);
|
||||
if (ret >= 0) {
|
||||
ret = dict_get_iatt (xdata, GF_POSTSTAT, &poststat);
|
||||
mdc_inode_iatt_set_validate (this, local->fd->inode, &prestat,
|
||||
&poststat, _gf_true);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
mdc_inode_iatt_invalidate (this, local->fd->inode);
|
||||
|
||||
out:
|
||||
MDC_STACK_UNWIND (fremovexattr, frame, op_ret, op_errno, xdata);
|
||||
|
||||
|
@ -1238,7 +1238,7 @@ posix_unlink (call_frame_t *frame, xlator_t *this,
|
||||
"fstat failed on fd=%d", fd);
|
||||
goto out;
|
||||
}
|
||||
op_ret = posix_set_iatt_in_dict (unwind_dict, &postbuf);
|
||||
op_ret = posix_set_iatt_in_dict (unwind_dict, NULL, &postbuf);
|
||||
}
|
||||
|
||||
op_ret = posix_pstat (this, loc->parent, loc->pargfid, par_path,
|
||||
|
@ -2846,25 +2846,56 @@ posix_is_bulk_removexattr (char *name, dict_t *xdata)
|
||||
}
|
||||
|
||||
int32_t
|
||||
posix_set_iatt_in_dict (dict_t *dict, struct iatt *in_stbuf)
|
||||
posix_set_iatt_in_dict (dict_t *dict, struct iatt *preop, struct iatt *postop)
|
||||
{
|
||||
int ret = -1;
|
||||
struct iatt *stbuf = NULL;
|
||||
int32_t len = sizeof(struct iatt);
|
||||
struct iatt *prebuf = NULL;
|
||||
struct iatt *postbuf = NULL;
|
||||
|
||||
if (!dict || !in_stbuf)
|
||||
if (!dict)
|
||||
return ret;
|
||||
|
||||
stbuf = GF_CALLOC (1, len, gf_common_mt_char);
|
||||
if (!stbuf)
|
||||
return ret;
|
||||
if (postop) {
|
||||
stbuf = GF_CALLOC (1, len, gf_common_mt_char);
|
||||
if (!stbuf)
|
||||
goto out;
|
||||
memcpy (stbuf, postop, len);
|
||||
ret = dict_set_iatt (dict, DHT_IATT_IN_XDATA_KEY, stbuf,
|
||||
false);
|
||||
if (ret < 0) {
|
||||
GF_FREE (stbuf);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (stbuf, in_stbuf, len);
|
||||
if (preop) {
|
||||
prebuf = GF_CALLOC (1, len, gf_common_mt_char);
|
||||
if (!prebuf)
|
||||
goto out;
|
||||
memcpy (prebuf, preop, len);
|
||||
ret = dict_set_iatt (dict, GF_PRESTAT, prebuf, false);
|
||||
if (ret < 0) {
|
||||
GF_FREE (prebuf);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = dict_set_iatt (dict, DHT_IATT_IN_XDATA_KEY, stbuf, false);
|
||||
if (ret)
|
||||
GF_FREE (stbuf);
|
||||
if (postop) {
|
||||
postbuf = GF_CALLOC (1, len, gf_common_mt_char);
|
||||
if (!postbuf)
|
||||
goto out;
|
||||
memcpy (postbuf, postop, len);
|
||||
ret = dict_set_iatt (dict, GF_POSTSTAT, postbuf, false);
|
||||
if (ret < 0) {
|
||||
GF_FREE (postbuf);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2212,7 +2212,8 @@ posix_setxattr (call_frame_t *frame, xlator_t *this,
|
||||
int32_t op_errno = 0;
|
||||
char * real_path = NULL;
|
||||
char *acl_xattr = NULL;
|
||||
struct iatt stbuf = {0};
|
||||
struct iatt preop = {0};
|
||||
struct iatt postop = {0};
|
||||
int32_t ret = 0;
|
||||
ssize_t acl_size = 0;
|
||||
dict_t *xattr = NULL;
|
||||
@ -2245,7 +2246,7 @@ posix_setxattr (call_frame_t *frame, xlator_t *this,
|
||||
goto out;
|
||||
}
|
||||
|
||||
posix_pstat(this, loc->inode, loc->gfid, real_path, &stbuf, _gf_false);
|
||||
posix_pstat(this, loc->inode, loc->gfid, real_path, &preop, _gf_false);
|
||||
|
||||
op_ret = -1;
|
||||
|
||||
@ -2259,7 +2260,7 @@ posix_setxattr (call_frame_t *frame, xlator_t *this,
|
||||
/*TODO: move the following to a different function */
|
||||
LOCK (&loc->inode->lock);
|
||||
{
|
||||
state = posix_cs_check_status (this, real_path, NULL, &stbuf);
|
||||
state = posix_cs_check_status (this, real_path, NULL, &preop);
|
||||
if (state != GF_CS_LOCAL) {
|
||||
op_errno = EINVAL;
|
||||
ret = posix_cs_set_state (this, &xattr, state, real_path,
|
||||
@ -2350,7 +2351,7 @@ unlock:
|
||||
|
||||
filler.real_path = real_path;
|
||||
filler.this = this;
|
||||
filler.stbuf = &stbuf;
|
||||
filler.stbuf = &preop;
|
||||
|
||||
#ifdef GF_DARWIN_HOST_OS
|
||||
filler.flags = map_xattr_flags(flags);
|
||||
@ -2374,14 +2375,12 @@ unlock:
|
||||
* This is used by DHT to redirect FOPs if the file is being migrated
|
||||
* Ignore errors for now
|
||||
*/
|
||||
if (xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) {
|
||||
ret = posix_pstat(this, loc->inode, loc->gfid, real_path,
|
||||
&stbuf, _gf_false);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = posix_pstat(this, loc->inode, loc->gfid, real_path, &postop,
|
||||
_gf_false);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = posix_set_iatt_in_dict (xattr, &stbuf);
|
||||
}
|
||||
ret = posix_set_iatt_in_dict (xattr, &preop, &postop);
|
||||
|
||||
/*
|
||||
* ACL can be set on a file/folder using GF_POSIX_ACL_*_KEY xattrs which
|
||||
@ -3720,7 +3719,8 @@ posix_fsetxattr (call_frame_t *frame, xlator_t *this,
|
||||
struct posix_fd *pfd = NULL;
|
||||
int _fd = -1;
|
||||
int ret = -1;
|
||||
struct iatt stbuf = {0,};
|
||||
struct iatt preop = {0,};
|
||||
struct iatt postop = {0,};
|
||||
dict_t *xattr = NULL;
|
||||
posix_xattr_filler_t filler = {0,};
|
||||
struct posix_private *priv = NULL;
|
||||
@ -3744,7 +3744,7 @@ posix_fsetxattr (call_frame_t *frame, xlator_t *this,
|
||||
}
|
||||
_fd = pfd->fd;
|
||||
|
||||
ret = posix_fdstat (this, fd->inode, pfd->fd, &stbuf);
|
||||
ret = posix_fdstat (this, fd->inode, pfd->fd, &preop);
|
||||
if (ret == -1) {
|
||||
op_errno = errno;
|
||||
gf_msg (this->name, GF_LOG_ERROR, op_errno,
|
||||
@ -3759,7 +3759,7 @@ posix_fsetxattr (call_frame_t *frame, xlator_t *this,
|
||||
filler.fdnum = _fd;
|
||||
filler.this = this;
|
||||
filler.frame = frame;
|
||||
filler.stbuf = &stbuf;
|
||||
filler.stbuf = &preop;
|
||||
filler.fd = fd;
|
||||
#ifdef GF_DARWIN_HOST_OS
|
||||
filler.flags = map_xattr_flags(flags);
|
||||
@ -3785,21 +3785,19 @@ posix_fsetxattr (call_frame_t *frame, xlator_t *this,
|
||||
}
|
||||
}
|
||||
|
||||
if (xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) {
|
||||
ret = posix_fdstat (this, fd->inode, pfd->fd, &stbuf);
|
||||
if (ret == -1) {
|
||||
op_errno = errno;
|
||||
gf_msg (this->name, GF_LOG_ERROR, op_errno,
|
||||
P_MSG_XATTR_FAILED, "fsetxattr (fstat)"
|
||||
"failed on fd=%p", fd);
|
||||
goto out;
|
||||
}
|
||||
|
||||
xattr = dict_new ();
|
||||
if (!xattr)
|
||||
goto out;
|
||||
ret = posix_set_iatt_in_dict (xattr, &stbuf);
|
||||
ret = posix_fdstat (this, fd->inode, pfd->fd, &postop);
|
||||
if (ret == -1) {
|
||||
op_errno = errno;
|
||||
gf_msg (this->name, GF_LOG_ERROR, op_errno,
|
||||
P_MSG_XATTR_FAILED, "fsetxattr (fstat)"
|
||||
"failed on fd=%p", fd);
|
||||
goto out;
|
||||
}
|
||||
xattr = dict_new ();
|
||||
if (!xattr)
|
||||
goto out;
|
||||
|
||||
ret = posix_set_iatt_in_dict (xattr, &preop, &postop);
|
||||
|
||||
out:
|
||||
SET_TO_OLD_FS_ID ();
|
||||
@ -3877,7 +3875,8 @@ posix_common_removexattr (call_frame_t *frame, loc_t *loc, fd_t *fd,
|
||||
char *real_path = NULL;
|
||||
struct posix_fd *pfd = NULL;
|
||||
int op_ret = 0;
|
||||
struct iatt stbuf = {0};
|
||||
struct iatt preop = {0,};
|
||||
struct iatt postop = {0,};
|
||||
int ret = 0;
|
||||
int _fd = -1;
|
||||
xlator_t *this = frame->this;
|
||||
@ -3913,6 +3912,12 @@ posix_common_removexattr (call_frame_t *frame, loc_t *loc, fd_t *fd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (loc)
|
||||
ret = posix_pstat(this, inode, loc->gfid, real_path,
|
||||
&preop, _gf_false);
|
||||
else
|
||||
ret = posix_fdstat (this, inode, _fd, &preop);
|
||||
|
||||
if (gf_get_index_by_elem (disallow_removexattrs, (char *)name) >= 0) {
|
||||
gf_msg (this->name, GF_LOG_WARNING, 0, P_MSG_XATTR_NOT_REMOVED,
|
||||
"Remove xattr called on %s for file/dir %s with gfid: "
|
||||
@ -3968,24 +3973,20 @@ posix_common_removexattr (call_frame_t *frame, loc_t *loc, fd_t *fd,
|
||||
|
||||
if (loc) {
|
||||
posix_set_ctime (frame, this, real_path, -1, inode, NULL);
|
||||
ret = posix_pstat(this, inode, loc->gfid, real_path, &postop,
|
||||
_gf_false);
|
||||
} else {
|
||||
posix_set_ctime (frame, this, NULL, _fd, inode, NULL);
|
||||
ret = posix_fdstat (this, inode, _fd, &postop);
|
||||
}
|
||||
if (ret)
|
||||
goto out;
|
||||
*xdata_rsp = dict_new();
|
||||
if (!*xdata_rsp)
|
||||
goto out;
|
||||
|
||||
if (xdata && dict_get (xdata, DHT_IATT_IN_XDATA_KEY)) {
|
||||
if (loc)
|
||||
ret = posix_pstat(this, inode, loc->gfid,
|
||||
real_path, &stbuf, _gf_false);
|
||||
else
|
||||
ret = posix_fdstat (this, inode, _fd, &stbuf);
|
||||
if (ret)
|
||||
goto out;
|
||||
*xdata_rsp = dict_new();
|
||||
if (!*xdata_rsp)
|
||||
goto out;
|
||||
ret = posix_set_iatt_in_dict (*xdata_rsp, &preop, &postop);
|
||||
|
||||
ret = posix_set_iatt_in_dict (*xdata_rsp, &stbuf);
|
||||
}
|
||||
op_ret = 0;
|
||||
out:
|
||||
SET_TO_OLD_FS_ID ();
|
||||
|
@ -396,7 +396,7 @@ gf_boolean_t
|
||||
posix_is_bulk_removexattr (char *name, dict_t *dict);
|
||||
|
||||
int32_t
|
||||
posix_set_iatt_in_dict (dict_t *, struct iatt *);
|
||||
posix_set_iatt_in_dict (dict_t *, struct iatt *, struct iatt *);
|
||||
|
||||
mode_t
|
||||
posix_override_umask (mode_t , mode_t);
|
||||
|
Reference in New Issue
Block a user