summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/cluster/ec/src/ec-combine.c241
-rw-r--r--xlators/cluster/ec/src/ec.c5
2 files changed, 141 insertions, 105 deletions
diff --git a/xlators/cluster/ec/src/ec-combine.c b/xlators/cluster/ec/src/ec-combine.c
index f949dbd..e09381b 100644
--- a/xlators/cluster/ec/src/ec-combine.c
+++ b/xlators/cluster/ec/src/ec-combine.c
@@ -22,6 +22,8 @@
#define EC_QUOTA_PREFIX "trusted.glusterfs.quota."
+#define EC_MISSING_DATA ((data_t *)1ULL)
+
struct _ec_dict_info;
typedef struct _ec_dict_info ec_dict_info_t;
@@ -270,35 +272,45 @@ ec_dict_compare (dict_t *dict1, dict_t *dict2)
return 0;
}
-int32_t ec_dict_list(data_t ** list, int32_t * count, ec_cbk_data_t * cbk,
- int32_t which, char * key)
+static uint32_t
+ec_dict_list(data_t **list, ec_cbk_data_t *cbk, int32_t which, char *key,
+ gf_boolean_t global)
{
- ec_cbk_data_t *ans = NULL;
- dict_t *dict = NULL;
- int32_t i, max;
-
- max = *count;
- i = 0;
- for (ans = cbk; ans != NULL; ans = ans->next) {
- if (i >= max) {
- gf_msg (cbk->fop->xl->name, GF_LOG_ERROR, EINVAL,
- EC_MSG_INVALID_DICT_NUMS,
- "Unexpected number of "
- "dictionaries");
-
- return -EINVAL;
+ ec_t *ec = cbk->fop->xl->private;
+ ec_cbk_data_t *ans = NULL;
+ dict_t *dict = NULL;
+ data_t *data;
+ uint32_t count;
+ int32_t i;
+
+ for (i = 0; i < ec->nodes; i++) {
+ /* We initialize the list with EC_MISSING_DATA if we are
+ * returning a global list or the current subvolume belongs
+ * to the group of the accepted answer. Note that if some
+ * subvolume is known to be down before issuing the request,
+ * we won't have any answer from it, so we set here the
+ * appropriate default value. */
+ if (global || ((cbk->mask & (1ULL << i)) != 0)) {
+ list[i] = EC_MISSING_DATA;
+ } else {
+ list[i] = NULL;
+ }
}
- dict = (which == EC_COMBINE_XDATA) ? ans->xdata : ans->dict;
- list[i] = dict_get(dict, key);
- if (list[i] != NULL) {
- i++;
+ count = 0;
+ list_for_each_entry(ans, &cbk->fop->answer_list, answer_list) {
+ if (global || ((cbk->mask & ans->mask) != 0)) {
+ dict = (which == EC_COMBINE_XDATA) ? ans->xdata
+ : ans->dict;
+ data = dict_get(dict, key);
+ if (data != NULL) {
+ list[ans->idx] = data;
+ count++;
+ }
+ }
}
- }
-
- *count = i;
- return 0;
+ return count;
}
int32_t ec_concat_prepare(xlator_t *xl, char **str, char **sep, char **post,
@@ -337,23 +349,21 @@ out:
return -EINVAL;
}
-int32_t ec_dict_data_concat(const char * fmt, ec_cbk_data_t * cbk,
- int32_t which, char * key, ...)
+static int32_t
+ec_dict_data_concat(const char *fmt, ec_cbk_data_t *cbk, int32_t which,
+ char *key, const char *def, gf_boolean_t global, ...)
{
- data_t * data[cbk->count];
- char * str = NULL, * pre = NULL, * sep, * post;
- dict_t * dict;
+ ec_t *ec = cbk->fop->xl->private;
+ data_t *data[ec->nodes];
+ char *str = NULL, *pre = NULL, *sep, *post;
+ dict_t *dict;
va_list args;
- int32_t i, num, len, prelen, postlen, seplen, tmp;
+ int32_t i, num, len, deflen, prelen, postlen, seplen, tmp;
int32_t err;
- num = cbk->count;
- err = ec_dict_list(data, &num, cbk, which, key);
- if (err != 0) {
- return err;
- }
+ ec_dict_list(data, cbk, which, key, global);
- va_start(args, key);
+ va_start(args, global);
err = ec_concat_prepare(cbk->fop->xl, &pre, &sep, &post, fmt, args);
va_end(args);
@@ -365,9 +375,29 @@ int32_t ec_dict_data_concat(const char * fmt, ec_cbk_data_t * cbk,
seplen = strlen(sep);
postlen = strlen(post);
- len = prelen + (num - 1) * seplen + postlen + 1;
- for (i = 0; i < num; i++) {
- len += data[i]->len - 1;
+ deflen = 0;
+ if (def != NULL) {
+ deflen = strlen(def);
+ }
+
+ len = prelen + postlen + 1;
+ num = -1;
+ for (i = 0; i < ec->nodes; i++) {
+ if (data[i] == NULL) {
+ continue;
+ }
+ if (data[i] == EC_MISSING_DATA) {
+ if (def == NULL) {
+ continue;
+ }
+ len += deflen;
+ } else {
+ len += data[i]->len - 1;
+ }
+ if (num >= 0) {
+ len += seplen;
+ }
+ num++;
}
err = -ENOMEM;
@@ -379,14 +409,25 @@ int32_t ec_dict_data_concat(const char * fmt, ec_cbk_data_t * cbk,
memcpy(str, pre, prelen);
len = prelen;
- for (i = 0; i < num; i++) {
- if (i > 0) {
+ for (i = 0; i < ec->nodes; i++) {
+ if (data[i] == NULL) {
+ continue;
+ }
+ if (data[i] == EC_MISSING_DATA) {
+ if (deflen == 0) {
+ continue;
+ }
+ tmp = deflen;
+ memcpy(str + len, def, tmp);
+ } else {
+ tmp = data[i]->len - 1;
+ memcpy(str + len, data[i]->data, tmp);
+ }
+ len += tmp;
+ if (i < num) {
memcpy(str + len, sep, seplen);
len += seplen;
}
- tmp = data[i]->len - 1;
- memcpy(str + len, data[i]->data, tmp);
- len += tmp;
}
memcpy(str + len, post, postlen + 1);
@@ -407,30 +448,26 @@ out:
int32_t ec_dict_data_merge(ec_cbk_data_t *cbk, int32_t which, char *key)
{
- data_t *data[cbk->count];
+ ec_t *ec = cbk->fop->xl->private;
+ data_t *data[ec->nodes];
dict_t *dict, *lockinfo, *tmp = NULL;
char *ptr = NULL;
- int32_t i, num, len;
+ int32_t i, len;
int32_t err;
- num = cbk->count;
- err = ec_dict_list(data, &num, cbk, which, key);
- if (err != 0) {
- return err;
- }
+
+ ec_dict_list(data, cbk, which, key, _gf_false);
lockinfo = dict_new();
if (lockinfo == NULL) {
return -ENOMEM;
}
- err = dict_unserialize(data[0]->data, data[0]->len, &lockinfo);
- if (err != 0) {
- goto out;
- }
+ for (i = 0; i < ec->nodes; i++) {
+ if ((data[i] == NULL) || (data[i] == EC_MISSING_DATA)) {
+ continue;
+ }
- for (i = 1; i < num; i++)
- {
tmp = dict_new();
if (tmp == NULL) {
err = -ENOMEM;
@@ -517,19 +554,20 @@ int32_t ec_dict_data_uuid(ec_cbk_data_t * cbk, int32_t which, char * key)
int32_t ec_dict_data_max32(ec_cbk_data_t *cbk, int32_t which, char *key)
{
- data_t * data[cbk->count];
- dict_t * dict;
- int32_t i, num, err;
+ ec_t *ec = cbk->fop->xl->private;
+ data_t *data[ec->nodes];
+ dict_t *dict;
+ int32_t i;
uint32_t max, tmp;
- num = cbk->count;
- err = ec_dict_list(data, &num, cbk, which, key);
- if (err != 0) {
- return err;
- }
+ ec_dict_list(data, cbk, which, key, _gf_false);
+
+ max = 0;
+ for (i = 0; i < ec->nodes; i++) {
+ if ((data[i] == NULL) || (data[i] == EC_MISSING_DATA)) {
+ continue;
+ }
- max = data_to_uint32(data[0]);
- for (i = 1; i < num; i++) {
tmp = data_to_uint32(data[i]);
if (max < tmp) {
max = tmp;
@@ -542,19 +580,20 @@ int32_t ec_dict_data_max32(ec_cbk_data_t *cbk, int32_t which, char *key)
int32_t ec_dict_data_max64(ec_cbk_data_t *cbk, int32_t which, char *key)
{
- data_t *data[cbk->count];
+ ec_t *ec = cbk->fop->xl->private;
+ data_t *data[ec->nodes];
dict_t *dict;
- int32_t i, num, err;
+ int32_t i;
uint64_t max, tmp;
- num = cbk->count;
- err = ec_dict_list(data, &num, cbk, which, key);
- if (err != 0) {
- return err;
- }
+ ec_dict_list(data, cbk, which, key, _gf_false);
+
+ max = 0;
+ for (i = 0; i < ec->nodes; i++) {
+ if ((data[i] == NULL) || (data[i] == EC_MISSING_DATA)) {
+ continue;
+ }
- max = data_to_uint64(data[0]);
- for (i = 1; i < num; i++) {
tmp = data_to_uint64(data[i]);
if (max < tmp) {
max = tmp;
@@ -567,22 +606,14 @@ int32_t ec_dict_data_max64(ec_cbk_data_t *cbk, int32_t which, char *key)
int32_t ec_dict_data_quota(ec_cbk_data_t *cbk, int32_t which, char *key)
{
- data_t *data[cbk->count];
+ ec_t *ec = cbk->fop->xl->private;
+ data_t *data[ec->nodes];
dict_t *dict = NULL;
- ec_t *ec = NULL;
int32_t i = 0;
- int32_t num = 0;
- int32_t err = 0;
quota_meta_t size = {0, };
quota_meta_t max_size = {0, };
- num = cbk->count;
- err = ec_dict_list(data, &num, cbk, which, key);
- if (err != 0) {
- return err;
- }
-
- if (num == 0) {
+ if (ec_dict_list(data, cbk, which, key, _gf_false) == 0) {
return 0;
}
@@ -591,8 +622,9 @@ int32_t ec_dict_data_quota(ec_cbk_data_t *cbk, int32_t which, char *key)
* bricks and we can receive slightly different values. If that's the
* case, we take the maximum of all received values.
*/
- for (i = 0; i < num; i++) {
- if (quota_data_to_meta (data[i], QUOTA_SIZE_KEY, &size) < 0) {
+ for (i = 0; i < ec->nodes; i++) {
+ if ((data[i] == NULL) || (data[i] == EC_MISSING_DATA) ||
+ (quota_data_to_meta (data[i], QUOTA_SIZE_KEY, &size) < 0)) {
continue;
}
@@ -604,7 +636,6 @@ int32_t ec_dict_data_quota(ec_cbk_data_t *cbk, int32_t which, char *key)
max_size.dir_count = size.dir_count;
}
- ec = cbk->fop->xl->private;
max_size.size *= ec->fragments;
dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict;
@@ -613,18 +644,18 @@ int32_t ec_dict_data_quota(ec_cbk_data_t *cbk, int32_t which, char *key)
int32_t ec_dict_data_stime(ec_cbk_data_t * cbk, int32_t which, char * key)
{
- data_t * data[cbk->count];
- dict_t * dict;
- int32_t i, num, err;
+ ec_t *ec = cbk->fop->xl->private;
+ data_t *data[ec->nodes];
+ dict_t *dict;
+ int32_t i, err;
- num = cbk->count;
- err = ec_dict_list(data, &num, cbk, which, key);
- if (err != 0) {
- return err;
- }
+ ec_dict_list(data, cbk, which, key, _gf_false);
dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict;
- for (i = 1; i < num; i++) {
+ for (i = 0; i < ec->nodes; i++) {
+ if ((data[i] == NULL) || (data[i] == EC_MISSING_DATA)) {
+ continue;
+ }
err = gf_get_max_stime(cbk->fop->xl, dict, key, data[i]);
if (err != 0) {
gf_msg (cbk->fop->xl->name, GF_LOG_ERROR, -err,
@@ -646,12 +677,14 @@ int32_t ec_dict_data_combine(dict_t * dict, char * key, data_t * value,
(strcmp(key, GF_XATTR_USER_PATHINFO_KEY) == 0))
{
return ec_dict_data_concat("(<EC:%s> { })", data->cbk, data->which,
- key, data->cbk->fop->xl->name);
+ key, NULL, _gf_false,
+ data->cbk->fop->xl->name);
}
if (strncmp(key, GF_XATTR_CLRLK_CMD, strlen(GF_XATTR_CLRLK_CMD)) == 0)
{
- return ec_dict_data_concat("{\n}", data->cbk, data->which, key);
+ return ec_dict_data_concat("{\n}", data->cbk, data->which, key, NULL,
+ _gf_false);
}
if (strncmp(key, GF_XATTR_LOCKINFO_KEY,
@@ -681,9 +714,9 @@ int32_t ec_dict_data_combine(dict_t * dict, char * key, data_t * value,
return 0;
}
- if (XATTR_IS_NODE_UUID(key))
- {
- return ec_dict_data_uuid(data->cbk, data->which, key);
+ if (XATTR_IS_NODE_UUID(key)) {
+ return ec_dict_data_concat("{ }", data->cbk, data->which, key,
+ UUID0_STR, _gf_true);
}
if (fnmatch(GF_XATTR_STIME_PATTERN, key, FNM_NOESCAPE) == 0)
diff --git a/xlators/cluster/ec/src/ec.c b/xlators/cluster/ec/src/ec.c
index e628183..2009fac 100644
--- a/xlators/cluster/ec/src/ec.c
+++ b/xlators/cluster/ec/src/ec.c
@@ -863,8 +863,11 @@ ec_gf_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
NULL, ec_marker_populate_args) == 0)
return 0;
- if (name && (fnmatch (GF_XATTR_STIME_PATTERN, name, 0) == 0))
+ if (name &&
+ ((fnmatch (GF_XATTR_STIME_PATTERN, name, 0) == 0) ||
+ (XATTR_IS_NODE_UUID(name)))) {
minimum = EC_MINIMUM_ALL;
+ }
ec_getxattr (frame, this, -1, minimum, default_getxattr_cbk,
NULL, loc, name, xdata);