diff options
author | Raghavendra G <rgowdapp@redhat.com> | 2013-09-16 17:46:50 +0530 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2013-11-26 10:24:02 -0800 |
commit | ab3ab1978a4768e9eed8e23b47e72b25046e607a (patch) | |
tree | f4e8d1a5aecd24d45a9db531d658a947cd94261d /xlators/features/quota/src/quotad.c | |
parent | 460ce40d3e2069bf6262dccea6f5ae2fac60d90f (diff) |
features/quota: Improvements to quota
* Two stages of quota enforcement is done:
Soft and hard quota Upon reaching soft quota limit on the directory
it logs/alerts in the quota daemon log (ie DEFAULT_LOG_DIR/quotad.log)
and no more writes allowed after hard
quota limit. After reaching the soft-limit the daemon alerts the
user/admin repeatively for every 'alert-time', which is
configurable.
* Quota enforcer is moved to server-side.
It takes care of enforcing quota. Since enforcer doesn't have the
cluster view, it relies on another service called
quota-aggregator. Aggregator, on query can return the size of a
directory based on the cluster view.
Enforcer is always loaded in the server graph and is by passed if
the feature is not enabled.
Options specific to enforcer:
server-quota - Specifies whether the feature is on/off. It is used
to by pass the quota if turned off.
deem-statfs - If set to on, it takes quota limits into consideration
while estimating fs size. (df command). The algorithm followed is,
i. Adjust statvfs based on limit configured on root.
ii. If limit is set on the inode passed, use size/limits on that inode to
populate statvfs. Otherwise, use size/limits configured on root.
iii. Upon statvfs, update the ctx->size on the inode.
iv. Don't let DHT aggregate, instead take the maximum of the usages from the
subvols of the DHT, since each of it contains the complete information.
Enforcer also makes use of gfid-to-path conversion functionality to
work correctly when a client like nfs predominently relies on
nameless lookups.
* Quota Aggregator acts as a thin client to provide cluster view
Its a lightweight *gluster client* process with no mount point,
started upon enabling quota or restarting the volume. This is a
single process run on each brick, which can answer queries on all
volumes in the cluster. Its volfile stored in
GLUSTERD_DEFAULT_WORKING_DIR/quotad/quotad.vol.
Credits:
Raghavendra Bhat <rabhat@redhat.com>
Varun Shastry <vshastry@redhat.com>
Shishir Gowda <sgowda@redhat.com>
Kruthika Dhananjay <kdhananj@redhat.com>
Brian Foster <bfoster@redhat.com>
Krishnan Parthasarathi <kparthas@redhat.com>
Change-Id: Id1cb25b414951da34c665a55f77385d482e0f9de
BUG: 969461
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
Reviewed-on: http://review.gluster.org/5952
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'xlators/features/quota/src/quotad.c')
-rw-r--r-- | xlators/features/quota/src/quotad.c | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/xlators/features/quota/src/quotad.c b/xlators/features/quota/src/quotad.c new file mode 100644 index 00000000000..243b943e986 --- /dev/null +++ b/xlators/features/quota/src/quotad.c @@ -0,0 +1,210 @@ +/* + Copyright (c) 2013 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 "quota.h" +#include "quotad-aggregator.h" +#include "common-utils.h" + +int32_t +mem_acct_init (xlator_t *this) +{ + int ret = -1; + + if (!this) + return ret; + + ret = xlator_mem_acct_init (this, gf_quota_mt_end + 1); + + if (0 != ret) { + gf_log (this->name, GF_LOG_WARNING, "Memory accounting " + "init failed"); + return ret; + } + + return ret; +} + +int32_t +qd_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, struct iatt *postparent) +{ + quotad_aggregator_lookup_cbk_t lookup_cbk = NULL; + gfs3_lookup_rsp rsp = {0, }; + + lookup_cbk = cookie; + + rsp.op_ret = op_ret; + rsp.op_errno = op_errno; + + gf_stat_from_iatt (&rsp.postparent, postparent); + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, (&rsp.xdata.xdata_val), + rsp.xdata.xdata_len, rsp.op_errno, out); + + gf_stat_from_iatt (&rsp.stat, buf); + +out: + lookup_cbk (this, frame, &rsp); + + GF_FREE (rsp.xdata.xdata_val); + + inode_unref (inode); + + return 0; +} + +xlator_t * +qd_find_subvol (xlator_t *this, char *volume_uuid) +{ + xlator_list_t *child = NULL; + xlator_t *subvol = NULL; + char key[1024]; + char *optstr = NULL; + + if (!this || !volume_uuid) + goto out; + + for (child = this->children; child; child = child->next) { + snprintf(key, 1024, "%s.volume-id", child->xlator->name); + if (dict_get_str(this->options, key, &optstr) < 0) + continue; + + if (strcmp (optstr, volume_uuid) == 0) { + subvol = child->xlator; + break; + } + } + +out: + return subvol; +} + +int +qd_nameless_lookup (xlator_t *this, call_frame_t *frame, gfs3_lookup_req *req, + dict_t *xdata, quotad_aggregator_lookup_cbk_t lookup_cbk) +{ + gfs3_lookup_rsp rsp = {0, }; + int op_errno = 0, ret = -1; + loc_t loc = {0, }; + quotad_aggregator_state_t *state = NULL; + quota_priv_t *priv = NULL; + xlator_t *subvol = NULL; + char *volume_uuid = NULL; + + priv = this->private; + state = frame->root->state; + + frame->root->op = GF_FOP_LOOKUP; + + loc.inode = inode_new (state->itable); + if (loc.inode == NULL) { + op_errno = ENOMEM; + goto out; + } + + memcpy (loc.gfid, req->gfid, 16); + + ret = dict_get_str (xdata, "volume-uuid", &volume_uuid); + if (ret < 0) { + op_errno = EINVAL; + goto out; + } + + subvol = qd_find_subvol (this, volume_uuid); + if (subvol == NULL) { + op_errno = EINVAL; + goto out; + } + + STACK_WIND_COOKIE (frame, qd_lookup_cbk, lookup_cbk, subvol, + subvol->fops->lookup, &loc, xdata); + return 0; + +out: + rsp.op_ret = -1; + rsp.op_errno = op_errno; + + lookup_cbk (this, frame, &rsp); + + inode_unref (loc.inode); + return 0; +} + +int +qd_reconfigure (xlator_t *this, dict_t *options) +{ + /* As of now quotad is restarted upon alteration of volfile */ + return 0; +} + +void +qd_fini (xlator_t *this) +{ + return; +} + +int32_t +qd_init (xlator_t *this) +{ + int32_t ret = -1; + quota_priv_t *priv = NULL; + + if (NULL == this->children) { + gf_log (this->name, GF_LOG_ERROR, + "FATAL: quota (%s) not configured for min of 1 child", + this->name); + ret = -1; + goto err; + } + + QUOTA_ALLOC_OR_GOTO (priv, quota_priv_t, err); + LOCK_INIT (&priv->lock); + + this->private = priv; + + ret = quotad_aggregator_init (this); + if (ret < 0) + goto err; + + ret = 0; +err: + if (ret) { + GF_FREE (priv); + } + return ret; +} + +class_methods_t class_methods = { + .init = qd_init, + .fini = qd_fini, + .reconfigure = qd_reconfigure, +}; + +struct xlator_fops fops = { +}; + +struct xlator_cbks cbks = { +}; + +struct volume_options options[] = { + { .key = {"transport-type"}, + .value = {"rpc", "rpc-over-rdma", "tcp", "socket", "ib-verbs", + "unix", "ib-sdp", "tcp/server", "ib-verbs/server", "rdma", + "rdma*([ \t]),*([ \t])socket", + "rdma*([ \t]),*([ \t])tcp", + "tcp*([ \t]),*([ \t])rdma", + "socket*([ \t]),*([ \t])rdma"}, + .type = GF_OPTION_TYPE_STR + }, + { .key = {"transport.*"}, + .type = GF_OPTION_TYPE_ANY, + }, + {.key = {NULL}} +}; |