"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-7.6/xlators/cluster/afr/src/afr-dir-write.c" (18 May 2020, 35227 Bytes) of package /linux/misc/glusterfs-7.6.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 "afr-dir-write.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 7.5_vs_7.6.

    1 /*
    2   Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
    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 <libgen.h>
   12 #include <unistd.h>
   13 #include <sys/time.h>
   14 #include <stdlib.h>
   15 #include <signal.h>
   16 
   17 #include <glusterfs/glusterfs.h>
   18 #include "afr.h"
   19 #include <glusterfs/dict.h>
   20 #include <glusterfs/logging.h>
   21 #include <glusterfs/list.h>
   22 #include <glusterfs/defaults.h>
   23 #include <glusterfs/common-utils.h>
   24 #include <glusterfs/compat-errno.h>
   25 #include <glusterfs/compat.h>
   26 #include <glusterfs/byte-order.h>
   27 
   28 #include "afr.h"
   29 #include "afr-transaction.h"
   30 
   31 void
   32 afr_mark_entry_pending_changelog(call_frame_t *frame, xlator_t *this);
   33 
   34 int
   35 afr_build_parent_loc(loc_t *parent, loc_t *child, int32_t *op_errno)
   36 {
   37     int ret = -1;
   38     char *child_path = NULL;
   39 
   40     if (!child->parent) {
   41         if (op_errno)
   42             *op_errno = EINVAL;
   43         goto out;
   44     }
   45 
   46     child_path = gf_strdup(child->path);
   47     if (!child_path) {
   48         if (op_errno)
   49             *op_errno = ENOMEM;
   50         goto out;
   51     }
   52 
   53     parent->path = gf_strdup(dirname(child_path));
   54     if (!parent->path) {
   55         if (op_errno)
   56             *op_errno = ENOMEM;
   57         goto out;
   58     }
   59 
   60     parent->inode = inode_ref(child->parent);
   61     gf_uuid_copy(parent->gfid, child->pargfid);
   62 
   63     ret = 0;
   64 out:
   65     GF_FREE(child_path);
   66 
   67     return ret;
   68 }
   69 
   70 static void
   71 __afr_dir_write_finalize(call_frame_t *frame, xlator_t *this)
   72 {
   73     afr_local_t *local = NULL;
   74     afr_private_t *priv = NULL;
   75     int inode_read_subvol = -1;
   76     int parent_read_subvol = -1;
   77     int parent2_read_subvol = -1;
   78     int i = 0;
   79     afr_read_subvol_args_t args = {
   80         0,
   81     };
   82 
   83     local = frame->local;
   84     priv = this->private;
   85 
   86     for (i = 0; i < priv->child_count; i++) {
   87         if (!local->replies[i].valid)
   88             continue;
   89         if (local->replies[i].op_ret == -1)
   90             continue;
   91         gf_uuid_copy(args.gfid, local->replies[i].poststat.ia_gfid);
   92         args.ia_type = local->replies[i].poststat.ia_type;
   93         break;
   94     }
   95 
   96     if (local->inode) {
   97         if (local->op != GF_FOP_RENAME && local->op != GF_FOP_LINK)
   98             afr_replies_interpret(frame, this, local->inode, NULL);
   99 
  100         inode_read_subvol = afr_data_subvol_get(local->inode, this, NULL, NULL,
  101                                                 NULL, &args);
  102     }
  103 
  104     if (local->parent)
  105         parent_read_subvol = afr_data_subvol_get(local->parent, this, NULL,
  106                                                  local->readable, NULL, NULL);
  107 
  108     if (local->parent2)
  109         parent2_read_subvol = afr_data_subvol_get(local->parent2, this, NULL,
  110                                                   local->readable2, NULL, NULL);
  111 
  112     local->op_ret = -1;
  113     local->op_errno = afr_final_errno(local, priv);
  114     afr_pick_error_xdata(local, priv, local->parent, local->readable,
  115                          local->parent2, local->readable2);
  116 
  117     for (i = 0; i < priv->child_count; i++) {
  118         if (!local->replies[i].valid)
  119             continue;
  120         if (local->replies[i].op_ret < 0) {
  121             if (local->inode)
  122                 afr_inode_need_refresh_set(local->inode, this);
  123             if (local->parent)
  124                 afr_inode_need_refresh_set(local->parent, this);
  125             if (local->parent2)
  126                 afr_inode_need_refresh_set(local->parent2, this);
  127             continue;
  128         }
  129 
  130         if (local->op_ret == -1) {
  131             local->op_ret = local->replies[i].op_ret;
  132             local->op_errno = local->replies[i].op_errno;
  133 
  134             local->cont.dir_fop.buf = local->replies[i].poststat;
  135             local->cont.dir_fop.preparent = local->replies[i].preparent;
  136             local->cont.dir_fop.postparent = local->replies[i].postparent;
  137             local->cont.dir_fop.prenewparent = local->replies[i].preparent2;
  138             local->cont.dir_fop.postnewparent = local->replies[i].postparent2;
  139             if (local->xdata_rsp) {
  140                 dict_unref(local->xdata_rsp);
  141                 local->xdata_rsp = NULL;
  142             }
  143 
  144             if (local->replies[i].xdata)
  145                 local->xdata_rsp = dict_ref(local->replies[i].xdata);
  146             continue;
  147         }
  148 
  149         if (i == inode_read_subvol) {
  150             local->cont.dir_fop.buf = local->replies[i].poststat;
  151             if (local->replies[i].xdata) {
  152                 if (local->xdata_rsp)
  153                     dict_unref(local->xdata_rsp);
  154                 local->xdata_rsp = dict_ref(local->replies[i].xdata);
  155             }
  156         }
  157 
  158         if (i == parent_read_subvol) {
  159             local->cont.dir_fop.preparent = local->replies[i].preparent;
  160             local->cont.dir_fop.postparent = local->replies[i].postparent;
  161         }
  162 
  163         if (i == parent2_read_subvol) {
  164             local->cont.dir_fop.prenewparent = local->replies[i].preparent2;
  165             local->cont.dir_fop.postnewparent = local->replies[i].postparent2;
  166         }
  167     }
  168 }
  169 
  170 static void
  171 __afr_dir_write_fill(call_frame_t *frame, xlator_t *this, int child_index,
  172                      int op_ret, int op_errno, struct iatt *poststat,
  173                      struct iatt *preparent, struct iatt *postparent,
  174                      struct iatt *preparent2, struct iatt *postparent2,
  175                      dict_t *xdata)
  176 {
  177     afr_local_t *local = NULL;
  178     afr_fd_ctx_t *fd_ctx = NULL;
  179 
  180     local = frame->local;
  181     fd_ctx = local->fd_ctx;
  182 
  183     local->replies[child_index].valid = 1;
  184     local->replies[child_index].op_ret = op_ret;
  185     local->replies[child_index].op_errno = op_errno;
  186     if (xdata)
  187         local->replies[child_index].xdata = dict_ref(xdata);
  188 
  189     if (op_ret >= 0) {
  190         if (poststat)
  191             local->replies[child_index].poststat = *poststat;
  192         if (preparent)
  193             local->replies[child_index].preparent = *preparent;
  194         if (postparent)
  195             local->replies[child_index].postparent = *postparent;
  196         if (preparent2)
  197             local->replies[child_index].preparent2 = *preparent2;
  198         if (postparent2)
  199             local->replies[child_index].postparent2 = *postparent2;
  200         if (fd_ctx)
  201             fd_ctx->opened_on[child_index] = AFR_FD_OPENED;
  202     } else {
  203         if (op_errno != ENOTEMPTY)
  204             afr_transaction_fop_failed(frame, this, child_index);
  205         if (fd_ctx)
  206             fd_ctx->opened_on[child_index] = AFR_FD_NOT_OPENED;
  207     }
  208 
  209     return;
  210 }
  211 
  212 static int
  213 __afr_dir_write_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  214                     int op_ret, int op_errno, struct iatt *buf,
  215                     struct iatt *preparent, struct iatt *postparent,
  216                     struct iatt *preparent2, struct iatt *postparent2,
  217                     dict_t *xdata)
  218 {
  219     afr_local_t *local = NULL;
  220     int child_index = (long)cookie;
  221     int call_count = -1;
  222     afr_private_t *priv = NULL;
  223 
  224     priv = this->private;
  225     local = frame->local;
  226 
  227     LOCK(&frame->lock);
  228     {
  229         __afr_dir_write_fill(frame, this, child_index, op_ret, op_errno, buf,
  230                              preparent, postparent, preparent2, postparent2,
  231                              xdata);
  232     }
  233     UNLOCK(&frame->lock);
  234     call_count = afr_frame_return(frame);
  235 
  236     if (call_count == 0) {
  237         __afr_dir_write_finalize(frame, this);
  238 
  239         if (afr_txn_nothing_failed(frame, this)) {
  240             /*if it did pre-op, it will do post-op changing ctime*/
  241             if (priv->consistent_metadata && afr_needs_changelog_update(local))
  242                 afr_zero_fill_stat(local);
  243             local->transaction.unwind(frame, this);
  244         }
  245 
  246         afr_mark_entry_pending_changelog(frame, this);
  247 
  248         afr_transaction_resume(frame, this);
  249     }
  250 
  251     return 0;
  252 }
  253 
  254 int
  255 afr_mark_new_entry_changelog_cbk(call_frame_t *frame, void *cookie,
  256                                  xlator_t *this, int op_ret, int op_errno,
  257                                  dict_t *xattr, dict_t *xdata)
  258 {
  259     int call_count = 0;
  260 
  261     call_count = afr_frame_return(frame);
  262 
  263     if (call_count == 0)
  264         AFR_STACK_DESTROY(frame);
  265 
  266     return 0;
  267 }
  268 
  269 void
  270 afr_mark_new_entry_changelog(call_frame_t *frame, xlator_t *this)
  271 {
  272     call_frame_t *new_frame = NULL;
  273     afr_local_t *local = NULL;
  274     afr_local_t *new_local = NULL;
  275     afr_private_t *priv = NULL;
  276     dict_t *xattr = NULL;
  277     int32_t **changelog = NULL;
  278     int i = 0;
  279     int op_errno = ENOMEM;
  280     unsigned char *pending = NULL;
  281     int call_count = 0;
  282 
  283     local = frame->local;
  284     priv = this->private;
  285 
  286     new_frame = copy_frame(frame);
  287     if (!new_frame)
  288         goto out;
  289 
  290     new_local = AFR_FRAME_INIT(new_frame, op_errno);
  291     if (!new_local)
  292         goto out;
  293 
  294     xattr = dict_new();
  295     if (!xattr)
  296         goto out;
  297 
  298     pending = alloca0(priv->child_count);
  299 
  300     for (i = 0; i < priv->child_count; i++) {
  301         if (local->transaction.pre_op[i] &&
  302             !local->transaction.failed_subvols[i]) {
  303             call_count++;
  304             continue;
  305         }
  306         pending[i] = 1;
  307     }
  308 
  309     changelog = afr_mark_pending_changelog(priv, pending, xattr,
  310                                            local->cont.dir_fop.buf.ia_type);
  311     if (!changelog)
  312         goto out;
  313 
  314     new_local->pending = changelog;
  315     gf_uuid_copy(new_local->loc.gfid, local->cont.dir_fop.buf.ia_gfid);
  316     new_local->loc.inode = inode_ref(local->inode);
  317 
  318     new_local->call_count = call_count;
  319 
  320     for (i = 0; i < priv->child_count; i++) {
  321         if (pending[i])
  322             continue;
  323 
  324         STACK_WIND_COOKIE(new_frame, afr_mark_new_entry_changelog_cbk,
  325                           (void *)(long)i, priv->children[i],
  326                           priv->children[i]->fops->xattrop, &new_local->loc,
  327                           GF_XATTROP_ADD_ARRAY, xattr, NULL);
  328         if (!--call_count)
  329             break;
  330     }
  331 
  332     new_frame = NULL;
  333 out:
  334     if (new_frame)
  335         AFR_STACK_DESTROY(new_frame);
  336     if (xattr)
  337         dict_unref(xattr);
  338     return;
  339 }
  340 
  341 void
  342 afr_mark_entry_pending_changelog(call_frame_t *frame, xlator_t *this)
  343 {
  344     afr_local_t *local = NULL;
  345     afr_private_t *priv = NULL;
  346     int pre_op_count = 0;
  347     int failed_count = 0;
  348 
  349     local = frame->local;
  350     priv = this->private;
  351 
  352     if (local->op_ret < 0)
  353         return;
  354 
  355     if (local->op != GF_FOP_CREATE && local->op != GF_FOP_MKNOD &&
  356         local->op != GF_FOP_MKDIR)
  357         return;
  358 
  359     pre_op_count = AFR_COUNT(local->transaction.pre_op, priv->child_count);
  360     failed_count = AFR_COUNT(local->transaction.failed_subvols,
  361                              priv->child_count);
  362 
  363     if (pre_op_count == priv->child_count && !failed_count)
  364         return;
  365 
  366     if (priv->thin_arbiter_count) {
  367         /*Mark new entry using ta file*/
  368         local->is_new_entry = _gf_true;
  369         return;
  370     }
  371 
  372     afr_mark_new_entry_changelog(frame, this);
  373 
  374     return;
  375 }
  376 
  377 /* {{{ create */
  378 
  379 int
  380 afr_create_unwind(call_frame_t *frame, xlator_t *this)
  381 {
  382     call_frame_t *main_frame = NULL;
  383     afr_local_t *local = NULL;
  384 
  385     local = frame->local;
  386 
  387     main_frame = afr_transaction_detach_fop_frame(frame);
  388 
  389     if (!main_frame)
  390         return 0;
  391 
  392     AFR_STACK_UNWIND(create, main_frame, local->op_ret, local->op_errno,
  393                      local->cont.create.fd, local->inode,
  394                      &local->cont.dir_fop.buf, &local->cont.dir_fop.preparent,
  395                      &local->cont.dir_fop.postparent, local->xdata_rsp);
  396     return 0;
  397 }
  398 
  399 int
  400 afr_create_wind_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  401                     int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode,
  402                     struct iatt *buf, struct iatt *preparent,
  403                     struct iatt *postparent, dict_t *xdata)
  404 {
  405     return __afr_dir_write_cbk(frame, cookie, this, op_ret, op_errno, buf,
  406                                preparent, postparent, NULL, NULL, xdata);
  407 }
  408 
  409 int
  410 afr_create_wind(call_frame_t *frame, xlator_t *this, int subvol)
  411 {
  412     afr_local_t *local = NULL;
  413     afr_private_t *priv = NULL;
  414 
  415     local = frame->local;
  416     priv = this->private;
  417 
  418     STACK_WIND_COOKIE(frame, afr_create_wind_cbk, (void *)(long)subvol,
  419                       priv->children[subvol],
  420                       priv->children[subvol]->fops->create, &local->loc,
  421                       local->cont.create.flags, local->cont.create.mode,
  422                       local->umask, local->cont.create.fd, local->xdata_req);
  423     return 0;
  424 }
  425 
  426 int
  427 afr_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
  428            mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata)
  429 {
  430     afr_local_t *local = NULL;
  431     call_frame_t *transaction_frame = NULL;
  432     int ret = -1;
  433     int op_errno = ENOMEM;
  434 
  435     transaction_frame = copy_frame(frame);
  436     if (!transaction_frame)
  437         goto out;
  438 
  439     local = AFR_FRAME_INIT(transaction_frame, op_errno);
  440     if (!local)
  441         goto out;
  442 
  443     loc_copy(&local->loc, loc);
  444 
  445     local->fd_ctx = afr_fd_ctx_get(fd, this);
  446     if (!local->fd_ctx)
  447         goto out;
  448 
  449     local->inode = inode_ref(loc->inode);
  450     local->parent = inode_ref(loc->parent);
  451 
  452     local->op = GF_FOP_CREATE;
  453     local->cont.create.flags = flags;
  454     local->fd_ctx->flags = flags;
  455     local->cont.create.mode = mode;
  456     local->cont.create.fd = fd_ref(fd);
  457     local->umask = umask;
  458 
  459     if (xdata)
  460         local->xdata_req = dict_copy_with_ref(xdata, NULL);
  461     else
  462         local->xdata_req = dict_new();
  463 
  464     if (!local->xdata_req)
  465         goto out;
  466 
  467     local->transaction.wind = afr_create_wind;
  468     local->transaction.unwind = afr_create_unwind;
  469 
  470     ret = afr_build_parent_loc(&local->transaction.parent_loc, loc, &op_errno);
  471     if (ret)
  472         goto out;
  473 
  474     local->transaction.main_frame = frame;
  475     local->transaction.basename = AFR_BASENAME(loc->path);
  476     ret = afr_transaction(transaction_frame, this, AFR_ENTRY_TRANSACTION);
  477     if (ret < 0) {
  478         op_errno = -ret;
  479         goto out;
  480     }
  481 
  482     return 0;
  483 out:
  484     if (transaction_frame)
  485         AFR_STACK_DESTROY(transaction_frame);
  486 
  487     AFR_STACK_UNWIND(create, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL,
  488                      NULL);
  489     return 0;
  490 }
  491 
  492 /* }}} */
  493 
  494 /* {{{ mknod */
  495 
  496 int
  497 afr_mknod_unwind(call_frame_t *frame, xlator_t *this)
  498 {
  499     call_frame_t *main_frame = NULL;
  500     afr_local_t *local = NULL;
  501 
  502     local = frame->local;
  503 
  504     main_frame = afr_transaction_detach_fop_frame(frame);
  505     if (!main_frame)
  506         return 0;
  507 
  508     AFR_STACK_UNWIND(mknod, main_frame, local->op_ret, local->op_errno,
  509                      local->inode, &local->cont.dir_fop.buf,
  510                      &local->cont.dir_fop.preparent,
  511                      &local->cont.dir_fop.postparent, local->xdata_rsp);
  512     return 0;
  513 }
  514 
  515 int
  516 afr_mknod_wind_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  517                    int32_t op_ret, int32_t op_errno, inode_t *inode,
  518                    struct iatt *buf, struct iatt *preparent,
  519                    struct iatt *postparent, dict_t *xdata)
  520 {
  521     return __afr_dir_write_cbk(frame, cookie, this, op_ret, op_errno, buf,
  522                                preparent, postparent, NULL, NULL, xdata);
  523 }
  524 
  525 int
  526 afr_mknod_wind(call_frame_t *frame, xlator_t *this, int subvol)
  527 {
  528     afr_local_t *local = NULL;
  529     afr_private_t *priv = NULL;
  530 
  531     local = frame->local;
  532     priv = this->private;
  533 
  534     STACK_WIND_COOKIE(frame, afr_mknod_wind_cbk, (void *)(long)subvol,
  535                       priv->children[subvol],
  536                       priv->children[subvol]->fops->mknod, &local->loc,
  537                       local->cont.mknod.mode, local->cont.mknod.dev,
  538                       local->umask, local->xdata_req);
  539     return 0;
  540 }
  541 
  542 int
  543 afr_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
  544           dev_t dev, mode_t umask, dict_t *xdata)
  545 {
  546     afr_local_t *local = NULL;
  547     call_frame_t *transaction_frame = NULL;
  548     int ret = -1;
  549     int op_errno = ENOMEM;
  550 
  551     transaction_frame = copy_frame(frame);
  552     if (!transaction_frame)
  553         goto out;
  554 
  555     local = AFR_FRAME_INIT(transaction_frame, op_errno);
  556     if (!local)
  557         goto out;
  558 
  559     loc_copy(&local->loc, loc);
  560     local->inode = inode_ref(loc->inode);
  561     local->parent = inode_ref(loc->parent);
  562 
  563     local->op = GF_FOP_MKNOD;
  564     local->cont.mknod.mode = mode;
  565     local->cont.mknod.dev = dev;
  566     local->umask = umask;
  567 
  568     if (xdata)
  569         local->xdata_req = dict_copy_with_ref(xdata, NULL);
  570     else
  571         local->xdata_req = dict_new();
  572 
  573     if (!local->xdata_req)
  574         goto out;
  575 
  576     local->transaction.wind = afr_mknod_wind;
  577     local->transaction.unwind = afr_mknod_unwind;
  578 
  579     ret = afr_build_parent_loc(&local->transaction.parent_loc, loc, &op_errno);
  580     if (ret)
  581         goto out;
  582 
  583     local->transaction.main_frame = frame;
  584     local->transaction.basename = AFR_BASENAME(loc->path);
  585     ret = afr_transaction(transaction_frame, this, AFR_ENTRY_TRANSACTION);
  586     if (ret < 0) {
  587         op_errno = -ret;
  588         goto out;
  589     }
  590 
  591     return 0;
  592 out:
  593     if (transaction_frame)
  594         AFR_STACK_DESTROY(transaction_frame);
  595 
  596     AFR_STACK_UNWIND(mknod, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL);
  597     return 0;
  598 }
  599 
  600 /* }}} */
  601 
  602 /* {{{ mkdir */
  603 
  604 int
  605 afr_mkdir_unwind(call_frame_t *frame, xlator_t *this)
  606 {
  607     call_frame_t *main_frame = NULL;
  608     afr_local_t *local = NULL;
  609 
  610     local = frame->local;
  611 
  612     main_frame = afr_transaction_detach_fop_frame(frame);
  613     if (!main_frame)
  614         return 0;
  615 
  616     AFR_STACK_UNWIND(mkdir, main_frame, local->op_ret, local->op_errno,
  617                      local->inode, &local->cont.dir_fop.buf,
  618                      &local->cont.dir_fop.preparent,
  619                      &local->cont.dir_fop.postparent, local->xdata_rsp);
  620     return 0;
  621 }
  622 
  623 int
  624 afr_mkdir_wind_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  625                    int32_t op_ret, int32_t op_errno, inode_t *inode,
  626                    struct iatt *buf, struct iatt *preparent,
  627                    struct iatt *postparent, dict_t *xdata)
  628 {
  629     return __afr_dir_write_cbk(frame, cookie, this, op_ret, op_errno, buf,
  630                                preparent, postparent, NULL, NULL, xdata);
  631 }
  632 
  633 int
  634 afr_mkdir_wind(call_frame_t *frame, xlator_t *this, int subvol)
  635 {
  636     afr_local_t *local = NULL;
  637     afr_private_t *priv = NULL;
  638 
  639     local = frame->local;
  640     priv = this->private;
  641 
  642     STACK_WIND_COOKIE(frame, afr_mkdir_wind_cbk, (void *)(long)subvol,
  643                       priv->children[subvol],
  644                       priv->children[subvol]->fops->mkdir, &local->loc,
  645                       local->cont.mkdir.mode, local->umask, local->xdata_req);
  646     return 0;
  647 }
  648 
  649 int
  650 afr_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
  651           mode_t umask, dict_t *xdata)
  652 {
  653     afr_local_t *local = NULL;
  654     call_frame_t *transaction_frame = NULL;
  655     int ret = -1;
  656     int op_errno = ENOMEM;
  657 
  658     transaction_frame = copy_frame(frame);
  659     if (!transaction_frame)
  660         goto out;
  661 
  662     local = AFR_FRAME_INIT(transaction_frame, op_errno);
  663     if (!local)
  664         goto out;
  665 
  666     loc_copy(&local->loc, loc);
  667     local->inode = inode_ref(loc->inode);
  668     local->parent = inode_ref(loc->parent);
  669 
  670     local->cont.mkdir.mode = mode;
  671     local->umask = umask;
  672 
  673     if (!xdata || !dict_get_sizen(xdata, "gfid-req")) {
  674         op_errno = EPERM;
  675         gf_msg_callingfn(this->name, GF_LOG_WARNING, op_errno,
  676                          AFR_MSG_GFID_NULL,
  677                          "mkdir: %s is received "
  678                          "without gfid-req %p",
  679                          loc->path, xdata);
  680         goto out;
  681     }
  682 
  683     local->xdata_req = dict_copy_with_ref(xdata, NULL);
  684     if (!local->xdata_req) {
  685         op_errno = ENOMEM;
  686         goto out;
  687     }
  688 
  689     local->op = GF_FOP_MKDIR;
  690     local->transaction.wind = afr_mkdir_wind;
  691     local->transaction.unwind = afr_mkdir_unwind;
  692 
  693     ret = afr_build_parent_loc(&local->transaction.parent_loc, loc, &op_errno);
  694     if (ret)
  695         goto out;
  696 
  697     local->transaction.main_frame = frame;
  698     local->transaction.basename = AFR_BASENAME(loc->path);
  699     ret = afr_transaction(transaction_frame, this, AFR_ENTRY_TRANSACTION);
  700     if (ret < 0) {
  701         op_errno = -ret;
  702         goto out;
  703     }
  704 
  705     return 0;
  706 out:
  707     if (transaction_frame)
  708         AFR_STACK_DESTROY(transaction_frame);
  709 
  710     AFR_STACK_UNWIND(mkdir, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL);
  711     return 0;
  712 }
  713 
  714 /* }}} */
  715 
  716 /* {{{ link */
  717 
  718 int
  719 afr_link_unwind(call_frame_t *frame, xlator_t *this)
  720 {
  721     call_frame_t *main_frame = NULL;
  722     afr_local_t *local = NULL;
  723 
  724     local = frame->local;
  725 
  726     main_frame = afr_transaction_detach_fop_frame(frame);
  727     if (!main_frame)
  728         return 0;
  729 
  730     AFR_STACK_UNWIND(link, main_frame, local->op_ret, local->op_errno,
  731                      local->inode, &local->cont.dir_fop.buf,
  732                      &local->cont.dir_fop.preparent,
  733                      &local->cont.dir_fop.postparent, local->xdata_rsp);
  734     return 0;
  735 }
  736 
  737 int
  738 afr_link_wind_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  739                   int32_t op_ret, int32_t op_errno, inode_t *inode,
  740                   struct iatt *buf, struct iatt *preparent,
  741                   struct iatt *postparent, dict_t *xdata)
  742 {
  743     return __afr_dir_write_cbk(frame, cookie, this, op_ret, op_errno, buf,
  744                                preparent, postparent, NULL, NULL, xdata);
  745 }
  746 
  747 int
  748 afr_link_wind(call_frame_t *frame, xlator_t *this, int subvol)
  749 {
  750     afr_local_t *local = NULL;
  751     afr_private_t *priv = NULL;
  752 
  753     local = frame->local;
  754     priv = this->private;
  755 
  756     STACK_WIND_COOKIE(frame, afr_link_wind_cbk, (void *)(long)subvol,
  757                       priv->children[subvol],
  758                       priv->children[subvol]->fops->link, &local->loc,
  759                       &local->newloc, local->xdata_req);
  760     return 0;
  761 }
  762 
  763 int
  764 afr_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
  765          dict_t *xdata)
  766 {
  767     afr_local_t *local = NULL;
  768     call_frame_t *transaction_frame = NULL;
  769     int ret = -1;
  770     int op_errno = ENOMEM;
  771 
  772     transaction_frame = copy_frame(frame);
  773     if (!transaction_frame)
  774         goto out;
  775 
  776     local = AFR_FRAME_INIT(transaction_frame, op_errno);
  777     if (!local)
  778         goto out;
  779 
  780     loc_copy(&local->loc, oldloc);
  781     loc_copy(&local->newloc, newloc);
  782 
  783     local->inode = inode_ref(oldloc->inode);
  784     local->parent = inode_ref(newloc->parent);
  785 
  786     if (xdata)
  787         local->xdata_req = dict_copy_with_ref(xdata, NULL);
  788     else
  789         local->xdata_req = dict_new();
  790 
  791     if (!local->xdata_req)
  792         goto out;
  793 
  794     local->op = GF_FOP_LINK;
  795 
  796     local->transaction.wind = afr_link_wind;
  797     local->transaction.unwind = afr_link_unwind;
  798 
  799     ret = afr_build_parent_loc(&local->transaction.parent_loc, newloc,
  800                                &op_errno);
  801     if (ret)
  802         goto out;
  803 
  804     local->transaction.main_frame = frame;
  805     local->transaction.basename = AFR_BASENAME(newloc->path);
  806     ret = afr_transaction(transaction_frame, this, AFR_ENTRY_TRANSACTION);
  807     if (ret < 0) {
  808         op_errno = -ret;
  809         goto out;
  810     }
  811 
  812     return 0;
  813 out:
  814     if (transaction_frame)
  815         AFR_STACK_DESTROY(transaction_frame);
  816 
  817     AFR_STACK_UNWIND(link, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL);
  818     return 0;
  819 }
  820 
  821 /* }}} */
  822 
  823 /* {{{ symlink */
  824 
  825 int
  826 afr_symlink_unwind(call_frame_t *frame, xlator_t *this)
  827 {
  828     call_frame_t *main_frame = NULL;
  829     afr_local_t *local = NULL;
  830 
  831     local = frame->local;
  832 
  833     main_frame = afr_transaction_detach_fop_frame(frame);
  834     if (!main_frame)
  835         return 0;
  836 
  837     AFR_STACK_UNWIND(symlink, main_frame, local->op_ret, local->op_errno,
  838                      local->inode, &local->cont.dir_fop.buf,
  839                      &local->cont.dir_fop.preparent,
  840                      &local->cont.dir_fop.postparent, local->xdata_rsp);
  841     return 0;
  842 }
  843 
  844 int
  845 afr_symlink_wind_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  846                      int32_t op_ret, int32_t op_errno, inode_t *inode,
  847                      struct iatt *buf, struct iatt *preparent,
  848                      struct iatt *postparent, dict_t *xdata)
  849 {
  850     return __afr_dir_write_cbk(frame, cookie, this, op_ret, op_errno, buf,
  851                                preparent, postparent, NULL, NULL, xdata);
  852 }
  853 
  854 int
  855 afr_symlink_wind(call_frame_t *frame, xlator_t *this, int subvol)
  856 {
  857     afr_local_t *local = NULL;
  858     afr_private_t *priv = NULL;
  859 
  860     local = frame->local;
  861     priv = this->private;
  862 
  863     STACK_WIND_COOKIE(frame, afr_symlink_wind_cbk, (void *)(long)subvol,
  864                       priv->children[subvol],
  865                       priv->children[subvol]->fops->symlink,
  866                       local->cont.symlink.linkpath, &local->loc, local->umask,
  867                       local->xdata_req);
  868     return 0;
  869 }
  870 
  871 int
  872 afr_symlink(call_frame_t *frame, xlator_t *this, const char *linkpath,
  873             loc_t *loc, mode_t umask, dict_t *xdata)
  874 {
  875     afr_local_t *local = NULL;
  876     call_frame_t *transaction_frame = NULL;
  877     int ret = -1;
  878     int op_errno = ENOMEM;
  879 
  880     transaction_frame = copy_frame(frame);
  881     if (!transaction_frame)
  882         goto out;
  883 
  884     local = AFR_FRAME_INIT(transaction_frame, op_errno);
  885     if (!local)
  886         goto out;
  887 
  888     loc_copy(&local->loc, loc);
  889     local->inode = inode_ref(loc->inode);
  890     local->parent = inode_ref(loc->parent);
  891 
  892     local->cont.symlink.linkpath = gf_strdup(linkpath);
  893     local->umask = umask;
  894 
  895     if (xdata)
  896         local->xdata_req = dict_copy_with_ref(xdata, NULL);
  897     else
  898         local->xdata_req = dict_new();
  899 
  900     if (!local->xdata_req)
  901         goto out;
  902 
  903     local->op = GF_FOP_SYMLINK;
  904     local->transaction.wind = afr_symlink_wind;
  905     local->transaction.unwind = afr_symlink_unwind;
  906 
  907     ret = afr_build_parent_loc(&local->transaction.parent_loc, loc, &op_errno);
  908     if (ret)
  909         goto out;
  910 
  911     local->transaction.main_frame = frame;
  912     local->transaction.basename = AFR_BASENAME(loc->path);
  913     ret = afr_transaction(transaction_frame, this, AFR_ENTRY_TRANSACTION);
  914     if (ret < 0) {
  915         op_errno = -ret;
  916         goto out;
  917     }
  918 
  919     return 0;
  920 out:
  921     if (transaction_frame)
  922         AFR_STACK_DESTROY(transaction_frame);
  923 
  924     AFR_STACK_UNWIND(symlink, frame, -1, op_errno, NULL, NULL, NULL, NULL,
  925                      NULL);
  926     return 0;
  927 }
  928 
  929 /* }}} */
  930 
  931 /* {{{ rename */
  932 
  933 int
  934 afr_rename_unwind(call_frame_t *frame, xlator_t *this)
  935 {
  936     call_frame_t *main_frame = NULL;
  937     afr_local_t *local = NULL;
  938 
  939     local = frame->local;
  940 
  941     main_frame = afr_transaction_detach_fop_frame(frame);
  942     if (!main_frame)
  943         return 0;
  944 
  945     AFR_STACK_UNWIND(rename, main_frame, local->op_ret, local->op_errno,
  946                      &local->cont.dir_fop.buf, &local->cont.dir_fop.preparent,
  947                      &local->cont.dir_fop.postparent,
  948                      &local->cont.dir_fop.prenewparent,
  949                      &local->cont.dir_fop.postnewparent, local->xdata_rsp);
  950     return 0;
  951 }
  952 
  953 int
  954 afr_rename_wind_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  955                     int32_t op_ret, int32_t op_errno, struct iatt *buf,
  956                     struct iatt *preoldparent, struct iatt *postoldparent,
  957                     struct iatt *prenewparent, struct iatt *postnewparent,
  958                     dict_t *xdata)
  959 {
  960     return __afr_dir_write_cbk(frame, cookie, this, op_ret, op_errno, buf,
  961                                preoldparent, postoldparent, prenewparent,
  962                                postnewparent, xdata);
  963 }
  964 
  965 int
  966 afr_rename_wind(call_frame_t *frame, xlator_t *this, int subvol)
  967 {
  968     afr_local_t *local = NULL;
  969     afr_private_t *priv = NULL;
  970 
  971     local = frame->local;
  972     priv = this->private;
  973 
  974     STACK_WIND_COOKIE(frame, afr_rename_wind_cbk, (void *)(long)subvol,
  975                       priv->children[subvol],
  976                       priv->children[subvol]->fops->rename, &local->loc,
  977                       &local->newloc, local->xdata_req);
  978     return 0;
  979 }
  980 
  981 int
  982 afr_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
  983            dict_t *xdata)
  984 {
  985     afr_local_t *local = NULL;
  986     call_frame_t *transaction_frame = NULL;
  987     int ret = -1;
  988     int op_errno = ENOMEM;
  989 
  990     transaction_frame = copy_frame(frame);
  991     if (!transaction_frame) {
  992         op_errno = ENOMEM;
  993         goto out;
  994     }
  995 
  996     local = AFR_FRAME_INIT(transaction_frame, op_errno);
  997     if (!local)
  998         goto out;
  999 
 1000     loc_copy(&local->loc, oldloc);
 1001     loc_copy(&local->newloc, newloc);
 1002 
 1003     local->inode = inode_ref(oldloc->inode);
 1004     local->parent = inode_ref(oldloc->parent);
 1005     local->parent2 = inode_ref(newloc->parent);
 1006 
 1007     if (xdata)
 1008         local->xdata_req = dict_copy_with_ref(xdata, NULL);
 1009     else
 1010         local->xdata_req = dict_new();
 1011 
 1012     if (!local->xdata_req)
 1013         goto out;
 1014 
 1015     local->op = GF_FOP_RENAME;
 1016     local->transaction.wind = afr_rename_wind;
 1017     local->transaction.unwind = afr_rename_unwind;
 1018 
 1019     ret = afr_build_parent_loc(&local->transaction.parent_loc, oldloc,
 1020                                &op_errno);
 1021     if (ret)
 1022         goto out;
 1023     ret = afr_build_parent_loc(&local->transaction.new_parent_loc, newloc,
 1024                                &op_errno);
 1025     if (ret)
 1026         goto out;
 1027 
 1028     local->transaction.main_frame = frame;
 1029     local->transaction.basename = AFR_BASENAME(oldloc->path);
 1030     local->transaction.new_basename = AFR_BASENAME(newloc->path);
 1031     ret = afr_transaction(transaction_frame, this,
 1032                           AFR_ENTRY_RENAME_TRANSACTION);
 1033     if (ret < 0) {
 1034         op_errno = -ret;
 1035         goto out;
 1036     }
 1037 
 1038     return 0;
 1039 out:
 1040     if (transaction_frame)
 1041         AFR_STACK_DESTROY(transaction_frame);
 1042 
 1043     AFR_STACK_UNWIND(rename, frame, -1, op_errno, NULL, NULL, NULL, NULL, NULL,
 1044                      NULL);
 1045     return 0;
 1046 }
 1047 
 1048 /* }}} */
 1049 
 1050 /* {{{ unlink */
 1051 
 1052 int
 1053 afr_unlink_unwind(call_frame_t *frame, xlator_t *this)
 1054 {
 1055     call_frame_t *main_frame = NULL;
 1056     afr_local_t *local = NULL;
 1057 
 1058     local = frame->local;
 1059 
 1060     main_frame = afr_transaction_detach_fop_frame(frame);
 1061     if (!main_frame)
 1062         return 0;
 1063 
 1064     AFR_STACK_UNWIND(unlink, main_frame, local->op_ret, local->op_errno,
 1065                      &local->cont.dir_fop.preparent,
 1066                      &local->cont.dir_fop.postparent, local->xdata_rsp);
 1067     return 0;
 1068 }
 1069 
 1070 int
 1071 afr_unlink_wind_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1072                     int32_t op_ret, int32_t op_errno, struct iatt *preparent,
 1073                     struct iatt *postparent, dict_t *xdata)
 1074 {
 1075     return __afr_dir_write_cbk(frame, cookie, this, op_ret, op_errno, NULL,
 1076                                preparent, postparent, NULL, NULL, xdata);
 1077 }
 1078 
 1079 int
 1080 afr_unlink_wind(call_frame_t *frame, xlator_t *this, int subvol)
 1081 {
 1082     afr_local_t *local = NULL;
 1083     afr_private_t *priv = NULL;
 1084 
 1085     local = frame->local;
 1086     priv = this->private;
 1087 
 1088     STACK_WIND_COOKIE(frame, afr_unlink_wind_cbk, (void *)(long)subvol,
 1089                       priv->children[subvol],
 1090                       priv->children[subvol]->fops->unlink, &local->loc,
 1091                       local->xflag, local->xdata_req);
 1092     return 0;
 1093 }
 1094 
 1095 int
 1096 afr_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag,
 1097            dict_t *xdata)
 1098 {
 1099     afr_local_t *local = NULL;
 1100     call_frame_t *transaction_frame = NULL;
 1101     int ret = -1;
 1102     int op_errno = ENOMEM;
 1103 
 1104     transaction_frame = copy_frame(frame);
 1105     if (!transaction_frame)
 1106         goto out;
 1107 
 1108     local = AFR_FRAME_INIT(transaction_frame, op_errno);
 1109     if (!local)
 1110         goto out;
 1111 
 1112     loc_copy(&local->loc, loc);
 1113     local->xflag = xflag;
 1114 
 1115     local->inode = inode_ref(loc->inode);
 1116     local->parent = inode_ref(loc->parent);
 1117 
 1118     if (xdata)
 1119         local->xdata_req = dict_copy_with_ref(xdata, NULL);
 1120     else
 1121         local->xdata_req = dict_new();
 1122 
 1123     if (!local->xdata_req)
 1124         goto out;
 1125 
 1126     local->op = GF_FOP_UNLINK;
 1127     local->transaction.wind = afr_unlink_wind;
 1128     local->transaction.unwind = afr_unlink_unwind;
 1129 
 1130     ret = afr_build_parent_loc(&local->transaction.parent_loc, loc, &op_errno);
 1131     if (ret)
 1132         goto out;
 1133 
 1134     local->transaction.main_frame = frame;
 1135     local->transaction.basename = AFR_BASENAME(loc->path);
 1136     ret = afr_transaction(transaction_frame, this, AFR_ENTRY_TRANSACTION);
 1137     if (ret < 0) {
 1138         op_errno = -ret;
 1139         goto out;
 1140     }
 1141 
 1142     return 0;
 1143 out:
 1144     if (transaction_frame)
 1145         AFR_STACK_DESTROY(transaction_frame);
 1146 
 1147     AFR_STACK_UNWIND(unlink, frame, -1, op_errno, NULL, NULL, NULL);
 1148     return 0;
 1149 }
 1150 
 1151 /* }}} */
 1152 
 1153 /* {{{ rmdir */
 1154 
 1155 int
 1156 afr_rmdir_unwind(call_frame_t *frame, xlator_t *this)
 1157 {
 1158     call_frame_t *main_frame = NULL;
 1159     afr_local_t *local = NULL;
 1160 
 1161     local = frame->local;
 1162 
 1163     main_frame = afr_transaction_detach_fop_frame(frame);
 1164     if (!main_frame)
 1165         return 0;
 1166 
 1167     AFR_STACK_UNWIND(rmdir, main_frame, local->op_ret, local->op_errno,
 1168                      &local->cont.dir_fop.preparent,
 1169                      &local->cont.dir_fop.postparent, local->xdata_rsp);
 1170     return 0;
 1171 }
 1172 
 1173 int
 1174 afr_rmdir_wind_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1175                    int32_t op_ret, int32_t op_errno, struct iatt *preparent,
 1176                    struct iatt *postparent, dict_t *xdata)
 1177 {
 1178     return __afr_dir_write_cbk(frame, cookie, this, op_ret, op_errno, NULL,
 1179                                preparent, postparent, NULL, NULL, xdata);
 1180 }
 1181 
 1182 int
 1183 afr_rmdir_wind(call_frame_t *frame, xlator_t *this, int subvol)
 1184 {
 1185     afr_local_t *local = NULL;
 1186     afr_private_t *priv = NULL;
 1187 
 1188     local = frame->local;
 1189     priv = this->private;
 1190 
 1191     STACK_WIND_COOKIE(frame, afr_rmdir_wind_cbk, (void *)(long)subvol,
 1192                       priv->children[subvol],
 1193                       priv->children[subvol]->fops->rmdir, &local->loc,
 1194                       local->cont.rmdir.flags, local->xdata_req);
 1195     return 0;
 1196 }
 1197 
 1198 int
 1199 afr_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags,
 1200           dict_t *xdata)
 1201 {
 1202     afr_local_t *local = NULL;
 1203     call_frame_t *transaction_frame = NULL;
 1204     int ret = -1;
 1205     int op_errno = ENOMEM;
 1206 
 1207     transaction_frame = copy_frame(frame);
 1208     if (!transaction_frame)
 1209         goto out;
 1210 
 1211     local = AFR_FRAME_INIT(transaction_frame, op_errno);
 1212     if (!local)
 1213         goto out;
 1214 
 1215     loc_copy(&local->loc, loc);
 1216     local->inode = inode_ref(loc->inode);
 1217     local->parent = inode_ref(loc->parent);
 1218 
 1219     local->cont.rmdir.flags = flags;
 1220 
 1221     if (xdata)
 1222         local->xdata_req = dict_copy_with_ref(xdata, NULL);
 1223     else
 1224         local->xdata_req = dict_new();
 1225 
 1226     if (!local->xdata_req)
 1227         goto out;
 1228 
 1229     local->op = GF_FOP_RMDIR;
 1230     local->transaction.wind = afr_rmdir_wind;
 1231     local->transaction.unwind = afr_rmdir_unwind;
 1232 
 1233     ret = afr_build_parent_loc(&local->transaction.parent_loc, loc, &op_errno);
 1234     if (ret)
 1235         goto out;
 1236 
 1237     local->transaction.main_frame = frame;
 1238     local->transaction.basename = AFR_BASENAME(loc->path);
 1239     ret = afr_transaction(transaction_frame, this, AFR_ENTRY_TRANSACTION);
 1240     if (ret < 0) {
 1241         op_errno = -ret;
 1242         goto out;
 1243     }
 1244 
 1245     return 0;
 1246 out:
 1247     if (transaction_frame)
 1248         AFR_STACK_DESTROY(transaction_frame);
 1249 
 1250     AFR_STACK_UNWIND(rmdir, frame, -1, op_errno, NULL, NULL, NULL);
 1251     return 0;
 1252 }
 1253 
 1254 /* }}} */