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