diff options
Diffstat (limited to 'xlators/cluster/ec/src/ec-data.c')
| -rw-r--r-- | xlators/cluster/ec/src/ec-data.c | 247 |
1 files changed, 137 insertions, 110 deletions
diff --git a/xlators/cluster/ec/src/ec-data.c b/xlators/cluster/ec/src/ec-data.c index 0e72fbbd3b6..06388833546 100644 --- a/xlators/cluster/ec/src/ec-data.c +++ b/xlators/cluster/ec/src/ec-data.c @@ -1,66 +1,56 @@ /* - Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + Copyright (c) 2012-2014 DataLab, s.l. <http://www.datalab.es> + This file is part of GlusterFS. - 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/>. + 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 "ec-mem-types.h" #include "ec-helpers.h" #include "ec-common.h" #include "ec-data.h" +#include "ec-messages.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 * +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; + 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); + if (fop->xl != this) { + gf_msg(this->name, GF_LOG_ERROR, EINVAL, EC_MSG_XLATOR_MISMATCH, + "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); + if (fop->frame != frame) { + gf_msg(this->name, GF_LOG_ERROR, EINVAL, EC_MSG_FRAME_MISMATCH, + "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); + if (fop->id != id) { + gf_msg(this->name, GF_LOG_ERROR, EINVAL, EC_MSG_FOP_MISMATCH, + "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."); + if (cbk == NULL) { + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, EC_MSG_NO_MEMORY, + "Failed to allocate memory for an " + "answer."); + return NULL; } cbk->fop = fop; @@ -69,6 +59,7 @@ ec_cbk_data_t * ec_cbk_data_allocate(call_frame_t * frame, xlator_t * this, cbk->count = 1; cbk->op_ret = op_ret; cbk->op_errno = op_errno; + INIT_LIST_HEAD(&cbk->entries.list); LOCK(&fop->lock); @@ -79,51 +70,58 @@ ec_cbk_data_t * ec_cbk_data_allocate(call_frame_t * frame, xlator_t * this, return cbk; } -void ec_cbk_data_destroy(ec_cbk_data_t * cbk) +void +ec_cbk_data_destroy(ec_cbk_data_t *cbk) { - if (cbk->xdata != NULL) - { + if (cbk->xdata != NULL) { dict_unref(cbk->xdata); } - if (cbk->dict != NULL) - { + if (cbk->dict != NULL) { dict_unref(cbk->dict); } - if (cbk->inode != NULL) - { + if (cbk->inode != NULL) { inode_unref(cbk->inode); } - if (cbk->fd != NULL) - { + if (cbk->fd != NULL) { fd_unref(cbk->fd); } - if (cbk->buffers != NULL) - { + if (cbk->buffers != NULL) { iobref_unref(cbk->buffers); } GF_FREE(cbk->vector); + gf_dirent_free(&cbk->entries); + GF_FREE(cbk->str); 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 * +ec_fop_data_allocate(call_frame_t *frame, xlator_t *this, int32_t id, + uint32_t flags, uintptr_t target, uint32_t fop_flags, + 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; + 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."); + if (fop == NULL) { + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, EC_MSG_NO_MEMORY, + "Failed to allocate memory for a " + "request."); return NULL; } + INIT_LIST_HEAD(&fop->cbk_list); + INIT_LIST_HEAD(&fop->healer); + INIT_LIST_HEAD(&fop->answer_list); + INIT_LIST_HEAD(&fop->pending_list); + INIT_LIST_HEAD(&fop->locks[0].owner_list); + INIT_LIST_HEAD(&fop->locks[0].wait_list); + INIT_LIST_HEAD(&fop->locks[1].owner_list); + INIT_LIST_HEAD(&fop->locks[1].wait_list); + fop->xl = this; fop->req_frame = frame; @@ -134,18 +132,15 @@ ec_fop_data_t * ec_fop_data_allocate(call_frame_t * frame, xlator_t * this, * TODO: minimize usage of private frames. Reuse req_frame as much as * possible. */ - if (frame != NULL) - { + if (frame != NULL) { fop->frame = copy_frame(frame); - } - else - { + } 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"); + if (fop->frame == NULL) { + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, EC_MSG_NO_MEMORY, + "Failed to create a private frame " + "for a request"); mem_put(fop); @@ -155,42 +150,42 @@ ec_fop_data_t * ec_fop_data_allocate(call_frame_t * frame, xlator_t * this, fop->refs = 1; fop->flags = flags; - fop->minimum = minimum; + fop->minimum = EC_FOP_MINIMUM(fop_flags); + fop->fop_flags = EC_FOP_FLAGS(fop_flags); 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; + fop->uid = fop->frame->root->uid; + fop->gid = fop->frame->root->gid; + LOCK_INIT(&fop->lock); fop->frame->local = fop; - if (frame != NULL) - { + if (frame != NULL) { parent = frame->local; - if (parent != NULL) - { - LOCK(&parent->lock); - - parent->jobs++; - parent->refs++; - - UNLOCK(&parent->lock); + if (parent != NULL) { + ec_sleep(parent); } fop->parent = parent; } + LOCK(&ec->lock); + + list_add_tail(&fop->pending_list, &ec->pending_fops); + + UNLOCK(&ec->lock); + return fop; } -void ec_fop_data_acquire(ec_fop_data_t * fop) +void +ec_fop_data_acquire(ec_fop_data_t *fop) { LOCK(&fop->lock); @@ -201,44 +196,74 @@ void ec_fop_data_acquire(ec_fop_data_t * fop) UNLOCK(&fop->lock); } -void ec_fop_data_release(ec_fop_data_t * fop) +static void +ec_handle_last_pending_fop_completion(ec_fop_data_t *fop, gf_boolean_t *notify) { - ec_cbk_data_t * cbk, * tmp; + ec_t *ec = fop->xl->private; + + *notify = _gf_false; + + if (!list_empty(&fop->pending_list)) { + LOCK(&ec->lock); + { + list_del_init(&fop->pending_list); + *notify = __ec_is_last_fop(ec); + } + UNLOCK(&ec->lock); + } +} + +void +ec_fop_cleanup(ec_fop_data_t *fop) +{ + ec_cbk_data_t *cbk, *tmp; + + list_for_each_entry_safe(cbk, tmp, &fop->answer_list, answer_list) + { + list_del_init(&cbk->answer_list); + + ec_cbk_data_destroy(cbk); + } + INIT_LIST_HEAD(&fop->cbk_list); + + fop->answer = NULL; +} + +void +ec_fop_data_release(ec_fop_data_t *fop) +{ + ec_t *ec = NULL; int32_t refs; + gf_boolean_t notify = _gf_false; LOCK(&fop->lock); ec_trace("RELEASE", fop, ""); + GF_ASSERT(fop->refs > 0); refs = --fop->refs; UNLOCK(&fop->lock); - if (refs == 0) - { + if (refs == 0) { fop->frame->local = NULL; STACK_DESTROY(fop->frame->root); LOCK_DESTROY(&fop->lock); - if (fop->xdata != NULL) - { + if (fop->xdata != NULL) { dict_unref(fop->xdata); } - if (fop->dict != NULL) - { + if (fop->dict != NULL) { dict_unref(fop->dict); } - if (fop->inode != NULL) - { + if (fop->inode != NULL) { inode_unref(fop->inode); } - if (fop->fd != NULL) - { + if (fop->fd != NULL) { fd_unref(fop->fd); } - if (fop->buffers != NULL) - { + if (fop->buffers != NULL) { iobref_unref(fop->buffers); } GF_FREE(fop->vector); @@ -246,16 +271,18 @@ void ec_fop_data_release(ec_fop_data_t * fop) GF_FREE(fop->str[1]); loc_wipe(&fop->loc[0]); loc_wipe(&fop->loc[1]); + GF_FREE(fop->errstr); - ec_resume_parent(fop, fop->error); + ec_resume_parent(fop); - list_for_each_entry_safe(cbk, tmp, &fop->answer_list, answer_list) - { - list_del_init(&cbk->answer_list); - - ec_cbk_data_destroy(cbk); - } + ec_fop_cleanup(fop); + ec = fop->xl->private; + ec_handle_last_pending_fop_completion(fop, ¬ify); + ec_handle_healers_done(fop); mem_put(fop); + if (notify) { + ec_pending_fops_completed(ec); + } } } |
