diff options
Diffstat (limited to 'xlators/features/marker/src/marker-quota-helper.c')
| -rw-r--r-- | xlators/features/marker/src/marker-quota-helper.c | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/xlators/features/marker/src/marker-quota-helper.c b/xlators/features/marker/src/marker-quota-helper.c new file mode 100644 index 00000000000..ecd85d67b2b --- /dev/null +++ b/xlators/features/marker/src/marker-quota-helper.c @@ -0,0 +1,380 @@ +/* + Copyright (c) 2008-2012 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/locking.h> +#include "marker-quota.h" +#include "marker-common.h" +#include "marker-quota-helper.h" +#include "marker-mem-types.h" + +int +mq_loc_fill(loc_t *loc, inode_t *inode, inode_t *parent, char *path) +{ + int ret = -1; + + GF_VALIDATE_OR_GOTO("marker", loc, out); + GF_VALIDATE_OR_GOTO("marker", inode, out); + GF_VALIDATE_OR_GOTO("marker", path, out); + /* Not checking for parent because while filling + * loc of root, parent will be NULL + */ + + if (inode) { + loc->inode = inode_ref(inode); + } + + if (parent) + loc->parent = inode_ref(parent); + + if (!gf_uuid_is_null(inode->gfid)) + gf_uuid_copy(loc->gfid, inode->gfid); + + loc->path = gf_strdup(path); + if (!loc->path) { + gf_log("loc fill", GF_LOG_ERROR, "strdup failed"); + goto out; + } + + loc->name = strrchr(loc->path, '/'); + if (loc->name) + loc->name++; + else + goto out; + + ret = 0; + +out: + if (ret < 0) + loc_wipe(loc); + + return ret; +} + +int32_t +mq_inode_loc_fill(const char *parent_gfid, inode_t *inode, loc_t *loc) +{ + char *resolvedpath = NULL; + inode_t *parent = NULL; + quota_inode_ctx_t *ctx = NULL; + xlator_t *this = NULL; + int ret = -1; + + this = THIS; + + if (inode == NULL) { + gf_log_callingfn("marker", GF_LOG_ERROR, + "loc fill failed, " + "inode is NULL"); + return ret; + } + + if (loc == NULL) + return ret; + + if ((inode) && __is_root_gfid(inode->gfid)) { + loc->parent = NULL; + goto ignore_parent; + } + + if (parent_gfid == NULL) + parent = inode_parent(inode, 0, NULL); + else + parent = inode_find(inode->table, (unsigned char *)parent_gfid); + + if (parent == NULL) { + gf_log("marker", GF_LOG_ERROR, "parent is NULL for %s", + uuid_utoa(inode->gfid)); + goto err; + } + +ignore_parent: + ret = inode_path(inode, NULL, &resolvedpath); + if (ret < 0) { + gf_log("marker", GF_LOG_ERROR, "failed to resolve path for %s", + uuid_utoa(inode->gfid)); + goto err; + } + + ret = mq_loc_fill(loc, inode, parent, resolvedpath); + if (ret < 0) + goto err; + + ret = mq_inode_ctx_get(inode, this, &ctx); + if (ret < 0 || ctx == NULL) + ctx = mq_inode_ctx_new(inode, this); + if (ctx == NULL) { + gf_log(this->name, GF_LOG_WARNING, + "mq_inode_ctx_new " + "failed for %s", + uuid_utoa(inode->gfid)); + ret = -1; + goto err; + } + ret = 0; + +err: + if (parent) + inode_unref(parent); + + GF_FREE(resolvedpath); + + return ret; +} + +quota_inode_ctx_t * +mq_alloc_inode_ctx() +{ + int32_t ret = -1; + quota_inode_ctx_t *ctx = NULL; + + QUOTA_ALLOC(ctx, quota_inode_ctx_t, ret); + if (ret == -1) + goto out; + + ctx->size = 0; + ctx->dirty = 0; + ctx->updation_status = _gf_false; + LOCK_INIT(&ctx->lock); + INIT_LIST_HEAD(&ctx->contribution_head); +out: + return ctx; +} + +static void +mq_contri_fini(inode_contribution_t *contri) +{ + LOCK_DESTROY(&contri->lock); + GF_FREE(contri); +} + +inode_contribution_t * +mq_contri_init(inode_t *inode) +{ + inode_contribution_t *contri = NULL; + int32_t ret = 0; + + QUOTA_ALLOC(contri, inode_contribution_t, ret); + if (ret == -1) + goto out; + + GF_REF_INIT(contri, mq_contri_fini); + + contri->contribution = 0; + contri->file_count = 0; + contri->dir_count = 0; + gf_uuid_copy(contri->gfid, inode->gfid); + + LOCK_INIT(&contri->lock); + INIT_LIST_HEAD(&contri->contri_list); + +out: + return contri; +} + +inode_contribution_t * +mq_get_contribution_node(inode_t *inode, quota_inode_ctx_t *ctx) +{ + inode_contribution_t *contri = NULL; + inode_contribution_t *temp = NULL; + + if (!inode || !ctx) + goto out; + + LOCK(&ctx->lock); + { + if (list_empty(&ctx->contribution_head)) + goto unlock; + + list_for_each_entry(temp, &ctx->contribution_head, contri_list) + { + if (gf_uuid_compare(temp->gfid, inode->gfid) == 0) { + contri = temp; + GF_REF_GET(contri); + break; + } + } + } +unlock: + UNLOCK(&ctx->lock); + +out: + return contri; +} + +inode_contribution_t * +__mq_add_new_contribution_node(xlator_t *this, quota_inode_ctx_t *ctx, + loc_t *loc) +{ + inode_contribution_t *contribution = NULL; + + if (!loc->parent) { + if (!gf_uuid_is_null(loc->pargfid)) + loc->parent = inode_find(loc->inode->table, loc->pargfid); + + if (!loc->parent) + loc->parent = inode_parent(loc->inode, loc->pargfid, loc->name); + if (!loc->parent) + goto out; + } + + list_for_each_entry(contribution, &ctx->contribution_head, contri_list) + { + if (loc->parent && + gf_uuid_compare(contribution->gfid, loc->parent->gfid) == 0) { + goto out; + } + } + + contribution = mq_contri_init(loc->parent); + if (contribution == NULL) + goto out; + + list_add_tail(&contribution->contri_list, &ctx->contribution_head); + +out: + return contribution; +} + +inode_contribution_t * +mq_add_new_contribution_node(xlator_t *this, quota_inode_ctx_t *ctx, loc_t *loc) +{ + inode_contribution_t *contribution = NULL; + + if ((ctx == NULL) || (loc == NULL)) + return NULL; + + if (((loc->path) && (strcmp(loc->path, "/") == 0)) || + (!loc->path && gf_uuid_is_null(loc->pargfid))) + return NULL; + + LOCK(&ctx->lock); + { + contribution = __mq_add_new_contribution_node(this, ctx, loc); + if (contribution) + GF_REF_GET(contribution); + } + UNLOCK(&ctx->lock); + + return contribution; +} + +int32_t +mq_dict_set_contribution(xlator_t *this, dict_t *dict, loc_t *loc, uuid_t gfid, + char *contri_key) +{ + int32_t ret = -1; + char key[QUOTA_KEY_MAX] = { + 0, + }; + + GF_VALIDATE_OR_GOTO("marker", this, out); + GF_VALIDATE_OR_GOTO("marker", dict, out); + GF_VALIDATE_OR_GOTO("marker", loc, out); + + if (gfid && !gf_uuid_is_null(gfid)) { + GET_CONTRI_KEY(this, key, gfid, ret); + } else if (loc->parent) { + GET_CONTRI_KEY(this, key, loc->parent->gfid, ret); + } else { + /* nameless lookup, fetch contributions to all parents */ + GET_CONTRI_KEY(this, key, NULL, ret); + } + + if (ret < 0) + goto out; + + ret = dict_set_int64(dict, key, 0); + if (ret < 0) + goto out; + + if (contri_key) + if (snprintf(contri_key, QUOTA_KEY_MAX, "%s", key) >= QUOTA_KEY_MAX) { + ret = -1; + goto out; + } + +out: + if (ret < 0) + gf_log_callingfn(this ? this->name : "Marker", GF_LOG_ERROR, + "dict set failed"); + + return ret; +} + +int32_t +mq_inode_ctx_get(inode_t *inode, xlator_t *this, quota_inode_ctx_t **ctx) +{ + int32_t ret = -1; + uint64_t ctx_int = 0; + marker_inode_ctx_t *mark_ctx = NULL; + + GF_VALIDATE_OR_GOTO("marker", inode, out); + GF_VALIDATE_OR_GOTO("marker", this, out); + GF_VALIDATE_OR_GOTO("marker", ctx, out); + + ret = inode_ctx_get(inode, this, &ctx_int); + if (ret < 0) { + ret = -1; + *ctx = NULL; + goto out; + } + + mark_ctx = (marker_inode_ctx_t *)(unsigned long)ctx_int; + if (mark_ctx->quota_ctx == NULL) { + ret = -1; + goto out; + } + + *ctx = mark_ctx->quota_ctx; + + ret = 0; + +out: + return ret; +} + +quota_inode_ctx_t * +__mq_inode_ctx_new(inode_t *inode, xlator_t *this) +{ + int32_t ret = -1; + quota_inode_ctx_t *quota_ctx = NULL; + marker_inode_ctx_t *mark_ctx = NULL; + + ret = marker_force_inode_ctx_get(inode, this, &mark_ctx); + if (ret < 0) { + gf_log(this->name, GF_LOG_ERROR, "marker_force_inode_ctx_get() failed"); + goto out; + } + + LOCK(&inode->lock); + { + if (mark_ctx->quota_ctx == NULL) { + quota_ctx = mq_alloc_inode_ctx(); + if (quota_ctx == NULL) { + ret = -1; + goto unlock; + } + mark_ctx->quota_ctx = quota_ctx; + } else { + quota_ctx = mark_ctx->quota_ctx; + } + + ret = 0; + } +unlock: + UNLOCK(&inode->lock); +out: + return quota_ctx; +} + +quota_inode_ctx_t * +mq_inode_ctx_new(inode_t *inode, xlator_t *this) +{ + return __mq_inode_ctx_new(inode, this); +} |
