glusterfs
255 строк · 6.0 Кб
1/*
2Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com>
3This file is part of GlusterFS.
4
5This file is licensed to you under your choice of the GNU Lesser
6General Public License, version 3 or any later version (LGPLv3 or
7later), or the GNU General Public License, version 2 (GPLv2), in all
8cases as published by the Free Software Foundation.
9*/
10
11#include "glusterfs/dict.h"12#include "glusterfs/logging.h"13#include "glusterfs/quota-common-utils.h"14#include "glusterfs/libglusterfs-messages.h"15#include <glusterfs/syscall.h>16
17gf_boolean_t
18quota_meta_is_null(const quota_meta_t *meta)19{
20if (meta->size == 0 && meta->file_count == 0 && meta->dir_count == 0)21return _gf_true;22
23return _gf_false;24}
25
26int32_t
27quota_data_to_meta(data_t *data, quota_meta_t *meta)28{
29int32_t ret = -1;30quota_meta_t *value = NULL;31int64_t *size = NULL;32
33if (!data || !meta)34goto out;35
36if (data->len > sizeof(int64_t)) {37value = (quota_meta_t *)data->data;38meta->size = be64toh(value->size);39meta->file_count = be64toh(value->file_count);40if (data->len > (sizeof(int64_t)) * 2)41meta->dir_count = be64toh(value->dir_count);42else43meta->dir_count = 0;44} else {45size = (int64_t *)data->data;46meta->size = be64toh(*size);47meta->file_count = 0;48meta->dir_count = 0;49/* This can happen during software upgrade.50* Older version of glusterfs will not have inode count.
51* Return failure, this will be healed as part of lookup
52*/
53gf_msg_callingfn("quota", GF_LOG_DEBUG, 0, LG_MSG_QUOTA_XATTRS_MISSING,54"Object quota "55"xattrs missing: len = %d",56data->len);57ret = -2;58goto out;59}60
61ret = 0;62out:63
64return ret;65}
66
67int32_t
68quota_dict_get_inode_meta(dict_t *dict, char *key, const int keylen,69quota_meta_t *meta)70{
71int32_t ret = -1;72data_t *data = NULL;73
74if (!dict || !key || !meta)75goto out;76
77data = dict_getn(dict, key, keylen);78if (!data || !data->data)79goto out;80
81ret = quota_data_to_meta(data, meta);82
83out:84
85return ret;86}
87
88int32_t
89quota_dict_get_meta(dict_t *dict, char *key, const int keylen,90quota_meta_t *meta)91{
92int32_t ret = -1;93
94ret = quota_dict_get_inode_meta(dict, key, keylen, meta);95if (ret == -2)96ret = 0;97
98return ret;99}
100
101int32_t
102quota_dict_set_meta(dict_t *dict, char *key, const quota_meta_t *meta,103ia_type_t ia_type)104{
105int32_t ret = -ENOMEM;106quota_meta_t *value = NULL;107
108value = GF_MALLOC(sizeof(quota_meta_t), gf_common_quota_meta_t);109if (value == NULL) {110goto out;111}112
113value->size = htobe64(meta->size);114value->file_count = htobe64(meta->file_count);115value->dir_count = htobe64(meta->dir_count);116
117if (ia_type == IA_IFDIR) {118ret = dict_set_bin(dict, key, value, sizeof(*value));119} else {120/* For a file we don't need to store dir_count in the121* quota size xattr, so we set the len of the data in the dict
122* as 128bits, so when the posix xattrop reads the dict, it only
123* performs operations on size and file_count
124*/
125ret = dict_set_bin(dict, key, value, sizeof(*value) - sizeof(int64_t));126}127
128if (ret < 0) {129gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_DICT_SET_FAILED,130"dict set failed");131GF_FREE(value);132}133
134out:135return ret;136}
137
138int32_t
139quota_conf_read_header(int fd, char *buf)140{
141int ret = 0;142const int header_len = SLEN(QUOTA_CONF_HEADER);143
144ret = gf_nread(fd, buf, header_len);145if (ret <= 0) {146goto out;147} else if (ret > 0 && ret != header_len) {148ret = -1;149goto out;150}151
152buf[header_len - 1] = 0;153
154out:155if (ret < 0)156gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR,157"failed to read "158"header from a quota conf");159
160return ret;161}
162
163int32_t
164quota_conf_read_version(int fd, float *version)165{
166int ret = 0;167char buf[PATH_MAX] = "";168char *tail = NULL;169float value = 0.0f;170
171ret = quota_conf_read_header(fd, buf);172if (ret == 0) {173/* quota.conf is empty */174value = GF_QUOTA_CONF_VERSION;175goto out;176} else if (ret < 0) {177goto out;178}179
180value = strtof((buf + strlen(buf) - 3), &tail);181if (tail[0] != '\0') {182ret = -1;183gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR,184"invalid quota conf"185" version");186goto out;187}188
189ret = 0;190
191out:192if (ret >= 0)193*version = value;194else195gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR,196"failed to "197"read version from a quota conf header");198
199return ret;200}
201
202int32_t
203quota_conf_read_gfid(int fd, void *buf, char *type, float version)204{
205int ret = 0;206
207ret = gf_nread(fd, buf, 16);208if (ret <= 0)209goto out;210
211if (ret != 16) {212ret = -1;213goto out;214}215
216if (version >= 1.2f) {217ret = gf_nread(fd, type, 1);218if (ret != 1) {219ret = -1;220goto out;221}222ret = 17;223} else {224*type = GF_QUOTA_CONF_TYPE_USAGE;225}226
227out:228if (ret < 0)229gf_msg_callingfn("quota", GF_LOG_ERROR, 0, LG_MSG_QUOTA_CONF_ERROR,230"failed to "231"read gfid from a quota conf");232
233return ret;234}
235
236static int237gf_skip_header_section(int fd, int header_len)238{
239int ret = -1;240
241ret = sys_lseek(fd, header_len, SEEK_SET);242if (ret == (off_t)-1) {243gf_smsg("", GF_LOG_ERROR, 0, LG_MSG_SKIP_HEADER_FAILED, NULL);244} else {245ret = 0;246}247
248return ret;249}
250
251int32_t
252quota_conf_skip_header(int fd)253{
254return gf_skip_header_section(fd, strlen(QUOTA_CONF_HEADER));255}
256