diff options
author | Xavier Hernandez <xhernandez@datalab.es> | 2014-05-05 12:57:34 +0200 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2014-07-11 10:33:40 -0700 |
commit | ad112305a1c7452b13c92238b40ded80361838f3 (patch) | |
tree | 82dbf9aa0b77eb76d43c8b1ccb3ba58e61bc4e2a /xlators/cluster/ec/src/ec-data.c | |
parent | 6b4702897bd56e29db4db06f8cf896f89df1133c (diff) |
cluster/ec: Added erasure code translator
Change-Id: I293917501d5c2ca4cdc6303df30cf0b568cea361
BUG: 1118629
Signed-off-by: Xavier Hernandez <xhernandez@datalab.es>
Reviewed-on: http://review.gluster.org/7749
Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
Reviewed-by: Jeff Darcy <jdarcy@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'xlators/cluster/ec/src/ec-data.c')
-rw-r--r-- | xlators/cluster/ec/src/ec-data.c | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/xlators/cluster/ec/src/ec-data.c b/xlators/cluster/ec/src/ec-data.c new file mode 100644 index 00000000000..0e72fbbd3b6 --- /dev/null +++ b/xlators/cluster/ec/src/ec-data.c @@ -0,0 +1,261 @@ +/* + Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + + This file is part of the cluster/ec translator for GlusterFS. + + The cluster/ec translator for GlusterFS is free software: you can + redistribute it and/or modify it under the terms of the GNU General + Public License as published by the Free Software Foundation, either + version 3 of the License, or (at your option) any later version. + + The cluster/ec translator for GlusterFS is distributed in the hope + that it will be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the cluster/ec translator for GlusterFS. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#include "ec-mem-types.h" +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-data.h" + +ec_cbk_data_t * ec_cbk_data_allocate(call_frame_t * frame, xlator_t * this, + ec_fop_data_t * fop, int32_t id, + int32_t idx, int32_t op_ret, + int32_t op_errno) +{ + ec_cbk_data_t * cbk; + ec_t * ec = this->private; + + if (fop->xl != this) + { + gf_log(this->name, GF_LOG_ERROR, "Mismatching xlators between request " + "and answer (req=%s, ans=%s).", + fop->xl->name, this->name); + + return NULL; + } + if (fop->frame != frame) + { + gf_log(this->name, GF_LOG_ERROR, "Mismatching frames between request " + "and answer (req=%p, ans=%p).", + fop->frame, frame); + + return NULL; + } + if (fop->id != id) + { + gf_log(this->name, GF_LOG_ERROR, "Mismatching fops between request " + "and answer (req=%d, ans=%d).", + fop->id, id); + + return NULL; + } + + cbk = mem_get0(ec->cbk_pool); + if (cbk == NULL) + { + gf_log(this->name, GF_LOG_ERROR, "Failed to allocate memory for an " + "answer."); + } + + cbk->fop = fop; + cbk->idx = idx; + cbk->mask = 1ULL << idx; + cbk->count = 1; + cbk->op_ret = op_ret; + cbk->op_errno = op_errno; + + LOCK(&fop->lock); + + list_add_tail(&cbk->answer_list, &fop->answer_list); + + UNLOCK(&fop->lock); + + return cbk; +} + +void ec_cbk_data_destroy(ec_cbk_data_t * cbk) +{ + if (cbk->xdata != NULL) + { + dict_unref(cbk->xdata); + } + if (cbk->dict != NULL) + { + dict_unref(cbk->dict); + } + if (cbk->inode != NULL) + { + inode_unref(cbk->inode); + } + if (cbk->fd != NULL) + { + fd_unref(cbk->fd); + } + if (cbk->buffers != NULL) + { + iobref_unref(cbk->buffers); + } + GF_FREE(cbk->vector); + + mem_put(cbk); +} + +ec_fop_data_t * ec_fop_data_allocate(call_frame_t * frame, xlator_t * this, + int32_t id, uint32_t flags, + uintptr_t target, int32_t minimum, + ec_wind_f wind, ec_handler_f handler, + ec_cbk_t cbks, void * data) +{ + ec_fop_data_t * fop, * parent; + ec_t * ec = this->private; + + fop = mem_get0(ec->fop_pool); + if (fop == NULL) + { + gf_log(this->name, GF_LOG_ERROR, "Failed to allocate memory for a " + "request."); + + return NULL; + } + + fop->xl = this; + fop->req_frame = frame; + + /* fops need a private frame to be able to execute some postop operations + * even if the original fop has completed and reported back to the upper + * xlator and it has destroyed the base frame. + * + * TODO: minimize usage of private frames. Reuse req_frame as much as + * possible. + */ + if (frame != NULL) + { + fop->frame = copy_frame(frame); + } + else + { + fop->frame = create_frame(this, this->ctx->pool); + } + if (fop->frame == NULL) + { + gf_log(this->name, GF_LOG_ERROR, "Failed to create a private frame " + "for a request"); + + mem_put(fop); + + return NULL; + } + fop->id = id; + fop->refs = 1; + + fop->flags = flags; + fop->minimum = minimum; + fop->mask = target; + + INIT_LIST_HEAD(&fop->lock_list); + INIT_LIST_HEAD(&fop->cbk_list); + INIT_LIST_HEAD(&fop->answer_list); + + fop->wind = wind; + fop->handler = handler; + fop->cbks = cbks; + fop->data = data; + + LOCK_INIT(&fop->lock); + + fop->frame->local = fop; + + if (frame != NULL) + { + parent = frame->local; + if (parent != NULL) + { + LOCK(&parent->lock); + + parent->jobs++; + parent->refs++; + + UNLOCK(&parent->lock); + } + + fop->parent = parent; + } + + return fop; +} + +void ec_fop_data_acquire(ec_fop_data_t * fop) +{ + LOCK(&fop->lock); + + ec_trace("ACQUIRE", fop, ""); + + fop->refs++; + + UNLOCK(&fop->lock); +} + +void ec_fop_data_release(ec_fop_data_t * fop) +{ + ec_cbk_data_t * cbk, * tmp; + int32_t refs; + + LOCK(&fop->lock); + + ec_trace("RELEASE", fop, ""); + + refs = --fop->refs; + + UNLOCK(&fop->lock); + + if (refs == 0) + { + fop->frame->local = NULL; + STACK_DESTROY(fop->frame->root); + + LOCK_DESTROY(&fop->lock); + + if (fop->xdata != NULL) + { + dict_unref(fop->xdata); + } + if (fop->dict != NULL) + { + dict_unref(fop->dict); + } + if (fop->inode != NULL) + { + inode_unref(fop->inode); + } + if (fop->fd != NULL) + { + fd_unref(fop->fd); + } + if (fop->buffers != NULL) + { + iobref_unref(fop->buffers); + } + GF_FREE(fop->vector); + GF_FREE(fop->str[0]); + GF_FREE(fop->str[1]); + loc_wipe(&fop->loc[0]); + loc_wipe(&fop->loc[1]); + + ec_resume_parent(fop, fop->error); + + list_for_each_entry_safe(cbk, tmp, &fop->answer_list, answer_list) + { + list_del_init(&cbk->answer_list); + + ec_cbk_data_destroy(cbk); + } + + mem_put(fop); + } +} |