diff options
-rw-r--r-- | libglusterfs/src/dict.c | 87 | ||||
-rw-r--r-- | libglusterfs/src/dict.h | 5 | ||||
-rwxr-xr-x | tests/basic/geo-replication/marker-xattrs.t | 4 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 41 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-combine.c | 108 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-inode-read.c | 20 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec.c | 6 |
7 files changed, 152 insertions, 119 deletions
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index b8b6aeab248..ffc92e72724 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -31,6 +31,11 @@ #include "globals.h" #include "statedump.h" +struct dict_cmp { + dict_t *dict; + gf_boolean_t (*value_ignore) (char *k); +}; + data_t * get_new_data () { @@ -107,7 +112,6 @@ dict_new (void) return dict; } - int32_t is_data_equal (data_t *one, data_t *two) @@ -134,6 +138,87 @@ is_data_equal (data_t *one, return 0; } +static int +key_value_cmp (dict_t *one, char *key1, data_t *value1, void *data) +{ + struct dict_cmp *cmp = data; + dict_t *two = NULL; + data_t *value2 = NULL; + + two = cmp->dict; + value2 = dict_get (two, key1); + + if (value2) { + if (cmp->value_ignore && cmp->value_ignore (key1)) + return 0; + + if (is_data_equal (value1, value2) == 1) + return 0; + } + + if (value2 == NULL) { + gf_log (THIS->name, GF_LOG_DEBUG, + "'%s' found only on one dict", key1); + } else { + gf_log (THIS->name, GF_LOG_DEBUG, "'%s' is different in two " + "dicts (%u, %u)", key1, value1->len, value2->len); + } + + return -1; +} + +/* If both dicts are NULL then equal. If one of the dicts is NULL but the + * other has only ignorable keys then also they are equal. If both dicts are + * non-null then check if for each non-ignorable key, values are same or + * not. value_ignore function is used to skip comparing values for the keys + * which must be present in both the dictionaries but the value could be + * different. + */ +gf_boolean_t +are_dicts_equal (dict_t *one, dict_t *two, + gf_boolean_t (*match) (dict_t *d, char *k, data_t *v, + void *data), + gf_boolean_t (*value_ignore) (char *k)) +{ + int num_matches1 = 0; + int num_matches2 = 0; + struct dict_cmp cmp = {0}; + + if (one == two) + return _gf_true; + + if (!match) + match = dict_match_everything; + + cmp.dict = two; + cmp.value_ignore = value_ignore; + if (!two) { + num_matches1 = dict_foreach_match (one, match, NULL, + dict_null_foreach_fn, NULL); + goto done; + } else { + num_matches1 = dict_foreach_match (one, match, NULL, + key_value_cmp, &cmp); + } + + if (num_matches1 == -1) + return _gf_false; + + if ((num_matches1 == one->count) && (one->count == two->count)) + return _gf_true; + + num_matches2 = dict_foreach_match (two, match, NULL, + dict_null_foreach_fn, NULL); +done: + /* If the number of matches is same in 'two' then for all the + * valid-keys that exist in 'one' the value matched and no extra valid + * keys exist in 'two' alone. Otherwise there exists at least one extra + * valid-key in 'two' which doesn't exist in 'one' */ + if (num_matches1 == num_matches2) + return _gf_true; + return _gf_false; +} + void data_destroy (data_t *data) { diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h index 3708eede06d..a9004e96a50 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -264,4 +264,9 @@ dict_match_everything (dict_t *d, char *k, data_t *v, void *data); dict_t * dict_for_key_value (const char *name, const char *value, size_t size); +gf_boolean_t +are_dicts_equal (dict_t *one, dict_t *two, + gf_boolean_t (*match) (dict_t *d, char *k, data_t *v, + void *data), + gf_boolean_t (*value_ignore) (char *k)); #endif diff --git a/tests/basic/geo-replication/marker-xattrs.t b/tests/basic/geo-replication/marker-xattrs.t index 7061b4532a3..dd5483d7e95 100755 --- a/tests/basic/geo-replication/marker-xattrs.t +++ b/tests/basic/geo-replication/marker-xattrs.t @@ -59,12 +59,16 @@ TEST touch $M0 vol_uuid=$(get_volume_mark $M1) xtime=trusted.glusterfs.$vol_uuid.xtime +stime=trusted.glusterfs.$vol_uuid.stime +stime_val=$(getfattr -e hex -n $xtime $M1 | grep ${xtime}= | cut -f2 -d'=') +TEST "setfattr -n $stime -v $stime_val $B0/${V0}-1" TEST "getfattr -n $xtime $M1 | grep -q ${xtime}=" TEST kill_brick $V0 $H0 $B0/${V0}-0 TEST "getfattr -n $xtime $M1 | grep -q ${xtime}=" +TEST "getfattr -n $stime $M1 | grep -q ${stime}=" TEST getfattr -d -m. -e hex $M1 EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0 diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index 5654e3ad03d..8993b164b91 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -1239,48 +1239,19 @@ afr_is_xattr_ignorable (char *key) return _gf_false; } -int -xattr_is_equal (dict_t *this, char *key1, data_t *value1, void *data) +static gf_boolean_t +afr_xattr_match (dict_t *this, char *key1, data_t *value1, void *data) { - dict_t *xattr2 = (dict_t *)data; - data_t *value2 = NULL; - - if (afr_is_xattr_ignorable (key1)) - return 0; - - value2 = dict_get (xattr2, key1); - if (!value2) - return -1; - - if (value1->len != value2->len) - return -1; - if(memcmp(value1->data, value2->data, value1->len)) - return -1; - else - return 0; + if (!afr_is_xattr_ignorable (key1)) + return _gf_true; + return _gf_false; } -/* To conclude that both dicts are equal, we need to check if - * 1) For every key-val pair in dict1, a match is present in dict2 - * 2) For every key-val pair in dict2, a match is present in dict1 - * We need to do both because ignoring glusterfs' internal xattrs - * happens only in xattr_is_equal(). - */ gf_boolean_t afr_xattrs_are_equal (dict_t *dict1, dict_t *dict2) { - int ret = 0; - - ret = dict_foreach (dict1, xattr_is_equal, dict2); - if (ret == -1) - return _gf_false; - - ret = dict_foreach (dict2, xattr_is_equal, dict1); - if (ret == -1) - return _gf_false; - - return _gf_true; + return are_dicts_equal (dict1, dict2, afr_xattr_match, NULL); } static int diff --git a/xlators/cluster/ec/src/ec-combine.c b/xlators/cluster/ec/src/ec-combine.c index e84055c51e4..9d4a18999f1 100644 --- a/xlators/cluster/ec/src/ec-combine.c +++ b/xlators/cluster/ec/src/ec-combine.c @@ -168,96 +168,40 @@ void ec_iatt_rebuild(ec_t * ec, struct iatt * iatt, int32_t count, } } -int32_t ec_dict_data_compare(dict_t * dict, char * key, data_t * value, - void * arg) +gf_boolean_t +ec_xattr_match (dict_t *dict, char *key, data_t *value, void *arg) { - ec_dict_info_t * info = arg; - data_t * data; - - data = dict_get(info->dict, key); - if (data == NULL) - { - gf_log("ec", GF_LOG_DEBUG, "key '%s' found only on one dict", key); - - return -1; - } - - info->count--; - - if ((strcmp(key, GF_CONTENT_KEY) == 0) || - (strcmp(key, GF_XATTR_PATHINFO_KEY) == 0) || - (strcmp(key, GF_XATTR_USER_PATHINFO_KEY) == 0) || - (strcmp(key, GF_XATTR_LOCKINFO_KEY) == 0) || - (strcmp(key, GLUSTERFS_OPEN_FD_COUNT) == 0) || - (strncmp(key, GF_XATTR_CLRLK_CMD, strlen(GF_XATTR_CLRLK_CMD)) == 0) || - (strncmp(key, EC_QUOTA_PREFIX, strlen(EC_QUOTA_PREFIX)) == 0) || - (fnmatch(GF_XATTR_STIME_PATTERN, key, 0) == 0) || - (fnmatch(MARKER_XATTR_PREFIX ".*." XTIME, key, 0) == 0) || - (fnmatch(GF_XATTR_MARKER_KEY ".*", key, 0) == 0) || - (XATTR_IS_NODE_UUID(key))) - { - return 0; - } + if (fnmatch(GF_XATTR_STIME_PATTERN, key, 0) == 0) + return _gf_false; - if ((data->len != value->len) || - (memcmp(data->data, value->data, data->len) != 0)) - { - gf_log("ec", GF_LOG_DEBUG, "key '%s' is different (size: %u, %u)", - key, data->len, value->len); - - return -1; - } - - return 0; + return _gf_true; } -int32_t ec_dict_data_show(dict_t * dict, char * key, data_t * value, - void * arg) +gf_boolean_t +ec_value_ignore (char *key) { - if (dict_get(arg, key) == NULL) - { - gf_log("ec", GF_LOG_DEBUG, "key '%s' found only on one dict", key); - } - - return 0; + if ((strcmp(key, GF_CONTENT_KEY) == 0) || + (strcmp(key, GF_XATTR_PATHINFO_KEY) == 0) || + (strcmp(key, GF_XATTR_USER_PATHINFO_KEY) == 0) || + (strcmp(key, GF_XATTR_LOCKINFO_KEY) == 0) || + (strcmp(key, GLUSTERFS_OPEN_FD_COUNT) == 0) || + (strncmp(key, GF_XATTR_CLRLK_CMD, + strlen (GF_XATTR_CLRLK_CMD)) == 0) || + (strncmp(key, EC_QUOTA_PREFIX, strlen(EC_QUOTA_PREFIX)) == 0) || + (fnmatch(MARKER_XATTR_PREFIX ".*." XTIME, key, 0) == 0) || + (fnmatch(GF_XATTR_MARKER_KEY ".*", key, 0) == 0) || + (XATTR_IS_NODE_UUID(key))) { + return _gf_true; + } + return _gf_false; } -int32_t ec_dict_compare(dict_t * dict1, dict_t * dict2) +int32_t +ec_dict_compare (dict_t *dict1, dict_t *dict2) { - ec_dict_info_t info; - dict_t * dict; - - if (dict1 != NULL) - { - info.dict = dict1; - info.count = dict1->count; - dict = dict2; - } - else if (dict2 != NULL) - { - info.dict = dict2; - info.count = dict2->count; - dict = dict1; - } - else - { - return 1; - } - - if (dict != NULL) - { - if (dict_foreach(dict, ec_dict_data_compare, &info) != 0) - { - return 0; - } - } - - if (info.count != 0) - { - dict_foreach(info.dict, ec_dict_data_show, dict); - } - - return (info.count == 0); + if (are_dicts_equal (dict1, dict2, ec_xattr_match, ec_value_ignore)) + return 1; + return 0; } int32_t ec_dict_list(data_t ** list, int32_t * count, ec_cbk_data_t * cbk, diff --git a/xlators/cluster/ec/src/ec-inode-read.c b/xlators/cluster/ec/src/ec-inode-read.c index 365ea3db0ec..f87df4016c0 100644 --- a/xlators/cluster/ec/src/ec-inode-read.c +++ b/xlators/cluster/ec/src/ec-inode-read.c @@ -234,6 +234,25 @@ void ec_wind_getxattr(ec_t * ec, ec_fop_data_t * fop, int32_t idx) &fop->loc[0], fop->str[0], fop->xdata); } +void +ec_handle_special_xattrs (ec_fop_data_t *fop) +{ + ec_cbk_data_t *cbk = NULL; + /* Stime may not be available on all the bricks, so even if some of the + * subvols succeed the operation, treat it as answer.*/ + if (fop->str[0] && + fnmatch (GF_XATTR_STIME_PATTERN, fop->str[0], 0) == 0) { + if (!fop->answer || (fop->answer->op_ret < 0)) { + list_for_each_entry (cbk, &fop->cbk_list, list) { + if (cbk->op_ret >= 0) { + fop->answer = cbk; + break; + } + } + } + } +} + int32_t ec_manager_getxattr(ec_fop_data_t * fop, int32_t state) { ec_cbk_data_t * cbk; @@ -263,6 +282,7 @@ int32_t ec_manager_getxattr(ec_fop_data_t * fop, int32_t state) return EC_STATE_PREPARE_ANSWER; case EC_STATE_PREPARE_ANSWER: + ec_handle_special_xattrs (fop); cbk = fop->answer; if (cbk != NULL) { diff --git a/xlators/cluster/ec/src/ec.c b/xlators/cluster/ec/src/ec.c index 5476ac6562e..3dd04299541 100644 --- a/xlators/cluster/ec/src/ec.c +++ b/xlators/cluster/ec/src/ec.c @@ -670,6 +670,7 @@ ec_gf_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, { int error = 0; ec_t *ec = this->private; + int32_t minimum = EC_MINIMUM_MIN; if (name && strcmp (name, EC_XATTR_HEAL) != 0) { EC_INTERNAL_XATTR_OR_GOTO(name, NULL, error, out); @@ -682,7 +683,10 @@ ec_gf_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, NULL, ec_marker_populate_args) == 0) return 0; - ec_getxattr (frame, this, -1, EC_MINIMUM_MIN, default_getxattr_cbk, + if (name && (fnmatch (GF_XATTR_STIME_PATTERN, name, 0) == 0)) + minimum = EC_MINIMUM_ALL; + + ec_getxattr (frame, this, -1, minimum, default_getxattr_cbk, NULL, loc, name, xdata); return 0; |