diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 0d57c858e..7c5743af7 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -2783,7 +2783,14 @@ print_quota_list_from_mountdir (cli_local_t *local, char *mountdir, xattr_size = sys_lgetxattr (mountdir, "trusted.glusterfs.quota.size", NULL, 0); - if (xattr_size > (sizeof (int64_t) * 2)) { + if (xattr_size < (sizeof (int64_t) * 2) && + type == GF_QUOTA_OPTION_TYPE_LIST_OBJECTS) { + ret = -1; + + /* This can happen when glusterfs is upgraded from 3.6 to 3.7 + * and the xattr healing is not completed. + */ + } else if (xattr_size > (sizeof (int64_t) * 2)) { ret = sys_lgetxattr (mountdir, "trusted.glusterfs.quota.size", &used_space, sizeof (used_space)); } else if (xattr_size > 0) { @@ -2962,6 +2969,16 @@ print_quota_list_from_quotad (call_frame_t *frame, dict_t *rsp_dict) limits.sl = ntoh64 (size_limits->sl); ret = quota_dict_get_meta (rsp_dict, QUOTA_SIZE_KEY, &used_space); + if (ret == -2 && type == GF_QUOTA_OPTION_TYPE_LIST) { + ret = 0; + /* quota_dict_get_meta returns -2 if metadata for inode + * quotas is missing. + * This can happen when glusterfs is upgraded from 3.6 to 3.7 + * and the xattr healing is not completed. + * We can contiue as success if we are listing only file usage + */ + } + if (ret < 0) { gf_log ("cli", GF_LOG_WARNING, "size key not present in dict"); diff --git a/libglusterfs/src/quota-common-utils.c b/libglusterfs/src/quota-common-utils.c index 8cc09e8ff..ab153209d 100644 --- a/libglusterfs/src/quota-common-utils.c +++ b/libglusterfs/src/quota-common-utils.c @@ -15,18 +15,13 @@ #include "quota-common-utils.h" int32_t -quota_dict_get_meta (dict_t *dict, char *key, quota_meta_t *meta) +quota_data_to_meta (data_t *data, char *key, quota_meta_t *meta) { int32_t ret = -1; - data_t *data = NULL; quota_meta_t *value = NULL; int64_t *size = NULL; - if (!dict || !key || !meta) - goto out; - - data = dict_get (dict, key); - if (!data || !data->data) + if (!data || !key || !meta) goto out; if (data->len > sizeof (int64_t)) { @@ -58,6 +53,26 @@ out: return ret; } +int32_t +quota_dict_get_meta (dict_t *dict, char *key, quota_meta_t *meta) +{ + int32_t ret = -1; + data_t *data = NULL; + + if (!dict || !key || !meta) + goto out; + + data = dict_get (dict, key); + if (!data || !data->data) + goto out; + + ret = quota_data_to_meta (data, key, meta); + +out: + + return ret; +} + int32_t quota_dict_set_meta (dict_t *dict, char *key, const quota_meta_t *meta, ia_type_t ia_type) diff --git a/libglusterfs/src/quota-common-utils.h b/libglusterfs/src/quota-common-utils.h index 423017243..eff86850d 100644 --- a/libglusterfs/src/quota-common-utils.h +++ b/libglusterfs/src/quota-common-utils.h @@ -26,6 +26,9 @@ struct _quota_meta { } __attribute__ ((__packed__)); typedef struct _quota_meta quota_meta_t; +int32_t +quota_data_to_meta (data_t *data, char *key, quota_meta_t *meta); + int32_t quota_dict_get_meta (dict_t *dict, char *key, quota_meta_t *meta); diff --git a/xlators/cluster/ec/src/ec-combine.c b/xlators/cluster/ec/src/ec-combine.c index 5f5d97275..e84055c51 100644 --- a/xlators/cluster/ec/src/ec-combine.c +++ b/xlators/cluster/ec/src/ec-combine.c @@ -17,6 +17,7 @@ #include "ec-helpers.h" #include "ec-common.h" #include "ec-combine.h" +#include "quota-common-utils.h" #define EC_QUOTA_PREFIX "trusted.glusterfs.quota." @@ -584,11 +585,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]; - dict_t *dict; - ec_t *ec; - int32_t i, num; - uint64_t max, tmp; + data_t *data[cbk->count]; + dict_t *dict = NULL; + ec_t *ec = NULL; + int32_t i = 0; + int32_t num = 0; + int32_t ret = -1; + quota_meta_t size = {0, }; + quota_meta_t max_size = {0, }; num = cbk->count; if (!ec_dict_list(data, &num, cbk, which, key)) { @@ -604,19 +608,24 @@ 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. */ - max = ntoh64(*(uint64_t *)data_to_ptr(data[0])); - for (i = 1; i < num; i++) { - tmp = ntoh64(*(uint64_t *)data_to_ptr(data[i])); - if (max < tmp) { - max = tmp; - } + for (i = 0; i < num; i++) { + ret = quota_data_to_meta (data[i], QUOTA_SIZE_KEY, &size); + if (ret == -1) + continue; + + if (size.size > max_size.size) + max_size.size = size.size; + if (size.file_count > max_size.file_count) + max_size.file_count = size.file_count; + if (size.dir_count > max_size.dir_count) + max_size.dir_count = size.dir_count; } ec = cbk->fop->xl->private; - max *= ec->fragments; + max_size.size *= ec->fragments; dict = (which == EC_COMBINE_XDATA) ? cbk->xdata : cbk->dict; - if (ec_dict_set_number(dict, key, max) != 0) { + if (quota_dict_set_meta (dict, key, &max_size, IA_IFDIR) != 0) { return -1; }