Blame libglusterfs/src/quota-common-utils.c

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
}