"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/xlators/cluster/dht/src/dht-inode-write.c" (16 Sep 2020, 41588 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 "dht-inode-write.c" see the Fossies "Dox" file reference documentation.

    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 "dht-common.h"
   12 
   13 static int
   14 dht_writev2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret);
   15 static int
   16 dht_truncate2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret);
   17 static int
   18 dht_setattr2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret);
   19 static int
   20 dht_fallocate2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret);
   21 static int
   22 dht_discard2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret);
   23 static int
   24 dht_zerofill2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret);
   25 
   26 int
   27 dht_writev_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
   28                int op_errno, struct iatt *prebuf, struct iatt *postbuf,
   29                dict_t *xdata)
   30 {
   31     dht_local_t *local = NULL;
   32     xlator_t *prev = NULL;
   33     int ret = -1;
   34     xlator_t *subvol1 = NULL;
   35     xlator_t *subvol2 = NULL;
   36 
   37     local = frame->local;
   38     prev = cookie;
   39 
   40     if (!local) {
   41         op_ret = -1;
   42         op_errno = EINVAL;
   43         goto out;
   44     }
   45 
   46     /* writev fails with EBADF if dht has not yet opened the fd
   47      * on the cached subvol. This could happen if the file was migrated
   48      * and a lookup updated the cached subvol in the inode ctx.
   49      * We only check once as this could be a valid bad fd error.
   50      */
   51 
   52     if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
   53         ret = dht_check_and_open_fd_on_subvol(this, frame);
   54         if (ret)
   55             goto out;
   56         return 0;
   57     }
   58 
   59     if (op_ret == -1 && !dht_inode_missing(op_errno)) {
   60         local->op_errno = op_errno;
   61         local->op_ret = -1;
   62         gf_msg_debug(this->name, 0, "subvolume %s returned -1 (%s)", prev->name,
   63                      strerror(op_errno));
   64         goto out;
   65     }
   66 
   67     if (local->call_cnt != 1) {
   68         /* preserve the modes of source */
   69         if (local->stbuf.ia_blocks) {
   70             dht_iatt_merge(this, postbuf, &local->stbuf);
   71             dht_iatt_merge(this, prebuf, &local->prebuf);
   72         }
   73         goto out;
   74     }
   75 
   76     local->rebalance.target_op_fn = dht_writev2;
   77 
   78     local->op_ret = op_ret;
   79     local->op_errno = op_errno;
   80 
   81     /* We might need to pass the stbuf information to the higher DHT
   82      * layer for appropriate handling.
   83      */
   84 
   85     dht_set_local_rebalance(this, local, NULL, prebuf, postbuf, xdata);
   86 
   87     /* Phase 2 of migration */
   88     if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2(postbuf)) {
   89         ret = dht_rebalance_complete_check(this, frame);
   90         if (!ret)
   91             return 0;
   92     }
   93 
   94     /* Check if the rebalance phase1 is true */
   95     if (IS_DHT_MIGRATION_PHASE1(postbuf)) {
   96         if (!dht_is_tier_xlator(this)) {
   97             if (!local->xattr_req) {
   98                 local->xattr_req = dict_new();
   99                 if (!local->xattr_req) {
  100                     gf_msg(this->name, GF_LOG_ERROR, DHT_MSG_NO_MEMORY, ENOMEM,
  101                            "insufficient memory");
  102                     local->op_errno = ENOMEM;
  103                     local->op_ret = -1;
  104                     goto out;
  105                 }
  106             }
  107 
  108             ret = dict_set_uint32(local->xattr_req,
  109                                   GF_PROTECT_FROM_EXTERNAL_WRITES, 1);
  110             if (ret) {
  111                 gf_msg(this->name, GF_LOG_ERROR, DHT_MSG_DICT_SET_FAILED, 0,
  112                        "Failed to set key %s in dictionary",
  113                        GF_PROTECT_FROM_EXTERNAL_WRITES);
  114                 local->op_errno = ENOMEM;
  115                 local->op_ret = -1;
  116                 goto out;
  117             }
  118         }
  119 
  120         dht_iatt_merge(this, &local->stbuf, postbuf);
  121         dht_iatt_merge(this, &local->prebuf, prebuf);
  122 
  123         ret = dht_inode_ctx_get_mig_info(this, local->fd->inode, &subvol1,
  124                                          &subvol2);
  125         if (!dht_mig_info_is_invalid(local->cached_subvol, subvol1, subvol2)) {
  126             if (dht_fd_open_on_dst(this, local->fd, subvol2)) {
  127                 dht_writev2(this, subvol2, frame, 0);
  128                 return 0;
  129             }
  130         }
  131         ret = dht_rebalance_in_progress_check(this, frame);
  132         if (!ret)
  133             return 0;
  134     }
  135 
  136 out:
  137     DHT_STRIP_PHASE1_FLAGS(postbuf);
  138     DHT_STRIP_PHASE1_FLAGS(prebuf);
  139 
  140     DHT_STACK_UNWIND(writev, frame, op_ret, op_errno, prebuf, postbuf, xdata);
  141 
  142     return 0;
  143 }
  144 
  145 static int
  146 dht_writev2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret)
  147 {
  148     dht_local_t *local = NULL;
  149     int32_t op_errno = EINVAL;
  150 
  151     if ((frame == NULL) || (frame->local == NULL))
  152         goto out;
  153 
  154     local = frame->local;
  155     op_errno = local->op_errno;
  156 
  157     if (we_are_not_migrating(ret)) {
  158         /* This dht xlator is not migrating the file. Unwind and
  159          * pass on the original mode bits so the higher DHT layer
  160          * can handle this.
  161          */
  162         DHT_STACK_UNWIND(writev, frame, local->op_ret, local->op_errno,
  163                          &local->rebalance.prebuf, &local->rebalance.postbuf,
  164                          local->rebalance.xdata);
  165         return 0;
  166     }
  167 
  168     if (subvol == NULL)
  169         goto out;
  170 
  171     local->call_cnt = 2; /* This is the second attempt */
  172 
  173     STACK_WIND_COOKIE(frame, dht_writev_cbk, subvol, subvol,
  174                       subvol->fops->writev, local->fd, local->rebalance.vector,
  175                       local->rebalance.count, local->rebalance.offset,
  176                       local->rebalance.flags, local->rebalance.iobref,
  177                       local->xattr_req);
  178 
  179     return 0;
  180 
  181 out:
  182     DHT_STACK_UNWIND(writev, frame, -1, op_errno, NULL, NULL, NULL);
  183 
  184     return 0;
  185 }
  186 
  187 int
  188 dht_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector,
  189            int count, off_t off, uint32_t flags, struct iobref *iobref,
  190            dict_t *xdata)
  191 {
  192     xlator_t *subvol = NULL;
  193     int op_errno = -1;
  194     dht_local_t *local = NULL;
  195 
  196     VALIDATE_OR_GOTO(frame, err);
  197     VALIDATE_OR_GOTO(this, err);
  198     VALIDATE_OR_GOTO(fd, err);
  199 
  200     local = dht_local_init(frame, NULL, fd, GF_FOP_WRITE);
  201     if (!local) {
  202         op_errno = ENOMEM;
  203         goto err;
  204     }
  205 
  206     subvol = local->cached_subvol;
  207     if (!subvol) {
  208         gf_msg_debug(this->name, 0, "no cached subvolume for fd=%p", fd);
  209         op_errno = EINVAL;
  210         goto err;
  211     }
  212 
  213     if (xdata)
  214         local->xattr_req = dict_ref(xdata);
  215 
  216     local->rebalance.vector = iov_dup(vector, count);
  217     local->rebalance.offset = off;
  218     local->rebalance.count = count;
  219     local->rebalance.flags = flags;
  220     local->rebalance.iobref = iobref_ref(iobref);
  221     local->call_cnt = 1;
  222 
  223     STACK_WIND_COOKIE(frame, dht_writev_cbk, subvol, subvol,
  224                       subvol->fops->writev, fd, local->rebalance.vector,
  225                       local->rebalance.count, local->rebalance.offset,
  226                       local->rebalance.flags, local->rebalance.iobref,
  227                       local->xattr_req);
  228 
  229     return 0;
  230 
  231 err:
  232     op_errno = (op_errno == -1) ? errno : op_errno;
  233     DHT_STACK_UNWIND(writev, frame, -1, op_errno, NULL, NULL, NULL);
  234 
  235     return 0;
  236 }
  237 
  238 int
  239 dht_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
  240                  int op_errno, struct iatt *prebuf, struct iatt *postbuf,
  241                  dict_t *xdata)
  242 {
  243     dht_local_t *local = NULL;
  244     xlator_t *prev = NULL;
  245     int ret = -1;
  246     xlator_t *src_subvol = NULL;
  247     xlator_t *dst_subvol = NULL;
  248     inode_t *inode = NULL;
  249 
  250     GF_VALIDATE_OR_GOTO("dht", frame, err);
  251     GF_VALIDATE_OR_GOTO("dht", this, out);
  252     GF_VALIDATE_OR_GOTO("dht", frame->local, out);
  253     GF_VALIDATE_OR_GOTO("dht", cookie, out);
  254 
  255     local = frame->local;
  256     prev = cookie;
  257 
  258     /* Needs to be checked only for ftruncate.
  259      * ftruncate fails with EBADF/EINVAL if dht has not yet opened the fd
  260      * on the cached subvol. This could happen if the file was migrated
  261      * and a lookup updated the cached subvol in the inode ctx.
  262      * We only check once as this could actually be a valid error.
  263      */
  264 
  265     if ((local->fop == GF_FOP_FTRUNCATE) &&
  266         dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
  267         ret = dht_check_and_open_fd_on_subvol(this, frame);
  268         if (ret)
  269             goto out;
  270         return 0;
  271     }
  272 
  273     if ((op_ret == -1) && !dht_inode_missing(op_errno)) {
  274         local->op_errno = op_errno;
  275         local->op_ret = -1;
  276         gf_msg_debug(this->name, op_errno, "subvolume %s returned -1",
  277                      prev->name);
  278 
  279         goto out;
  280     }
  281 
  282     if (local->call_cnt != 1) {
  283         if (local->stbuf.ia_blocks) {
  284             dht_iatt_merge(this, postbuf, &local->stbuf);
  285             dht_iatt_merge(this, prebuf, &local->prebuf);
  286         }
  287         goto out;
  288     }
  289 
  290     local->rebalance.target_op_fn = dht_truncate2;
  291 
  292     local->op_ret = op_ret;
  293     local->op_errno = op_errno;
  294 
  295     /* We might need to pass the stbuf information to the higher DHT
  296      * layer for appropriate handling.
  297      */
  298 
  299     dht_set_local_rebalance(this, local, NULL, prebuf, postbuf, xdata);
  300 
  301     /* Phase 2 of migration */
  302     if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2(postbuf)) {
  303         ret = dht_rebalance_complete_check(this, frame);
  304         if (!ret)
  305             return 0;
  306     }
  307 
  308     /* Check if the rebalance phase1 is true */
  309     if (IS_DHT_MIGRATION_PHASE1(postbuf)) {
  310         dht_iatt_merge(this, &local->stbuf, postbuf);
  311         dht_iatt_merge(this, &local->prebuf, prebuf);
  312 
  313         inode = (local->fd) ? local->fd->inode : local->loc.inode;
  314 
  315         dht_inode_ctx_get_mig_info(this, inode, &src_subvol, &dst_subvol);
  316         if (!dht_mig_info_is_invalid(local->cached_subvol, src_subvol,
  317                                      dst_subvol)) {
  318             if ((!local->fd) ||
  319                 ((local->fd) &&
  320                  dht_fd_open_on_dst(this, local->fd, dst_subvol))) {
  321                 dht_truncate2(this, dst_subvol, frame, 0);
  322                 return 0;
  323             }
  324         }
  325         ret = dht_rebalance_in_progress_check(this, frame);
  326         if (!ret)
  327             return 0;
  328     }
  329 
  330 out:
  331     DHT_STRIP_PHASE1_FLAGS(postbuf);
  332     DHT_STRIP_PHASE1_FLAGS(prebuf);
  333 
  334     DHT_STACK_UNWIND(truncate, frame, op_ret, op_errno, prebuf, postbuf, xdata);
  335 err:
  336     return 0;
  337 }
  338 
  339 static int
  340 dht_truncate2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret)
  341 {
  342     dht_local_t *local = NULL;
  343     int32_t op_errno = EINVAL;
  344 
  345     if (!frame || !frame->local)
  346         goto out;
  347 
  348     local = frame->local;
  349     op_errno = local->op_errno;
  350 
  351     /* This dht xlator is not migrating the file  */
  352     if (we_are_not_migrating(ret)) {
  353         DHT_STACK_UNWIND(truncate, frame, local->op_ret, local->op_errno,
  354                          &local->rebalance.prebuf, &local->rebalance.postbuf,
  355                          local->rebalance.xdata);
  356         return 0;
  357     }
  358 
  359     if (subvol == NULL)
  360         goto out;
  361 
  362     local->call_cnt = 2; /* This is the second attempt */
  363 
  364     if (local->fop == GF_FOP_TRUNCATE) {
  365         STACK_WIND_COOKIE(frame, dht_truncate_cbk, subvol, subvol,
  366                           subvol->fops->truncate, &local->loc,
  367                           local->rebalance.offset, local->xattr_req);
  368     } else {
  369         STACK_WIND_COOKIE(frame, dht_truncate_cbk, subvol, subvol,
  370                           subvol->fops->ftruncate, local->fd,
  371                           local->rebalance.offset, local->xattr_req);
  372     }
  373 
  374     return 0;
  375 
  376 out:
  377     DHT_STACK_UNWIND(truncate, frame, -1, op_errno, NULL, NULL, NULL);
  378     return 0;
  379 }
  380 
  381 int
  382 dht_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset,
  383              dict_t *xdata)
  384 {
  385     xlator_t *subvol = NULL;
  386     int op_errno = -1;
  387     dht_local_t *local = NULL;
  388 
  389     VALIDATE_OR_GOTO(frame, err);
  390     VALIDATE_OR_GOTO(this, err);
  391     VALIDATE_OR_GOTO(loc, err);
  392     VALIDATE_OR_GOTO(loc->inode, err);
  393 
  394     local = dht_local_init(frame, loc, NULL, GF_FOP_TRUNCATE);
  395     if (!local) {
  396         op_errno = ENOMEM;
  397         goto err;
  398     }
  399 
  400     local->rebalance.offset = offset;
  401     local->call_cnt = 1;
  402     subvol = local->cached_subvol;
  403     if (!subvol) {
  404         gf_msg_debug(this->name, 0, "no cached subvolume for gfid=%s",
  405                      uuid_utoa(loc->inode->gfid));
  406         op_errno = EINVAL;
  407         goto err;
  408     }
  409 
  410     if (xdata)
  411         local->xattr_req = dict_ref(xdata);
  412 
  413     STACK_WIND_COOKIE(frame, dht_truncate_cbk, subvol, subvol,
  414                       subvol->fops->truncate, loc, offset, xdata);
  415 
  416     return 0;
  417 
  418 err:
  419     op_errno = (op_errno == -1) ? errno : op_errno;
  420     DHT_STACK_UNWIND(truncate, frame, -1, op_errno, NULL, NULL, NULL);
  421 
  422     return 0;
  423 }
  424 
  425 int
  426 dht_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
  427               dict_t *xdata)
  428 {
  429     xlator_t *subvol = NULL;
  430     int op_errno = -1;
  431     dht_local_t *local = NULL;
  432 
  433     VALIDATE_OR_GOTO(frame, err);
  434     VALIDATE_OR_GOTO(this, err);
  435     VALIDATE_OR_GOTO(fd, err);
  436 
  437     local = dht_local_init(frame, NULL, fd, GF_FOP_FTRUNCATE);
  438     if (!local) {
  439         op_errno = ENOMEM;
  440         goto err;
  441     }
  442 
  443     local->rebalance.offset = offset;
  444     local->call_cnt = 1;
  445     subvol = local->cached_subvol;
  446     if (!subvol) {
  447         gf_msg_debug(this->name, 0, "no cached subvolume for fd=%p", fd);
  448         op_errno = EINVAL;
  449         goto err;
  450     }
  451 
  452     if (xdata)
  453         local->xattr_req = dict_ref(xdata);
  454 
  455     STACK_WIND_COOKIE(frame, dht_truncate_cbk, subvol, subvol,
  456                       subvol->fops->ftruncate, fd, local->rebalance.offset,
  457                       local->xattr_req);
  458     return 0;
  459 
  460 err:
  461     op_errno = (op_errno == -1) ? errno : op_errno;
  462     DHT_STACK_UNWIND(ftruncate, frame, -1, op_errno, NULL, NULL, NULL);
  463 
  464     return 0;
  465 }
  466 
  467 int
  468 dht_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
  469                   int op_errno, struct iatt *prebuf, struct iatt *postbuf,
  470                   dict_t *xdata)
  471 {
  472     dht_local_t *local = NULL;
  473     xlator_t *prev = NULL;
  474     int ret = -1;
  475     xlator_t *src_subvol = NULL;
  476     xlator_t *dst_subvol = NULL;
  477 
  478     GF_VALIDATE_OR_GOTO("dht", frame, err);
  479     GF_VALIDATE_OR_GOTO("dht", this, out);
  480     GF_VALIDATE_OR_GOTO("dht", frame->local, out);
  481     GF_VALIDATE_OR_GOTO("dht", cookie, out);
  482 
  483     local = frame->local;
  484     prev = cookie;
  485 
  486     /* fallocate fails with EBADF if dht has not yet opened the fd
  487      * on the cached subvol. This could happen if the file was migrated
  488      * and a lookup updated the cached subvol in the inode ctx.
  489      * We only check once as this could actually be a valid error.
  490      */
  491 
  492     if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
  493         ret = dht_check_and_open_fd_on_subvol(this, frame);
  494         if (ret)
  495             goto out;
  496         return 0;
  497     }
  498 
  499     if ((op_ret == -1) && !dht_inode_missing(op_errno)) {
  500         local->op_errno = op_errno;
  501         local->op_ret = -1;
  502         gf_msg_debug(this->name, op_errno, "subvolume %s returned -1",
  503                      prev->name);
  504 
  505         goto out;
  506     }
  507 
  508     if (local->call_cnt != 1) {
  509         if (local->stbuf.ia_blocks) {
  510             dht_iatt_merge(this, postbuf, &local->stbuf);
  511             dht_iatt_merge(this, prebuf, &local->prebuf);
  512         }
  513         goto out;
  514     }
  515 
  516     local->op_ret = op_ret;
  517     local->op_errno = op_errno;
  518     local->rebalance.target_op_fn = dht_fallocate2;
  519 
  520     dht_set_local_rebalance(this, local, NULL, prebuf, postbuf, xdata);
  521 
  522     /* Phase 2 of migration */
  523     if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2(postbuf)) {
  524         ret = dht_rebalance_complete_check(this, frame);
  525         if (!ret)
  526             return 0;
  527     }
  528 
  529     /* Check if the rebalance phase1 is true */
  530     if (IS_DHT_MIGRATION_PHASE1(postbuf)) {
  531         dht_iatt_merge(this, &local->stbuf, postbuf);
  532         dht_iatt_merge(this, &local->prebuf, prebuf);
  533 
  534         dht_inode_ctx_get_mig_info(this, local->fd->inode, &src_subvol,
  535                                    &dst_subvol);
  536         if (!dht_mig_info_is_invalid(local->cached_subvol, src_subvol,
  537                                      dst_subvol)) {
  538             if (dht_fd_open_on_dst(this, local->fd, dst_subvol)) {
  539                 dht_fallocate2(this, dst_subvol, frame, 0);
  540                 return 0;
  541             }
  542         }
  543         ret = dht_rebalance_in_progress_check(this, frame);
  544         if (!ret)
  545             return 0;
  546     }
  547 
  548 out:
  549     DHT_STRIP_PHASE1_FLAGS(postbuf);
  550     DHT_STRIP_PHASE1_FLAGS(prebuf);
  551 
  552     DHT_STACK_UNWIND(fallocate, frame, op_ret, op_errno, prebuf, postbuf,
  553                      xdata);
  554 err:
  555     return 0;
  556 }
  557 
  558 static int
  559 dht_fallocate2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret)
  560 {
  561     dht_local_t *local = NULL;
  562     int32_t op_errno = EINVAL;
  563 
  564     if (!frame || !frame->local)
  565         goto out;
  566 
  567     local = frame->local;
  568     op_errno = local->op_errno;
  569 
  570     if (we_are_not_migrating(ret)) {
  571         /* This dht xlator is not migrating the file. Unwind and
  572          * pass on the original mode bits so the higher DHT layer
  573          * can handle this.
  574          */
  575         DHT_STACK_UNWIND(fallocate, frame, local->op_ret, local->op_errno,
  576                          &local->rebalance.prebuf, &local->rebalance.postbuf,
  577                          local->rebalance.xdata);
  578         return 0;
  579     }
  580 
  581     if (subvol == NULL)
  582         goto out;
  583 
  584     local->call_cnt = 2; /* This is the second attempt */
  585 
  586     STACK_WIND_COOKIE(frame, dht_fallocate_cbk, subvol, subvol,
  587                       subvol->fops->fallocate, local->fd,
  588                       local->rebalance.flags, local->rebalance.offset,
  589                       local->rebalance.size, local->xattr_req);
  590 
  591     return 0;
  592 
  593 out:
  594     DHT_STACK_UNWIND(fallocate, frame, -1, op_errno, NULL, NULL, NULL);
  595     return 0;
  596 }
  597 
  598 int
  599 dht_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode,
  600               off_t offset, size_t len, dict_t *xdata)
  601 {
  602     xlator_t *subvol = NULL;
  603     int op_errno = -1;
  604     dht_local_t *local = NULL;
  605 
  606     VALIDATE_OR_GOTO(frame, err);
  607     VALIDATE_OR_GOTO(this, err);
  608     VALIDATE_OR_GOTO(fd, err);
  609 
  610     local = dht_local_init(frame, NULL, fd, GF_FOP_FALLOCATE);
  611     if (!local) {
  612         op_errno = ENOMEM;
  613         goto err;
  614     }
  615 
  616     local->rebalance.flags = mode;
  617     local->rebalance.offset = offset;
  618     local->rebalance.size = len;
  619 
  620     local->call_cnt = 1;
  621     subvol = local->cached_subvol;
  622     if (!subvol) {
  623         gf_msg_debug(this->name, 0, "no cached subvolume for fd=%p", fd);
  624         op_errno = EINVAL;
  625         goto err;
  626     }
  627 
  628     if (xdata)
  629         local->xattr_req = dict_ref(xdata);
  630 
  631     STACK_WIND_COOKIE(frame, dht_fallocate_cbk, subvol, subvol,
  632                       subvol->fops->fallocate, fd, local->rebalance.flags,
  633                       local->rebalance.offset, local->rebalance.size,
  634                       local->xattr_req);
  635 
  636     return 0;
  637 
  638 err:
  639     op_errno = (op_errno == -1) ? errno : op_errno;
  640     DHT_STACK_UNWIND(fallocate, frame, -1, op_errno, NULL, NULL, NULL);
  641 
  642     return 0;
  643 }
  644 
  645 int
  646 dht_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
  647                 int op_errno, struct iatt *prebuf, struct iatt *postbuf,
  648                 dict_t *xdata)
  649 {
  650     dht_local_t *local = NULL;
  651     xlator_t *prev = NULL;
  652     int ret = -1;
  653     xlator_t *src_subvol = NULL;
  654     xlator_t *dst_subvol = NULL;
  655 
  656     GF_VALIDATE_OR_GOTO("dht", frame, err);
  657     GF_VALIDATE_OR_GOTO("dht", this, out);
  658     GF_VALIDATE_OR_GOTO("dht", frame->local, out);
  659     GF_VALIDATE_OR_GOTO("dht", cookie, out);
  660 
  661     local = frame->local;
  662     prev = cookie;
  663 
  664     /* discard fails with EBADF if dht has not yet opened the fd
  665      * on the cached subvol. This could happen if the file was migrated
  666      * and a lookup updated the cached subvol in the inode ctx.
  667      * We only check once as this could actually be a valid error.
  668      */
  669     if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
  670         ret = dht_check_and_open_fd_on_subvol(this, frame);
  671         if (ret)
  672             goto out;
  673         return 0;
  674     }
  675 
  676     if ((op_ret == -1) && !dht_inode_missing(op_errno)) {
  677         local->op_errno = op_errno;
  678         local->op_ret = -1;
  679         gf_msg_debug(this->name, op_errno, "subvolume %s returned -1",
  680                      prev->name);
  681 
  682         goto out;
  683     }
  684 
  685     if (local->call_cnt != 1) {
  686         if (local->stbuf.ia_blocks) {
  687             dht_iatt_merge(this, postbuf, &local->stbuf);
  688             dht_iatt_merge(this, prebuf, &local->prebuf);
  689         }
  690         goto out;
  691     }
  692 
  693     local->rebalance.target_op_fn = dht_discard2;
  694     local->op_ret = op_ret;
  695     local->op_errno = op_errno;
  696 
  697     dht_set_local_rebalance(this, local, NULL, prebuf, postbuf, xdata);
  698 
  699     /* Phase 2 of migration */
  700     if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2(postbuf)) {
  701         ret = dht_rebalance_complete_check(this, frame);
  702         if (!ret)
  703             return 0;
  704     }
  705 
  706     /* Check if the rebalance phase1 is true */
  707     if (IS_DHT_MIGRATION_PHASE1(postbuf)) {
  708         dht_iatt_merge(this, &local->stbuf, postbuf);
  709         dht_iatt_merge(this, &local->prebuf, prebuf);
  710 
  711         dht_inode_ctx_get_mig_info(this, local->fd->inode, &src_subvol,
  712                                    &dst_subvol);
  713         if (!dht_mig_info_is_invalid(local->cached_subvol, src_subvol,
  714                                      dst_subvol)) {
  715             if (dht_fd_open_on_dst(this, local->fd, dst_subvol)) {
  716                 dht_discard2(this, dst_subvol, frame, 0);
  717                 return 0;
  718             }
  719         }
  720         ret = dht_rebalance_in_progress_check(this, frame);
  721         if (!ret)
  722             return 0;
  723     }
  724 
  725 out:
  726     DHT_STRIP_PHASE1_FLAGS(postbuf);
  727     DHT_STRIP_PHASE1_FLAGS(prebuf);
  728 
  729     DHT_STACK_UNWIND(discard, frame, op_ret, op_errno, prebuf, postbuf, xdata);
  730 err:
  731     return 0;
  732 }
  733 
  734 static int
  735 dht_discard2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret)
  736 {
  737     dht_local_t *local = NULL;
  738     int32_t op_errno = EINVAL;
  739 
  740     if (!frame || !frame->local)
  741         goto out;
  742 
  743     local = frame->local;
  744     op_errno = local->op_errno;
  745 
  746     if (we_are_not_migrating(ret)) {
  747         /* This dht xlator is not migrating the file. Unwind and
  748          * pass on the original mode bits so the higher DHT layer
  749          * can handle this.
  750          */
  751         DHT_STACK_UNWIND(discard, frame, local->op_ret, local->op_errno,
  752                          &local->rebalance.prebuf, &local->rebalance.postbuf,
  753                          local->rebalance.xdata);
  754         return 0;
  755     }
  756 
  757     if (subvol == NULL)
  758         goto out;
  759 
  760     local->call_cnt = 2; /* This is the second attempt */
  761 
  762     STACK_WIND_COOKIE(frame, dht_discard_cbk, subvol, subvol,
  763                       subvol->fops->discard, local->fd, local->rebalance.offset,
  764                       local->rebalance.size, local->xattr_req);
  765 
  766     return 0;
  767 
  768 out:
  769     DHT_STACK_UNWIND(discard, frame, -1, op_errno, NULL, NULL, NULL);
  770     return 0;
  771 }
  772 
  773 int
  774 dht_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
  775             size_t len, dict_t *xdata)
  776 {
  777     xlator_t *subvol = NULL;
  778     int op_errno = -1;
  779     dht_local_t *local = NULL;
  780 
  781     VALIDATE_OR_GOTO(frame, err);
  782     VALIDATE_OR_GOTO(this, err);
  783     VALIDATE_OR_GOTO(fd, err);
  784 
  785     local = dht_local_init(frame, NULL, fd, GF_FOP_DISCARD);
  786     if (!local) {
  787         op_errno = ENOMEM;
  788         goto err;
  789     }
  790 
  791     local->rebalance.offset = offset;
  792     local->rebalance.size = len;
  793 
  794     local->call_cnt = 1;
  795     subvol = local->cached_subvol;
  796     if (!subvol) {
  797         gf_msg_debug(this->name, 0, "no cached subvolume for fd=%p", fd);
  798         op_errno = EINVAL;
  799         goto err;
  800     }
  801 
  802     if (xdata)
  803         local->xattr_req = dict_ref(xdata);
  804 
  805     STACK_WIND_COOKIE(frame, dht_discard_cbk, subvol, subvol,
  806                       subvol->fops->discard, fd, local->rebalance.offset,
  807                       local->rebalance.size, local->xattr_req);
  808 
  809     return 0;
  810 
  811 err:
  812     op_errno = (op_errno == -1) ? errno : op_errno;
  813     DHT_STACK_UNWIND(discard, frame, -1, op_errno, NULL, NULL, NULL);
  814 
  815     return 0;
  816 }
  817 
  818 int
  819 dht_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
  820                  int op_errno, struct iatt *prebuf, struct iatt *postbuf,
  821                  dict_t *xdata)
  822 {
  823     dht_local_t *local = NULL;
  824     xlator_t *prev = NULL;
  825     int ret = -1;
  826     xlator_t *subvol1 = NULL, *subvol2 = NULL;
  827 
  828     GF_VALIDATE_OR_GOTO("dht", frame, err);
  829     GF_VALIDATE_OR_GOTO("dht", this, out);
  830     GF_VALIDATE_OR_GOTO("dht", frame->local, out);
  831     GF_VALIDATE_OR_GOTO("dht", cookie, out);
  832 
  833     local = frame->local;
  834     prev = cookie;
  835 
  836     /* zerofill fails with EBADF if dht has not yet opened the fd
  837      * on the cached subvol. This could happen if the file was migrated
  838      * and a lookup updated the cached subvol in the inode ctx.
  839      * We only check once as this could actually be a valid error.
  840      */
  841     if (dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
  842         ret = dht_check_and_open_fd_on_subvol(this, frame);
  843         if (ret)
  844             goto out;
  845         return 0;
  846     }
  847 
  848     if ((op_ret == -1) && !dht_inode_missing(op_errno)) {
  849         local->op_errno = op_errno;
  850         local->op_ret = -1;
  851         gf_msg_debug(this->name, op_errno, "subvolume %s returned -1",
  852                      prev->name);
  853         goto out;
  854     }
  855 
  856     if (local->call_cnt != 1) {
  857         if (local->stbuf.ia_blocks) {
  858             dht_iatt_merge(this, postbuf, &local->stbuf);
  859             dht_iatt_merge(this, prebuf, &local->prebuf);
  860         }
  861         goto out;
  862     }
  863 
  864     local->rebalance.target_op_fn = dht_zerofill2;
  865     local->op_ret = op_ret;
  866     local->op_errno = op_errno;
  867 
  868     dht_set_local_rebalance(this, local, NULL, prebuf, postbuf, xdata);
  869 
  870     /* Phase 2 of migration */
  871     if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2(postbuf)) {
  872         ret = dht_rebalance_complete_check(this, frame);
  873         if (!ret)
  874             return 0;
  875     }
  876 
  877     /* Check if the rebalance phase1 is true */
  878     if (IS_DHT_MIGRATION_PHASE1(postbuf)) {
  879         dht_iatt_merge(this, &local->stbuf, postbuf);
  880         dht_iatt_merge(this, &local->prebuf, prebuf);
  881 
  882         ret = dht_inode_ctx_get_mig_info(this, local->fd->inode, &subvol1,
  883                                          &subvol2);
  884         if (!dht_mig_info_is_invalid(local->cached_subvol, subvol1, subvol2)) {
  885             if (dht_fd_open_on_dst(this, local->fd, subvol2)) {
  886                 dht_zerofill2(this, subvol2, frame, 0);
  887                 return 0;
  888             }
  889         }
  890 
  891         ret = dht_rebalance_in_progress_check(this, frame);
  892         if (!ret)
  893             return 0;
  894     }
  895 
  896 out:
  897     DHT_STRIP_PHASE1_FLAGS(postbuf);
  898     DHT_STRIP_PHASE1_FLAGS(prebuf);
  899 
  900     DHT_STACK_UNWIND(zerofill, frame, op_ret, op_errno, prebuf, postbuf, xdata);
  901 err:
  902     return 0;
  903 }
  904 
  905 static int
  906 dht_zerofill2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret)
  907 {
  908     dht_local_t *local = NULL;
  909     int32_t op_errno = EINVAL;
  910 
  911     if (!frame || !frame->local)
  912         goto out;
  913 
  914     local = frame->local;
  915 
  916     op_errno = local->op_errno;
  917 
  918     if (we_are_not_migrating(ret)) {
  919         /* This dht xlator is not migrating the file. Unwind and
  920          * pass on the original mode bits so the higher DHT layer
  921          * can handle this.
  922          */
  923         DHT_STACK_UNWIND(zerofill, frame, local->op_ret, local->op_errno,
  924                          &local->rebalance.prebuf, &local->rebalance.postbuf,
  925                          local->rebalance.xdata);
  926 
  927         return 0;
  928     }
  929 
  930     if (subvol == NULL)
  931         goto out;
  932 
  933     local->call_cnt = 2; /* This is the second attempt */
  934 
  935     STACK_WIND_COOKIE(frame, dht_zerofill_cbk, subvol, subvol,
  936                       subvol->fops->zerofill, local->fd,
  937                       local->rebalance.offset, local->rebalance.size,
  938                       local->xattr_req);
  939 
  940     return 0;
  941 
  942 out:
  943 
  944     DHT_STACK_UNWIND(zerofill, frame, -1, op_errno, NULL, NULL, NULL);
  945     return 0;
  946 }
  947 
  948 int
  949 dht_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
  950              off_t len, dict_t *xdata)
  951 {
  952     xlator_t *subvol = NULL;
  953     int op_errno = -1;
  954     dht_local_t *local = NULL;
  955 
  956     VALIDATE_OR_GOTO(frame, err);
  957     VALIDATE_OR_GOTO(this, err);
  958     VALIDATE_OR_GOTO(fd, err);
  959 
  960     local = dht_local_init(frame, NULL, fd, GF_FOP_ZEROFILL);
  961     if (!local) {
  962         op_errno = ENOMEM;
  963         goto err;
  964     }
  965 
  966     local->rebalance.offset = offset;
  967     local->rebalance.size = len;
  968 
  969     local->call_cnt = 1;
  970     subvol = local->cached_subvol;
  971     if (!subvol) {
  972         gf_msg_debug(this->name, 0, "no cached subvolume for fd=%p", fd);
  973         op_errno = EINVAL;
  974         goto err;
  975     }
  976 
  977     if (xdata)
  978         local->xattr_req = dict_ref(xdata);
  979 
  980     STACK_WIND_COOKIE(frame, dht_zerofill_cbk, subvol, subvol,
  981                       subvol->fops->zerofill, fd, local->rebalance.offset,
  982                       local->rebalance.size, local->xattr_req);
  983 
  984     return 0;
  985 
  986 err:
  987     op_errno = (op_errno == -1) ? errno : op_errno;
  988     DHT_STACK_UNWIND(zerofill, frame, -1, op_errno, NULL, NULL, NULL);
  989 
  990     return 0;
  991 }
  992 
  993 /* handle cases of migration here for 'setattr()' calls */
  994 int
  995 dht_file_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  996                      int op_ret, int op_errno, struct iatt *prebuf,
  997                      struct iatt *postbuf, dict_t *xdata)
  998 {
  999     dht_local_t *local = NULL;
 1000     xlator_t *prev = NULL;
 1001     int ret = -1;
 1002 
 1003     local = frame->local;
 1004     prev = cookie;
 1005 
 1006     local->op_errno = op_errno;
 1007 
 1008     if ((local->fop == GF_FOP_FSETATTR) &&
 1009         dht_check_remote_fd_failed_error(local, op_ret, op_errno)) {
 1010         ret = dht_check_and_open_fd_on_subvol(this, frame);
 1011         if (ret)
 1012             goto out;
 1013         return 0;
 1014     }
 1015 
 1016     if ((op_ret == -1) && !dht_inode_missing(op_errno)) {
 1017         gf_msg_debug(this->name, op_errno, "subvolume %s returned -1",
 1018                      prev->name);
 1019         goto out;
 1020     }
 1021 
 1022     if (local->call_cnt != 1)
 1023         goto out;
 1024 
 1025     local->op_ret = op_ret;
 1026     local->op_errno = op_errno;
 1027 
 1028     local->rebalance.target_op_fn = dht_setattr2;
 1029 
 1030     /* Phase 2 of migration */
 1031     if ((op_ret == -1) || IS_DHT_MIGRATION_PHASE2(postbuf)) {
 1032         dht_set_local_rebalance(this, local, NULL, prebuf, postbuf, xdata);
 1033 
 1034         ret = dht_rebalance_complete_check(this, frame);
 1035         if (!ret)
 1036             return 0;
 1037     }
 1038 
 1039     /* At the end of the migration process, whatever 'attr' we
 1040        have on source file will be migrated to destination file
 1041        in one shot, hence we don't need to check for in progress
 1042        state here (ie, PHASE1) */
 1043 out:
 1044     DHT_STRIP_PHASE1_FLAGS(postbuf);
 1045     DHT_STRIP_PHASE1_FLAGS(prebuf);
 1046 
 1047     DHT_STACK_UNWIND(setattr, frame, op_ret, op_errno, prebuf, postbuf, xdata);
 1048 
 1049     return 0;
 1050 }
 1051 
 1052 static int
 1053 dht_setattr2(xlator_t *this, xlator_t *subvol, call_frame_t *frame, int ret)
 1054 {
 1055     dht_local_t *local = NULL;
 1056     int32_t op_errno = EINVAL;
 1057 
 1058     if (!frame || !frame->local)
 1059         goto out;
 1060 
 1061     local = frame->local;
 1062     op_errno = local->op_errno;
 1063 
 1064     if (we_are_not_migrating(ret)) {
 1065         /* This dht xlator is not migrating the file. Unwind and
 1066          * pass on the original mode bits so the higher DHT layer
 1067          * can handle this.
 1068          */
 1069         DHT_STACK_UNWIND(setattr, frame, local->op_ret, local->op_errno,
 1070                          &local->rebalance.prebuf, &local->rebalance.postbuf,
 1071                          local->rebalance.xdata);
 1072         return 0;
 1073     }
 1074 
 1075     if (subvol == NULL)
 1076         goto out;
 1077 
 1078     local->call_cnt = 2; /* This is the second attempt */
 1079 
 1080     if (local->fop == GF_FOP_SETATTR) {
 1081         STACK_WIND_COOKIE(frame, dht_file_setattr_cbk, subvol, subvol,
 1082                           subvol->fops->setattr, &local->loc,
 1083                           &local->rebalance.stbuf, local->rebalance.flags,
 1084                           local->xattr_req);
 1085     } else {
 1086         STACK_WIND_COOKIE(frame, dht_file_setattr_cbk, subvol, subvol,
 1087                           subvol->fops->fsetattr, local->fd,
 1088                           &local->rebalance.stbuf, local->rebalance.flags,
 1089                           local->xattr_req);
 1090     }
 1091 
 1092     return 0;
 1093 
 1094 out:
 1095     DHT_STACK_UNWIND(setattr, frame, -1, op_errno, NULL, NULL, NULL);
 1096     return 0;
 1097 }
 1098 
 1099 /* Keep the existing code same for all the cases other than regular file */
 1100 int
 1101 dht_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
 1102                 int op_errno, struct iatt *statpre, struct iatt *statpost,
 1103                 dict_t *xdata)
 1104 {
 1105     dht_local_t *local = NULL;
 1106     int this_call_cnt = 0;
 1107     xlator_t *prev = NULL;
 1108 
 1109     local = frame->local;
 1110     prev = cookie;
 1111 
 1112     LOCK(&frame->lock);
 1113     {
 1114         if (op_ret == -1) {
 1115             local->op_errno = op_errno;
 1116             UNLOCK(&frame->lock);
 1117             gf_msg_debug(this->name, op_errno, "subvolume %s returned -1",
 1118                          prev->name);
 1119             goto post_unlock;
 1120         }
 1121 
 1122         dht_iatt_merge(this, &local->prebuf, statpre);
 1123         dht_iatt_merge(this, &local->stbuf, statpost);
 1124 
 1125         local->op_ret = 0;
 1126         local->op_errno = 0;
 1127     }
 1128     UNLOCK(&frame->lock);
 1129 post_unlock:
 1130     this_call_cnt = dht_frame_return(frame);
 1131     if (is_last_call(this_call_cnt)) {
 1132         if (local->op_ret == 0)
 1133             dht_inode_ctx_time_set(local->loc.inode, this, &local->stbuf);
 1134         DHT_STACK_UNWIND(setattr, frame, local->op_ret, local->op_errno,
 1135                          &local->prebuf, &local->stbuf, xdata);
 1136     }
 1137 
 1138     return 0;
 1139 }
 1140 
 1141 /* Keep the existing code same for all the cases other than regular file */
 1142 int
 1143 dht_non_mds_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1144                         int op_ret, int op_errno, struct iatt *statpre,
 1145                         struct iatt *statpost, dict_t *xdata)
 1146 {
 1147     dht_local_t *local = NULL;
 1148     int this_call_cnt = 0;
 1149     xlator_t *prev = NULL;
 1150 
 1151     local = frame->local;
 1152     prev = cookie;
 1153 
 1154     if (op_ret == -1) {
 1155         gf_msg(this->name, op_errno, 0, 0, "subvolume %s returned -1",
 1156                prev->name);
 1157         goto post_unlock;
 1158     }
 1159 
 1160     LOCK(&frame->lock);
 1161     {
 1162         dht_iatt_merge(this, &local->prebuf, statpre);
 1163         dht_iatt_merge(this, &local->stbuf, statpost);
 1164 
 1165         local->op_ret = 0;
 1166         local->op_errno = 0;
 1167     }
 1168     UNLOCK(&frame->lock);
 1169 post_unlock:
 1170     this_call_cnt = dht_frame_return(frame);
 1171     if (is_last_call(this_call_cnt)) {
 1172         dht_inode_ctx_time_set(local->loc.inode, this, &local->stbuf);
 1173         DHT_STACK_UNWIND(setattr, frame, 0, 0, &local->prebuf, &local->stbuf,
 1174                          xdata);
 1175     }
 1176 
 1177     return 0;
 1178 }
 1179 
 1180 int
 1181 dht_mds_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1182                     int op_ret, int op_errno, struct iatt *statpre,
 1183                     struct iatt *statpost, dict_t *xdata)
 1184 
 1185 {
 1186     dht_local_t *local = NULL;
 1187     dht_conf_t *conf = NULL;
 1188     xlator_t *prev = NULL;
 1189     xlator_t *mds_subvol = NULL;
 1190     struct iatt loc_stbuf = {
 1191         0,
 1192     };
 1193     int i = 0;
 1194 
 1195     local = frame->local;
 1196     prev = cookie;
 1197     conf = this->private;
 1198     mds_subvol = local->mds_subvol;
 1199 
 1200     if (op_ret == -1) {
 1201         local->op_ret = op_ret;
 1202         local->op_errno = op_errno;
 1203         gf_msg_debug(this->name, op_errno, "subvolume %s returned -1",
 1204                      prev->name);
 1205         goto out;
 1206     }
 1207 
 1208     local->op_ret = 0;
 1209     loc_stbuf = local->stbuf;
 1210     dht_iatt_merge(this, &local->prebuf, statpre);
 1211     dht_iatt_merge(this, &local->stbuf, statpost);
 1212 
 1213     local->call_cnt = conf->subvolume_cnt - 1;
 1214     for (i = 0; i < conf->subvolume_cnt; i++) {
 1215         if (mds_subvol == conf->subvolumes[i])
 1216             continue;
 1217         STACK_WIND_COOKIE(frame, dht_non_mds_setattr_cbk, conf->subvolumes[i],
 1218                           conf->subvolumes[i],
 1219                           conf->subvolumes[i]->fops->setattr, &local->loc,
 1220                           &loc_stbuf, local->valid, local->xattr_req);
 1221     }
 1222 
 1223     return 0;
 1224 out:
 1225     DHT_STACK_UNWIND(setattr, frame, local->op_ret, local->op_errno,
 1226                      &local->prebuf, &local->stbuf, xdata);
 1227 
 1228     return 0;
 1229 }
 1230 
 1231 int
 1232 dht_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *stbuf,
 1233             int32_t valid, dict_t *xdata)
 1234 {
 1235     xlator_t *subvol = NULL;
 1236     xlator_t *mds_subvol = NULL;
 1237     dht_layout_t *layout = NULL;
 1238     dht_local_t *local = NULL;
 1239     int op_errno = -1;
 1240     int i = -1;
 1241     int ret = -1;
 1242     int call_cnt = 0;
 1243     dht_conf_t *conf = NULL;
 1244 
 1245     VALIDATE_OR_GOTO(frame, err);
 1246     VALIDATE_OR_GOTO(this, err);
 1247     VALIDATE_OR_GOTO(loc, err);
 1248     VALIDATE_OR_GOTO(loc->inode, err);
 1249     VALIDATE_OR_GOTO(loc->path, err);
 1250 
 1251     conf = this->private;
 1252     local = dht_local_init(frame, loc, NULL, GF_FOP_SETATTR);
 1253     if (!local) {
 1254         op_errno = ENOMEM;
 1255         goto err;
 1256     }
 1257 
 1258     layout = local->layout;
 1259     if (!layout) {
 1260         gf_msg_debug(this->name, 0, "no layout for path=%s", loc->path);
 1261         op_errno = EINVAL;
 1262         goto err;
 1263     }
 1264 
 1265     if (!layout_is_sane(layout)) {
 1266         gf_msg_debug(this->name, 0, "layout is not sane for path=%s",
 1267                      loc->path);
 1268         op_errno = EINVAL;
 1269         goto err;
 1270     }
 1271     if (xdata)
 1272         local->xattr_req = dict_ref(xdata);
 1273 
 1274     if (IA_ISREG(loc->inode->ia_type)) {
 1275         /* in the regular file _cbk(), we need to check for
 1276            migration possibilities */
 1277         local->rebalance.stbuf = *stbuf;
 1278         local->rebalance.flags = valid;
 1279         local->call_cnt = 1;
 1280         subvol = local->cached_subvol;
 1281 
 1282         STACK_WIND_COOKIE(frame, dht_file_setattr_cbk, subvol, subvol,
 1283                           subvol->fops->setattr, loc, stbuf, valid, xdata);
 1284 
 1285         return 0;
 1286     }
 1287 
 1288     local->call_cnt = call_cnt = layout->cnt;
 1289 
 1290     if (IA_ISDIR(loc->inode->ia_type) && !__is_root_gfid(loc->inode->gfid) &&
 1291         call_cnt != 1) {
 1292         ret = dht_inode_ctx_mdsvol_get(loc->inode, this, &mds_subvol);
 1293         if (ret || !mds_subvol) {
 1294             gf_msg(this->name, GF_LOG_ERROR, 0,
 1295                    DHT_MSG_HASHED_SUBVOL_GET_FAILED,
 1296                    "Failed to get mds subvol for path %s", local->loc.path);
 1297             op_errno = EINVAL;
 1298             goto err;
 1299         }
 1300 
 1301         local->mds_subvol = mds_subvol;
 1302         for (i = 0; i < conf->subvolume_cnt; i++) {
 1303             if (conf->subvolumes[i] == mds_subvol) {
 1304                 if (!conf->subvolume_status[i]) {
 1305                     gf_msg(this->name, GF_LOG_WARNING, layout->list[i].err,
 1306                            DHT_MSG_HASHED_SUBVOL_DOWN,
 1307                            "MDS subvol is down for path "
 1308                            " %s Unable to set attr ",
 1309                            local->loc.path);
 1310                     op_errno = ENOTCONN;
 1311                     goto err;
 1312                 }
 1313             }
 1314         }
 1315         local->valid = valid;
 1316         local->stbuf = *stbuf;
 1317 
 1318         STACK_WIND_COOKIE(frame, dht_mds_setattr_cbk, local->mds_subvol,
 1319                           local->mds_subvol, local->mds_subvol->fops->setattr,
 1320                           loc, stbuf, valid, xdata);
 1321         return 0;
 1322     } else {
 1323         for (i = 0; i < call_cnt; i++) {
 1324             STACK_WIND_COOKIE(frame, dht_setattr_cbk, layout->list[i].xlator,
 1325                               layout->list[i].xlator,
 1326                               layout->list[i].xlator->fops->setattr, loc, stbuf,
 1327                               valid, xdata);
 1328         }
 1329     }
 1330 
 1331     return 0;
 1332 
 1333 err:
 1334     op_errno = (op_errno == -1) ? errno : op_errno;
 1335     DHT_STACK_UNWIND(setattr, frame, -1, op_errno, NULL, NULL, NULL);
 1336 
 1337     return 0;
 1338 }
 1339 
 1340 int
 1341 dht_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iatt *stbuf,
 1342              int32_t valid, dict_t *xdata)
 1343 {
 1344     xlator_t *subvol = NULL;
 1345     dht_layout_t *layout = NULL;
 1346     dht_local_t *local = NULL;
 1347     int op_errno = -1;
 1348     int i = -1;
 1349     int call_cnt = 0;
 1350 
 1351     VALIDATE_OR_GOTO(frame, err);
 1352     VALIDATE_OR_GOTO(this, err);
 1353     VALIDATE_OR_GOTO(fd, err);
 1354 
 1355     local = dht_local_init(frame, NULL, fd, GF_FOP_FSETATTR);
 1356     if (!local) {
 1357         op_errno = ENOMEM;
 1358         goto err;
 1359     }
 1360 
 1361     layout = local->layout;
 1362     if (!layout) {
 1363         gf_msg_debug(this->name, 0, "no layout for fd=%p", fd);
 1364         op_errno = EINVAL;
 1365         goto err;
 1366     }
 1367 
 1368     if (!layout_is_sane(layout)) {
 1369         gf_msg_debug(this->name, 0, "layout is not sane for fd=%p", fd);
 1370         op_errno = EINVAL;
 1371         goto err;
 1372     }
 1373     if (xdata)
 1374         local->xattr_req = dict_ref(xdata);
 1375 
 1376     if (IA_ISREG(fd->inode->ia_type)) {
 1377         /* in the regular file _cbk(), we need to check for
 1378            migration possibilities */
 1379         local->rebalance.stbuf = *stbuf;
 1380         local->rebalance.flags = valid;
 1381         local->call_cnt = 1;
 1382         subvol = local->cached_subvol;
 1383 
 1384         STACK_WIND_COOKIE(frame, dht_file_setattr_cbk, subvol, subvol,
 1385                           subvol->fops->fsetattr, fd, &local->rebalance.stbuf,
 1386                           local->rebalance.flags, local->xattr_req);
 1387         return 0;
 1388     }
 1389 
 1390     local->call_cnt = call_cnt = layout->cnt;
 1391 
 1392     for (i = 0; i < call_cnt; i++) {
 1393         STACK_WIND_COOKIE(frame, dht_setattr_cbk, layout->list[i].xlator,
 1394                           layout->list[i].xlator,
 1395                           layout->list[i].xlator->fops->fsetattr, fd, stbuf,
 1396                           valid, xdata);
 1397     }
 1398 
 1399     return 0;
 1400 
 1401 err:
 1402     op_errno = (op_errno == -1) ? errno : op_errno;
 1403     DHT_STACK_UNWIND(fsetattr, frame, -1, op_errno, NULL, NULL, NULL);
 1404 
 1405     return 0;
 1406 }