diff options
Diffstat (limited to 'libglusterfs/src/quota-common-utils.c')
| -rw-r--r-- | libglusterfs/src/quota-common-utils.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/libglusterfs/src/quota-common-utils.c b/libglusterfs/src/quota-common-utils.c new file mode 100644 index 00000000000..804e2f0ad4b --- /dev/null +++ b/libglusterfs/src/quota-common-utils.c @@ -0,0 +1,241 @@ +/* + Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "glusterfs/dict.h" +#include "glusterfs/logging.h" +#include "glusterfs/byte-order.h" +#include "glusterfs/quota-common-utils.h" +#include "glusterfs/common-utils.h" +#include "glusterfs/libglusterfs-messages.h" + +gf_boolean_t +quota_meta_is_null(const quota_meta_t *meta) +{ + if (meta->size == 0 && meta->file_count == 0 && meta->dir_count == 0) + return _gf_true; + + return _gf_false; +} + +int32_t +quota_data_to_meta(data_t *data, quota_meta_t *meta) +{ + int32_t ret = -1; + quota_meta_t *value = NULL; + int64_t *size = NULL; + + if (!data || !meta) + goto out; + + if (data->len > sizeof(int64_t)) { + value = (quota_meta_t *)data->data; + meta->size = ntoh64(value->size); + meta->file_count = ntoh64(value->file_count); + if (data->len > (sizeof(int64_t)) * 2) + meta->dir_count = ntoh64(value->dir_count); + else + meta->dir_count = 0; + } else { + size = (int64_t *)data->data; + meta->size = ntoh64(*size); + meta->file_count = 0; + meta->dir_count = 0; + /* This can happen during software upgrade. + * Older version of glusterfs will not have inode count. + * Return failure, this will be healed as part of lookup + */ + gf_msg_callingfn("quota", GF_LOG_DEBUG, 0, LG_MSG_QUOTA_XATTRS_MISSING, + "Object quota " + "xattrs missing: len = %d", + data->len); + ret = -2; + goto out; + } + + ret = 0; +out: + + return ret; +} + +int32_t +quota_dict_get_inode_meta(dict_t *dict, char *key, const int keylen, + quota_meta_t *meta) +{ + int32_t ret = -1; + data_t *data = NULL; + + if (!dict || !key || !meta) + goto out; + + data = dict_getn(dict, key, keylen); + if (!data || !data->data) + goto out; + + ret = quota_data_to_meta(data, meta); + +out: + + return ret; +} + +int32_t +quota_dict_get_meta(dict_t *dict, char *key, const int keylen, + quota_meta_t *meta) +{ + int32_t ret = -1; + + ret = quota_dict_get_inode_meta(dict, key, keylen, meta); + if (ret == -2) + ret = 0; + + return ret; +} + +int32_t +quota_dict_set_meta(dict_t *dict, char *key, const quota_meta_t *meta, + ia_type_t ia_type) +{ + int32_t ret = -ENOMEM; + quota_meta_t *value = NULL; + + value = GF_MALLOC(sizeof(quota_meta_t), gf_common_quota_meta_t); + if (value == NULL) { + goto out; + } + + value->size = hton64(meta->size); + value->file_count = hton64(meta->file_count); + value->dir_count = hton64(meta->dir_count); + + if (ia_type == IA_IFDIR) { + ret = dict_set_bin(dict, key, value, sizeof(*value)); + } else { + /* For a file we don't need to store dir_count in the + * quota size xattr, so we set the len of the data in the dict + * as 128bits, so when the posix xattrop reads the dict, it only + * performs operations on size and file_count + */ + ret = dict_set_bin(dict, key, value, sizeof(*value) - sizeof(int64_t)); + } + + if (ret < 0) { + gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_DICT_SET_FAILED, + "dict set failed"); + GF_FREE(value); + } + +out: + return ret; +} + +int32_t +quota_conf_read_header(int fd, char *buf) +{ + int ret = 0; + const int header_len = SLEN(QUOTA_CONF_HEADER); + + ret = gf_nread(fd, buf, header_len); + if (ret <= 0) { + goto out; + } else if (ret > 0 && ret != header_len) { + ret = -1; + goto out; + } + + buf[header_len - 1] = 0; + +out: + if (ret < 0) + gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR, + "failed to read " + "header from a quota conf"); + + return ret; +} + +int32_t +quota_conf_read_version(int fd, float *version) +{ + int ret = 0; + char buf[PATH_MAX] = ""; + char *tail = NULL; + float value = 0.0f; + + ret = quota_conf_read_header(fd, buf); + if (ret == 0) { + /* quota.conf is empty */ + value = GF_QUOTA_CONF_VERSION; + goto out; + } else if (ret < 0) { + goto out; + } + + value = strtof((buf + strlen(buf) - 3), &tail); + if (tail[0] != '\0') { + ret = -1; + gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR, + "invalid quota conf" + " version"); + goto out; + } + + ret = 0; + +out: + if (ret >= 0) + *version = value; + else + gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR, + "failed to " + "read version from a quota conf header"); + + return ret; +} + +int32_t +quota_conf_read_gfid(int fd, void *buf, char *type, float version) +{ + int ret = 0; + + ret = gf_nread(fd, buf, 16); + if (ret <= 0) + goto out; + + if (ret != 16) { + ret = -1; + goto out; + } + + if (version >= 1.2f) { + ret = gf_nread(fd, type, 1); + if (ret != 1) { + ret = -1; + goto out; + } + ret = 17; + } else { + *type = GF_QUOTA_CONF_TYPE_USAGE; + } + +out: + if (ret < 0) + gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR, + "failed to " + "read gfid from a quota conf"); + + return ret; +} + +int32_t +quota_conf_skip_header(int fd) +{ + return gf_skip_header_section(fd, strlen(QUOTA_CONF_HEADER)); +} |
