"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/xlators/cluster/ec/src/ec-generic.c" (16 Sep 2020, 43966 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ec-generic.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2   Copyright (c) 2012-2014 DataLab, s.l. <http://www.datalab.es>
    3   This file is part of GlusterFS.
    4 
    5   This file is licensed to you under your choice of the GNU Lesser
    6   General Public License, version 3 or any later version (LGPLv3 or
    7   later), or the GNU General Public License, version 2 (GPLv2), in all
    8   cases as published by the Free Software Foundation.
    9 */
   10 
   11 #include <glusterfs/byte-order.h>
   12 
   13 #include "ec.h"
   14 #include "ec-messages.h"
   15 #include "ec-helpers.h"
   16 #include "ec-common.h"
   17 #include "ec-combine.h"
   18 #include "ec-fops.h"
   19 
   20 /* FOP: flush */
   21 
   22 int32_t
   23 ec_flush_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
   24              int32_t op_errno, dict_t *xdata)
   25 {
   26     ec_fop_data_t *fop = NULL;
   27     ec_cbk_data_t *cbk = NULL;
   28     int32_t idx = (int32_t)(uintptr_t)cookie;
   29 
   30     VALIDATE_OR_GOTO(this, out);
   31     GF_VALIDATE_OR_GOTO(this->name, frame, out);
   32     GF_VALIDATE_OR_GOTO(this->name, frame->local, out);
   33     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
   34 
   35     fop = frame->local;
   36 
   37     ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, frame,
   38              op_ret, op_errno);
   39 
   40     cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FLUSH, idx, op_ret,
   41                                op_errno);
   42     if (cbk != NULL) {
   43         if (xdata != NULL) {
   44             cbk->xdata = dict_ref(xdata);
   45             if (cbk->xdata == NULL) {
   46                 gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
   47                        "Failed to reference a "
   48                        "dictionary.");
   49 
   50                 goto out;
   51             }
   52         }
   53 
   54         ec_combine(cbk, NULL);
   55     }
   56 
   57 out:
   58     if (fop != NULL) {
   59         ec_complete(fop);
   60     }
   61 
   62     return 0;
   63 }
   64 
   65 void
   66 ec_wind_flush(ec_t *ec, ec_fop_data_t *fop, int32_t idx)
   67 {
   68     ec_trace("WIND", fop, "idx=%d", idx);
   69 
   70     STACK_WIND_COOKIE(fop->frame, ec_flush_cbk, (void *)(uintptr_t)idx,
   71                       ec->xl_list[idx], ec->xl_list[idx]->fops->flush, fop->fd,
   72                       fop->xdata);
   73 }
   74 
   75 int32_t
   76 ec_manager_flush(ec_fop_data_t *fop, int32_t state)
   77 {
   78     ec_cbk_data_t *cbk;
   79 
   80     switch (state) {
   81         case EC_STATE_INIT:
   82         case EC_STATE_LOCK:
   83             ec_lock_prepare_fd(fop, fop->fd, 0, 0, EC_RANGE_FULL);
   84             ec_lock(fop);
   85 
   86             return EC_STATE_DISPATCH;
   87 
   88         case EC_STATE_DISPATCH:
   89             ec_flush_size_version(fop);
   90 
   91             return EC_STATE_DELAYED_START;
   92 
   93         case EC_STATE_DELAYED_START:
   94             ec_dispatch_all(fop);
   95 
   96             return EC_STATE_PREPARE_ANSWER;
   97 
   98         case EC_STATE_PREPARE_ANSWER:
   99             ec_fop_prepare_answer(fop, _gf_false);
  100 
  101             return EC_STATE_REPORT;
  102 
  103         case EC_STATE_REPORT:
  104             cbk = fop->answer;
  105 
  106             GF_ASSERT(cbk != NULL);
  107 
  108             if (fop->cbks.flush != NULL) {
  109                 fop->cbks.flush(fop->req_frame, fop, fop->xl, cbk->op_ret,
  110                                 cbk->op_errno, cbk->xdata);
  111             }
  112 
  113             return EC_STATE_LOCK_REUSE;
  114 
  115         case -EC_STATE_INIT:
  116         case -EC_STATE_LOCK:
  117         case -EC_STATE_DELAYED_START:
  118         case -EC_STATE_DISPATCH:
  119         case -EC_STATE_PREPARE_ANSWER:
  120         case -EC_STATE_REPORT:
  121             GF_ASSERT(fop->error != 0);
  122 
  123             if (fop->cbks.flush != NULL) {
  124                 fop->cbks.flush(fop->req_frame, fop, fop->xl, -1, fop->error,
  125                                 NULL);
  126             }
  127 
  128             return EC_STATE_LOCK_REUSE;
  129 
  130         case -EC_STATE_LOCK_REUSE:
  131         case EC_STATE_LOCK_REUSE:
  132             ec_lock_reuse(fop);
  133 
  134             return EC_STATE_UNLOCK;
  135 
  136         case -EC_STATE_UNLOCK:
  137         case EC_STATE_UNLOCK:
  138             ec_unlock(fop);
  139 
  140             return EC_STATE_END;
  141 
  142         default:
  143             gf_msg(fop->xl->name, GF_LOG_ERROR, EINVAL, EC_MSG_UNHANDLED_STATE,
  144                    "Unhandled state %d for %s", state, ec_fop_name(fop->id));
  145 
  146             return EC_STATE_END;
  147     }
  148 }
  149 
  150 static int32_t
  151 ec_validate_fd(fd_t *fd, xlator_t *xl)
  152 {
  153     uint64_t iversion = 0;
  154     uint64_t fversion = 0;
  155     ec_inode_t *inode_ctx = NULL;
  156     ec_fd_t *fd_ctx = NULL;
  157 
  158     LOCK(&fd->lock);
  159     {
  160         fd_ctx = __ec_fd_get(fd, xl);
  161         if (fd_ctx) {
  162             fversion = fd_ctx->bad_version;
  163         }
  164     }
  165     UNLOCK(&fd->lock);
  166 
  167     LOCK(&fd->inode->lock);
  168     {
  169         inode_ctx = __ec_inode_get(fd->inode, xl);
  170         if (inode_ctx) {
  171             iversion = inode_ctx->bad_version;
  172         }
  173     }
  174     UNLOCK(&fd->inode->lock);
  175     if (fversion < iversion) {
  176         return EBADF;
  177     }
  178     return 0;
  179 }
  180 
  181 void
  182 ec_flush(call_frame_t *frame, xlator_t *this, uintptr_t target,
  183          uint32_t fop_flags, fop_flush_cbk_t func, void *data, fd_t *fd,
  184          dict_t *xdata)
  185 {
  186     ec_cbk_t callback = {.flush = func};
  187     ec_fop_data_t *fop = NULL;
  188     int32_t error = ENOMEM;
  189 
  190     gf_msg_trace("ec", 0, "EC(FLUSH) %p", frame);
  191 
  192     VALIDATE_OR_GOTO(this, out);
  193     GF_VALIDATE_OR_GOTO(this->name, frame, out);
  194     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
  195 
  196     if (fd) {
  197         error = ec_validate_fd(fd, this);
  198         if (error) {
  199             gf_msg(this->name, GF_LOG_ERROR, EBADF, EC_MSG_FD_BAD,
  200                    "Failing %s on %s", gf_fop_list[GF_FOP_FLUSH],
  201                    fd->inode ? uuid_utoa(fd->inode->gfid) : "");
  202             goto out;
  203         }
  204     }
  205 
  206     fop = ec_fop_data_allocate(frame, this, GF_FOP_FLUSH, 0, target, fop_flags,
  207                                ec_wind_flush, ec_manager_flush, callback, data);
  208     if (fop == NULL) {
  209         goto out;
  210     }
  211 
  212     fop->use_fd = 1;
  213 
  214     if (fd != NULL) {
  215         fop->fd = fd_ref(fd);
  216         if (fop->fd == NULL) {
  217             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_FILE_DESC_REF_FAIL,
  218                    "Failed to reference a "
  219                    "file descriptor.");
  220 
  221             goto out;
  222         }
  223     }
  224     if (xdata != NULL) {
  225         fop->xdata = dict_ref(xdata);
  226         if (fop->xdata == NULL) {
  227             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
  228                    "Failed to reference a "
  229                    "dictionary.");
  230 
  231             goto out;
  232         }
  233     }
  234 
  235     error = 0;
  236 
  237 out:
  238     if (fop != NULL) {
  239         ec_manager(fop, error);
  240     } else {
  241         func(frame, NULL, this, -1, error, NULL);
  242     }
  243 }
  244 
  245 /* FOP: fsync */
  246 
  247 int32_t
  248 ec_combine_fsync(ec_fop_data_t *fop, ec_cbk_data_t *dst, ec_cbk_data_t *src)
  249 {
  250     if (!ec_iatt_combine(fop, dst->iatt, src->iatt, 2)) {
  251         gf_msg(fop->xl->name, GF_LOG_NOTICE, 0, EC_MSG_IATT_MISMATCH,
  252                "Mismatching iatt in "
  253                "answers of 'GF_FOP_FSYNC'");
  254 
  255         return 0;
  256     }
  257 
  258     return 1;
  259 }
  260 
  261 int32_t
  262 ec_fsync_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
  263              int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf,
  264              dict_t *xdata)
  265 {
  266     ec_fop_data_t *fop = NULL;
  267     ec_cbk_data_t *cbk = NULL;
  268     int32_t idx = (int32_t)(uintptr_t)cookie;
  269 
  270     VALIDATE_OR_GOTO(this, out);
  271     GF_VALIDATE_OR_GOTO(this->name, frame, out);
  272     GF_VALIDATE_OR_GOTO(this->name, frame->local, out);
  273     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
  274 
  275     fop = frame->local;
  276 
  277     ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, frame,
  278              op_ret, op_errno);
  279 
  280     cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FSYNC, idx, op_ret,
  281                                op_errno);
  282     if (cbk != NULL) {
  283         if (op_ret >= 0) {
  284             if (prebuf != NULL) {
  285                 cbk->iatt[0] = *prebuf;
  286             }
  287             if (postbuf != NULL) {
  288                 cbk->iatt[1] = *postbuf;
  289             }
  290         }
  291         if (xdata != NULL) {
  292             cbk->xdata = dict_ref(xdata);
  293             if (cbk->xdata == NULL) {
  294                 gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
  295                        "Failed to reference a "
  296                        "dictionary.");
  297 
  298                 goto out;
  299             }
  300         }
  301 
  302         ec_combine(cbk, ec_combine_fsync);
  303     }
  304 
  305 out:
  306     if (fop != NULL) {
  307         ec_complete(fop);
  308     }
  309 
  310     return 0;
  311 }
  312 
  313 void
  314 ec_wind_fsync(ec_t *ec, ec_fop_data_t *fop, int32_t idx)
  315 {
  316     ec_trace("WIND", fop, "idx=%d", idx);
  317 
  318     STACK_WIND_COOKIE(fop->frame, ec_fsync_cbk, (void *)(uintptr_t)idx,
  319                       ec->xl_list[idx], ec->xl_list[idx]->fops->fsync, fop->fd,
  320                       fop->int32, fop->xdata);
  321 }
  322 
  323 int32_t
  324 ec_manager_fsync(ec_fop_data_t *fop, int32_t state)
  325 {
  326     ec_cbk_data_t *cbk;
  327 
  328     switch (state) {
  329         case EC_STATE_INIT:
  330         case EC_STATE_LOCK:
  331             ec_lock_prepare_fd(fop, fop->fd, EC_QUERY_INFO, 0, EC_RANGE_FULL);
  332             ec_lock(fop);
  333 
  334             return EC_STATE_DISPATCH;
  335 
  336         case EC_STATE_DISPATCH:
  337             ec_flush_size_version(fop);
  338 
  339             return EC_STATE_DELAYED_START;
  340 
  341         case EC_STATE_DELAYED_START:
  342             ec_dispatch_all(fop);
  343 
  344             return EC_STATE_PREPARE_ANSWER;
  345 
  346         case EC_STATE_PREPARE_ANSWER:
  347             cbk = ec_fop_prepare_answer(fop, _gf_false);
  348             if (cbk != NULL) {
  349                 ec_iatt_rebuild(fop->xl->private, cbk->iatt, 2, cbk->count);
  350 
  351                 /* This shouldn't fail because we have the inode locked. */
  352                 GF_ASSERT(ec_get_inode_size(fop, fop->fd->inode,
  353                                             &cbk->iatt[0].ia_size));
  354                 cbk->iatt[1].ia_size = cbk->iatt[0].ia_size;
  355             }
  356 
  357             return EC_STATE_REPORT;
  358 
  359         case EC_STATE_REPORT:
  360             cbk = fop->answer;
  361 
  362             GF_ASSERT(cbk != NULL);
  363 
  364             if (fop->cbks.fsync != NULL) {
  365                 fop->cbks.fsync(fop->req_frame, fop, fop->xl, cbk->op_ret,
  366                                 cbk->op_errno, &cbk->iatt[0], &cbk->iatt[1],
  367                                 cbk->xdata);
  368             }
  369 
  370             return EC_STATE_LOCK_REUSE;
  371 
  372         case -EC_STATE_INIT:
  373         case -EC_STATE_LOCK:
  374         case -EC_STATE_DISPATCH:
  375         case -EC_STATE_PREPARE_ANSWER:
  376         case -EC_STATE_REPORT:
  377         case -EC_STATE_DELAYED_START:
  378             GF_ASSERT(fop->error != 0);
  379 
  380             if (fop->cbks.fsync != NULL) {
  381                 fop->cbks.fsync(fop->req_frame, fop, fop->xl, -1, fop->error,
  382                                 NULL, NULL, NULL);
  383             }
  384 
  385             return EC_STATE_LOCK_REUSE;
  386 
  387         case -EC_STATE_LOCK_REUSE:
  388         case EC_STATE_LOCK_REUSE:
  389             ec_lock_reuse(fop);
  390 
  391             return EC_STATE_UNLOCK;
  392 
  393         case -EC_STATE_UNLOCK:
  394         case EC_STATE_UNLOCK:
  395             ec_unlock(fop);
  396 
  397             return EC_STATE_END;
  398 
  399         default:
  400             gf_msg(fop->xl->name, GF_LOG_ERROR, EINVAL, EC_MSG_UNHANDLED_STATE,
  401                    "Unhandled state %d for %s", state, ec_fop_name(fop->id));
  402 
  403             return EC_STATE_END;
  404     }
  405 }
  406 
  407 void
  408 ec_fsync(call_frame_t *frame, xlator_t *this, uintptr_t target,
  409          uint32_t fop_flags, fop_fsync_cbk_t func, void *data, fd_t *fd,
  410          int32_t datasync, dict_t *xdata)
  411 {
  412     ec_cbk_t callback = {.fsync = func};
  413     ec_fop_data_t *fop = NULL;
  414     int32_t error = ENOMEM;
  415 
  416     gf_msg_trace("ec", 0, "EC(FSYNC) %p", frame);
  417 
  418     VALIDATE_OR_GOTO(this, out);
  419     GF_VALIDATE_OR_GOTO(this->name, frame, out);
  420     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
  421 
  422     if (fd) {
  423         error = ec_validate_fd(fd, this);
  424         if (error) {
  425             gf_msg(this->name, GF_LOG_ERROR, EBADF, EC_MSG_FD_BAD,
  426                    "Failing %s on %s", gf_fop_list[GF_FOP_FSYNC],
  427                    fd->inode ? uuid_utoa(fd->inode->gfid) : "");
  428             goto out;
  429         }
  430     }
  431 
  432     fop = ec_fop_data_allocate(frame, this, GF_FOP_FSYNC, 0, target, fop_flags,
  433                                ec_wind_fsync, ec_manager_fsync, callback, data);
  434     if (fop == NULL) {
  435         goto out;
  436     }
  437 
  438     fop->use_fd = 1;
  439 
  440     fop->int32 = datasync;
  441 
  442     if (fd != NULL) {
  443         fop->fd = fd_ref(fd);
  444         if (fop->fd == NULL) {
  445             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_FILE_DESC_REF_FAIL,
  446                    "Failed to reference a "
  447                    "file descriptor.");
  448 
  449             goto out;
  450         }
  451     }
  452     if (xdata != NULL) {
  453         fop->xdata = dict_ref(xdata);
  454         if (fop->xdata == NULL) {
  455             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
  456                    "Failed to reference a "
  457                    "dictionary.");
  458 
  459             goto out;
  460         }
  461     }
  462 
  463     error = 0;
  464 
  465 out:
  466     if (fop != NULL) {
  467         ec_manager(fop, error);
  468     } else {
  469         func(frame, NULL, this, -1, error, NULL, NULL, NULL);
  470     }
  471 }
  472 
  473 /* FOP: fsyncdir */
  474 
  475 int32_t
  476 ec_fsyncdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  477                 int32_t op_ret, int32_t op_errno, dict_t *xdata)
  478 {
  479     ec_fop_data_t *fop = NULL;
  480     ec_cbk_data_t *cbk = NULL;
  481     int32_t idx = (int32_t)(uintptr_t)cookie;
  482 
  483     VALIDATE_OR_GOTO(this, out);
  484     GF_VALIDATE_OR_GOTO(this->name, frame, out);
  485     GF_VALIDATE_OR_GOTO(this->name, frame->local, out);
  486     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
  487 
  488     fop = frame->local;
  489 
  490     ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, frame,
  491              op_ret, op_errno);
  492 
  493     cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_FSYNCDIR, idx, op_ret,
  494                                op_errno);
  495     if (cbk != NULL) {
  496         if (xdata != NULL) {
  497             cbk->xdata = dict_ref(xdata);
  498             if (cbk->xdata == NULL) {
  499                 gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
  500                        "Failed to reference a "
  501                        "dictionary.");
  502 
  503                 goto out;
  504             }
  505         }
  506 
  507         ec_combine(cbk, NULL);
  508     }
  509 
  510 out:
  511     if (fop != NULL) {
  512         ec_complete(fop);
  513     }
  514 
  515     return 0;
  516 }
  517 
  518 void
  519 ec_wind_fsyncdir(ec_t *ec, ec_fop_data_t *fop, int32_t idx)
  520 {
  521     ec_trace("WIND", fop, "idx=%d", idx);
  522 
  523     STACK_WIND_COOKIE(fop->frame, ec_fsyncdir_cbk, (void *)(uintptr_t)idx,
  524                       ec->xl_list[idx], ec->xl_list[idx]->fops->fsyncdir,
  525                       fop->fd, fop->int32, fop->xdata);
  526 }
  527 
  528 int32_t
  529 ec_manager_fsyncdir(ec_fop_data_t *fop, int32_t state)
  530 {
  531     ec_cbk_data_t *cbk;
  532 
  533     switch (state) {
  534         case EC_STATE_INIT:
  535         case EC_STATE_LOCK:
  536             ec_lock_prepare_fd(fop, fop->fd, 0, 0, EC_RANGE_FULL);
  537             ec_lock(fop);
  538 
  539             return EC_STATE_DISPATCH;
  540 
  541         case EC_STATE_DISPATCH:
  542             ec_flush_size_version(fop);
  543 
  544             return EC_STATE_DELAYED_START;
  545 
  546         case EC_STATE_DELAYED_START:
  547             ec_dispatch_all(fop);
  548 
  549             return EC_STATE_PREPARE_ANSWER;
  550 
  551         case EC_STATE_PREPARE_ANSWER:
  552             ec_fop_prepare_answer(fop, _gf_false);
  553 
  554             return EC_STATE_REPORT;
  555 
  556         case EC_STATE_REPORT:
  557             cbk = fop->answer;
  558 
  559             GF_ASSERT(cbk != NULL);
  560 
  561             if (fop->cbks.fsyncdir != NULL) {
  562                 fop->cbks.fsyncdir(fop->req_frame, fop, fop->xl, cbk->op_ret,
  563                                    cbk->op_errno, cbk->xdata);
  564             }
  565 
  566             return EC_STATE_LOCK_REUSE;
  567 
  568         case -EC_STATE_INIT:
  569         case -EC_STATE_LOCK:
  570         case -EC_STATE_DISPATCH:
  571         case -EC_STATE_PREPARE_ANSWER:
  572         case -EC_STATE_REPORT:
  573         case -EC_STATE_DELAYED_START:
  574             GF_ASSERT(fop->error != 0);
  575 
  576             if (fop->cbks.fsyncdir != NULL) {
  577                 fop->cbks.fsyncdir(fop->req_frame, fop, fop->xl, -1, fop->error,
  578                                    NULL);
  579             }
  580 
  581             return EC_STATE_LOCK_REUSE;
  582 
  583         case -EC_STATE_LOCK_REUSE:
  584         case EC_STATE_LOCK_REUSE:
  585             ec_lock_reuse(fop);
  586 
  587             return EC_STATE_UNLOCK;
  588 
  589         case -EC_STATE_UNLOCK:
  590         case EC_STATE_UNLOCK:
  591             ec_unlock(fop);
  592 
  593             return EC_STATE_END;
  594 
  595         default:
  596             gf_msg(fop->xl->name, GF_LOG_ERROR, EINVAL, EC_MSG_UNHANDLED_STATE,
  597                    "Unhandled state %d for %s", state, ec_fop_name(fop->id));
  598 
  599             return EC_STATE_END;
  600     }
  601 }
  602 
  603 void
  604 ec_fsyncdir(call_frame_t *frame, xlator_t *this, uintptr_t target,
  605             uint32_t fop_flags, fop_fsyncdir_cbk_t func, void *data, fd_t *fd,
  606             int32_t datasync, dict_t *xdata)
  607 {
  608     ec_cbk_t callback = {.fsyncdir = func};
  609     ec_fop_data_t *fop = NULL;
  610     int32_t error = ENOMEM;
  611 
  612     gf_msg_trace("ec", 0, "EC(FSYNCDIR) %p", frame);
  613 
  614     VALIDATE_OR_GOTO(this, out);
  615     GF_VALIDATE_OR_GOTO(this->name, frame, out);
  616     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
  617 
  618     fop = ec_fop_data_allocate(frame, this, GF_FOP_FSYNCDIR, 0, target,
  619                                fop_flags, ec_wind_fsyncdir, ec_manager_fsyncdir,
  620                                callback, data);
  621     if (fop == NULL) {
  622         goto out;
  623     }
  624 
  625     fop->use_fd = 1;
  626 
  627     fop->int32 = datasync;
  628 
  629     if (fd != NULL) {
  630         fop->fd = fd_ref(fd);
  631         if (fop->fd == NULL) {
  632             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_FILE_DESC_REF_FAIL,
  633                    "Failed to reference a "
  634                    "file descriptor.");
  635 
  636             goto out;
  637         }
  638     }
  639     if (xdata != NULL) {
  640         fop->xdata = dict_ref(xdata);
  641         if (fop->xdata == NULL) {
  642             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
  643                    "Failed to reference a "
  644                    "dictionary.");
  645 
  646             goto out;
  647         }
  648     }
  649 
  650     error = 0;
  651 
  652 out:
  653     if (fop != NULL) {
  654         ec_manager(fop, error);
  655     } else {
  656         func(frame, NULL, this, -1, error, NULL);
  657     }
  658 }
  659 
  660 /* FOP: lookup */
  661 
  662 void
  663 ec_lookup_rebuild(ec_t *ec, ec_fop_data_t *fop, ec_cbk_data_t *cbk)
  664 {
  665     ec_inode_t *ctx = NULL;
  666     uint64_t size = 0;
  667     int32_t have_size = 0, err;
  668 
  669     if (cbk->op_ret < 0) {
  670         return;
  671     }
  672 
  673     ec_dict_del_array(cbk->xdata, EC_XATTR_VERSION, cbk->version,
  674                       EC_VERSION_SIZE);
  675 
  676     err = ec_loc_update(fop->xl, &fop->loc[0], cbk->inode, &cbk->iatt[0]);
  677     if (ec_cbk_set_error(cbk, -err, _gf_true)) {
  678         return;
  679     }
  680 
  681     LOCK(&cbk->inode->lock);
  682 
  683     ctx = __ec_inode_get(cbk->inode, fop->xl);
  684     if (ctx != NULL) {
  685         if (ctx->have_version) {
  686             cbk->version[0] = ctx->post_version[0];
  687             cbk->version[1] = ctx->post_version[1];
  688         }
  689         if (ctx->have_size) {
  690             size = ctx->post_size;
  691             have_size = 1;
  692         }
  693     }
  694 
  695     UNLOCK(&cbk->inode->lock);
  696 
  697     if (cbk->iatt[0].ia_type == IA_IFREG) {
  698         cbk->size = cbk->iatt[0].ia_size;
  699         ec_dict_del_number(cbk->xdata, EC_XATTR_SIZE, &cbk->iatt[0].ia_size);
  700         if (have_size) {
  701             cbk->iatt[0].ia_size = size;
  702         }
  703     }
  704 }
  705 
  706 int32_t
  707 ec_combine_lookup(ec_fop_data_t *fop, ec_cbk_data_t *dst, ec_cbk_data_t *src)
  708 {
  709     if (!ec_iatt_combine(fop, dst->iatt, src->iatt, 2)) {
  710         gf_msg(fop->xl->name, GF_LOG_DEBUG, 0, EC_MSG_IATT_MISMATCH,
  711                "Mismatching iatt in "
  712                "answers of 'GF_FOP_LOOKUP'");
  713 
  714         return 0;
  715     }
  716 
  717     return 1;
  718 }
  719 
  720 int32_t
  721 ec_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
  722               int32_t op_errno, inode_t *inode, struct iatt *buf, dict_t *xdata,
  723               struct iatt *postparent)
  724 {
  725     ec_fop_data_t *fop = NULL;
  726     ec_cbk_data_t *cbk = NULL;
  727     int32_t idx = (int32_t)(uintptr_t)cookie;
  728     uint64_t dirty[2] = {0};
  729 
  730     VALIDATE_OR_GOTO(this, out);
  731     GF_VALIDATE_OR_GOTO(this->name, frame, out);
  732     GF_VALIDATE_OR_GOTO(this->name, frame->local, out);
  733     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
  734 
  735     fop = frame->local;
  736 
  737     ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, frame,
  738              op_ret, op_errno);
  739 
  740     cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_LOOKUP, idx, op_ret,
  741                                op_errno);
  742     if (cbk != NULL) {
  743         if (op_ret >= 0) {
  744             if (inode != NULL) {
  745                 cbk->inode = inode_ref(inode);
  746                 if (cbk->inode == NULL) {
  747                     gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_INODE_REF_FAIL,
  748                            "Failed to reference an inode.");
  749 
  750                     goto out;
  751                 }
  752             }
  753             if (buf != NULL) {
  754                 cbk->iatt[0] = *buf;
  755             }
  756             if (postparent != NULL) {
  757                 cbk->iatt[1] = *postparent;
  758             }
  759         }
  760         if (xdata != NULL) {
  761             cbk->xdata = dict_ref(xdata);
  762             if (cbk->xdata == NULL) {
  763                 gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
  764                        "Failed to reference a "
  765                        "dictionary.");
  766 
  767                 goto out;
  768             }
  769             ec_dict_del_array(xdata, EC_XATTR_DIRTY, dirty, EC_VERSION_SIZE);
  770         }
  771 
  772         ec_combine(cbk, ec_combine_lookup);
  773     }
  774 
  775 out:
  776     if (fop != NULL) {
  777         ec_complete(fop);
  778     }
  779 
  780     return 0;
  781 }
  782 
  783 void
  784 ec_wind_lookup(ec_t *ec, ec_fop_data_t *fop, int32_t idx)
  785 {
  786     ec_trace("WIND", fop, "idx=%d", idx);
  787 
  788     STACK_WIND_COOKIE(fop->frame, ec_lookup_cbk, (void *)(uintptr_t)idx,
  789                       ec->xl_list[idx], ec->xl_list[idx]->fops->lookup,
  790                       &fop->loc[0], fop->xdata);
  791 }
  792 
  793 int32_t
  794 ec_manager_lookup(ec_fop_data_t *fop, int32_t state)
  795 {
  796     ec_cbk_data_t *cbk;
  797     int32_t err;
  798 
  799     switch (state) {
  800         case EC_STATE_INIT:
  801             if (fop->xdata == NULL) {
  802                 fop->xdata = dict_new();
  803                 if (fop->xdata == NULL) {
  804                     gf_msg(fop->xl->name, GF_LOG_ERROR, ENOMEM,
  805                            EC_MSG_LOOKUP_REQ_PREP_FAIL,
  806                            "Unable to prepare "
  807                            "lookup request");
  808 
  809                     fop->error = ENOMEM;
  810 
  811                     return EC_STATE_REPORT;
  812                 }
  813             } else {
  814                 /*TODO: To be handled once we have 'syndromes' */
  815                 dict_del(fop->xdata, GF_CONTENT_KEY);
  816             }
  817             err = dict_set_uint64(fop->xdata, EC_XATTR_SIZE, 0);
  818             if (err == 0) {
  819                 err = dict_set_uint64(fop->xdata, EC_XATTR_VERSION, 0);
  820             }
  821             if (err == 0) {
  822                 err = dict_set_uint64(fop->xdata, EC_XATTR_DIRTY, 0);
  823             }
  824             if (err != 0) {
  825                 gf_msg(fop->xl->name, GF_LOG_ERROR, -err,
  826                        EC_MSG_LOOKUP_REQ_PREP_FAIL,
  827                        "Unable to prepare lookup "
  828                        "request");
  829 
  830                 fop->error = -err;
  831 
  832                 return EC_STATE_REPORT;
  833             }
  834 
  835             /* Fall through */
  836 
  837         case EC_STATE_DISPATCH:
  838             ec_dispatch_all(fop);
  839 
  840             return EC_STATE_PREPARE_ANSWER;
  841 
  842         case EC_STATE_PREPARE_ANSWER:
  843             /*
  844              * Lookup happens without any lock, so there is a chance that it
  845              * will have answers before modification happened and after
  846              * modification happened in the same response. So choose the next
  847              * best answer when the answers don't match for EC_MINIMUM_MIN
  848              */
  849 
  850             if (!fop->answer && !list_empty(&fop->cbk_list)) {
  851                 fop->answer = list_entry(fop->cbk_list.next, ec_cbk_data_t,
  852                                          list);
  853             }
  854 
  855             cbk = ec_fop_prepare_answer(fop, _gf_true);
  856             if (cbk != NULL) {
  857                 ec_iatt_rebuild(fop->xl->private, cbk->iatt, 2, cbk->count);
  858 
  859                 ec_lookup_rebuild(fop->xl->private, fop, cbk);
  860             }
  861 
  862             return EC_STATE_REPORT;
  863 
  864         case EC_STATE_REPORT:
  865             cbk = fop->answer;
  866 
  867             GF_ASSERT(cbk != NULL);
  868 
  869             if (fop->cbks.lookup != NULL) {
  870                 fop->cbks.lookup(fop->req_frame, fop, fop->xl, cbk->op_ret,
  871                                  cbk->op_errno, cbk->inode, &cbk->iatt[0],
  872                                  cbk->xdata, &cbk->iatt[1]);
  873             }
  874 
  875             return EC_STATE_END;
  876 
  877         case -EC_STATE_INIT:
  878         case -EC_STATE_DISPATCH:
  879         case -EC_STATE_PREPARE_ANSWER:
  880         case -EC_STATE_REPORT:
  881             GF_ASSERT(fop->error != 0);
  882 
  883             if (fop->cbks.lookup != NULL) {
  884                 fop->cbks.lookup(fop->req_frame, fop, fop->xl, -1, fop->error,
  885                                  NULL, NULL, NULL, NULL);
  886             }
  887 
  888             return EC_STATE_END;
  889 
  890         default:
  891             gf_msg(fop->xl->name, GF_LOG_ERROR, EINVAL, EC_MSG_UNHANDLED_STATE,
  892                    "Unhandled state %d for %s", state, ec_fop_name(fop->id));
  893 
  894             return EC_STATE_END;
  895     }
  896 }
  897 
  898 void
  899 ec_lookup(call_frame_t *frame, xlator_t *this, uintptr_t target,
  900           uint32_t fop_flags, fop_lookup_cbk_t func, void *data, loc_t *loc,
  901           dict_t *xdata)
  902 {
  903     ec_cbk_t callback = {.lookup = func};
  904     ec_fop_data_t *fop = NULL;
  905     int32_t error = ENOMEM;
  906 
  907     gf_msg_trace("ec", 0, "EC(LOOKUP) %p", frame);
  908 
  909     VALIDATE_OR_GOTO(this, out);
  910     GF_VALIDATE_OR_GOTO(this->name, frame, out);
  911     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
  912 
  913     fop = ec_fop_data_allocate(frame, this, GF_FOP_LOOKUP, EC_FLAG_LOCK_SHARED,
  914                                target, fop_flags, ec_wind_lookup,
  915                                ec_manager_lookup, callback, data);
  916     if (fop == NULL) {
  917         goto out;
  918     }
  919 
  920     if (loc != NULL) {
  921         if (loc_copy(&fop->loc[0], loc) != 0) {
  922             gf_msg(this->name, GF_LOG_ERROR, ENOMEM, EC_MSG_LOC_COPY_FAIL,
  923                    "Failed to copy a location.");
  924 
  925             goto out;
  926         }
  927     }
  928     if (xdata != NULL) {
  929         fop->xdata = dict_copy_with_ref(xdata, NULL);
  930         /* Do not log failures here as a memory problem would have already
  931          * been logged by the corresponding alloc functions */
  932         if (fop->xdata == NULL)
  933             goto out;
  934     }
  935 
  936     error = 0;
  937 
  938 out:
  939     if (fop != NULL) {
  940         ec_manager(fop, error);
  941     } else {
  942         func(frame, NULL, this, -1, error, NULL, NULL, NULL, NULL);
  943     }
  944 }
  945 
  946 /* FOP: statfs */
  947 
  948 int32_t
  949 ec_combine_statfs(ec_fop_data_t *fop, ec_cbk_data_t *dst, ec_cbk_data_t *src)
  950 {
  951     ec_statvfs_combine(&dst->statvfs, &src->statvfs);
  952 
  953     return 1;
  954 }
  955 
  956 int32_t
  957 ec_statfs_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
  958               int32_t op_errno, struct statvfs *buf, dict_t *xdata)
  959 {
  960     ec_fop_data_t *fop = NULL;
  961     ec_cbk_data_t *cbk = NULL;
  962     int32_t idx = (int32_t)(uintptr_t)cookie;
  963 
  964     VALIDATE_OR_GOTO(this, out);
  965     GF_VALIDATE_OR_GOTO(this->name, frame, out);
  966     GF_VALIDATE_OR_GOTO(this->name, frame->local, out);
  967     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
  968 
  969     fop = frame->local;
  970 
  971     ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, frame,
  972              op_ret, op_errno);
  973 
  974     cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_STATFS, idx, op_ret,
  975                                op_errno);
  976     if (cbk != NULL) {
  977         if (op_ret >= 0) {
  978             if (buf != NULL) {
  979                 cbk->statvfs = *buf;
  980             }
  981         }
  982         if (xdata != NULL) {
  983             cbk->xdata = dict_ref(xdata);
  984             if (cbk->xdata == NULL) {
  985                 gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
  986                        "Failed to reference a "
  987                        "dictionary.");
  988 
  989                 goto out;
  990             }
  991         }
  992 
  993         ec_combine(cbk, ec_combine_statfs);
  994     }
  995 
  996 out:
  997     if (fop != NULL) {
  998         ec_complete(fop);
  999     }
 1000 
 1001     return 0;
 1002 }
 1003 
 1004 void
 1005 ec_wind_statfs(ec_t *ec, ec_fop_data_t *fop, int32_t idx)
 1006 {
 1007     ec_trace("WIND", fop, "idx=%d", idx);
 1008 
 1009     STACK_WIND_COOKIE(fop->frame, ec_statfs_cbk, (void *)(uintptr_t)idx,
 1010                       ec->xl_list[idx], ec->xl_list[idx]->fops->statfs,
 1011                       &fop->loc[0], fop->xdata);
 1012 }
 1013 
 1014 int32_t
 1015 ec_manager_statfs(ec_fop_data_t *fop, int32_t state)
 1016 {
 1017     ec_cbk_data_t *cbk = NULL;
 1018     gf_boolean_t deem_statfs_enabled = _gf_false;
 1019     int32_t err = 0;
 1020 
 1021     switch (state) {
 1022         case EC_STATE_INIT:
 1023         case EC_STATE_DISPATCH:
 1024             ec_dispatch_all(fop);
 1025 
 1026             return EC_STATE_PREPARE_ANSWER;
 1027 
 1028         case EC_STATE_PREPARE_ANSWER:
 1029             cbk = ec_fop_prepare_answer(fop, _gf_true);
 1030             if (cbk != NULL) {
 1031                 ec_t *ec = fop->xl->private;
 1032 
 1033                 if (cbk->xdata) {
 1034                     err = dict_get_int8(cbk->xdata, "quota-deem-statfs",
 1035                                         (int8_t *)&deem_statfs_enabled);
 1036                     if (err != -ENOENT) {
 1037                         ec_cbk_set_error(cbk, -err, _gf_true);
 1038                     }
 1039                 }
 1040 
 1041                 if (err != 0 || deem_statfs_enabled == _gf_false) {
 1042                     cbk->statvfs.f_blocks *= ec->fragments;
 1043                     cbk->statvfs.f_bfree *= ec->fragments;
 1044                     cbk->statvfs.f_bavail *= ec->fragments;
 1045                 }
 1046             }
 1047 
 1048             return EC_STATE_REPORT;
 1049 
 1050         case EC_STATE_REPORT:
 1051             cbk = fop->answer;
 1052 
 1053             GF_ASSERT(cbk != NULL);
 1054 
 1055             if (fop->cbks.statfs != NULL) {
 1056                 fop->cbks.statfs(fop->req_frame, fop, fop->xl, cbk->op_ret,
 1057                                  cbk->op_errno, &cbk->statvfs, cbk->xdata);
 1058             }
 1059 
 1060             return EC_STATE_END;
 1061 
 1062         case -EC_STATE_INIT:
 1063         case -EC_STATE_DISPATCH:
 1064         case -EC_STATE_PREPARE_ANSWER:
 1065         case -EC_STATE_REPORT:
 1066             GF_ASSERT(fop->error != 0);
 1067 
 1068             if (fop->cbks.statfs != NULL) {
 1069                 fop->cbks.statfs(fop->req_frame, fop, fop->xl, -1, fop->error,
 1070                                  NULL, NULL);
 1071             }
 1072 
 1073             return EC_STATE_END;
 1074 
 1075         default:
 1076             gf_msg(fop->xl->name, GF_LOG_ERROR, EINVAL, EC_MSG_UNHANDLED_STATE,
 1077                    "Unhandled state %d for %s", state, ec_fop_name(fop->id));
 1078 
 1079             return EC_STATE_END;
 1080     }
 1081 }
 1082 
 1083 void
 1084 ec_statfs(call_frame_t *frame, xlator_t *this, uintptr_t target,
 1085           uint32_t fop_flags, fop_statfs_cbk_t func, void *data, loc_t *loc,
 1086           dict_t *xdata)
 1087 {
 1088     ec_cbk_t callback = {.statfs = func};
 1089     ec_fop_data_t *fop = NULL;
 1090     int32_t error = ENOMEM;
 1091 
 1092     gf_msg_trace("ec", 0, "EC(STATFS) %p", frame);
 1093 
 1094     VALIDATE_OR_GOTO(this, out);
 1095     GF_VALIDATE_OR_GOTO(this->name, frame, out);
 1096     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
 1097 
 1098     fop = ec_fop_data_allocate(frame, this, GF_FOP_STATFS, EC_FLAG_LOCK_SHARED,
 1099                                target, fop_flags, ec_wind_statfs,
 1100                                ec_manager_statfs, callback, data);
 1101     if (fop == NULL) {
 1102         goto out;
 1103     }
 1104 
 1105     if (loc != NULL) {
 1106         if (loc_copy(&fop->loc[0], loc) != 0) {
 1107             gf_msg(this->name, GF_LOG_ERROR, ENOMEM, EC_MSG_LOC_COPY_FAIL,
 1108                    "Failed to copy a location.");
 1109 
 1110             goto out;
 1111         }
 1112     }
 1113     if (xdata != NULL) {
 1114         fop->xdata = dict_ref(xdata);
 1115         if (fop->xdata == NULL) {
 1116             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
 1117                    "Failed to reference a "
 1118                    "dictionary.");
 1119 
 1120             goto out;
 1121         }
 1122     }
 1123 
 1124     error = 0;
 1125 
 1126 out:
 1127     if (fop != NULL) {
 1128         ec_manager(fop, error);
 1129     } else {
 1130         func(frame, NULL, this, -1, error, NULL, NULL);
 1131     }
 1132 }
 1133 
 1134 /* FOP: xattrop */
 1135 
 1136 int32_t
 1137 ec_combine_xattrop(ec_fop_data_t *fop, ec_cbk_data_t *dst, ec_cbk_data_t *src)
 1138 {
 1139     if (!ec_dict_compare(dst->dict, src->dict)) {
 1140         gf_msg(fop->xl->name, GF_LOG_DEBUG, 0, EC_MSG_DICT_MISMATCH,
 1141                "Mismatching dictionary in "
 1142                "answers of 'GF_FOP_XATTROP'");
 1143 
 1144         return 0;
 1145     }
 1146 
 1147     return 1;
 1148 }
 1149 
 1150 int32_t
 1151 ec_xattrop_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1152                int32_t op_ret, int32_t op_errno, dict_t *xattr, dict_t *xdata)
 1153 {
 1154     ec_fop_data_t *fop = NULL;
 1155     ec_lock_link_t *link = NULL;
 1156     ec_cbk_data_t *cbk = NULL;
 1157     uint64_t dirty[2] = {0};
 1158     data_t *data;
 1159     uint64_t *version;
 1160     int32_t idx = (int32_t)(uintptr_t)cookie;
 1161 
 1162     VALIDATE_OR_GOTO(this, out);
 1163     GF_VALIDATE_OR_GOTO(this->name, frame, out);
 1164     GF_VALIDATE_OR_GOTO(this->name, frame->local, out);
 1165     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
 1166 
 1167     fop = frame->local;
 1168 
 1169     ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, frame,
 1170              op_ret, op_errno);
 1171 
 1172     cbk = ec_cbk_data_allocate(frame, this, fop, fop->id, idx, op_ret,
 1173                                op_errno);
 1174     if (!cbk)
 1175         goto out;
 1176 
 1177     if (op_ret >= 0) {
 1178         cbk->dict = dict_ref(xattr);
 1179 
 1180         data = dict_get(cbk->dict, EC_XATTR_VERSION);
 1181         if ((data != NULL) && (data->len >= sizeof(uint64_t))) {
 1182             version = (uint64_t *)data->data;
 1183 
 1184             if (((ntoh64(version[0]) >> EC_SELFHEAL_BIT) & 1) != 0) {
 1185                 LOCK(&fop->lock);
 1186 
 1187                 fop->healing |= 1ULL << idx;
 1188 
 1189                 UNLOCK(&fop->lock);
 1190             }
 1191         }
 1192 
 1193         ec_dict_del_array(xattr, EC_XATTR_DIRTY, dirty, EC_VERSION_SIZE);
 1194         link = fop->data;
 1195         if (link) {
 1196             /*Keep a note of if the dirty is already set or not*/
 1197             link->dirty[0] |= (dirty[0] != 0);
 1198             link->dirty[1] |= (dirty[1] != 0);
 1199         }
 1200     }
 1201 
 1202     if (xdata)
 1203         cbk->xdata = dict_ref(xdata);
 1204 
 1205     ec_combine(cbk, ec_combine_xattrop);
 1206 
 1207 out:
 1208     if (fop)
 1209         ec_complete(fop);
 1210 
 1211     return 0;
 1212 }
 1213 
 1214 void
 1215 ec_wind_xattrop(ec_t *ec, ec_fop_data_t *fop, int32_t idx)
 1216 {
 1217     ec_trace("WIND", fop, "idx=%d", idx);
 1218 
 1219     STACK_WIND_COOKIE(fop->frame, ec_xattrop_cbk, (void *)(uintptr_t)idx,
 1220                       ec->xl_list[idx], ec->xl_list[idx]->fops->xattrop,
 1221                       &fop->loc[0], fop->xattrop_flags, fop->dict, fop->xdata);
 1222 }
 1223 
 1224 int32_t
 1225 ec_manager_xattrop(ec_fop_data_t *fop, int32_t state)
 1226 {
 1227     ec_cbk_data_t *cbk;
 1228 
 1229     switch (state) {
 1230         case EC_STATE_INIT:
 1231         case EC_STATE_LOCK:
 1232             if (fop->fd == NULL) {
 1233                 ec_lock_prepare_inode(fop, &fop->loc[0], EC_UPDATE_META, 0,
 1234                                       EC_RANGE_FULL);
 1235             } else {
 1236                 ec_lock_prepare_fd(fop, fop->fd, EC_UPDATE_META, 0,
 1237                                    EC_RANGE_FULL);
 1238             }
 1239             ec_lock(fop);
 1240 
 1241             return EC_STATE_DISPATCH;
 1242 
 1243         case EC_STATE_DISPATCH:
 1244             ec_dispatch_all(fop);
 1245 
 1246             return EC_STATE_PREPARE_ANSWER;
 1247 
 1248         case EC_STATE_PREPARE_ANSWER:
 1249             cbk = ec_fop_prepare_answer(fop, _gf_false);
 1250             if (cbk != NULL) {
 1251                 int32_t err;
 1252 
 1253                 err = ec_dict_combine(cbk, EC_COMBINE_DICT);
 1254                 ec_cbk_set_error(cbk, -err, _gf_false);
 1255             }
 1256 
 1257             return EC_STATE_REPORT;
 1258 
 1259         case EC_STATE_REPORT:
 1260             cbk = fop->answer;
 1261 
 1262             GF_ASSERT(cbk != NULL);
 1263 
 1264             if (fop->id == GF_FOP_XATTROP) {
 1265                 if (fop->cbks.xattrop != NULL) {
 1266                     fop->cbks.xattrop(fop->req_frame, fop, fop->xl, cbk->op_ret,
 1267                                       cbk->op_errno, cbk->dict, cbk->xdata);
 1268                 }
 1269             } else {
 1270                 if (fop->cbks.fxattrop != NULL) {
 1271                     fop->cbks.fxattrop(fop->req_frame, fop, fop->xl,
 1272                                        cbk->op_ret, cbk->op_errno, cbk->dict,
 1273                                        cbk->xdata);
 1274                 }
 1275             }
 1276 
 1277             return EC_STATE_LOCK_REUSE;
 1278 
 1279         case -EC_STATE_INIT:
 1280         case -EC_STATE_LOCK:
 1281         case -EC_STATE_DISPATCH:
 1282         case -EC_STATE_PREPARE_ANSWER:
 1283         case -EC_STATE_REPORT:
 1284             GF_ASSERT(fop->error != 0);
 1285 
 1286             if (fop->id == GF_FOP_XATTROP) {
 1287                 if (fop->cbks.xattrop != NULL) {
 1288                     fop->cbks.xattrop(fop->req_frame, fop, fop->xl, -1,
 1289                                       fop->error, NULL, NULL);
 1290                 }
 1291             } else {
 1292                 if (fop->cbks.fxattrop != NULL) {
 1293                     fop->cbks.fxattrop(fop->req_frame, fop, fop->xl, -1,
 1294                                        fop->error, NULL, NULL);
 1295                 }
 1296             }
 1297 
 1298             return EC_STATE_LOCK_REUSE;
 1299 
 1300         case -EC_STATE_LOCK_REUSE:
 1301         case EC_STATE_LOCK_REUSE:
 1302             ec_lock_reuse(fop);
 1303 
 1304             return EC_STATE_UNLOCK;
 1305 
 1306         case -EC_STATE_UNLOCK:
 1307         case EC_STATE_UNLOCK:
 1308             ec_unlock(fop);
 1309 
 1310             return EC_STATE_END;
 1311 
 1312         default:
 1313             gf_msg(fop->xl->name, GF_LOG_ERROR, EINVAL, EC_MSG_UNHANDLED_STATE,
 1314                    "Unhandled state %d for %s", state, ec_fop_name(fop->id));
 1315 
 1316             return EC_STATE_END;
 1317     }
 1318 }
 1319 
 1320 void
 1321 ec_xattrop(call_frame_t *frame, xlator_t *this, uintptr_t target,
 1322            uint32_t fop_flags, fop_xattrop_cbk_t func, void *data, loc_t *loc,
 1323            gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata)
 1324 {
 1325     ec_cbk_t callback = {.xattrop = func};
 1326     ec_fop_data_t *fop = NULL;
 1327     int32_t error = ENOMEM;
 1328 
 1329     gf_msg_trace("ec", 0, "EC(XATTROP) %p", frame);
 1330 
 1331     VALIDATE_OR_GOTO(this, out);
 1332     GF_VALIDATE_OR_GOTO(this->name, frame, out);
 1333     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
 1334 
 1335     fop = ec_fop_data_allocate(frame, this, GF_FOP_XATTROP, 0, target,
 1336                                fop_flags, ec_wind_xattrop, ec_manager_xattrop,
 1337                                callback, data);
 1338     if (fop == NULL) {
 1339         goto out;
 1340     }
 1341 
 1342     fop->xattrop_flags = optype;
 1343 
 1344     if (loc != NULL) {
 1345         if (loc_copy(&fop->loc[0], loc) != 0) {
 1346             gf_msg(this->name, GF_LOG_ERROR, ENOMEM, EC_MSG_LOC_COPY_FAIL,
 1347                    "Failed to copy a location.");
 1348 
 1349             goto out;
 1350         }
 1351     }
 1352     if (xattr != NULL) {
 1353         fop->dict = dict_ref(xattr);
 1354         if (fop->dict == NULL) {
 1355             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
 1356                    "Failed to reference a "
 1357                    "dictionary.");
 1358 
 1359             goto out;
 1360         }
 1361     }
 1362     if (xdata != NULL) {
 1363         fop->xdata = dict_ref(xdata);
 1364         if (fop->xdata == NULL) {
 1365             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
 1366                    "Failed to reference a "
 1367                    "dictionary.");
 1368 
 1369             goto out;
 1370         }
 1371     }
 1372 
 1373     error = 0;
 1374 
 1375 out:
 1376     if (fop != NULL) {
 1377         ec_manager(fop, error);
 1378     } else {
 1379         func(frame, NULL, this, -1, error, NULL, NULL);
 1380     }
 1381 }
 1382 
 1383 void
 1384 ec_wind_fxattrop(ec_t *ec, ec_fop_data_t *fop, int32_t idx)
 1385 {
 1386     ec_trace("WIND", fop, "idx=%d", idx);
 1387 
 1388     STACK_WIND_COOKIE(fop->frame, ec_xattrop_cbk, (void *)(uintptr_t)idx,
 1389                       ec->xl_list[idx], ec->xl_list[idx]->fops->fxattrop,
 1390                       fop->fd, fop->xattrop_flags, fop->dict, fop->xdata);
 1391 }
 1392 
 1393 void
 1394 ec_fxattrop(call_frame_t *frame, xlator_t *this, uintptr_t target,
 1395             uint32_t fop_flags, fop_fxattrop_cbk_t func, void *data, fd_t *fd,
 1396             gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata)
 1397 {
 1398     ec_cbk_t callback = {.fxattrop = func};
 1399     ec_fop_data_t *fop = NULL;
 1400     int32_t error = ENOMEM;
 1401 
 1402     gf_msg_trace("ec", 0, "EC(FXATTROP) %p", frame);
 1403 
 1404     VALIDATE_OR_GOTO(this, out);
 1405     GF_VALIDATE_OR_GOTO(this->name, frame, out);
 1406     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
 1407 
 1408     fop = ec_fop_data_allocate(frame, this, GF_FOP_FXATTROP, 0, target,
 1409                                fop_flags, ec_wind_fxattrop, ec_manager_xattrop,
 1410                                callback, data);
 1411     if (fop == NULL) {
 1412         goto out;
 1413     }
 1414 
 1415     fop->use_fd = 1;
 1416 
 1417     fop->xattrop_flags = optype;
 1418 
 1419     if (fd != NULL) {
 1420         fop->fd = fd_ref(fd);
 1421         if (fop->fd == NULL) {
 1422             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_FILE_DESC_REF_FAIL,
 1423                    "Failed to reference a "
 1424                    "file descriptor.");
 1425 
 1426             goto out;
 1427         }
 1428     }
 1429     if (xattr != NULL) {
 1430         fop->dict = dict_ref(xattr);
 1431         if (fop->dict == NULL) {
 1432             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
 1433                    "Failed to reference a "
 1434                    "dictionary.");
 1435 
 1436             goto out;
 1437         }
 1438     }
 1439     if (xdata != NULL) {
 1440         fop->xdata = dict_ref(xdata);
 1441         if (fop->xdata == NULL) {
 1442             gf_msg(this->name, GF_LOG_ERROR, 0, EC_MSG_DICT_REF_FAIL,
 1443                    "Failed to reference a "
 1444                    "dictionary.");
 1445 
 1446             goto out;
 1447         }
 1448     }
 1449 
 1450     error = 0;
 1451 
 1452 out:
 1453     if (fop != NULL) {
 1454         ec_manager(fop, error);
 1455     } else {
 1456         func(frame, NULL, this, -1, error, NULL, NULL);
 1457     }
 1458 }
 1459 
 1460 /* FOP: IPC */
 1461 
 1462 int32_t
 1463 ec_ipc_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
 1464            int32_t op_errno, dict_t *xdata)
 1465 {
 1466     ec_fop_data_t *fop = NULL;
 1467     ec_cbk_data_t *cbk = NULL;
 1468     int32_t idx = (int32_t)(uintptr_t)cookie;
 1469 
 1470     VALIDATE_OR_GOTO(this, out);
 1471     GF_VALIDATE_OR_GOTO(this->name, frame, out);
 1472     GF_VALIDATE_OR_GOTO(this->name, frame->local, out);
 1473     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
 1474 
 1475     fop = frame->local;
 1476 
 1477     ec_trace("CBK", fop, "idx=%d, frame=%p, op_ret=%d, op_errno=%d", idx, frame,
 1478              op_ret, op_errno);
 1479 
 1480     cbk = ec_cbk_data_allocate(frame, this, fop, GF_FOP_IPC, idx, op_ret,
 1481                                op_errno);
 1482 
 1483     if (cbk != NULL) {
 1484         if (xdata != NULL) {
 1485             cbk->xdata = dict_ref(xdata);
 1486         }
 1487 
 1488         ec_combine(cbk, NULL);
 1489     }
 1490 
 1491 out:
 1492     if (fop != NULL) {
 1493         ec_complete(fop);
 1494     }
 1495 
 1496     return 0;
 1497 }
 1498 
 1499 void
 1500 ec_wind_ipc(ec_t *ec, ec_fop_data_t *fop, int32_t idx)
 1501 {
 1502     ec_trace("WIND", fop, "idx=%d", idx);
 1503 
 1504     STACK_WIND_COOKIE(fop->frame, ec_ipc_cbk, (void *)(uintptr_t)idx,
 1505                       ec->xl_list[idx], ec->xl_list[idx]->fops->ipc, fop->int32,
 1506                       fop->xdata);
 1507 }
 1508 
 1509 int32_t
 1510 ec_manager_ipc(ec_fop_data_t *fop, int32_t state)
 1511 {
 1512     ec_cbk_data_t *cbk;
 1513 
 1514     switch (state) {
 1515         case EC_STATE_INIT:
 1516         case EC_STATE_DISPATCH:
 1517             ec_dispatch_all(fop);
 1518 
 1519             return EC_STATE_PREPARE_ANSWER;
 1520 
 1521         case EC_STATE_PREPARE_ANSWER:
 1522             ec_fop_prepare_answer(fop, _gf_true);
 1523 
 1524             return EC_STATE_REPORT;
 1525 
 1526         case EC_STATE_REPORT:
 1527             cbk = fop->answer;
 1528 
 1529             GF_ASSERT(cbk != NULL);
 1530             if (fop->cbks.ipc != NULL) {
 1531                 fop->cbks.ipc(fop->req_frame, fop, fop->xl, cbk->op_ret,
 1532                               cbk->op_errno, cbk->xdata);
 1533             }
 1534 
 1535             return EC_STATE_END;
 1536 
 1537         case -EC_STATE_INIT:
 1538         case -EC_STATE_DISPATCH:
 1539         case -EC_STATE_PREPARE_ANSWER:
 1540         case -EC_STATE_REPORT:
 1541             GF_ASSERT(fop->error != 0);
 1542 
 1543             if (fop->cbks.ipc != NULL) {
 1544                 fop->cbks.ipc(fop->req_frame, fop, fop->xl, -1, fop->error,
 1545                               NULL);
 1546             }
 1547 
 1548             return EC_STATE_END;
 1549 
 1550         default:
 1551             gf_msg(fop->xl->name, GF_LOG_ERROR, EINVAL, EC_MSG_UNHANDLED_STATE,
 1552                    "Unhandled state %d for %s", state, ec_fop_name(fop->id));
 1553 
 1554             return EC_STATE_END;
 1555     }
 1556 }
 1557 
 1558 void
 1559 ec_ipc(call_frame_t *frame, xlator_t *this, uintptr_t target,
 1560        uint32_t fop_flags, fop_ipc_cbk_t func, void *data, int32_t op,
 1561        dict_t *xdata)
 1562 {
 1563     ec_cbk_t callback = {.ipc = func};
 1564     ec_fop_data_t *fop = NULL;
 1565     int32_t error = ENOMEM;
 1566 
 1567     gf_msg_trace("ec", 0, "EC(IPC) %p", frame);
 1568 
 1569     VALIDATE_OR_GOTO(this, out);
 1570     GF_VALIDATE_OR_GOTO(this->name, frame, out);
 1571     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
 1572 
 1573     fop = ec_fop_data_allocate(frame, this, GF_FOP_IPC, 0, target, fop_flags,
 1574                                ec_wind_ipc, ec_manager_ipc, callback, data);
 1575     if (fop == NULL) {
 1576         goto out;
 1577     }
 1578     if (xdata != NULL) {
 1579         fop->xdata = dict_ref(xdata);
 1580     }
 1581     fop->int32 = op;
 1582 
 1583     error = 0;
 1584 
 1585 out:
 1586     if (fop != NULL) {
 1587         ec_manager(fop, error);
 1588     } else {
 1589         func(frame, NULL, this, -1, error, NULL);
 1590     }
 1591 }