"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/xlators/nfs/server/src/nfs3.c" (16 Sep 2020, 172592 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 "nfs3.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2   Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.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 "rpcsvc.h"
   12 #include <glusterfs/dict.h>
   13 #include <glusterfs/xlator.h>
   14 #include "mount3.h"
   15 #include "xdr-nfs3.h"
   16 #include "msg-nfs3.h"
   17 #include <glusterfs/iobuf.h>
   18 #include "nfs3.h"
   19 #include <glusterfs/mem-pool.h>
   20 #include <glusterfs/logging.h>
   21 #include "nfs-common.h"
   22 #include "nfs-fops.h"
   23 #include "nfs-inodes.h"
   24 #include "nfs-generics.h"
   25 #include "nfs3-helpers.h"
   26 #include "nfs-mem-types.h"
   27 #include "nfs.h"
   28 #include "xdr-rpc.h"
   29 #include "xdr-generic.h"
   30 #include "nfs-messages.h"
   31 #include "glfs-internal.h"
   32 
   33 #include <sys/socket.h>
   34 #include <sys/uio.h>
   35 #include <sys/statvfs.h>
   36 #include <time.h>
   37 
   38 #define nfs3_validate_strlen_or_goto(str, len, label, status, retval)          \
   39     do {                                                                       \
   40         if ((str)) {                                                           \
   41             if (strlen((str)) > (len)) {                                       \
   42                 gf_msg(GF_NFS3, GF_LOG_ERROR, ENAMETOOLONG,                    \
   43                        NFS_MSG_STR_TOO_LONG, "strlen too long");               \
   44                 status = NFS3ERR_NAMETOOLONG;                                  \
   45                 retval = -ENAMETOOLONG;                                        \
   46                 goto label;                                                    \
   47             }                                                                  \
   48         }                                                                      \
   49     } while (0);
   50 
   51 #define nfs3_validate_nfs3_state(request, state, status, label, retval)        \
   52     do {                                                                       \
   53         state = rpcsvc_request_program_private(request);                       \
   54         if (!state) {                                                          \
   55             gf_msg(GF_NFS3, GF_LOG_ERROR, EFAULT, NFS_MSG_STATE_MISSING,       \
   56                    "NFSv3 state "                                              \
   57                    "missing from RPC request");                                \
   58             status = NFS3ERR_SERVERFAULT;                                      \
   59             ret = -EFAULT;                                                     \
   60             goto label;                                                        \
   61         }                                                                      \
   62     } while (0);
   63 
   64 struct nfs3_export *
   65 __nfs3_get_export_by_index(struct nfs3_state *nfs3, uuid_t exportid)
   66 {
   67     struct nfs3_export *exp = NULL;
   68     int index = 0;
   69     int searchindex = 0;
   70 
   71     searchindex = nfs3_fh_exportid_to_index(exportid);
   72     list_for_each_entry(exp, &nfs3->exports, explist)
   73     {
   74         if (searchindex == index)
   75             goto found;
   76 
   77         ++index;
   78     }
   79 
   80     exp = NULL;
   81     gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_INDEX_NOT_FOUND,
   82            "searchindex=%d not found", searchindex);
   83 found:
   84     return exp;
   85 }
   86 
   87 struct nfs3_export *
   88 __nfs3_get_export_by_volumeid(struct nfs3_state *nfs3, uuid_t exportid)
   89 {
   90     struct nfs3_export *exp = NULL;
   91 
   92     list_for_each_entry(exp, &nfs3->exports, explist)
   93     {
   94         if (!gf_uuid_compare(exportid, exp->volumeid))
   95             goto found;
   96     }
   97 
   98     exp = NULL;
   99 found:
  100     return exp;
  101 }
  102 
  103 struct nfs3_export *
  104 __nfs3_get_export_by_exportid(struct nfs3_state *nfs3, uuid_t exportid)
  105 {
  106     struct nfs3_export *exp = NULL;
  107 
  108     if (!nfs3)
  109         return exp;
  110 
  111     if (gf_nfs_dvm_off(nfs_state(nfs3->nfsx)))
  112         exp = __nfs3_get_export_by_index(nfs3, exportid);
  113     else
  114         exp = __nfs3_get_export_by_volumeid(nfs3, exportid);
  115 
  116     return exp;
  117 }
  118 
  119 int
  120 nfs3_export_access(struct nfs3_state *nfs3, uuid_t exportid)
  121 {
  122     int ret = GF_NFS3_VOLACCESS_RO;
  123     struct nfs3_export *exp = NULL;
  124 
  125     GF_VALIDATE_OR_GOTO(GF_NFS3, nfs3, err);
  126 
  127     exp = __nfs3_get_export_by_exportid(nfs3, exportid);
  128 
  129     if (!exp) {
  130         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_EXPORT_ID_FAIL,
  131                "Failed to get export by ID");
  132         goto err;
  133     }
  134 
  135     ret = exp->access;
  136 
  137 err:
  138     return ret;
  139 }
  140 
  141 #define nfs3_check_rw_volaccess(nfs3state, exid, status, label)                \
  142     do {                                                                       \
  143         if (nfs3_export_access(nfs3state, exid) != GF_NFS3_VOLACCESS_RW) {     \
  144             gf_msg(GF_NFS3, GF_LOG_ERROR, EACCES, NFS_MSG_NO_RW_ACCESS,        \
  145                    "No read-write access");                                    \
  146             status = NFS3ERR_ROFS;                                             \
  147             goto label;                                                        \
  148         }                                                                      \
  149     } while (0)
  150 
  151 xlator_t *
  152 nfs3_fh_to_xlator(struct nfs3_state *nfs3, struct nfs3_fh *fh)
  153 {
  154     xlator_t *vol = NULL;
  155     struct nfs3_export *exp = NULL;
  156 
  157     GF_VALIDATE_OR_GOTO(GF_NFS3, nfs3, out);
  158     GF_VALIDATE_OR_GOTO(GF_NFS3, fh, out);
  159 
  160     exp = __nfs3_get_export_by_exportid(nfs3, fh->exportid);
  161     if (!exp)
  162         goto out;
  163 
  164     vol = exp->subvol;
  165 out:
  166     return vol;
  167 }
  168 
  169 int
  170 nfs3_is_root_looked_up(struct nfs3_state *nfs3, struct nfs3_fh *rootfh)
  171 {
  172     struct nfs3_export *exp = NULL;
  173     int ret = 0;
  174 
  175     GF_VALIDATE_OR_GOTO(GF_NFS3, nfs3, out);
  176     GF_VALIDATE_OR_GOTO(GF_NFS3, rootfh, out);
  177 
  178     exp = __nfs3_get_export_by_exportid(nfs3, rootfh->exportid);
  179     if (!exp)
  180         goto out;
  181 
  182     ret = exp->rootlookedup;
  183 out:
  184     return ret;
  185 }
  186 
  187 int
  188 nfs3_set_root_looked_up(struct nfs3_state *nfs3, struct nfs3_fh *rootfh)
  189 {
  190     struct nfs3_export *exp = NULL;
  191     int ret = 0;
  192 
  193     GF_VALIDATE_OR_GOTO(GF_NFS3, nfs3, out);
  194     GF_VALIDATE_OR_GOTO(GF_NFS3, rootfh, out);
  195 
  196     exp = __nfs3_get_export_by_exportid(nfs3, rootfh->exportid);
  197     if (!exp)
  198         goto out;
  199 
  200     exp->rootlookedup = 1;
  201 out:
  202     return ret;
  203 }
  204 
  205 #define nfs3_map_fh_to_volume(nfs3state, handle, req, volume, status, label)   \
  206     do {                                                                       \
  207         char exportid[256], gfid[256];                                         \
  208         rpc_transport_t *trans = NULL;                                         \
  209         volume = nfs3_fh_to_xlator((nfs3state), handle);                       \
  210         if (!volume) {                                                         \
  211             gf_uuid_unparse(handle->exportid, exportid);                       \
  212             gf_uuid_unparse(handle->gfid, gfid);                               \
  213             trans = rpcsvc_request_transport(req);                             \
  214             GF_LOG_OCCASIONALLY(nfs3state->occ_logger, GF_NFS3, GF_LOG_ERROR,  \
  215                                 "Failed to map "                               \
  216                                 "FH to vol: client=%s, exportid=%s, "          \
  217                                 "gfid=%s",                                     \
  218                                 trans->peerinfo.identifier, exportid, gfid);   \
  219             GF_LOG_OCCASIONALLY(nfs3state->occ_logger, GF_NFS3, GF_LOG_ERROR,  \
  220                                 "Stale nfs "                                   \
  221                                 "client %s must be trying to connect to"       \
  222                                 " a deleted volume, please unmount it.",       \
  223                                 trans->peerinfo.identifier);                   \
  224             status = NFS3ERR_STALE;                                            \
  225             goto label;                                                        \
  226         } else {                                                               \
  227             gf_msg_trace(GF_NFS3, 0,                                           \
  228                          "FH to Volume:"                                       \
  229                          "%s",                                                 \
  230                          volume->name);                                        \
  231             rpcsvc_request_set_private(req, volume);                           \
  232         }                                                                      \
  233     } while (0);
  234 
  235 #define nfs3_validate_gluster_fh(handle, status, errlabel)                     \
  236     do {                                                                       \
  237         if (!nfs3_fh_validate(handle)) {                                       \
  238             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_BAD_HANDLE,               \
  239                    "Bad Handle");                                              \
  240             status = NFS3ERR_BADHANDLE;                                        \
  241             goto errlabel;                                                     \
  242         }                                                                      \
  243     } while (0)
  244 
  245 #define nfs3_check_fh_auth_status(cst, nfstat, is_write_op, erlabl)            \
  246     do {                                                                       \
  247         int auth_ret = 0;                                                      \
  248         int auth_errno = 0;                                                    \
  249         xlator_t *xlatorp = NULL;                                              \
  250         char buf[256], gfid[GF_UUID_BUF_SIZE];                                 \
  251         rpc_transport_t *trans = NULL;                                         \
  252                                                                                \
  253         auth_ret = auth_errno = nfs3_fh_auth_nfsop(cst, is_write_op);          \
  254         if (auth_ret < 0) {                                                    \
  255             trans = rpcsvc_request_transport(cst->req);                        \
  256             xlatorp = nfs3_fh_to_xlator(cst->nfs3state, &cst->resolvefh);      \
  257             gf_uuid_unparse(cst->resolvefh.gfid, gfid);                        \
  258             sprintf(buf, "(%s) %s : %s", trans->peerinfo.identifier,           \
  259                     xlatorp ? xlatorp->name : "ERR", gfid);                    \
  260             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_RESOLVE_FH_FAIL,          \
  261                    "Unable to "                                                \
  262                    "resolve FH: %s",                                           \
  263                    buf);                                                       \
  264             nfstat = nfs3_errno_to_nfsstat3(-auth_errno);                      \
  265             goto erlabl;                                                       \
  266         }                                                                      \
  267     } while (0)
  268 
  269 #define nfs3_check_fh_resolve_status(cst, nfstat, erlabl)                      \
  270     do {                                                                       \
  271         xlator_t *xlatorp = NULL;                                              \
  272         char buf[256], gfid[GF_UUID_BUF_SIZE];                                 \
  273         rpc_transport_t *trans = NULL;                                         \
  274         if ((cst)->resolve_ret < 0) {                                          \
  275             trans = rpcsvc_request_transport(cst->req);                        \
  276             xlatorp = nfs3_fh_to_xlator(cst->nfs3state, &cst->resolvefh);      \
  277             gf_uuid_unparse(cst->resolvefh.gfid, gfid);                        \
  278             snprintf(buf, sizeof(buf), "(%s) %s : %s",                         \
  279                      trans->peerinfo.identifier,                               \
  280                      xlatorp ? xlatorp->name : "ERR", gfid);                   \
  281             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_RESOLVE_STAT, "%s: %s",   \
  282                    strerror(cst->resolve_errno), buf);                         \
  283             nfstat = nfs3_errno_to_nfsstat3(cst->resolve_errno);               \
  284             goto erlabl;                                                       \
  285         }                                                                      \
  286     } while (0)
  287 
  288 #define nfs3_check_new_fh_resolve_status(cst, nfstat, erlabl)                  \
  289     do {                                                                       \
  290         xlator_t *xlatorp = NULL;                                              \
  291         char buf[256], gfid[GF_UUID_BUF_SIZE];                                 \
  292         rpc_transport_t *trans = NULL;                                         \
  293         if (((cst)->resolve_ret < 0) && ((cst)->resolve_errno != ENOENT)) {    \
  294             trans = rpcsvc_request_transport(cst->req);                        \
  295             xlatorp = nfs3_fh_to_xlator(cst->nfs3state, &cst->resolvefh);      \
  296             gf_uuid_unparse(cst->resolvefh.gfid, gfid);                        \
  297             snprintf(buf, sizeof(buf), "(%s) %s : %s",                         \
  298                      trans->peerinfo.identifier,                               \
  299                      xlatorp ? xlatorp->name : "ERR", gfid);                   \
  300             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_RESOLVE_STAT, "%s: %s",   \
  301                    strerror(cst->resolve_errno), buf);                         \
  302             nfstat = nfs3_errno_to_nfsstat3(cs->resolve_errno);                \
  303             goto erlabl;                                                       \
  304         }                                                                      \
  305     } while (0)
  306 
  307 int
  308 __nfs3_get_volume_id(struct nfs3_state *nfs3, xlator_t *xl, uuid_t volumeid)
  309 {
  310     int ret = -1;
  311     struct nfs3_export *exp = NULL;
  312 
  313     GF_VALIDATE_OR_GOTO(GF_NFS3, nfs3, out);
  314     GF_VALIDATE_OR_GOTO(GF_NFS3, xl, out);
  315 
  316     list_for_each_entry(exp, &nfs3->exports, explist)
  317     {
  318         if (exp->subvol == xl) {
  319             gf_uuid_copy(volumeid, exp->volumeid);
  320             ret = 0;
  321             goto out;
  322         }
  323     }
  324 
  325 out:
  326     return ret;
  327 }
  328 
  329 static int
  330 nfs3_funge_webnfs_zerolen_fh(rpcsvc_request_t *req, struct nfs3_state *nfs3st,
  331                              struct nfs3_fh *fhd, char *name)
  332 {
  333     xlator_t *fungexl = NULL;
  334     struct nfs_state *nfs = NULL;
  335     glfs_t *fs = NULL;
  336     loc_t loc = {
  337         0,
  338     };
  339     int ret = -1;
  340     char *subdir = NULL;
  341     char volname[NAME_MAX] = {
  342         0,
  343     };
  344 
  345     fungexl = nfs_mntpath_to_xlator(nfs3st->exportslist, name);
  346     if (!fungexl) {
  347         gf_msg_trace(GF_NFS3, 0, "failed to find xlator for volume");
  348         ret = -ENOENT;
  349         goto out;
  350     }
  351     /* fungexl is valid, set for nfs3_request_xlator_deviceid() */
  352     rpcsvc_request_set_private(req, fungexl);
  353 
  354     /* Permission checks are done through mnt3_parse_dir_exports(). The
  355      * "nfs.export-dir" option gets checked as well. */
  356     nfs = nfs_state(nfs3st->nfsx);
  357     ret = mnt3_parse_dir_exports(req, nfs->mstate, name, _gf_false);
  358     if (ret) {
  359         gf_msg_trace(GF_NFS3, -ret, "mounting not possible");
  360         goto out;
  361     }
  362 
  363     /* glfs_resolve_at copied from UDP MNT support */
  364     fs = glfs_new_from_ctx(fungexl->ctx);
  365     if (!fs) {
  366         gf_msg_trace(GF_NFS3, 0, "failed to create glfs instance");
  367         ret = -ENOENT;
  368         goto out;
  369     }
  370 
  371     /* split name "volname/sub/dir/s" into pieces */
  372     subdir = mnt3_get_volume_subdir(name, (char **)&volname);
  373 
  374     ret = glfs_resolve_at(fs, fungexl, NULL, subdir, &loc, NULL, 1, 0);
  375     if (ret != 0) {
  376         gf_msg_trace(GF_NFS3, 0, "failed to resolve %s", subdir);
  377         ret = -ENOENT;
  378         goto out;
  379     }
  380 
  381     /* resolved subdir, copy gfid for the fh */
  382     gf_uuid_copy(fhd->gfid, loc.gfid);
  383     loc_wipe(&loc);
  384 
  385     if (gf_nfs_dvm_off(nfs_state(nfs3st->nfsx)))
  386         fhd->exportid[15] = nfs_xlator_to_xlid(nfs3st->exportslist, fungexl);
  387     else {
  388         if (__nfs3_get_volume_id(nfs3st, fungexl, fhd->exportid) < 0) {
  389             ret = -ESTALE;
  390             goto out;
  391         }
  392     }
  393 
  394     ret = 0;
  395 out:
  396     if (fs)
  397         glfs_free_from_ctx(fs);
  398 
  399     return ret;
  400 }
  401 
  402 /*
  403  * This macro checks if the volume is started or not.
  404  * If it is not started, it closes the client connection & logs it.
  405  *
  406  * Why do we do this?
  407  *
  408  * There is a "race condition" where gNFSd may start listening for RPC requests
  409  * prior to the volume being started. Presumably, that is why this macro exists
  410  * in the first place. In the NFS kernel client (specifically Linux's NFS
  411  * kernel client), they establish a TCP connection to our endpoint and
  412  * (re-)send requests. If we ignore the request, and return nothing back,
  413  * the NFS kernel client waits forever for our response. If for some reason,
  414  * the TCP connection were to die, and re-establish, the requests are
  415  * retransmitted and everything begins working as expected
  416  *
  417  * Now, this is clearly bad behavior on the client side,
  418  * but in order to make every user's life easier,
  419  * gNFSd should simply disconnect the TCP connection if it sees requests
  420  * before it is ready to accept them.
  421  *
  422  */
  423 
  424 #define nfs3_volume_started_check(nf3stt, vlm, rtval, erlbl)                   \
  425     do {                                                                       \
  426         if ((!nfs_subvolume_started(nfs_state(nf3stt->nfsx), vlm))) {          \
  427             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_VOL_DISABLE,              \
  428                    "Volume is disabled: %s", vlm->name);                       \
  429             nfs3_disconnect_transport(req->trans);                             \
  430             rtval = RPCSVC_ACTOR_IGNORE;                                       \
  431             goto erlbl;                                                        \
  432         }                                                                      \
  433     } while (0)
  434 
  435 void
  436 nfs3_disconnect_transport(rpc_transport_t *transport)
  437 {
  438     int ret = 0;
  439 
  440     GF_VALIDATE_OR_GOTO(GF_NFS3, transport, out);
  441 
  442     ret = rpc_transport_disconnect(transport, _gf_false);
  443     if (ret != 0) {
  444         gf_log(GF_NFS3, GF_LOG_WARNING,
  445                "Unable to close client connection to %s.",
  446                transport->peerinfo.identifier);
  447     } else {
  448         gf_log(GF_NFS3, GF_LOG_WARNING, "Closed client connection to %s.",
  449                transport->peerinfo.identifier);
  450     }
  451 out:
  452     return;
  453 }
  454 
  455 int
  456 nfs3_export_sync_trusted(struct nfs3_state *nfs3, uuid_t exportid)
  457 {
  458     struct nfs3_export *exp = NULL;
  459     int ret = 0;
  460 
  461     GF_VALIDATE_OR_GOTO(GF_NFS3, nfs3, err);
  462 
  463     exp = __nfs3_get_export_by_exportid(nfs3, exportid);
  464     if (!exp)
  465         goto err;
  466 
  467     ret = exp->trusted_sync;
  468 err:
  469     return ret;
  470 }
  471 
  472 int
  473 nfs3_export_write_trusted(struct nfs3_state *nfs3, uuid_t exportid)
  474 {
  475     struct nfs3_export *exp = NULL;
  476     int ret = 0;
  477 
  478     GF_VALIDATE_OR_GOTO(GF_NFS3, nfs3, err);
  479 
  480     exp = __nfs3_get_export_by_exportid(nfs3, exportid);
  481     if (!exp)
  482         goto err;
  483 
  484     ret = exp->trusted_write;
  485 err:
  486     return ret;
  487 }
  488 
  489 int
  490 nfs3_solaris_zerolen_fh(struct nfs3_fh *fh, int fhlen)
  491 {
  492     if (!fh)
  493         return 0;
  494 
  495     if (nfs3_fh_validate(fh))
  496         return 0;
  497 
  498     if (fhlen == 0) {
  499         gf_msg_trace(GF_NFS3, 0, "received WebNFS request");
  500         return 1;
  501     }
  502 
  503     return 0;
  504 }
  505 
  506 /* Function pointer that represents the generic prototypes of functions used
  507  * to serialize NFS3 message structures into the XDR format.
  508  * For usage, see the nfs3svc_XXX_cbk functions.
  509  */
  510 typedef ssize_t (*nfs3_serializer)(struct iovec outmsg, void *args);
  511 
  512 static void
  513 __nfs3_call_state_wipe(nfs3_call_state_t *cs)
  514 {
  515     if (cs->fd) {
  516         gf_msg_trace(GF_NFS3, 0, "fd 0x%lx ref: %" PRId64, (long)cs->fd,
  517                      GF_ATOMIC_GET(cs->fd->refcount));
  518         fd_unref(cs->fd);
  519     }
  520 
  521     GF_FREE(cs->resolventry);
  522 
  523     GF_FREE(cs->pathname);
  524 
  525     if (!list_empty(&cs->entries.list))
  526         gf_dirent_free(&cs->entries);
  527 
  528     nfs_loc_wipe(&cs->oploc);
  529     nfs_loc_wipe(&cs->resolvedloc);
  530     if (cs->iob)
  531         iobuf_unref(cs->iob);
  532     if (cs->iobref)
  533         iobref_unref(cs->iobref);
  534     if (cs->trans)
  535         rpc_transport_unref(cs->trans);
  536     memset(cs, 0, sizeof(*cs));
  537     mem_put(cs);
  538     /* Already refd by fd_lookup, so no need to ref again. */
  539 }
  540 
  541 nfs3_call_state_t *
  542 nfs3_call_state_init(struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v)
  543 {
  544     nfs3_call_state_t *cs = NULL;
  545 
  546     GF_VALIDATE_OR_GOTO(GF_NFS3, s, err);
  547     GF_VALIDATE_OR_GOTO(GF_NFS3, req, err);
  548     /* GF_VALIDATE_OR_GOTO (GF_NFS3, v, err); NLM sets this later */
  549 
  550     cs = (nfs3_call_state_t *)mem_get(s->localpool);
  551     if (!cs) {
  552         gf_msg(GF_NFS3, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
  553                "out of memory");
  554         return NULL;
  555     }
  556 
  557     memset(cs, 0, sizeof(*cs));
  558     GF_REF_INIT(cs, __nfs3_call_state_wipe);
  559     INIT_LIST_HEAD(&cs->entries.list);
  560     INIT_LIST_HEAD(&cs->openwait_q);
  561     cs->operrno = EINVAL;
  562     cs->req = req;
  563     cs->vol = v;
  564     cs->nfsx = s->nfsx;
  565     cs->nfs3state = s;
  566 err:
  567     return cs;
  568 }
  569 
  570 void
  571 nfs3_call_state_wipe(nfs3_call_state_t *cs)
  572 {
  573     if (!cs) {
  574         gf_log_callingfn("nfs", GF_LOG_WARNING, "nfs calling state NULL");
  575         return;
  576     }
  577     GF_REF_PUT(cs);
  578 }
  579 
  580 #define nfs3_handle_call_state_init(nfs3state, calls, rq, vl, opstat,          \
  581                                     errlabel)                                  \
  582     do {                                                                       \
  583         calls = nfs3_call_state_init((nfs3state), (rq), (vl));                 \
  584         if (!calls) {                                                          \
  585             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_INIT_CALL_STAT_FAIL,      \
  586                    "Failed to"                                                 \
  587                    " init call state");                                        \
  588             opstat = NFS3ERR_SERVERFAULT;                                      \
  589             goto errlabel;                                                     \
  590         }                                                                      \
  591     } while (0)
  592 
  593 struct iobuf *
  594 nfs3_serialize_reply(rpcsvc_request_t *req, void *arg, nfs3_serializer sfunc,
  595                      struct iovec *outmsg)
  596 {
  597     struct nfs3_state *nfs3 = NULL;
  598     struct iobuf *iob = NULL;
  599     ssize_t retlen = -1;
  600 
  601     nfs3 = (struct nfs3_state *)rpcsvc_request_program_private(req);
  602     if (!nfs3) {
  603         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_STATE_MISSING,
  604                "NFSv3 state not found in RPC request");
  605         goto ret;
  606     }
  607 
  608     /* First, get the io buffer into which the reply in arg will
  609      * be serialized.
  610      */
  611     /* TODO: get rid of 'sfunc' and use 'xdrproc_t' so we
  612        can have 'xdr_sizeof' */
  613     iob = iobuf_get(nfs3->iobpool);
  614     if (!iob) {
  615         gf_msg(GF_NFS3, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
  616                "Failed to get iobuf");
  617         goto ret;
  618     }
  619 
  620     iobuf_to_iovec(iob, outmsg);
  621     /* Use the given serializer to translate the give C structure in arg
  622      * to XDR format which will be written into the buffer in outmsg.
  623      */
  624     /* retlen is used to received the error since size_t is unsigned and we
  625      * need -1 for error notification during encoding.
  626      */
  627     retlen = sfunc(*outmsg, arg);
  628     if (retlen == -1) {
  629         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ENCODE_FAIL,
  630                "Failed to encode message");
  631         goto ret;
  632     }
  633 
  634     outmsg->iov_len = retlen;
  635 ret:
  636     if (retlen == -1) {
  637         iobuf_unref(iob);
  638         iob = NULL;
  639     }
  640 
  641     return iob;
  642 }
  643 
  644 /* Generic reply function for NFSv3 specific replies. */
  645 int
  646 nfs3svc_submit_reply(rpcsvc_request_t *req, void *arg, nfs3_serializer sfunc)
  647 {
  648     struct iovec outmsg = {
  649         0,
  650     };
  651     struct iobuf *iob = NULL;
  652     int ret = -1;
  653     struct iobref *iobref = NULL;
  654 
  655     if (!req)
  656         return -1;
  657 
  658     iob = nfs3_serialize_reply(req, arg, sfunc, &outmsg);
  659     if (!iob) {
  660         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_SERIALIZE_REPLY_FAIL,
  661                "Failed to serialize reply");
  662         goto ret;
  663     }
  664 
  665     iobref = iobref_new();
  666     if (!iobref) {
  667         gf_msg(GF_NFS3, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
  668                "failed on iobref_new()");
  669         goto ret;
  670     }
  671 
  672     ret = iobref_add(iobref, iob);
  673     if (ret) {
  674         gf_msg(GF_NFS3, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
  675                "Failed to add iob to iobref");
  676         goto ret;
  677     }
  678 
  679     /* Then, submit the message for transmission. */
  680     ret = rpcsvc_submit_message(req, &outmsg, 1, NULL, 0, iobref);
  681     if (ret == -1) {
  682         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_SUBMIT_REPLY_FAIL,
  683                "Reply submission failed");
  684         goto ret;
  685     }
  686 
  687     ret = 0;
  688 ret:
  689     /* Now that we've done our job of handing the message to the RPC layer
  690      * we can safely unref the iob in the hope that RPC layer must have
  691      * ref'ed the iob on receiving into the txlist.
  692      */
  693     if (NULL != iob)
  694         iobuf_unref(iob);
  695     if (NULL != iobref)
  696         iobref_unref(iobref);
  697     return ret;
  698 }
  699 
  700 int
  701 nfs3svc_submit_vector_reply(rpcsvc_request_t *req, void *arg,
  702                             nfs3_serializer sfunc, struct iovec *payload,
  703                             int vcount, struct iobref *iobref)
  704 {
  705     struct iovec outmsg = {
  706         0,
  707     };
  708     struct iobuf *iob = NULL;
  709     int ret = -1;
  710     int new_iobref = 0;
  711 
  712     if (!req)
  713         return -1;
  714 
  715     iob = nfs3_serialize_reply(req, arg, sfunc, &outmsg);
  716     if (!iob) {
  717         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_SERIALIZE_REPLY_FAIL,
  718                "Failed to serialize reply");
  719         goto ret;
  720     }
  721     if (iobref == NULL) {
  722         iobref = iobref_new();
  723         if (!iobref) {
  724             gf_msg(GF_NFS3, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
  725                    "failed on iobref_new");
  726             goto ret;
  727         }
  728         new_iobref = 1;
  729     }
  730 
  731     ret = iobref_add(iobref, iob);
  732     if (ret) {
  733         gf_msg(GF_NFS3, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
  734                "Failed to add iob to iobref");
  735         goto ret;
  736     }
  737 
  738     /* Then, submit the message for transmission. */
  739     ret = rpcsvc_submit_message(req, &outmsg, 1, payload, vcount, iobref);
  740     if (ret == -1) {
  741         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_SUBMIT_REPLY_FAIL,
  742                "Reply submission failed");
  743         goto ret;
  744     }
  745 
  746     ret = 0;
  747 ret:
  748     /* Now that we've done our job of handing the message to the RPC layer
  749      * we can safely unref the iob in the hope that RPC layer must have
  750      * ref'ed the iob on receiving into the txlist.
  751      */
  752     if (NULL != iob)
  753         iobuf_unref(iob);
  754     if (new_iobref)
  755         iobref_unref(iobref);
  756     return ret;
  757 }
  758 
  759 uint64_t
  760 nfs3_request_xlator_deviceid(rpcsvc_request_t *rq)
  761 {
  762     struct nfs3_state *nfs3 = NULL;
  763     xlator_t *xl = NULL;
  764     uint64_t devid = 0;
  765     uuid_t volumeid = {
  766         0,
  767     };
  768 
  769     if (!rq)
  770         return 0;
  771 
  772     xl = rpcsvc_request_private(rq);
  773     nfs3 = rpcsvc_request_program_private(rq);
  774     if (nfs3 && (gf_nfs_dvm_off(nfs_state(nfs3->nfsx))))
  775         devid = (uint64_t)nfs_xlator_to_xlid(nfs3->exportslist, xl);
  776     else {
  777         __nfs3_get_volume_id(nfs3, xl, volumeid);
  778         memcpy(&devid, &volumeid[8], sizeof(devid));
  779     }
  780 
  781     return devid;
  782 }
  783 
  784 int
  785 nfs3svc_null(rpcsvc_request_t *req)
  786 {
  787     struct iovec dummyvec = {
  788         0,
  789     };
  790     if (!req)
  791         return RPCSVC_ACTOR_ERROR;
  792     rpcsvc_submit_generic(req, &dummyvec, 1, NULL, 0, NULL);
  793     return RPCSVC_ACTOR_SUCCESS;
  794 }
  795 
  796 int
  797 nfs3_getattr_reply(rpcsvc_request_t *req, nfsstat3 status, struct iatt *buf)
  798 {
  799     getattr3res res;
  800     uint64_t deviceid = 0;
  801 
  802     deviceid = nfs3_request_xlator_deviceid(req);
  803     nfs3_fill_getattr3res(&res, status, buf, deviceid);
  804     nfs3svc_submit_reply(req, &res, (nfs3_serializer)xdr_serialize_getattr3res);
  805 
  806     return 0;
  807 }
  808 
  809 int32_t
  810 nfs3svc_getattr_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  811                            int32_t op_ret, int32_t op_errno, inode_t *inode,
  812                            struct iatt *buf, dict_t *xattr,
  813                            struct iatt *postparent)
  814 {
  815     nfsstat3 status = NFS3_OK;
  816     nfs3_call_state_t *cs = NULL;
  817 
  818     cs = frame->local;
  819 
  820     /*
  821      * Somewhat counter-intuitively, we don't need to look for sh-failed
  822      * here. Failing this getattr will generate a new lookup from the
  823      * client, and nfs_fop_lookup_cbk will detect any self-heal failures.
  824      */
  825 
  826     if (op_ret == -1) {
  827         status = nfs3_cbk_errno_status(op_ret, op_errno);
  828     } else {
  829         nfs_fix_generation(this, inode);
  830     }
  831 
  832     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_GETATTR, status,
  833                         op_errno, cs->resolvedloc.path);
  834 
  835     nfs3_getattr_reply(cs->req, status, buf);
  836     nfs3_call_state_wipe(cs);
  837 
  838     return 0;
  839 }
  840 
  841 int32_t
  842 nfs3svc_getattr_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  843                          int32_t op_ret, int32_t op_errno, struct iatt *buf,
  844                          dict_t *xdata)
  845 {
  846     nfsstat3 status = NFS3_OK;
  847     nfs3_call_state_t *cs = NULL;
  848 
  849     cs = frame->local;
  850 
  851     if (op_ret == -1) {
  852         /* Prevent crashes for the case where this call fails
  853          * and buf is left in a NULL state, yet the op_errno == 0.
  854          */
  855         if (!buf && op_errno == 0) {
  856             op_errno = EIO;
  857         }
  858         status = nfs3_cbk_errno_status(op_ret, op_errno);
  859     }
  860 
  861     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_GETATTR, status,
  862                         op_errno, cs->resolvedloc.path);
  863 
  864     nfs3_getattr_reply(cs->req, status, buf);
  865     nfs3_call_state_wipe(cs);
  866 
  867     return 0;
  868 }
  869 
  870 int
  871 nfs3_getattr_resume(void *carg)
  872 {
  873     nfsstat3 stat = NFS3ERR_SERVERFAULT;
  874     int ret = -EFAULT;
  875     nfs_user_t nfu = {
  876         0,
  877     };
  878     nfs3_call_state_t *cs = NULL;
  879     uint64_t raw_ctx = 0;
  880     struct nfs_inode_ctx *ictx = NULL;
  881     struct nfs_state *priv = NULL;
  882 
  883     if (!carg)
  884         return ret;
  885 
  886     cs = (nfs3_call_state_t *)carg;
  887     nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
  888     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
  889     nfs_request_user_init(&nfu, cs->req);
  890     /* If inode which is to be getattr'd is the root, we need to do a
  891      * lookup instead because after a server reboot, it is not necessary
  892      * for the root to have been looked up when the getattr on the root is
  893      * sent. AND, this causes a problem for stat-prefetch in that it
  894      * expects even the root inode to have been looked up.
  895 
  896     if (__is_root_gfid (cs->resolvedloc.inode->gfid))
  897             ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
  898                               nfs3svc_getattr_lookup_cbk, cs);
  899     else
  900             ret = nfs_stat (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
  901     */
  902 
  903     if (cs->hardresolved) {
  904         ret = -EFAULT;
  905         stat = NFS3_OK;
  906         goto nfs3err;
  907     }
  908 
  909     /*
  910      * If brick state changed, we need to force a proper lookup cycle (as
  911      * would happen in native protocol) to do self-heal checks. We detect
  912      * this by comparing the generation number for the last successful
  913      * creation/lookup on the inode to the current number, so inodes that
  914      * haven't been validated since the state change are affected.
  915      */
  916     if (inode_ctx_get(cs->resolvedloc.inode, cs->nfsx, &raw_ctx) == 0) {
  917         ictx = (struct nfs_inode_ctx *)(uintptr_t)raw_ctx;
  918         priv = cs->nfsx->private;
  919         if (ictx->generation != priv->generation) {
  920             ret = nfs_lookup(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
  921                              nfs3svc_getattr_lookup_cbk, cs);
  922             goto check_err;
  923         }
  924     }
  925 
  926     ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
  927                    nfs3svc_getattr_stat_cbk, cs);
  928 
  929 check_err:
  930     if (ret < 0) {
  931         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_STAT_FOP_FAIL,
  932                "Stat fop failed: %s: %s", cs->oploc.path, strerror(-ret));
  933         stat = nfs3_errno_to_nfsstat3(-ret);
  934     }
  935 
  936 nfs3err:
  937     if (ret < 0) {
  938         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_GETATTR, stat,
  939                             -ret, cs->resolvedloc.path);
  940         nfs3_getattr_reply(cs->req, stat, &cs->stbuf);
  941         nfs3_call_state_wipe(cs);
  942         ret = 0;
  943     }
  944 
  945     return ret;
  946 }
  947 
  948 int
  949 nfs3_getattr(rpcsvc_request_t *req, struct nfs3_fh *fh)
  950 {
  951     xlator_t *vol = NULL;
  952     nfsstat3 stat = NFS3ERR_SERVERFAULT;
  953     int ret = -EFAULT;
  954     struct nfs3_state *nfs3 = NULL;
  955     nfs3_call_state_t *cstate = NULL;
  956 
  957     GF_VALIDATE_OR_GOTO(GF_NFS3, req, out);
  958     GF_VALIDATE_OR_GOTO(GF_NFS3, fh, out);
  959 
  960     nfs3_log_common_call(rpcsvc_request_xid(req), "GETATTR", fh);
  961     nfs3_validate_gluster_fh(fh, stat, nfs3err);
  962     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
  963     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
  964     nfs3_volume_started_check(nfs3, vol, ret, out);
  965     nfs3_handle_call_state_init(nfs3, cstate, req, vol, stat, nfs3err);
  966 
  967     ret = nfs3_fh_resolve_and_resume(cstate, fh, NULL, nfs3_getattr_resume);
  968     if (ret < 0)
  969         stat = nfs3_errno_to_nfsstat3(-ret);
  970 
  971 nfs3err:
  972     if (ret < 0) {
  973         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_GETATTR, stat, -ret,
  974                             NULL);
  975         nfs3_getattr_reply(req, stat, NULL);
  976         ret = 0;
  977         nfs3_call_state_wipe(cstate);
  978     }
  979 out:
  980     return ret;
  981 }
  982 
  983 int
  984 nfs3svc_getattr(rpcsvc_request_t *req)
  985 {
  986     struct nfs3_fh fh = {
  987         {0},
  988     };
  989     getattr3args args;
  990     int ret = RPCSVC_ACTOR_ERROR;
  991 
  992     if (!req)
  993         return ret;
  994 
  995     nfs3_prep_getattr3args(&args, &fh);
  996     if (xdr_to_getattr3args(req->msg[0], &args) <= 0) {
  997         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
  998                "Error decoding args");
  999         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 1000         goto rpcerr;
 1001     }
 1002 
 1003     ret = nfs3_getattr(req, &fh);
 1004     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 1005         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_GETATTR_FAIL,
 1006                "GETATTR procedure failed");
 1007         rpcsvc_request_seterr(req, SYSTEM_ERR);
 1008         ret = RPCSVC_ACTOR_ERROR;
 1009     }
 1010 
 1011 rpcerr:
 1012     return ret;
 1013 }
 1014 
 1015 int
 1016 nfs3_setattr_reply(rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preop,
 1017                    struct iatt *postop)
 1018 {
 1019     setattr3res res = {
 1020         0,
 1021     };
 1022     uint64_t deviceid = 0;
 1023 
 1024     deviceid = nfs3_request_xlator_deviceid(req);
 1025     nfs3_fill_setattr3res(&res, stat, preop, postop, deviceid);
 1026     nfs3svc_submit_reply(req, (void *)&res,
 1027                          (nfs3_serializer)xdr_serialize_setattr3res);
 1028     return 0;
 1029 }
 1030 
 1031 int32_t
 1032 nfs3svc_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1033                      int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
 1034                      struct iatt *postbuf, dict_t *xdata)
 1035 {
 1036     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1037     struct iatt *prestat = NULL;
 1038     nfs3_call_state_t *cs = NULL;
 1039 
 1040     cs = frame->local;
 1041     if (op_ret == -1) {
 1042         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 1043         goto nfs3err;
 1044     }
 1045 
 1046     /* If the first stat was got from the guarded setattr callback, or
 1047      * from an earlier setattr call then we'll need to use that stat
 1048      * instead of the preop returned here.
 1049      */
 1050     if (cs->preparent.ia_ino != 0)
 1051         prestat = &cs->preparent;
 1052     else
 1053         prestat = prebuf;
 1054 
 1055     stat = NFS3_OK;
 1056 nfs3err:
 1057     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_SETATTR, stat,
 1058                         op_errno, cs->resolvedloc.path);
 1059     nfs3_setattr_reply(cs->req, stat, prestat, postbuf);
 1060     nfs3_call_state_wipe(cs);
 1061 
 1062     return 0;
 1063 }
 1064 
 1065 int32_t
 1066 nfs3svc_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1067                     int32_t op_ret, int32_t op_errno, struct iatt *preop,
 1068                     struct iatt *postop, dict_t *xdata)
 1069 {
 1070     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1071     int ret = -1;
 1072     struct iatt *prebuf = NULL;
 1073     nfs_user_t nfu = {
 1074         0,
 1075     };
 1076     nfs3_call_state_t *cs = NULL;
 1077 
 1078     cs = frame->local;
 1079     if (op_ret == -1) {
 1080         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 1081         goto nfs3err;
 1082     }
 1083 
 1084     prebuf = preop;
 1085     /* Store the current preop in case we need to send a truncate,
 1086      * in which case the preop to be returned will be this one.
 1087      */
 1088     cs->preparent = *preop;
 1089 
 1090     /* Only truncate if the size is not already same as the requested
 1091      * truncation and also only if this is not a directory.
 1092      */
 1093     if ((gf_attr_size_set(cs->setattr_valid)) && (!IA_ISDIR(postop->ia_type)) &&
 1094         (preop->ia_size != cs->attr_in.ia_size)) {
 1095         nfs_request_user_init(&nfu, cs->req);
 1096         ret = nfs_truncate(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 1097                            cs->attr_in.ia_size, nfs3svc_truncate_cbk, cs);
 1098 
 1099         if (ret < 0)
 1100             stat = nfs3_errno_to_nfsstat3(-ret);
 1101     } else {
 1102         ret = -1; /* Force a reply in the branch below. */
 1103         stat = NFS3_OK;
 1104     }
 1105 
 1106 nfs3err:
 1107     if (ret < 0) {
 1108         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_SETATTR, stat,
 1109                             op_errno, cs->resolvedloc.path);
 1110         nfs3_setattr_reply(cs->req, stat, prebuf, postop);
 1111         nfs3_call_state_wipe(cs);
 1112     }
 1113 
 1114     return 0;
 1115 }
 1116 
 1117 int32_t
 1118 nfs3svc_setattr_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1119                          int32_t op_ret, int32_t op_errno, struct iatt *buf,
 1120                          dict_t *xdata)
 1121 {
 1122     int ret = -EFAULT;
 1123     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1124     nfs_user_t nfu = {
 1125         0,
 1126     };
 1127     nfs3_call_state_t *cs = NULL;
 1128 
 1129     cs = frame->local;
 1130     if (op_ret == -1) {
 1131         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 1132         goto nfs3err;
 1133     }
 1134 
 1135     if (buf->ia_ctime != cs->timestamp.seconds) {
 1136         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_TIMESTAMP_NO_SYNC,
 1137                "Timestamps not in sync");
 1138         stat = NFS3ERR_NOT_SYNC;
 1139         goto nfs3err;
 1140     }
 1141 
 1142     /* Not a clean way but no motivation to add a new member to local. */
 1143     cs->preparent = *buf;
 1144     nfs_request_user_init(&nfu, cs->req);
 1145     ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->stbuf,
 1146                       cs->setattr_valid, nfs3svc_setattr_cbk, cs);
 1147     if (ret < 0)
 1148         stat = nfs3_errno_to_nfsstat3(-ret);
 1149 
 1150 nfs3err:
 1151     if (ret < 0) {
 1152         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_SETATTR, stat,
 1153                             op_errno, cs->resolvedloc.path);
 1154         nfs3_setattr_reply(cs->req, stat, NULL, NULL);
 1155         nfs3_call_state_wipe(cs);
 1156     }
 1157 
 1158     return 0;
 1159 }
 1160 
 1161 int
 1162 nfs3_setattr_resume(void *carg)
 1163 {
 1164     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1165     int ret = -EFAULT;
 1166     nfs_user_t nfu = {
 1167         0,
 1168     };
 1169     nfs3_call_state_t *cs = NULL;
 1170 
 1171     if (!carg)
 1172         return ret;
 1173 
 1174     cs = (nfs3_call_state_t *)carg;
 1175     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 1176     nfs_request_user_init(&nfu, cs->req);
 1177     ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->attr_in,
 1178                       cs->setattr_valid, nfs3svc_setattr_cbk, cs);
 1179 
 1180     if (ret < 0)
 1181         stat = nfs3_errno_to_nfsstat3(-ret);
 1182 
 1183 nfs3err:
 1184     if (ret < 0) {
 1185         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_SETATTR, stat,
 1186                             -ret, cs->resolvedloc.path);
 1187         nfs3_setattr_reply(cs->req, stat, NULL, NULL);
 1188         nfs3_call_state_wipe(cs);
 1189     }
 1190 
 1191     return ret;
 1192 }
 1193 
 1194 int
 1195 nfs3_setattr(rpcsvc_request_t *req, struct nfs3_fh *fh, sattr3 *sattr,
 1196              sattrguard3 *guard)
 1197 {
 1198     xlator_t *vol = NULL;
 1199     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1200     int ret = -EFAULT;
 1201     struct nfs3_state *nfs3 = NULL;
 1202     nfs3_call_state_t *cs = NULL;
 1203 
 1204     GF_VALIDATE_OR_GOTO(GF_NFS3, req, out);
 1205     GF_VALIDATE_OR_GOTO(GF_NFS3, fh, out);
 1206     GF_VALIDATE_OR_GOTO(GF_NFS3, sattr, out);
 1207     GF_VALIDATE_OR_GOTO(GF_NFS3, guard, out);
 1208 
 1209     nfs3_log_common_call(rpcsvc_request_xid(req), "SETATTR", fh);
 1210     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 1211     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 1212     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 1213     nfs3_volume_started_check(nfs3, vol, ret, out);
 1214     nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
 1215     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 1216 
 1217     cs->setattr_valid = nfs3_sattr3_to_setattr_valid(sattr, &cs->attr_in, NULL);
 1218     if (guard->check) {
 1219         gf_msg_trace(GF_NFS3, 0, "Guard check required");
 1220         cs->timestamp = guard->sattrguard3_u.obj_ctime;
 1221         cs->sattrguardcheck = 1;
 1222     } else {
 1223         gf_msg_trace(GF_NFS3, 0, "Guard check not required");
 1224         cs->sattrguardcheck = 0;
 1225     }
 1226 
 1227     if (!cs->setattr_valid) {
 1228         ret = -EINVAL; /* Force a reply */
 1229         stat = NFS3_OK;
 1230         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_SETATTR_INVALID,
 1231                "cs->setattr_valid is invalid");
 1232         goto nfs3err;
 1233     }
 1234 
 1235     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_setattr_resume);
 1236     if (ret < 0)
 1237         stat = nfs3_errno_to_nfsstat3(-ret);
 1238 
 1239 nfs3err:
 1240     if (ret < 0) {
 1241         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_SETATTR, stat, -ret,
 1242                             cs ? cs->resolvedloc.path : NULL);
 1243         nfs3_setattr_reply(req, stat, NULL, NULL);
 1244         nfs3_call_state_wipe(cs);
 1245         /* Ret must be 0 after this so that the caller does not
 1246          * also send an RPC reply.
 1247          */
 1248         ret = 0;
 1249     }
 1250 out:
 1251     return ret;
 1252 }
 1253 
 1254 int
 1255 nfs3svc_setattr(rpcsvc_request_t *req)
 1256 {
 1257     struct nfs3_fh fh = {
 1258         {0},
 1259     };
 1260     setattr3args args;
 1261     int ret = RPCSVC_ACTOR_ERROR;
 1262 
 1263     GF_VALIDATE_OR_GOTO(GF_NFS3, req, rpcerr);
 1264 
 1265     nfs3_prep_setattr3args(&args, &fh);
 1266     if (xdr_to_setattr3args(req->msg[0], &args) <= 0) {
 1267         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 1268                "Error decoding args");
 1269         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 1270         goto rpcerr;
 1271     }
 1272 
 1273     ret = nfs3_setattr(req, &fh, &args.new_attributes, &args.guard);
 1274     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 1275         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_SETATTR_FAIL,
 1276                "SETATTR procedure failed");
 1277         rpcsvc_request_seterr(req, SYSTEM_ERR);
 1278         ret = RPCSVC_ACTOR_ERROR;
 1279     }
 1280 
 1281 rpcerr:
 1282     return ret;
 1283 }
 1284 
 1285 int
 1286 nfs3_lookup_reply(rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *newfh,
 1287                   struct iatt *stbuf, struct iatt *postparent)
 1288 {
 1289     lookup3res res = {
 1290         0,
 1291     };
 1292     uint64_t deviceid = 0;
 1293 
 1294     deviceid = nfs3_request_xlator_deviceid(req);
 1295     nfs3_fill_lookup3res(&res, stat, newfh, stbuf, postparent, deviceid);
 1296     return nfs3svc_submit_reply(req, &res,
 1297                                 (nfs3_serializer)xdr_serialize_lookup3res);
 1298 }
 1299 
 1300 int
 1301 nfs3_lookup_resume(void *carg);
 1302 
 1303 int
 1304 nfs3_fresh_lookup(nfs3_call_state_t *cs)
 1305 {
 1306     int ret = -EFAULT;
 1307     char *oldresolventry = NULL;
 1308 
 1309     GF_VALIDATE_OR_GOTO(GF_NFS3, cs, err);
 1310     gf_msg_debug(GF_NFS3, 0, "inode needs fresh lookup");
 1311     inode_unlink(cs->resolvedloc.inode, cs->resolvedloc.parent,
 1312                  cs->resolventry);
 1313     nfs_loc_wipe(&cs->resolvedloc);
 1314 
 1315     /* Store pointer to currently allocated resolventry because it gets over
 1316      * written in fh_resolve_and_resume.
 1317      */
 1318     oldresolventry = cs->resolventry;
 1319     cs->lookuptype = GF_NFS3_FRESH;
 1320     ret = nfs3_fh_resolve_and_resume(cs, &cs->resolvefh, cs->resolventry,
 1321                                      nfs3_lookup_resume);
 1322     /* Allocated in the previous call to fh_resolve_and_resume using the
 1323      * same call_state.
 1324      */
 1325     GF_FREE(oldresolventry);
 1326 err:
 1327     return ret;
 1328 }
 1329 
 1330 int
 1331 nfs3svc_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1332                    int32_t op_ret, int32_t op_errno, inode_t *inode,
 1333                    struct iatt *buf, dict_t *xattr, struct iatt *postparent)
 1334 {
 1335     struct nfs3_fh newfh = {
 1336         {0},
 1337     };
 1338     nfsstat3 status = NFS3_OK;
 1339     nfs3_call_state_t *cs = NULL;
 1340     inode_t *oldinode = NULL;
 1341 
 1342     cs = frame->local;
 1343     if (op_ret == -1) {
 1344         status = nfs3_cbk_errno_status(op_ret, op_errno);
 1345         goto xmit_res;
 1346     }
 1347 
 1348     nfs3_fh_build_child_fh(&cs->parent, buf, &newfh);
 1349     oldinode = inode_link(inode, cs->resolvedloc.parent, cs->resolvedloc.name,
 1350                           buf);
 1351 xmit_res:
 1352     /* Only send fresh lookup if it was a revalidate that failed. */
 1353     if ((op_ret == -1) && (nfs3_is_revalidate_lookup(cs))) {
 1354         op_ret = nfs3_fresh_lookup(cs);
 1355         goto out;
 1356     }
 1357 
 1358     nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_LOOKUP, status,
 1359                        op_errno, &newfh, cs->resolvedloc.path);
 1360     nfs3_lookup_reply(cs->req, status, &newfh, buf, postparent);
 1361     nfs3_call_state_wipe(cs);
 1362 out:
 1363     if (oldinode) {
 1364         inode_lookup(oldinode);
 1365         inode_unref(oldinode);
 1366     }
 1367     return 0;
 1368 }
 1369 
 1370 int
 1371 nfs3svc_lookup_parentdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1372                              int32_t op_ret, int32_t op_errno, inode_t *inode,
 1373                              struct iatt *buf, dict_t *xattr,
 1374                              struct iatt *postparent)
 1375 {
 1376     struct nfs3_fh newfh = {
 1377         {0},
 1378     };
 1379     nfsstat3 status = NFS3_OK;
 1380     nfs3_call_state_t *cs = NULL;
 1381     uuid_t volumeid = {
 1382         0,
 1383     };
 1384     uuid_t mountid = {
 1385         1,
 1386     };
 1387     struct nfs3_state *nfs3 = NULL;
 1388 
 1389     cs = frame->local;
 1390     if (op_ret == -1) {
 1391         status = nfs3_cbk_errno_status(op_ret, op_errno);
 1392         goto xmit_res;
 1393     }
 1394 
 1395     nfs3 = cs->nfs3state;
 1396     /* If the buf inode shows that this is a root dir's buf, then the file
 1397      * handle needs to be specially crafted, in all other cases, we'll just
 1398      * create the handle normally using the buffer of the parent dir.
 1399      */
 1400     if (buf->ia_ino != 1) {
 1401         nfs3_fh_build_parent_fh(&cs->fh, buf, &newfh);
 1402         goto xmit_res;
 1403     }
 1404 
 1405     if (gf_nfs_dvm_off(nfs_state(nfs3->nfsx)))
 1406         newfh = nfs3_fh_build_indexed_root_fh(nfs3->exportslist, cs->vol);
 1407     else {
 1408         __nfs3_get_volume_id(nfs3, cs->vol, volumeid);
 1409         newfh = nfs3_fh_build_uuid_root_fh(volumeid, mountid);
 1410     }
 1411 
 1412 xmit_res:
 1413     nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_LOOKUP, status,
 1414                        op_errno, &newfh, cs->resolvedloc.path);
 1415     nfs3_lookup_reply(cs->req, status, &newfh, buf, postparent);
 1416     nfs3_call_state_wipe(cs);
 1417 
 1418     return 0;
 1419 }
 1420 
 1421 int
 1422 nfs3_lookup_parentdir_resume(void *carg)
 1423 {
 1424     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1425     int ret = -EFAULT;
 1426     nfs_user_t nfu = {
 1427         0,
 1428     };
 1429     nfs3_call_state_t *cs = NULL;
 1430     inode_t *parent = NULL;
 1431 
 1432     if (!carg) {
 1433         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 1434                "Invalid argument, carg value NULL");
 1435         return EINVAL;
 1436     }
 1437 
 1438     cs = (nfs3_call_state_t *)carg;
 1439     nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
 1440     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 1441 
 1442     /* At this point now, the loc in cs is for the directory file handle
 1443      * sent by the client. This loc needs to be transformed into a loc that
 1444      * represents the parent dir of cs->resolvedloc.inode.
 1445      *
 1446      * EXCEPT in the case where the .. is a parent of the root directory.
 1447      * In this case we'll be returning the file handle and attributes of the
 1448      * root itself.
 1449      */
 1450     nfs_request_user_init(&nfu, cs->req);
 1451 
 1452     /* Save the file handle from the LOOKUP request. We'll use this to
 1453      * build the file handle of the parent directory in case the parent is
 1454      * not root dir.
 1455      */
 1456     cs->fh = cs->resolvefh;
 1457 
 1458     /* If fh is that of the root, the resolvedloc will already contain
 1459      * the loc for root. After that, we'll send lookup for the root dir
 1460      * itself since we cannot send the lookup on the parent of root.
 1461      *
 1462      * For all other cases, we'll send the lookup on the parent of the
 1463      * given directory file handle.
 1464      */
 1465     if (!nfs3_fh_is_root_fh(&cs->fh)) {
 1466         parent = inode_ref(cs->resolvedloc.parent);
 1467         nfs_loc_wipe(&cs->resolvedloc);
 1468         ret = nfs_inode_loc_fill(parent, &cs->resolvedloc, NFS_RESOLVE_CREATE);
 1469 
 1470         if (ret < 0) {
 1471             gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_INODE_LOC_FILL_ERROR,
 1472                    "nfs_inode_loc_fill"
 1473                    " error");
 1474             goto errtostat;
 1475         }
 1476     }
 1477 
 1478     ret = nfs_lookup(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 1479                      nfs3svc_lookup_parentdir_cbk, cs);
 1480 errtostat:
 1481     if (ret < 0)
 1482         stat = nfs3_errno_to_nfsstat3(-ret);
 1483 
 1484 nfs3err:
 1485     if (ret < 0) {
 1486         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_LOOKUP, stat,
 1487                             -ret, cs->resolvedloc.path);
 1488         nfs3_lookup_reply(cs->req, stat, NULL, NULL, NULL);
 1489         nfs3_call_state_wipe(cs);
 1490     }
 1491 
 1492     if (parent)
 1493         inode_unref(parent);
 1494 
 1495     return ret;
 1496 }
 1497 
 1498 int
 1499 nfs3_lookup_resume(void *carg)
 1500 {
 1501     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1502     int ret = -EFAULT;
 1503     nfs_user_t nfu = {
 1504         0,
 1505     };
 1506     nfs3_call_state_t *cs = NULL;
 1507     struct nfs3_fh newfh = {
 1508         {0},
 1509     };
 1510 
 1511     if (!carg) {
 1512         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 1513                "Invalid argument, carg value NULL");
 1514         return EINVAL;
 1515     }
 1516 
 1517     cs = (nfs3_call_state_t *)carg;
 1518     nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
 1519     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 1520     cs->parent = cs->resolvefh;
 1521 
 1522     if (cs->hardresolved) {
 1523         stat = NFS3_OK;
 1524         nfs3_fh_build_child_fh(&cs->parent, &cs->stbuf, &newfh);
 1525         goto nfs3err;
 1526     }
 1527 
 1528     nfs_request_user_init(&nfu, cs->req);
 1529     ret = nfs_lookup(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 1530                      nfs3svc_lookup_cbk, cs);
 1531     if (ret < 0)
 1532         stat = nfs3_errno_to_nfsstat3(-ret);
 1533 
 1534 nfs3err:
 1535     if (ret < 0) {
 1536         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_LOOKUP, stat,
 1537                             -ret, cs->resolvedloc.path);
 1538         nfs3_lookup_reply(cs->req, stat, &newfh, &cs->stbuf, &cs->postparent);
 1539         nfs3_call_state_wipe(cs);
 1540     }
 1541 
 1542     return ret;
 1543 }
 1544 
 1545 int
 1546 nfs3_lookup(rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name)
 1547 {
 1548     xlator_t *vol = NULL;
 1549     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1550     int ret = -EFAULT;
 1551     struct nfs3_state *nfs3 = NULL;
 1552     nfs3_call_state_t *cs = NULL;
 1553 
 1554     GF_VALIDATE_OR_GOTO(GF_NFS3, req, out);
 1555     GF_VALIDATE_OR_GOTO(GF_NFS3, fh, out);
 1556     GF_VALIDATE_OR_GOTO(GF_NFS3, name, out);
 1557 
 1558     nfs3_log_fh_entry_call(rpcsvc_request_xid(req), "LOOKUP", fh, name);
 1559     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 1560     if (nfs3_solaris_zerolen_fh(fh, fhlen)) {
 1561         ret = nfs3_funge_webnfs_zerolen_fh(req, nfs3, fh, name);
 1562         if (ret < 0)
 1563             goto nfs3err;
 1564 
 1565         /* this fh means we're doing a mount, name is no more useful */
 1566         name = NULL;
 1567     } else
 1568         nfs3_validate_gluster_fh(fh, stat, nfs3err);
 1569     nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
 1570     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 1571     nfs3_volume_started_check(nfs3, vol, ret, out);
 1572     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 1573 
 1574     cs->lookuptype = GF_NFS3_REVALIDATE;
 1575     ret = nfs3_fh_resolve_and_resume(cs, fh, name, nfs3_lookup_resume);
 1576 
 1577     if (ret < 0) {
 1578         gf_msg(GF_NFS, GF_LOG_ERROR, -ret, NFS_MSG_HARD_RESOLVE_FAIL,
 1579                "failed to start hard resolve");
 1580     }
 1581 
 1582 nfs3err:
 1583     if (ret < 0) {
 1584         stat = nfs3_errno_to_nfsstat3(-ret);
 1585         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_LOOKUP, stat, -ret,
 1586                             cs ? cs->resolvedloc.path : NULL);
 1587         nfs3_lookup_reply(req, stat, NULL, NULL, NULL);
 1588         if (cs)
 1589             nfs3_call_state_wipe(cs);
 1590         /* Ret must be 0 after this so that the caller does not
 1591          * also send an RPC reply.
 1592          */
 1593         ret = 0;
 1594     }
 1595 out:
 1596     return ret;
 1597 }
 1598 
 1599 int
 1600 nfs3svc_lookup(rpcsvc_request_t *req)
 1601 {
 1602     char name[NFS_PATH_MAX];
 1603     struct nfs3_fh fh = {
 1604         {0},
 1605     };
 1606     lookup3args args;
 1607     int ret = RPCSVC_ACTOR_ERROR;
 1608 
 1609     GF_VALIDATE_OR_GOTO(GF_NFS, req, rpcerr);
 1610 
 1611     nfs3_prep_lookup3args(&args, &fh, name);
 1612     if (xdr_to_lookup3args(req->msg[0], &args) <= 0) {
 1613         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 1614                "Error decoding args");
 1615         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 1616         goto rpcerr;
 1617     }
 1618 
 1619     ret = nfs3_lookup(req, &fh, args.what.dir.data.data_len, name);
 1620     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 1621         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_LOOKUP_PROC_FAIL,
 1622                "LOOKUP procedure failed");
 1623         rpcsvc_request_seterr(req, SYSTEM_ERR);
 1624         ret = RPCSVC_ACTOR_ERROR;
 1625     }
 1626 
 1627 rpcerr:
 1628     return ret;
 1629 }
 1630 
 1631 int
 1632 nfs3_access_reply(rpcsvc_request_t *req, nfsstat3 status, int32_t accbits,
 1633                   int32_t reqaccbits)
 1634 {
 1635     access3res res;
 1636 
 1637     nfs3_fill_access3res(&res, status, accbits, reqaccbits);
 1638     nfs3svc_submit_reply(req, &res, (nfs3_serializer)xdr_serialize_access3res);
 1639     return 0;
 1640 }
 1641 
 1642 int32_t
 1643 nfs3svc_access_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1644                    int32_t op_ret, int32_t op_errno, dict_t *xdata)
 1645 {
 1646     nfsstat3 status = NFS3_OK;
 1647     nfs3_call_state_t *cs = NULL;
 1648 
 1649     cs = frame->local;
 1650 
 1651     if (op_ret == -1) {
 1652         status = nfs3_cbk_errno_status(op_ret, op_errno);
 1653     }
 1654 
 1655     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_ACCESS, status,
 1656                         op_errno, cs->resolvedloc.path);
 1657     nfs3_access_reply(cs->req, status, op_errno, cs->accessbits);
 1658     nfs3_call_state_wipe(cs);
 1659 
 1660     return 0;
 1661 }
 1662 
 1663 int
 1664 nfs3_access_resume(void *carg)
 1665 {
 1666     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1667     int ret = -EFAULT;
 1668     nfs_user_t nfu = {
 1669         0,
 1670     };
 1671     nfs3_call_state_t *cs = NULL;
 1672 
 1673     if (!carg) {
 1674         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 1675                "Invalid argument, carg value NULL");
 1676         return EINVAL;
 1677     }
 1678 
 1679     cs = (nfs3_call_state_t *)carg;
 1680 
 1681     /* Additional checks on the NFS file handle
 1682      * go here. The path for an NFS ACCESS call
 1683      * goes like this:
 1684      * nfs3_access -> nfs3_fh_resolve_and_resume -> nfs3_resolve_resume ->
 1685      * nfs3_access_resume -> <macro/function performs check on FH> ->
 1686      * <continue or return from function based on check.> ('goto nfs3err'
 1687      * terminates this function and writes the appropriate response to the
 1688      * client). It is important that you do NOT stick any sort of check
 1689      * on the file handle outside of the nfs3_##OP_resume functions.
 1690      */
 1691     nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
 1692     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 1693     cs->fh = cs->resolvefh;
 1694     nfs_request_user_init(&nfu, cs->req);
 1695     ret = nfs_access(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, cs->accessbits,
 1696                      nfs3svc_access_cbk, cs);
 1697     if (ret < 0)
 1698         stat = nfs3_errno_to_nfsstat3(-ret);
 1699 
 1700 nfs3err:
 1701     if (ret < 0) {
 1702         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_ACCESS, stat,
 1703                             -ret, cs->resolvedloc.path);
 1704         nfs3_access_reply(cs->req, stat, 0, 0);
 1705         nfs3_call_state_wipe(cs);
 1706         ret = 0;
 1707     }
 1708 
 1709     return ret;
 1710 }
 1711 
 1712 int
 1713 nfs3_access(rpcsvc_request_t *req, struct nfs3_fh *fh, uint32_t accbits)
 1714 {
 1715     xlator_t *vol = NULL;
 1716     struct nfs3_state *nfs3 = NULL;
 1717     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1718     int ret = -EFAULT;
 1719     nfs3_call_state_t *cs = NULL;
 1720 
 1721     GF_VALIDATE_OR_GOTO(GF_NFS, req, out);
 1722     GF_VALIDATE_OR_GOTO(GF_NFS, fh, out);
 1723     nfs3_log_common_call(rpcsvc_request_xid(req), "ACCESS", fh);
 1724     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 1725     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 1726     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 1727     nfs3_volume_started_check(nfs3, vol, ret, out);
 1728     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 1729     cs->accessbits = accbits;
 1730 
 1731     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_access_resume);
 1732     if (ret < 0)
 1733         stat = nfs3_errno_to_nfsstat3(-ret);
 1734 
 1735 nfs3err:
 1736     if (ret < 0) {
 1737         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_ACCESS, stat, -ret,
 1738                             cs ? cs->resolvedloc.path : NULL);
 1739         nfs3_access_reply(req, stat, 0, 0);
 1740         nfs3_call_state_wipe(cs);
 1741         ret = 0;
 1742     }
 1743 out:
 1744     return ret;
 1745 }
 1746 
 1747 int
 1748 nfs3svc_access(rpcsvc_request_t *req)
 1749 {
 1750     struct nfs3_fh fh = {
 1751         {0},
 1752     };
 1753     access3args args;
 1754     int ret = RPCSVC_ACTOR_ERROR;
 1755 
 1756     if (!req)
 1757         return ret;
 1758 
 1759     nfs3_prep_access3args(&args, &fh);
 1760     if (xdr_to_access3args(req->msg[0], &args) <= 0) {
 1761         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 1762                "Error decoding args");
 1763         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 1764         goto rpcerr;
 1765     }
 1766 
 1767     ret = nfs3_access(req, &fh, args.access);
 1768     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 1769         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_ACCESS_PROC_FAIL,
 1770                "ACCESS procedure failed");
 1771         rpcsvc_request_seterr(req, SYSTEM_ERR);
 1772         ret = RPCSVC_ACTOR_ERROR;
 1773     }
 1774 
 1775 rpcerr:
 1776     return ret;
 1777 }
 1778 
 1779 int
 1780 nfs3_readlink_reply(rpcsvc_request_t *req, nfsstat3 stat, char *path,
 1781                     struct iatt *buf)
 1782 {
 1783     readlink3res res = {
 1784         0,
 1785     };
 1786     uint64_t deviceid = 0;
 1787 
 1788     deviceid = nfs3_request_xlator_deviceid(req);
 1789     nfs3_fill_readlink3res(&res, stat, path, buf, deviceid);
 1790     nfs3svc_submit_reply(req, (void *)&res,
 1791                          (nfs3_serializer)xdr_serialize_readlink3res);
 1792 
 1793     return 0;
 1794 }
 1795 
 1796 int32_t
 1797 nfs3svc_readlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1798                      int32_t op_ret, int32_t op_errno, const char *path,
 1799                      struct iatt *buf, dict_t *xdata)
 1800 {
 1801     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1802     nfs3_call_state_t *cs = NULL;
 1803 
 1804     cs = frame->local;
 1805     if (op_ret == -1) {
 1806         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 1807         goto nfs3err;
 1808     }
 1809 
 1810     stat = NFS3_OK;
 1811 
 1812 nfs3err:
 1813     nfs3_log_readlink_res(rpcsvc_request_xid(cs->req), stat, op_errno,
 1814                           (char *)path, cs->resolvedloc.path);
 1815     nfs3_readlink_reply(cs->req, stat, (char *)path, buf);
 1816     nfs3_call_state_wipe(cs);
 1817 
 1818     return 0;
 1819 }
 1820 
 1821 int
 1822 nfs3_readlink_resume(void *carg)
 1823 {
 1824     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1825     int ret = -EFAULT;
 1826     nfs3_call_state_t *cs = NULL;
 1827     nfs_user_t nfu = {
 1828         0,
 1829     };
 1830 
 1831     if (!carg)
 1832         return ret;
 1833 
 1834     cs = (nfs3_call_state_t *)carg;
 1835     nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
 1836     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 1837     nfs_request_user_init(&nfu, cs->req);
 1838     ret = nfs_readlink(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 1839                        nfs3svc_readlink_cbk, cs);
 1840     if (ret < 0)
 1841         stat = nfs3_errno_to_nfsstat3(-ret);
 1842 
 1843 nfs3err:
 1844     if (ret < 0) {
 1845         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_READLINK, stat,
 1846                             -ret, cs->resolvedloc.path);
 1847         nfs3_readlink_reply(cs->req, stat, NULL, NULL);
 1848         nfs3_call_state_wipe(cs);
 1849     }
 1850 
 1851     return ret;
 1852 }
 1853 
 1854 int
 1855 nfs3_readlink(rpcsvc_request_t *req, struct nfs3_fh *fh)
 1856 {
 1857     xlator_t *vol = NULL;
 1858     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1859     int ret = -EFAULT;
 1860     struct nfs3_state *nfs3 = NULL;
 1861     nfs3_call_state_t *cs = NULL;
 1862 
 1863     if ((!req) || (!fh)) {
 1864         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 1865                "Bad arguments");
 1866         return -1;
 1867     }
 1868 
 1869     nfs3_log_common_call(rpcsvc_request_xid(req), "READLINK", fh);
 1870     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 1871     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 1872     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 1873     nfs3_volume_started_check(nfs3, vol, ret, out);
 1874     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 1875 
 1876     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_readlink_resume);
 1877     if (ret < 0)
 1878         stat = nfs3_errno_to_nfsstat3(-ret);
 1879 
 1880 nfs3err:
 1881     if (ret < 0) {
 1882         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_READLINK, stat, -ret,
 1883                             cs ? cs->resolvedloc.path : NULL);
 1884         nfs3_readlink_reply(req, stat, NULL, NULL);
 1885         nfs3_call_state_wipe(cs);
 1886         /* Ret must be 0 after this so that the caller does not
 1887          * also send an RPC reply.
 1888          */
 1889         ret = 0;
 1890     }
 1891 out:
 1892     return ret;
 1893 }
 1894 
 1895 int
 1896 nfs3svc_readlink(rpcsvc_request_t *req)
 1897 {
 1898     struct nfs3_fh fh = {
 1899         {0},
 1900     };
 1901     readlink3args args;
 1902     int ret = RPCSVC_ACTOR_ERROR;
 1903 
 1904     if (!req)
 1905         return ret;
 1906 
 1907     nfs3_prep_readlink3args(&args, &fh);
 1908     if (xdr_to_readlink3args(req->msg[0], &args) <= 0) {
 1909         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 1910                "Error decoding args");
 1911         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 1912         goto rpcerr;
 1913     }
 1914 
 1915     ret = nfs3_readlink(req, &fh);
 1916     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 1917         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_READLINK_PROC_FAIL,
 1918                "READLINK procedure failed");
 1919         rpcsvc_request_seterr(req, SYSTEM_ERR);
 1920         ret = RPCSVC_ACTOR_ERROR;
 1921     }
 1922 
 1923 rpcerr:
 1924     return ret;
 1925 }
 1926 
 1927 int
 1928 nfs3_read_reply(rpcsvc_request_t *req, nfsstat3 stat, count3 count,
 1929                 struct iovec *vec, int vcount, struct iobref *iobref,
 1930                 struct iatt *poststat, int is_eof)
 1931 {
 1932     read3res res = {
 1933         0,
 1934     };
 1935     uint64_t deviceid = 0;
 1936 
 1937     deviceid = nfs3_request_xlator_deviceid(req);
 1938     nfs3_fill_read3res(&res, stat, count, poststat, is_eof, deviceid);
 1939     if (stat == NFS3_OK) {
 1940         xdr_vector_round_up(vec, vcount, count);
 1941         /* iob can be zero if the file size was zero. If so, op_ret
 1942          * would be 0 and count = 0.
 1943          */
 1944 
 1945         if (count != 0) {
 1946             nfs3svc_submit_vector_reply(
 1947                 req, (void *)&res,
 1948                 (nfs3_serializer)xdr_serialize_read3res_nocopy, vec, vcount,
 1949                 iobref);
 1950         } else
 1951 
 1952             nfs3svc_submit_reply(
 1953                 req, (void *)&res,
 1954                 (nfs3_serializer)xdr_serialize_read3res_nocopy);
 1955     } else
 1956         nfs3svc_submit_reply(req, (void *)&res,
 1957                              (nfs3_serializer)xdr_serialize_read3res_nocopy);
 1958 
 1959     return 0;
 1960 }
 1961 
 1962 int32_t
 1963 nfs3svc_read_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 1964                  int32_t op_ret, int32_t op_errno, struct iovec *vector,
 1965                  int32_t count, struct iatt *stbuf, struct iobref *iobref,
 1966                  dict_t *xdata)
 1967 {
 1968     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1969     int is_eof = 0;
 1970     nfs3_call_state_t *cs = NULL;
 1971 
 1972     cs = frame->local;
 1973     if (op_ret == -1) {
 1974         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 1975         goto err;
 1976     } else
 1977         stat = NFS3_OK;
 1978 
 1979     if (op_errno == ENOENT)
 1980         is_eof = 1;
 1981 
 1982 err:
 1983     nfs3_log_read_res(rpcsvc_request_xid(cs->req), stat, op_errno, op_ret,
 1984                       is_eof, vector, count, cs->resolvedloc.path);
 1985     nfs3_read_reply(cs->req, stat, op_ret, vector, count, iobref, stbuf,
 1986                     is_eof);
 1987     nfs3_call_state_wipe(cs);
 1988 
 1989     return 0;
 1990 }
 1991 
 1992 int
 1993 nfs3_read_fd_resume(void *carg)
 1994 {
 1995     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 1996     int ret = -EFAULT;
 1997     nfs_user_t nfu = {
 1998         0,
 1999     };
 2000     nfs3_call_state_t *cs = NULL;
 2001 
 2002     if (!carg)
 2003         return ret;
 2004 
 2005     cs = (nfs3_call_state_t *)carg;
 2006     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 2007     nfs_request_user_init(&nfu, cs->req);
 2008     ret = nfs_read(cs->nfsx, cs->vol, &nfu, cs->fd, cs->datacount,
 2009                    cs->dataoffset, nfs3svc_read_cbk, cs);
 2010     if (ret < 0)
 2011         stat = nfs3_errno_to_nfsstat3(-ret);
 2012 nfs3err:
 2013     if (ret < 0) {
 2014         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_READ, stat, -ret,
 2015                             cs->resolvedloc.path);
 2016         nfs3_read_reply(cs->req, stat, 0, NULL, 0, NULL, NULL, 0);
 2017         nfs3_call_state_wipe(cs);
 2018     }
 2019 
 2020     return ret;
 2021 }
 2022 
 2023 int
 2024 nfs3_read_resume(void *carg)
 2025 {
 2026     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2027     int ret = -EFAULT;
 2028     nfs3_call_state_t *cs = NULL;
 2029     fd_t *fd = NULL;
 2030 
 2031     if (!carg)
 2032         return ret;
 2033 
 2034     cs = (nfs3_call_state_t *)carg;
 2035     nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
 2036     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 2037     fd = fd_anonymous(cs->resolvedloc.inode);
 2038     if (!fd) {
 2039         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ANONYMOUS_FD_FAIL,
 2040                "Failed to create anonymous fd");
 2041         goto nfs3err;
 2042     }
 2043 
 2044     cs->fd = fd;
 2045     nfs3_read_fd_resume(cs);
 2046     ret = 0;
 2047 nfs3err:
 2048     if (ret < 0) {
 2049         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_READ, stat, -ret,
 2050                             cs->resolvedloc.path);
 2051         nfs3_read_reply(cs->req, stat, 0, NULL, 0, NULL, NULL, 0);
 2052         nfs3_call_state_wipe(cs);
 2053     }
 2054 
 2055     return ret;
 2056 }
 2057 
 2058 int
 2059 nfs3_read(rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
 2060           count3 count)
 2061 {
 2062     xlator_t *vol = NULL;
 2063     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2064     int ret = -EFAULT;
 2065     struct nfs3_state *nfs3 = NULL;
 2066     nfs3_call_state_t *cs = NULL;
 2067 
 2068     if ((!req) || (!fh)) {
 2069         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 2070                "Bad arguments");
 2071         return -1;
 2072     }
 2073 
 2074     nfs3_log_rw_call(rpcsvc_request_xid(req), "READ", fh, offset, count, -1);
 2075     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 2076     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 2077     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 2078     nfs3_volume_started_check(nfs3, vol, ret, out);
 2079     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 2080 
 2081     cs->datacount = count;
 2082     cs->dataoffset = offset;
 2083     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_read_resume);
 2084     if (ret < 0)
 2085         stat = nfs3_errno_to_nfsstat3(-ret);
 2086 
 2087 nfs3err:
 2088     if (ret < 0) {
 2089         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_READ, stat, -ret,
 2090                             cs ? cs->resolvedloc.path : NULL);
 2091         nfs3_read_reply(req, stat, 0, NULL, 0, NULL, NULL, 0);
 2092         nfs3_call_state_wipe(cs);
 2093         ret = 0;
 2094     }
 2095 out:
 2096     return ret;
 2097 }
 2098 
 2099 int
 2100 nfs3svc_read(rpcsvc_request_t *req)
 2101 {
 2102     struct nfs3_fh fh = {
 2103         {0},
 2104     };
 2105     read3args args;
 2106     int ret = RPCSVC_ACTOR_ERROR;
 2107 
 2108     if (!req)
 2109         return ret;
 2110 
 2111     nfs3_prep_read3args(&args, &fh);
 2112     if (xdr_to_read3args(req->msg[0], &args) <= 0) {
 2113         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 2114                "Error decoding args");
 2115         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 2116         goto rpcerr;
 2117     }
 2118 
 2119     ret = nfs3_read(req, &fh, args.offset, args.count);
 2120     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 2121         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_READ_FAIL,
 2122                "READ procedure failed");
 2123         rpcsvc_request_seterr(req, SYSTEM_ERR);
 2124         ret = RPCSVC_ACTOR_ERROR;
 2125     }
 2126 
 2127 rpcerr:
 2128     return ret;
 2129 }
 2130 
 2131 int
 2132 nfs3_write_reply(rpcsvc_request_t *req, nfsstat3 stat, count3 count,
 2133                  stable_how stable, uint64_t wverf, struct iatt *prestat,
 2134                  struct iatt *poststat)
 2135 {
 2136     write3res res = {
 2137         0,
 2138     };
 2139     uint64_t deviceid = 0;
 2140 
 2141     deviceid = nfs3_request_xlator_deviceid(req);
 2142     nfs3_fill_write3res(&res, stat, count, stable, wverf, prestat, poststat,
 2143                         deviceid);
 2144     nfs3svc_submit_reply(req, (void *)&res,
 2145                          (nfs3_serializer)xdr_serialize_write3res);
 2146 
 2147     return 0;
 2148 }
 2149 
 2150 int32_t
 2151 nfs3svc_write_fsync_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 2152                         int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
 2153                         struct iatt *postbuf, dict_t *xdata)
 2154 {
 2155     struct nfs3_state *nfs3 = NULL;
 2156     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2157     nfs3_call_state_t *cs = NULL;
 2158 
 2159     cs = frame->local;
 2160     nfs3 = rpcsvc_request_program_private(cs->req);
 2161 
 2162     if (op_ret == -1) {
 2163         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 2164     } else
 2165         stat = NFS3_OK;
 2166 
 2167     nfs3_log_write_res(rpcsvc_request_xid(cs->req), stat, op_errno,
 2168                        cs->maxcount, cs->writetype, nfs3->serverstart,
 2169                        cs->resolvedloc.path);
 2170     nfs3_write_reply(cs->req, stat, cs->maxcount, cs->writetype,
 2171                      nfs3->serverstart, &cs->stbuf, postbuf);
 2172     nfs3_call_state_wipe(cs);
 2173     return 0;
 2174 }
 2175 
 2176 /*
 2177  * Before going into the write reply logic, here is a matrix that shows the
 2178  * requirements for a write reply as given by RFC1813.
 2179  *
 2180  * Requested Write Type ||      Possible Returns
 2181  * ==============================================
 2182  * FILE_SYNC            ||      FILE_SYNC
 2183  * DATA_SYNC            ||      DATA_SYNC or FILE_SYNC
 2184  * UNSTABLE             ||      DATA_SYNC or FILE_SYNC or UNSTABLE
 2185  *
 2186  * Write types other than UNSTABLE are together called STABLE.
 2187  * RS - Return Stable
 2188  * RU - Return Unstable
 2189  * WS - Write Stable
 2190  * WU - Write Unstable
 2191  *
 2192  *+============================================+
 2193  *| Vol Opts -> || trusted-write| trusted-sync |
 2194  *| Write Type  ||              |              |
 2195  *|-------------||--------------|--------------|
 2196  *| STABLE      ||      WS      |   WU         |
 2197  *|             ||      RS      |   RS         |
 2198  *|-------------||--------------|--------------|
 2199  *| UNSTABLE    ||      WU      |   WU         |
 2200  *|             ||      RS      |   RS         |
 2201  *|-------------||--------------|--------------|
 2202  *| COMMIT      ||    fsync     | getattr      |
 2203  *+============================================+
 2204  *
 2205  *
 2206  */
 2207 int32_t
 2208 nfs3svc_write_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 2209                   int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
 2210                   struct iatt *postbuf, dict_t *xdata)
 2211 {
 2212     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2213     nfs3_call_state_t *cs = NULL;
 2214     struct nfs3_state *nfs3 = NULL;
 2215 
 2216     cs = frame->local;
 2217     nfs3 = rpcsvc_request_program_private(cs->req);
 2218     if (op_ret == -1) {
 2219         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 2220         goto err;
 2221     }
 2222 
 2223     stat = NFS3_OK;
 2224     cs->maxcount = op_ret;
 2225 
 2226 err:
 2227     nfs3_log_write_res(rpcsvc_request_xid(cs->req), stat, op_errno,
 2228                        cs->maxcount, cs->writetype, nfs3->serverstart,
 2229                        cs->resolvedloc.path);
 2230     nfs3_write_reply(cs->req, stat, cs->maxcount, cs->writetype,
 2231                      nfs3->serverstart, prebuf, postbuf);
 2232     nfs3_call_state_wipe(cs);
 2233 
 2234     return 0;
 2235 }
 2236 
 2237 int
 2238 __nfs3_write_resume(nfs3_call_state_t *cs)
 2239 {
 2240     int ret = -EFAULT;
 2241     nfs_user_t nfu = {
 2242         0,
 2243     };
 2244 
 2245     if (!cs)
 2246         return ret;
 2247 
 2248     nfs_request_user_init(&nfu, cs->req);
 2249     /* It is possible that the RPC record contains more bytes than
 2250      * than the size of write requested in this request. This means,
 2251      * that in the RPC message buffer, there could be more bytes
 2252      * beyind the @count bytes. Since @payload is referring to the write
 2253      * data directly inside the RPC request buffer(..since we performed a
 2254      * no-copy deXDRing..), we might end up writing more data than
 2255      * requested, because till now payload.iov_len accounts for all the
 2256      * bytes not just the write request bytes. These extra bytes are present
 2257      * as a requirement of the XDR encoding to round up the all string and
 2258      * opaque data buffers to multiples of 4 bytes.
 2259      */
 2260     cs->datavec.iov_len = cs->datacount;
 2261     ret = nfs_write(cs->nfsx, cs->vol, &nfu, cs->fd, cs->iobref, &cs->datavec,
 2262                     1, cs->dataoffset, nfs3svc_write_cbk, cs);
 2263 
 2264     return ret;
 2265 }
 2266 
 2267 int
 2268 nfs3_write_resume(void *carg)
 2269 {
 2270     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2271     int ret = -EFAULT;
 2272     nfs3_call_state_t *cs = NULL;
 2273     fd_t *fd = NULL;
 2274 
 2275     if (!carg)
 2276         return ret;
 2277 
 2278     cs = (nfs3_call_state_t *)carg;
 2279     nfs3_check_fh_auth_status(cs, stat, _gf_true, nfs3err);
 2280     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 2281     fd = fd_anonymous(cs->resolvedloc.inode);
 2282     if (!fd) {
 2283         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ANONYMOUS_FD_FAIL,
 2284                "Failed to create anonymous fd");
 2285         goto nfs3err;
 2286     }
 2287 
 2288     cs->fd = fd; /* Gets unrefd when the call state is wiped. */
 2289 
 2290     ret = __nfs3_write_resume(cs);
 2291     if (ret < 0)
 2292         stat = nfs3_errno_to_nfsstat3(-ret);
 2293 nfs3err:
 2294     if (ret < 0) {
 2295         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_WRITE, stat, -ret,
 2296                             cs->resolvedloc.path);
 2297         nfs3_write_reply(cs->req, stat, 0, cs->writetype, 0, NULL, NULL);
 2298         nfs3_call_state_wipe(cs);
 2299     }
 2300     return ret;
 2301 }
 2302 
 2303 int
 2304 nfs3_write(rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
 2305            count3 count, stable_how stable, struct iovec payload,
 2306            struct iobref *iobref)
 2307 {
 2308     xlator_t *vol = NULL;
 2309     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2310     int ret = -EFAULT;
 2311     struct nfs3_state *nfs3 = NULL;
 2312     nfs3_call_state_t *cs = NULL;
 2313 
 2314     if ((!req) || (!fh) || (!payload.iov_base)) {
 2315         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 2316                "Bad arguments");
 2317         return -1;
 2318     }
 2319 
 2320     nfs3_log_rw_call(rpcsvc_request_xid(req), "WRITE", fh, offset, count,
 2321                      stable);
 2322     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 2323     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 2324     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 2325     nfs3_volume_started_check(nfs3, vol, ret, out);
 2326     nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
 2327     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 2328     cs->datacount = count;
 2329     cs->dataoffset = offset;
 2330     cs->writetype = stable;
 2331     cs->iobref = iobref;
 2332     cs->datavec = payload;
 2333 
 2334     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_write_resume);
 2335     if (ret < 0)
 2336         stat = nfs3_errno_to_nfsstat3(-ret);
 2337 
 2338 nfs3err:
 2339     if (ret < 0) {
 2340         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_WRITE, stat, -ret,
 2341                             cs ? cs->resolvedloc.path : NULL);
 2342         nfs3_write_reply(req, stat, 0, stable, 0, NULL, NULL);
 2343         nfs3_call_state_wipe(cs);
 2344         ret = 0;
 2345     }
 2346 out:
 2347     return ret;
 2348 }
 2349 
 2350 #define NFS3_VECWRITE_READFHLEN 1
 2351 #define NFS3_VECWRITE_READFH 2
 2352 #define NFS3_VECWRITE_READREST 3
 2353 
 2354 #define NFS3_WRITE_POSTFH_SIZE 20
 2355 
 2356 int
 2357 nfs3svc_write_vecsizer(int state, ssize_t *readsize, char *base_addr,
 2358                        char *curr_addr)
 2359 {
 2360     int ret = 0;
 2361     uint32_t fhlen = 0;
 2362     uint32_t fhlen_n = 0;
 2363 
 2364     if (state == 0) {
 2365         ret = NFS3_VECWRITE_READFHLEN;
 2366         *readsize = 4;
 2367     } else if (state == NFS3_VECWRITE_READFHLEN) {
 2368         fhlen_n = *(uint32_t *)(curr_addr - 4);
 2369         fhlen = ntohl(fhlen_n);
 2370         *readsize = xdr_length_round_up(fhlen, NFS3_FHSIZE);
 2371         ret = NFS3_VECWRITE_READFH;
 2372     } else if (state == NFS3_VECWRITE_READFH) {
 2373         *readsize = NFS3_WRITE_POSTFH_SIZE;
 2374         ret = NFS3_VECWRITE_READREST;
 2375     } else if (state == NFS3_VECWRITE_READREST) {
 2376         ret = 0;
 2377         *readsize = 0;
 2378     } else
 2379         gf_msg("nfs", GF_LOG_ERROR, 0, NFS_MSG_STATE_WRONG, "state wrong");
 2380 
 2381     return ret;
 2382 }
 2383 
 2384 int
 2385 nfs3svc_write(rpcsvc_request_t *req)
 2386 {
 2387     struct nfs3_fh fh = {
 2388         {0},
 2389     };
 2390     write3args args;
 2391     int ret = RPCSVC_ACTOR_ERROR;
 2392 
 2393     if (!req)
 2394         return ret;
 2395     nfs3_prep_write3args(&args, &fh);
 2396     if (xdr_to_write3args(req->msg[0], &args) <= 0) {
 2397         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 2398                "Error decoding args");
 2399         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 2400         goto rpcerr;
 2401     }
 2402 
 2403     /* To ensure that the iobuf for the current record does not
 2404      * get returned to the iobpool, we need to keep a reference for
 2405      * ourselves because the RPC call handler who called us will unref its
 2406      * own ref of the record's iobuf when it is done handling the request.
 2407      */
 2408 
 2409     ret = nfs3_write(req, &fh, args.offset, args.count, args.stable,
 2410                      req->msg[1], rpcsvc_request_iobref_ref(req));
 2411     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 2412         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_WRITE_FAIL,
 2413                "WRITE procedure failed");
 2414         rpcsvc_request_seterr(req, SYSTEM_ERR);
 2415         ret = RPCSVC_ACTOR_ERROR;
 2416     }
 2417 
 2418 rpcerr:
 2419     return ret;
 2420 }
 2421 
 2422 int
 2423 nfs3_create_reply(rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *newfh,
 2424                   struct iatt *newbuf, struct iatt *preparent,
 2425                   struct iatt *postparent)
 2426 {
 2427     create3res res = {
 2428         0,
 2429     };
 2430     uint64_t deviceid = 0;
 2431 
 2432     deviceid = nfs3_request_xlator_deviceid(req);
 2433     nfs3_fill_create3res(&res, stat, newfh, newbuf, preparent, postparent,
 2434                          deviceid);
 2435     nfs3svc_submit_reply(req, (void *)&res,
 2436                          (nfs3_serializer)xdr_serialize_create3res);
 2437     return 0;
 2438 }
 2439 
 2440 int32_t
 2441 nfs3svc_create_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 2442                            int32_t op_ret, int32_t op_errno, struct iatt *preop,
 2443                            struct iatt *postop, dict_t *xdata)
 2444 {
 2445     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2446     nfs3_call_state_t *cs = NULL;
 2447 
 2448     cs = frame->local;
 2449     if (op_ret == -1) {
 2450         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 2451         goto nfs3err;
 2452     }
 2453 
 2454     stat = NFS3_OK;
 2455 nfs3err:
 2456     nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_CREATE, stat, op_errno,
 2457                        &cs->fh, cs->resolvedloc.path);
 2458     nfs3_create_reply(cs->req, stat, &cs->fh, postop, &cs->preparent,
 2459                       &cs->postparent);
 2460     nfs3_call_state_wipe(cs);
 2461 
 2462     return 0;
 2463 }
 2464 
 2465 int32_t
 2466 nfs3svc_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 2467                    int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode,
 2468                    struct iatt *buf, struct iatt *preparent,
 2469                    struct iatt *postparent, dict_t *xdata)
 2470 {
 2471     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2472     int ret = -EFAULT;
 2473     nfs_user_t nfu = {
 2474         0,
 2475     };
 2476     nfs3_call_state_t *cs = NULL;
 2477     inode_t *oldinode = NULL;
 2478 
 2479     cs = frame->local;
 2480     if (op_ret == -1) {
 2481         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 2482         goto nfs3err;
 2483     }
 2484 
 2485     nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
 2486     oldinode = inode_link(inode, cs->resolvedloc.parent, cs->resolvedloc.name,
 2487                           buf);
 2488 
 2489     /* Means no attributes were required to be set. */
 2490     if (!cs->setattr_valid) {
 2491         stat = NFS3_OK;
 2492         ret = -1;
 2493         goto nfs3err;
 2494     }
 2495 
 2496     cs->preparent = *preparent;
 2497     cs->postparent = *postparent;
 2498     nfs_request_user_init(&nfu, cs->req);
 2499     gf_uuid_copy(cs->resolvedloc.gfid, oldinode->gfid);
 2500     ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->stbuf,
 2501                       cs->setattr_valid, nfs3svc_create_setattr_cbk, cs);
 2502     if (ret < 0)
 2503         stat = nfs3_errno_to_nfsstat3(-ret);
 2504 
 2505 nfs3err:
 2506     if (oldinode) {
 2507         inode_lookup(oldinode);
 2508         inode_unref(oldinode);
 2509     }
 2510 
 2511     if (ret < 0) {
 2512         nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_CREATE, stat,
 2513                            op_errno, &cs->fh, cs->resolvedloc.path);
 2514         nfs3_create_reply(cs->req, stat, &cs->fh, buf, preparent, postparent);
 2515         nfs3_call_state_wipe(cs);
 2516     }
 2517 
 2518     return 0;
 2519 }
 2520 
 2521 int
 2522 nfs3_create_common(nfs3_call_state_t *cs)
 2523 {
 2524     int ret = -EFAULT;
 2525     int flags = 0;
 2526     nfs_user_t nfu = {
 2527         0,
 2528     };
 2529     uid_t uid = 0;
 2530     gid_t gid = 0;
 2531 
 2532     if (!cs)
 2533         return ret;
 2534 
 2535     if (cs->createmode == GUARDED)
 2536         flags = (O_RDWR | O_EXCL);
 2537     else
 2538         flags = O_RDWR;
 2539 
 2540     if (gf_attr_uid_set(cs->setattr_valid)) {
 2541         uid = cs->stbuf.ia_uid;
 2542         cs->setattr_valid &= ~GF_SET_ATTR_UID;
 2543     } else
 2544         uid = rpcsvc_request_uid(cs->req);
 2545 
 2546     if (gf_attr_gid_set(cs->setattr_valid)) {
 2547         gid = cs->stbuf.ia_gid;
 2548         cs->setattr_valid &= ~GF_SET_ATTR_GID;
 2549     } else
 2550         gid = rpcsvc_request_gid(cs->req);
 2551 
 2552     nfs_request_primary_user_init(&nfu, cs->req, uid, gid);
 2553     /* We can avoid sending the setattr call later if only the mode is
 2554      * required to be set. This is possible because the create fop allows
 2555      * us to specify a mode arg.
 2556      */
 2557     if (cs->setattr_valid & GF_SET_ATTR_MODE) {
 2558         cs->setattr_valid &= ~GF_SET_ATTR_MODE;
 2559         ret = nfs_create(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, flags,
 2560                          cs->mode, nfs3svc_create_cbk, cs);
 2561     } else
 2562         ret = nfs_create(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, flags,
 2563                          NFS_DEFAULT_CREATE_MODE, nfs3svc_create_cbk, cs);
 2564 
 2565     return ret;
 2566 }
 2567 
 2568 int32_t
 2569 nfs3svc_create_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 2570                         int32_t op_ret, int32_t op_errno, struct iatt *buf,
 2571                         dict_t *xdata)
 2572 {
 2573     int ret = -EFAULT;
 2574     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2575     nfs_user_t nfu = {
 2576         0,
 2577     };
 2578     nfs3_call_state_t *cs = NULL;
 2579 
 2580     cs = frame->local;
 2581     nfs_request_user_init(&nfu, cs->req);
 2582     if (op_ret == -1) {
 2583         ret = -op_errno;
 2584         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 2585         goto nfs3err;
 2586     }
 2587 
 2588     if ((cs->stbuf.ia_mtime == buf->ia_mtime) &&
 2589         (cs->stbuf.ia_atime == buf->ia_atime)) {
 2590         gf_msg_debug(GF_NFS3, 0,
 2591                      "Create req retransmitted verf %" PRId64 " %" PRId64,
 2592                      cs->stbuf.ia_mtime, cs->stbuf.ia_atime);
 2593         stat = NFS3_OK;
 2594         nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
 2595     } else {
 2596         gf_msg_debug(GF_NFS3, 0,
 2597                      "File already exist new_verf %" PRId64 " %" PRId64
 2598                      "old_verf %" PRId64 " %" PRId64,
 2599                      cs->stbuf.ia_mtime, cs->stbuf.ia_atime, buf->ia_mtime,
 2600                      buf->ia_atime);
 2601         stat = NFS3ERR_EXIST;
 2602     }
 2603 
 2604 nfs3err:
 2605     if (ret < 0) {
 2606         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_CREATE, stat,
 2607                             op_errno, cs->resolvedloc.path);
 2608         nfs3_create_reply(cs->req, stat, &cs->fh, buf, NULL, NULL);
 2609         nfs3_call_state_wipe(cs);
 2610     }
 2611 
 2612     return 0;
 2613 }
 2614 
 2615 int
 2616 nfs3_create_exclusive(nfs3_call_state_t *cs)
 2617 {
 2618     int ret = -EFAULT;
 2619     nfs_user_t nfu = {
 2620         0,
 2621     };
 2622 
 2623     if (!cs)
 2624         return ret;
 2625 
 2626     /* Storing verifier as a mtime and atime attribute, to store it
 2627      * in stable storage */
 2628     memcpy(&cs->stbuf.ia_atime, &cs->cookieverf, sizeof(cs->stbuf.ia_atime));
 2629     memcpy(&cs->stbuf.ia_mtime,
 2630            ((char *)&cs->cookieverf) + sizeof(cs->stbuf.ia_atime),
 2631            sizeof(cs->stbuf.ia_mtime));
 2632     cs->setattr_valid |= GF_SET_ATTR_ATIME;
 2633     cs->setattr_valid |= GF_SET_ATTR_MTIME;
 2634     nfs_request_user_init(&nfu, cs->req);
 2635 
 2636     /* If the file already existed we need to get that attributes so we can
 2637      * compare and check whether a previous create operation was
 2638      * interrupted due to server failure or dropped packets.
 2639      */
 2640     if ((cs->resolve_ret == 0) ||
 2641         ((cs->resolve_ret == -1) && (cs->resolve_errno != ENOENT))) {
 2642         ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 2643                        nfs3svc_create_stat_cbk, cs);
 2644         goto nfs3err;
 2645     }
 2646 
 2647     ret = nfs3_create_common(cs);
 2648 nfs3err:
 2649     return ret;
 2650 }
 2651 
 2652 int
 2653 nfs3_create_resume(void *carg)
 2654 {
 2655     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2656     int ret = -EFAULT;
 2657     nfs3_call_state_t *cs = NULL;
 2658 
 2659     if (!carg)
 2660         return ret;
 2661 
 2662     cs = (nfs3_call_state_t *)carg;
 2663     nfs3_check_fh_auth_status(cs, stat, _gf_true, nfs3err);
 2664     nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
 2665     if (cs->createmode == EXCLUSIVE)
 2666         ret = nfs3_create_exclusive(cs);
 2667     else
 2668         ret = nfs3_create_common(cs);
 2669 
 2670     /* Handle a failure return from either of the create functions above. */
 2671     if (ret < 0)
 2672         stat = nfs3_errno_to_nfsstat3(-ret);
 2673 
 2674 nfs3err:
 2675     if (ret < 0) {
 2676         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_CREATE, stat,
 2677                             -ret, cs->resolvedloc.path);
 2678         nfs3_create_reply(cs->req, stat, NULL, NULL, NULL, NULL);
 2679         nfs3_call_state_wipe(cs);
 2680     }
 2681 
 2682     return ret;
 2683 }
 2684 
 2685 int
 2686 nfs3_create(rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
 2687             createmode3 mode, sattr3 *sattr, uint64_t cverf)
 2688 {
 2689     xlator_t *vol = NULL;
 2690     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2691     int ret = -EFAULT;
 2692     struct nfs3_state *nfs3 = NULL;
 2693     nfs3_call_state_t *cs = NULL;
 2694 
 2695     if ((!req) || (!dirfh) || (!name) || (!sattr))
 2696         return -1;
 2697 
 2698     nfs3_log_create_call(rpcsvc_request_xid(req), dirfh, name, mode);
 2699     nfs3_validate_gluster_fh(dirfh, stat, nfs3err);
 2700     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 2701     nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
 2702     nfs3_map_fh_to_volume(nfs3, dirfh, req, vol, stat, nfs3err);
 2703     nfs3_volume_started_check(nfs3, vol, ret, out);
 2704     nfs3_check_rw_volaccess(nfs3, dirfh->exportid, stat, nfs3err);
 2705     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 2706 
 2707     cs->cookieverf = cverf;
 2708     /*In Exclusive create client is supposed to send cverf instead of
 2709      * sattr*/
 2710     if (mode != EXCLUSIVE)
 2711         cs->setattr_valid = nfs3_sattr3_to_setattr_valid(sattr, &cs->stbuf,
 2712                                                          &cs->mode);
 2713     cs->createmode = mode;
 2714     cs->parent = *dirfh;
 2715 
 2716     ret = nfs3_fh_resolve_and_resume(cs, dirfh, name, nfs3_create_resume);
 2717     if (ret < 0)
 2718         stat = nfs3_errno_to_nfsstat3(-ret);
 2719 
 2720 nfs3err:
 2721     if (ret < 0) {
 2722         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_CREATE, stat, -ret,
 2723                             cs ? cs->resolvedloc.path : NULL);
 2724         nfs3_create_reply(req, stat, NULL, NULL, NULL, NULL);
 2725         nfs3_call_state_wipe(cs);
 2726         ret = 0;
 2727     }
 2728 out:
 2729     return ret;
 2730 }
 2731 
 2732 int
 2733 nfs3svc_create(rpcsvc_request_t *req)
 2734 {
 2735     char name[NFS_PATH_MAX];
 2736     struct nfs3_fh dirfh = {
 2737         {0},
 2738     };
 2739     create3args args;
 2740     int ret = RPCSVC_ACTOR_ERROR;
 2741     uint64_t cverf = 0;
 2742     uint64_t *cval;
 2743 
 2744     if (!req)
 2745         return ret;
 2746 
 2747     nfs3_prep_create3args(&args, &dirfh, name);
 2748     if (xdr_to_create3args(req->msg[0], &args) <= 0) {
 2749         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 2750                "Error decoding args");
 2751         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 2752         goto rpcerr;
 2753     }
 2754 
 2755     cval = (uint64_t *)args.how.createhow3_u.verf;
 2756     cverf = *cval;
 2757 
 2758     ret = nfs3_create(req, &dirfh, name, args.how.mode,
 2759                       &args.how.createhow3_u.obj_attributes, cverf);
 2760     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 2761         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_CREATE_FAIL,
 2762                "CREATE procedure failed");
 2763         rpcsvc_request_seterr(req, SYSTEM_ERR);
 2764         ret = RPCSVC_ACTOR_ERROR;
 2765     }
 2766 
 2767 rpcerr:
 2768     return ret;
 2769 }
 2770 
 2771 int
 2772 nfs3_mkdir_reply(rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,
 2773                  struct iatt *buf, struct iatt *preparent,
 2774                  struct iatt *postparent)
 2775 {
 2776     mkdir3res res = {
 2777         0,
 2778     };
 2779     uint64_t deviceid = 0;
 2780 
 2781     deviceid = nfs3_request_xlator_deviceid(req);
 2782     nfs3_fill_mkdir3res(&res, stat, fh, buf, preparent, postparent, deviceid);
 2783     nfs3svc_submit_reply(req, &res, (nfs3_serializer)xdr_serialize_mkdir3res);
 2784     return 0;
 2785 }
 2786 
 2787 int32_t
 2788 nfs3svc_mkdir_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 2789                           int32_t op_ret, int32_t op_errno, struct iatt *preop,
 2790                           struct iatt *postop, dict_t *xdata)
 2791 {
 2792     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2793     nfs3_call_state_t *cs = NULL;
 2794 
 2795     cs = frame->local;
 2796     if (op_ret == -1) {
 2797         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 2798         goto nfs3err;
 2799     }
 2800 
 2801     stat = NFS3_OK;
 2802 nfs3err:
 2803     nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_MKDIR, stat, op_errno,
 2804                        &cs->fh, cs->resolvedloc.path);
 2805     nfs3_mkdir_reply(cs->req, stat, &cs->fh, postop, &cs->preparent,
 2806                      &cs->postparent);
 2807     nfs3_call_state_wipe(cs);
 2808 
 2809     return 0;
 2810 }
 2811 
 2812 int32_t
 2813 nfs3svc_mkdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 2814                   int32_t op_ret, int32_t op_errno, inode_t *inode,
 2815                   struct iatt *buf, struct iatt *preparent,
 2816                   struct iatt *postparent, dict_t *xdata)
 2817 {
 2818     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2819     int ret = -EFAULT;
 2820     nfs_user_t nfu = {
 2821         0,
 2822     };
 2823     nfs3_call_state_t *cs = NULL;
 2824 
 2825     cs = frame->local;
 2826     if (op_ret == -1) {
 2827         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 2828         goto nfs3err;
 2829     }
 2830 
 2831     nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
 2832 
 2833     /* Means no attributes were required to be set. */
 2834     if (!cs->setattr_valid) {
 2835         stat = NFS3_OK;
 2836         goto nfs3err;
 2837     }
 2838 
 2839     cs->preparent = *preparent;
 2840     cs->postparent = *postparent;
 2841     nfs_request_user_init(&nfu, cs->req);
 2842     ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->stbuf,
 2843                       cs->setattr_valid, nfs3svc_mkdir_setattr_cbk, cs);
 2844     if (ret < 0)
 2845         stat = nfs3_errno_to_nfsstat3(-ret);
 2846 
 2847 nfs3err:
 2848     if (ret < 0) {
 2849         nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_MKDIR, stat,
 2850                            op_errno, &cs->fh, cs->resolvedloc.path);
 2851         nfs3_mkdir_reply(cs->req, stat, &cs->fh, buf, preparent, postparent);
 2852         nfs3_call_state_wipe(cs);
 2853     }
 2854 
 2855     return 0;
 2856 }
 2857 
 2858 int
 2859 nfs3_mkdir_resume(void *carg)
 2860 {
 2861     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2862     int ret = -EFAULT;
 2863     nfs_user_t nfu = {
 2864         0,
 2865     };
 2866     nfs3_call_state_t *cs = NULL;
 2867 
 2868     if (!carg)
 2869         return ret;
 2870 
 2871     cs = (nfs3_call_state_t *)carg;
 2872     nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
 2873     nfs_request_user_init(&nfu, cs->req);
 2874 
 2875     if (gf_attr_mode_set(cs->setattr_valid)) {
 2876         cs->setattr_valid &= ~GF_SET_ATTR_MODE;
 2877         ret = nfs_mkdir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, cs->mode,
 2878                         nfs3svc_mkdir_cbk, cs);
 2879     } else
 2880         ret = nfs_mkdir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, cs->mode,
 2881                         nfs3svc_mkdir_cbk, cs);
 2882 
 2883     if (ret < 0)
 2884         stat = nfs3_errno_to_nfsstat3(-ret);
 2885 
 2886 nfs3err:
 2887     if (ret < 0) {
 2888         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_MKDIR, stat, -ret,
 2889                             cs->resolvedloc.path);
 2890         nfs3_mkdir_reply(cs->req, stat, NULL, NULL, NULL, NULL);
 2891         nfs3_call_state_wipe(cs);
 2892     }
 2893 
 2894     return 0;
 2895 }
 2896 
 2897 int
 2898 nfs3_mkdir(rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
 2899            sattr3 *sattr)
 2900 {
 2901     xlator_t *vol = NULL;
 2902     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2903     int ret = -EFAULT;
 2904     struct nfs3_state *nfs3 = NULL;
 2905     nfs3_call_state_t *cs = NULL;
 2906 
 2907     if ((!req) || (!dirfh) || (!name) || (!sattr)) {
 2908         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 2909                "Bad arguments");
 2910         return -1;
 2911     }
 2912 
 2913     nfs3_log_fh_entry_call(rpcsvc_request_xid(req), "MKDIR", dirfh, name);
 2914     nfs3_validate_gluster_fh(dirfh, stat, nfs3err);
 2915     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 2916     nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
 2917     nfs3_map_fh_to_volume(nfs3, dirfh, req, vol, stat, nfs3err);
 2918     nfs3_volume_started_check(nfs3, vol, ret, out);
 2919     nfs3_check_rw_volaccess(nfs3, dirfh->exportid, stat, nfs3err);
 2920     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 2921 
 2922     cs->parent = *dirfh;
 2923     cs->setattr_valid = nfs3_sattr3_to_setattr_valid(sattr, &cs->stbuf,
 2924                                                      &cs->mode);
 2925     ret = nfs3_fh_resolve_and_resume(cs, dirfh, name, nfs3_mkdir_resume);
 2926     if (ret < 0)
 2927         stat = nfs3_errno_to_nfsstat3(-ret);
 2928 
 2929 nfs3err:
 2930     if (ret < 0) {
 2931         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_MKDIR, stat, -ret,
 2932                             cs ? cs->resolvedloc.path : NULL);
 2933         nfs3_mkdir_reply(req, stat, NULL, NULL, NULL, NULL);
 2934         nfs3_call_state_wipe(cs);
 2935         ret = 0;
 2936     }
 2937 out:
 2938     return ret;
 2939 }
 2940 
 2941 int
 2942 nfs3svc_mkdir(rpcsvc_request_t *req)
 2943 {
 2944     char name[NFS_PATH_MAX];
 2945     struct nfs3_fh dirfh = {
 2946         {0},
 2947     };
 2948     mkdir3args args;
 2949     int ret = RPCSVC_ACTOR_ERROR;
 2950 
 2951     if (!req)
 2952         return ret;
 2953     nfs3_prep_mkdir3args(&args, &dirfh, name);
 2954     if (xdr_to_mkdir3args(req->msg[0], &args) <= 0) {
 2955         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 2956                "Error decoding args");
 2957         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 2958         goto rpcerr;
 2959     }
 2960 
 2961     ret = nfs3_mkdir(req, &dirfh, name, &args.attributes);
 2962     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 2963         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_DIR_OP_FAIL,
 2964                "MKDIR procedure failed");
 2965         rpcsvc_request_seterr(req, SYSTEM_ERR);
 2966         ret = RPCSVC_ACTOR_ERROR;
 2967     }
 2968 
 2969 rpcerr:
 2970     return ret;
 2971 }
 2972 
 2973 int
 2974 nfs3_symlink_reply(rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,
 2975                    struct iatt *buf, struct iatt *preparent,
 2976                    struct iatt *postparent)
 2977 {
 2978     symlink3res res = {
 2979         0,
 2980     };
 2981     uint64_t deviceid = 0;
 2982 
 2983     deviceid = nfs3_request_xlator_deviceid(req);
 2984     nfs3_fill_symlink3res(&res, stat, fh, buf, preparent, postparent, deviceid);
 2985     nfs3svc_submit_reply(req, (void *)&res,
 2986                          (nfs3_serializer)xdr_serialize_symlink3res);
 2987 
 2988     return 0;
 2989 }
 2990 
 2991 int32_t
 2992 nfs3svc_symlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 2993                     int32_t op_ret, int32_t op_errno, inode_t *inode,
 2994                     struct iatt *buf, struct iatt *preparent,
 2995                     struct iatt *postparent, dict_t *xdata)
 2996 {
 2997     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 2998     nfs3_call_state_t *cs = NULL;
 2999 
 3000     cs = frame->local;
 3001     if (op_ret == -1) {
 3002         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 3003         goto nfs3err;
 3004     }
 3005 
 3006     nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
 3007     stat = NFS3_OK;
 3008 
 3009 nfs3err:
 3010     nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_SYMLINK, stat,
 3011                        op_errno, &cs->fh, cs->resolvedloc.path);
 3012     nfs3_symlink_reply(cs->req, stat, &cs->fh, buf, preparent, postparent);
 3013     nfs3_call_state_wipe(cs);
 3014     return 0;
 3015 }
 3016 
 3017 int
 3018 nfs3_symlink_resume(void *carg)
 3019 {
 3020     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3021     int ret = -EFAULT;
 3022     nfs3_call_state_t *cs = NULL;
 3023     nfs_user_t nfu = {
 3024         0,
 3025     };
 3026 
 3027     if (!carg)
 3028         return ret;
 3029 
 3030     cs = (nfs3_call_state_t *)carg;
 3031     nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
 3032     nfs_request_user_init(&nfu, cs->req);
 3033     ret = nfs_symlink(cs->nfsx, cs->vol, &nfu, cs->pathname, &cs->resolvedloc,
 3034                       nfs3svc_symlink_cbk, cs);
 3035     if (ret < 0)
 3036         stat = nfs3_errno_to_nfsstat3(-ret);
 3037 
 3038 nfs3err:
 3039     if (ret < 0) {
 3040         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_SYMLINK, stat,
 3041                             -ret, cs->resolvedloc.path);
 3042         nfs3_symlink_reply(cs->req, stat, NULL, NULL, NULL, NULL);
 3043         nfs3_call_state_wipe(cs);
 3044     }
 3045 
 3046     return ret;
 3047 }
 3048 
 3049 int
 3050 nfs3_symlink(rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
 3051              char *target, sattr3 *sattr)
 3052 {
 3053     xlator_t *vol = NULL;
 3054     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3055     int ret = -EFAULT;
 3056     struct nfs3_state *nfs3 = NULL;
 3057     nfs3_call_state_t *cs = NULL;
 3058 
 3059     if ((!req) || (!dirfh) || (!name) || (!target) || (!sattr)) {
 3060         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 3061                "Bad arguments");
 3062         return -1;
 3063     }
 3064 
 3065     nfs3_log_symlink_call(rpcsvc_request_xid(req), dirfh, name, target);
 3066     nfs3_validate_gluster_fh(dirfh, stat, nfs3err);
 3067     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 3068     nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
 3069     nfs3_map_fh_to_volume(nfs3, dirfh, req, vol, stat, nfs3err);
 3070     nfs3_volume_started_check(nfs3, vol, ret, out);
 3071     nfs3_check_rw_volaccess(nfs3, dirfh->exportid, stat, nfs3err);
 3072     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 3073 
 3074     cs->parent = *dirfh;
 3075     cs->pathname = gf_strdup(target);
 3076     if (!cs->pathname) {
 3077         ret = -1;
 3078         stat = NFS3ERR_SERVERFAULT;
 3079         goto nfs3err;
 3080     }
 3081 
 3082     ret = nfs3_fh_resolve_and_resume(cs, dirfh, name, nfs3_symlink_resume);
 3083     if (ret < 0)
 3084         stat = nfs3_errno_to_nfsstat3(-ret);
 3085 
 3086 nfs3err:
 3087     if (ret < 0) {
 3088         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_SYMLINK, stat, -ret,
 3089                             cs ? cs->resolvedloc.path : NULL);
 3090         nfs3_symlink_reply(req, stat, NULL, NULL, NULL, NULL);
 3091         nfs3_call_state_wipe(cs);
 3092         /* Ret must be 0 after this so that the caller does not
 3093          * also send an RPC reply.
 3094          */
 3095         ret = 0;
 3096     }
 3097 out:
 3098     return ret;
 3099 }
 3100 
 3101 int
 3102 nfs3svc_symlink(rpcsvc_request_t *req)
 3103 {
 3104     char name[NFS_PATH_MAX];
 3105     struct nfs3_fh dirfh = {
 3106         {0},
 3107     };
 3108     char target[NFS_PATH_MAX];
 3109     symlink3args args;
 3110     int ret = RPCSVC_ACTOR_ERROR;
 3111 
 3112     if (!req)
 3113         return ret;
 3114     nfs3_prep_symlink3args(&args, &dirfh, name, target);
 3115     if (xdr_to_symlink3args(req->msg[0], &args) <= 0) {
 3116         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 3117                "Error decoding args");
 3118         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 3119         goto rpcerr;
 3120     }
 3121 
 3122     ret = nfs3_symlink(req, &dirfh, name, target,
 3123                        &args.symlink.symlink_attributes);
 3124     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 3125         gf_msg(GF_NFS3, GF_LOG_ERROR, EXDEV, NFS_MSG_SYMLINK_FAIL,
 3126                "SYMLINK procedure failed");
 3127         rpcsvc_request_seterr(req, SYSTEM_ERR);
 3128         ret = RPCSVC_ACTOR_ERROR;
 3129     }
 3130 
 3131 rpcerr:
 3132     return ret;
 3133 }
 3134 
 3135 static int
 3136 nfs3_mknod_reply(rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,
 3137                  struct iatt *buf, struct iatt *preparent,
 3138                  struct iatt *postparent)
 3139 {
 3140     mknod3res res = {
 3141         0,
 3142     };
 3143     uint64_t deviceid = 0;
 3144 
 3145     deviceid = nfs3_request_xlator_deviceid(req);
 3146     nfs3_fill_mknod3res(&res, stat, fh, buf, preparent, postparent, deviceid);
 3147     nfs3svc_submit_reply(req, (void *)&res,
 3148                          (nfs3_serializer)xdr_serialize_mknod3res);
 3149 
 3150     return 0;
 3151 }
 3152 
 3153 int32_t
 3154 nfs3svc_mknod_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 3155                           int32_t op_ret, int32_t op_errno, struct iatt *preop,
 3156                           struct iatt *postop, dict_t *xdata)
 3157 {
 3158     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3159     nfs3_call_state_t *cs = NULL;
 3160 
 3161     cs = frame->local;
 3162     if (op_ret == -1) {
 3163         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 3164         goto nfs3err;
 3165     }
 3166 
 3167     stat = NFS3_OK;
 3168 nfs3err:
 3169     nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_MKNOD, stat, op_errno,
 3170                        &cs->fh, cs->resolvedloc.path);
 3171     nfs3_mknod_reply(cs->req, stat, &cs->fh, postop, &cs->preparent,
 3172                      &cs->postparent);
 3173     nfs3_call_state_wipe(cs);
 3174     return 0;
 3175 }
 3176 
 3177 int32_t
 3178 nfs3svc_mknod_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 3179                   int32_t op_ret, int32_t op_errno, inode_t *inode,
 3180                   struct iatt *buf, struct iatt *preparent,
 3181                   struct iatt *postparent, dict_t *xdata)
 3182 {
 3183     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3184     int ret = -1;
 3185     nfs_user_t nfu = {
 3186         0,
 3187     };
 3188     nfs3_call_state_t *cs = NULL;
 3189 
 3190     cs = frame->local;
 3191     if (op_ret == -1) {
 3192         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 3193         goto nfs3err;
 3194     }
 3195 
 3196     nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
 3197 
 3198     /* Means no attributes were required to be set. */
 3199     if (!cs->setattr_valid) {
 3200         stat = NFS3_OK;
 3201         ret = -1;
 3202         goto nfs3err;
 3203     }
 3204 
 3205     cs->preparent = *preparent;
 3206     cs->postparent = *postparent;
 3207     nfs_request_user_init(&nfu, cs->req);
 3208     ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->stbuf,
 3209                       cs->setattr_valid, nfs3svc_mknod_setattr_cbk, cs);
 3210     if (ret < 0)
 3211         stat = nfs3_errno_to_nfsstat3(-ret);
 3212 nfs3err:
 3213     if (ret < 0) {
 3214         nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_MKNOD, stat,
 3215                            op_errno, &cs->fh, cs->resolvedloc.path);
 3216         nfs3_mknod_reply(cs->req, stat, &cs->fh, buf, preparent, postparent);
 3217         nfs3_call_state_wipe(cs);
 3218     }
 3219 
 3220     return 0;
 3221 }
 3222 
 3223 static int
 3224 nfs3_mknod_device(nfs3_call_state_t *cs)
 3225 {
 3226     int ret = -EFAULT;
 3227     dev_t devnum = 0;
 3228     mode_t mode = 0;
 3229     nfs_user_t nfu = {
 3230         0,
 3231     };
 3232 
 3233     if (!cs)
 3234         return ret;
 3235 
 3236     devnum = makedev(cs->devnums.specdata1, cs->devnums.specdata2);
 3237     if (cs->mknodtype == NF3CHR)
 3238         mode = S_IFCHR;
 3239     else
 3240         mode = S_IFBLK;
 3241 
 3242     nfs_request_user_init(&nfu, cs->req);
 3243     if (gf_attr_mode_set(cs->setattr_valid)) {
 3244         cs->setattr_valid &= ~GF_SET_ATTR_MODE;
 3245         mode |= cs->mode;
 3246         ret = nfs_mknod(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, mode, devnum,
 3247                         nfs3svc_mknod_cbk, cs);
 3248     } else
 3249         ret = nfs_mknod(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, mode, devnum,
 3250                         nfs3svc_mknod_cbk, cs);
 3251 
 3252     return ret;
 3253 }
 3254 
 3255 static int
 3256 nfs3_mknod_fifo(nfs3_call_state_t *cs, mode_t mode)
 3257 {
 3258     int ret = -EFAULT;
 3259     nfs_user_t nfu = {
 3260         0,
 3261     };
 3262 
 3263     if (!cs)
 3264         return ret;
 3265 
 3266     nfs_request_user_init(&nfu, cs->req);
 3267     if (gf_attr_mode_set(cs->setattr_valid)) {
 3268         cs->setattr_valid &= ~GF_SET_ATTR_MODE;
 3269         mode |= cs->mode;
 3270         ret = nfs_mknod(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, mode, 0,
 3271                         nfs3svc_mknod_cbk, cs);
 3272     } else
 3273         ret = nfs_mknod(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, mode, 0,
 3274                         nfs3svc_mknod_cbk, cs);
 3275 
 3276     return ret;
 3277 }
 3278 
 3279 static int
 3280 nfs3_mknod_resume(void *carg)
 3281 {
 3282     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3283     int ret = -EFAULT;
 3284     nfs3_call_state_t *cs = NULL;
 3285 
 3286     if (!carg)
 3287         return ret;
 3288 
 3289     cs = (nfs3_call_state_t *)carg;
 3290     nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
 3291     switch (cs->mknodtype) {
 3292         case NF3CHR:
 3293         case NF3BLK:
 3294             ret = nfs3_mknod_device(cs);
 3295             break;
 3296         case NF3SOCK:
 3297             ret = nfs3_mknod_fifo(cs, S_IFSOCK);
 3298             break;
 3299         case NF3FIFO:
 3300             ret = nfs3_mknod_fifo(cs, S_IFIFO);
 3301             break;
 3302         default:
 3303             ret = -EBADF;
 3304             break;
 3305     }
 3306 
 3307     if (ret < 0)
 3308         stat = nfs3_errno_to_nfsstat3(-ret);
 3309 
 3310 nfs3err:
 3311     if (ret < 0) {
 3312         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_MKNOD, stat, -ret,
 3313                             cs->resolvedloc.path);
 3314         nfs3_mknod_reply(cs->req, stat, NULL, NULL, NULL, NULL);
 3315         nfs3_call_state_wipe(cs);
 3316     }
 3317 
 3318     return ret;
 3319 }
 3320 
 3321 int
 3322 nfs3_mknod(rpcsvc_request_t *req, struct nfs3_fh *fh, char *name,
 3323            mknoddata3 *nodedata)
 3324 {
 3325     xlator_t *vol = NULL;
 3326     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3327     int ret = -EFAULT;
 3328     struct nfs3_state *nfs3 = NULL;
 3329     nfs3_call_state_t *cs = NULL;
 3330     sattr3 *sattr = NULL;
 3331 
 3332     if ((!req) || (!fh) || (!name) || (!nodedata)) {
 3333         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 3334                "Bad arguments");
 3335         return -1;
 3336     }
 3337 
 3338     nfs3_log_mknod_call(rpcsvc_request_xid(req), fh, name, nodedata->type);
 3339     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 3340     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 3341     nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
 3342     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 3343     nfs3_volume_started_check(nfs3, vol, ret, out);
 3344     nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
 3345     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 3346 
 3347     cs->mknodtype = nodedata->type;
 3348     switch (nodedata->type) {
 3349         case NF3CHR:
 3350         case NF3BLK:
 3351             cs->devnums = nodedata->mknoddata3_u.device.spec;
 3352             sattr = &nodedata->mknoddata3_u.device.dev_attributes;
 3353             cs->setattr_valid = nfs3_sattr3_to_setattr_valid(sattr, &cs->stbuf,
 3354                                                              &cs->mode);
 3355             break;
 3356         case NF3SOCK:
 3357         case NF3FIFO:
 3358             sattr = &nodedata->mknoddata3_u.pipe_attributes;
 3359             cs->setattr_valid = nfs3_sattr3_to_setattr_valid(sattr, &cs->stbuf,
 3360                                                              &cs->mode);
 3361             break;
 3362         default:
 3363             ret = -EBADF;
 3364             goto nfs3err;
 3365     }
 3366 
 3367     cs->parent = *fh;
 3368     ret = nfs3_fh_resolve_and_resume(cs, fh, name, nfs3_mknod_resume);
 3369     if (ret < 0)
 3370         stat = nfs3_errno_to_nfsstat3(-ret);
 3371 
 3372 nfs3err:
 3373     if (ret < 0) {
 3374         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_MKNOD, stat, -ret,
 3375                             cs ? cs->resolvedloc.path : NULL);
 3376         nfs3_mknod_reply(req, stat, NULL, NULL, NULL, NULL);
 3377         /* Ret must be 0 after this so that the caller does not
 3378          * also send an RPC reply.
 3379          */
 3380         nfs3_call_state_wipe(cs);
 3381         ret = 0;
 3382     }
 3383 out:
 3384     return ret;
 3385 }
 3386 
 3387 int
 3388 nfs3svc_mknod(rpcsvc_request_t *req)
 3389 {
 3390     char name[NFS_PATH_MAX];
 3391     struct nfs3_fh fh = {
 3392         {0},
 3393     };
 3394     mknod3args args;
 3395     int ret = RPCSVC_ACTOR_ERROR;
 3396 
 3397     if (!req)
 3398         return ret;
 3399     nfs3_prep_mknod3args(&args, &fh, name);
 3400     if (xdr_to_mknod3args(req->msg[0], &args) <= 0) {
 3401         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 3402                "Error decoding args");
 3403         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 3404         goto rpcerr;
 3405     }
 3406 
 3407     ret = nfs3_mknod(req, &fh, name, &args.what);
 3408     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 3409         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_MKNOD_FAIL,
 3410                "MKNOD procedure failed");
 3411         rpcsvc_request_seterr(req, SYSTEM_ERR);
 3412         ret = RPCSVC_ACTOR_ERROR;
 3413     }
 3414 
 3415 rpcerr:
 3416     return ret;
 3417 }
 3418 
 3419 int
 3420 nfs3_remove_reply(rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent,
 3421                   struct iatt *postparent)
 3422 {
 3423     remove3res res = {
 3424         0,
 3425     };
 3426     uint64_t deviceid = 0;
 3427 
 3428     deviceid = nfs3_request_xlator_deviceid(req);
 3429     nfs3_fill_remove3res(&res, stat, preparent, postparent, deviceid);
 3430     nfs3svc_submit_reply(req, (void *)&res,
 3431                          (nfs3_serializer)xdr_serialize_remove3res);
 3432     return 0;
 3433 }
 3434 
 3435 int32_t
 3436 nfs3svc_remove_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 3437                    int32_t op_ret, int32_t op_errno, struct iatt *preparent,
 3438                    struct iatt *postparent, dict_t *xdata)
 3439 {
 3440     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3441     nfs3_call_state_t *cs = NULL;
 3442 
 3443     cs = frame->local;
 3444     if (op_ret == -1) {
 3445         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 3446     }
 3447 
 3448     if (op_ret == 0)
 3449         stat = NFS3_OK;
 3450 
 3451     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_REMOVE, stat,
 3452                         op_errno, cs->resolvedloc.path);
 3453     nfs3_remove_reply(cs->req, stat, preparent, postparent);
 3454     nfs3_call_state_wipe(cs);
 3455 
 3456     return 0;
 3457 }
 3458 
 3459 int
 3460 __nfs3_remove(nfs3_call_state_t *cs)
 3461 {
 3462     int ret = -EFAULT;
 3463     nfs_user_t nfu = {
 3464         0,
 3465     };
 3466     ia_type_t type = 0;
 3467 
 3468     if (!cs)
 3469         return ret;
 3470     type = cs->resolvedloc.inode->ia_type;
 3471     nfs_request_user_init(&nfu, cs->req);
 3472     if (IA_ISDIR(type))
 3473         ret = nfs_rmdir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 3474                         nfs3svc_remove_cbk, cs);
 3475     else
 3476         ret = nfs_unlink(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 3477                          nfs3svc_remove_cbk, cs);
 3478 
 3479     return ret;
 3480 }
 3481 
 3482 int
 3483 nfs3_remove_resume(void *carg)
 3484 {
 3485     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3486     int ret = -EFAULT;
 3487     nfs3_call_state_t *cs = NULL;
 3488 
 3489     if (!carg)
 3490         return ret;
 3491 
 3492     cs = (nfs3_call_state_t *)carg;
 3493     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 3494     ret = __nfs3_remove(cs);
 3495     if (ret < 0)
 3496         stat = nfs3_errno_to_nfsstat3(-ret);
 3497 
 3498 nfs3err:
 3499     if (ret < 0) {
 3500         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_REMOVE, stat,
 3501                             -ret, cs->resolvedloc.path);
 3502         nfs3_remove_reply(cs->req, stat, NULL, NULL);
 3503         nfs3_call_state_wipe(cs);
 3504     }
 3505 
 3506     return ret;
 3507 }
 3508 
 3509 int
 3510 nfs3_remove(rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)
 3511 {
 3512     xlator_t *vol = NULL;
 3513     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3514     int ret = -EFAULT;
 3515     struct nfs3_state *nfs3 = NULL;
 3516     nfs3_call_state_t *cs = NULL;
 3517 
 3518     if ((!req) || (!fh) || (!name)) {
 3519         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 3520                "Bad arguments");
 3521         return -1;
 3522     }
 3523 
 3524     nfs3_log_fh_entry_call(rpcsvc_request_xid(req), "REMOVE", fh, name);
 3525     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 3526     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 3527     nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
 3528     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 3529     nfs3_volume_started_check(nfs3, vol, ret, out);
 3530     nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
 3531     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 3532 
 3533     ret = nfs3_fh_resolve_and_resume(cs, fh, name, nfs3_remove_resume);
 3534     if (ret < 0)
 3535         stat = nfs3_errno_to_nfsstat3(-ret);
 3536 
 3537 nfs3err:
 3538     if (ret < 0) {
 3539         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_REMOVE, stat, -ret,
 3540                             cs ? cs->resolvedloc.path : NULL);
 3541         nfs3_remove_reply(req, stat, NULL, NULL);
 3542         nfs3_call_state_wipe(cs);
 3543         /* Ret must be 0 after this so that the caller does not
 3544          * also send an RPC reply.
 3545          */
 3546         ret = 0;
 3547     }
 3548 out:
 3549     return ret;
 3550 }
 3551 
 3552 int
 3553 nfs3svc_remove(rpcsvc_request_t *req)
 3554 {
 3555     char name[NFS_PATH_MAX];
 3556     struct nfs3_fh fh = {
 3557         {0},
 3558     };
 3559     remove3args args;
 3560     int ret = RPCSVC_ACTOR_ERROR;
 3561 
 3562     if (!req)
 3563         return ret;
 3564     nfs3_prep_remove3args(&args, &fh, name);
 3565     if (xdr_to_remove3args(req->msg[0], &args) <= 0) {
 3566         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 3567                "Error decoding args");
 3568         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 3569         goto rpcerr;
 3570     }
 3571 
 3572     ret = nfs3_remove(req, &fh, name);
 3573     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 3574         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_REMOVE_FAIL,
 3575                "REMOVE procedure failed");
 3576         rpcsvc_request_seterr(req, SYSTEM_ERR);
 3577         ret = RPCSVC_ACTOR_ERROR;
 3578     }
 3579 
 3580 rpcerr:
 3581     return ret;
 3582 }
 3583 
 3584 int
 3585 nfs3_rmdir_reply(rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent,
 3586                  struct iatt *postparent)
 3587 {
 3588     rmdir3res res = {
 3589         0,
 3590     };
 3591     uint64_t deviceid = 0;
 3592 
 3593     deviceid = nfs3_request_xlator_deviceid(req);
 3594     nfs3_fill_rmdir3res(&res, stat, preparent, postparent, deviceid);
 3595     nfs3svc_submit_reply(req, (void *)&res,
 3596                          (nfs3_serializer)xdr_serialize_rmdir3res);
 3597     return 0;
 3598 }
 3599 
 3600 int32_t
 3601 nfs3svc_rmdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 3602                   int32_t op_ret, int32_t op_errno, struct iatt *preparent,
 3603                   struct iatt *postparent, dict_t *xdata)
 3604 {
 3605     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3606     nfs3_call_state_t *cs = NULL;
 3607 
 3608     cs = frame->local;
 3609     if (op_ret == -1) {
 3610         gf_msg(GF_NFS, GF_LOG_WARNING, op_errno, NFS_MSG_RMDIR_CBK,
 3611                "%x: %s => -1 (%s)", rpcsvc_request_xid(cs->req),
 3612                cs->resolvedloc.path, strerror(op_errno));
 3613         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 3614     } else {
 3615         stat = NFS3_OK;
 3616     }
 3617 
 3618     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_RMDIR, stat, op_errno,
 3619                         cs->resolvedloc.path);
 3620     nfs3_rmdir_reply(cs->req, stat, preparent, postparent);
 3621     nfs3_call_state_wipe(cs);
 3622 
 3623     return 0;
 3624 }
 3625 
 3626 int
 3627 nfs3_rmdir_resume(void *carg)
 3628 {
 3629     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3630     int ret = -EFAULT;
 3631     nfs3_call_state_t *cs = NULL;
 3632     nfs_user_t nfu = {
 3633         0,
 3634     };
 3635 
 3636     if (!carg)
 3637         return ret;
 3638 
 3639     cs = (nfs3_call_state_t *)carg;
 3640     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 3641     nfs_request_user_init(&nfu, cs->req);
 3642     ret = nfs_rmdir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 3643                     nfs3svc_rmdir_cbk, cs);
 3644     if (ret < 0)
 3645         stat = nfs3_errno_to_nfsstat3(-ret);
 3646 
 3647 nfs3err:
 3648     if (ret < 0) {
 3649         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_RMDIR, stat, -ret,
 3650                             cs->resolvedloc.path);
 3651         nfs3_rmdir_reply(cs->req, stat, NULL, NULL);
 3652         nfs3_call_state_wipe(cs);
 3653     }
 3654 
 3655     return ret;
 3656 }
 3657 
 3658 int
 3659 nfs3_rmdir(rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)
 3660 {
 3661     xlator_t *vol = NULL;
 3662     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3663     int ret = -EFAULT;
 3664     struct nfs3_state *nfs3 = NULL;
 3665     nfs3_call_state_t *cs = NULL;
 3666 
 3667     if ((!req) || (!fh) || (!name)) {
 3668         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 3669                "Bad arguments");
 3670         return -1;
 3671     }
 3672 
 3673     nfs3_log_fh_entry_call(rpcsvc_request_xid(req), "RMDIR", fh, name);
 3674     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 3675     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 3676     nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
 3677     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 3678     nfs3_volume_started_check(nfs3, vol, ret, out);
 3679     nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
 3680     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 3681 
 3682     ret = nfs3_fh_resolve_and_resume(cs, fh, name, nfs3_rmdir_resume);
 3683     if (ret < 0)
 3684         stat = nfs3_errno_to_nfsstat3(-ret);
 3685 
 3686 nfs3err:
 3687     if (ret < 0) {
 3688         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_RMDIR, stat, -ret,
 3689                             cs ? cs->resolvedloc.path : NULL);
 3690         nfs3_rmdir_reply(req, stat, NULL, NULL);
 3691         nfs3_call_state_wipe(cs);
 3692         /* Ret must be 0 after this so that the caller does not
 3693          * also send an RPC reply.
 3694          */
 3695         ret = 0;
 3696     }
 3697 out:
 3698     return ret;
 3699 }
 3700 
 3701 int
 3702 nfs3svc_rmdir(rpcsvc_request_t *req)
 3703 {
 3704     char name[NFS_PATH_MAX];
 3705     struct nfs3_fh fh = {
 3706         {0},
 3707     };
 3708     rmdir3args args;
 3709     int ret = RPCSVC_ACTOR_ERROR;
 3710 
 3711     if (!req)
 3712         return ret;
 3713     nfs3_prep_rmdir3args(&args, &fh, name);
 3714     if (xdr_to_rmdir3args(req->msg[0], &args) <= 0) {
 3715         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 3716                "Error decoding args");
 3717         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 3718         goto rpcerr;
 3719     }
 3720 
 3721     ret = nfs3_rmdir(req, &fh, name);
 3722     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 3723         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_DIR_OP_FAIL,
 3724                "RMDIR procedure failed");
 3725         rpcsvc_request_seterr(req, SYSTEM_ERR);
 3726         ret = RPCSVC_ACTOR_ERROR;
 3727     }
 3728 
 3729 rpcerr:
 3730     return ret;
 3731 }
 3732 
 3733 int
 3734 nfs3_rename_reply(rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf,
 3735                   struct iatt *preoldparent, struct iatt *postoldparent,
 3736                   struct iatt *prenewparent, struct iatt *postnewparent)
 3737 {
 3738     rename3res res = {
 3739         0,
 3740     };
 3741     uint64_t deviceid = 0;
 3742 
 3743     deviceid = nfs3_request_xlator_deviceid(req);
 3744     nfs3_fill_rename3res(&res, stat, buf, preoldparent, postoldparent,
 3745                          prenewparent, postnewparent, deviceid);
 3746 
 3747     nfs3svc_submit_reply(req, (void *)&res,
 3748                          (nfs3_serializer)xdr_serialize_rename3res);
 3749 
 3750     return 0;
 3751 }
 3752 
 3753 int32_t
 3754 nfs3svc_rename_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 3755                    int32_t op_ret, int32_t op_errno, struct iatt *buf,
 3756                    struct iatt *preoldparent, struct iatt *postoldparent,
 3757                    struct iatt *prenewparent, struct iatt *postnewparent,
 3758                    dict_t *xdata)
 3759 {
 3760     int ret = -EFAULT;
 3761     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3762     nfs3_call_state_t *cs = NULL;
 3763 
 3764     cs = frame->local;
 3765     if (op_ret == -1) {
 3766         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 3767         goto nfs3err;
 3768     }
 3769 
 3770     stat = NFS3_OK;
 3771 nfs3err:
 3772     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_RENAME, stat, -ret,
 3773                         cs->resolvedloc.path);
 3774     nfs3_rename_reply(cs->req, stat, buf, preoldparent, postoldparent,
 3775                       prenewparent, postnewparent);
 3776     nfs3_call_state_wipe(cs);
 3777     return 0;
 3778 }
 3779 
 3780 int
 3781 nfs3_rename_resume_dst(void *carg)
 3782 {
 3783     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3784     int ret = -EFAULT;
 3785     nfs3_call_state_t *cs = NULL;
 3786     nfs_user_t nfu = {
 3787         0,
 3788     };
 3789 
 3790     if (!carg)
 3791         return ret;
 3792 
 3793     cs = (nfs3_call_state_t *)carg;
 3794     nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
 3795     cs->parent = cs->resolvefh;
 3796     nfs_request_user_init(&nfu, cs->req);
 3797     ret = nfs_rename(cs->nfsx, cs->vol, &nfu, &cs->oploc, &cs->resolvedloc,
 3798                      nfs3svc_rename_cbk, cs);
 3799     if (ret < 0)
 3800         stat = nfs3_errno_to_nfsstat3(-ret);
 3801 
 3802 nfs3err:
 3803     if (ret < 0) {
 3804         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_RENAME, stat,
 3805                             -ret, cs->resolvedloc.path);
 3806         nfs3_rename_reply(cs->req, stat, NULL, NULL, NULL, NULL, NULL);
 3807         nfs3_call_state_wipe(cs);
 3808     }
 3809 
 3810     return ret;
 3811 }
 3812 
 3813 int
 3814 nfs3_rename_resume_src(void *carg)
 3815 {
 3816     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3817     int ret = -EFAULT;
 3818     nfs3_call_state_t *cs = NULL;
 3819 
 3820     if (!carg)
 3821         return ret;
 3822 
 3823     cs = (nfs3_call_state_t *)carg;
 3824     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 3825     /* Copy the resolved loc for the source file into another loc
 3826      * for safekeeping till we resolve the dest loc.
 3827      */
 3828     nfs_loc_copy(&cs->oploc, &cs->resolvedloc);
 3829     nfs_loc_wipe(&cs->resolvedloc);
 3830     GF_FREE(cs->resolventry);
 3831 
 3832     ret = nfs3_fh_resolve_and_resume(cs, &cs->fh, cs->pathname,
 3833                                      nfs3_rename_resume_dst);
 3834     if (ret < 0)
 3835         stat = nfs3_errno_to_nfsstat3(-ret);
 3836 
 3837 nfs3err:
 3838     if (ret < 0) {
 3839         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_RENAME, stat,
 3840                             -ret, cs->resolvedloc.path);
 3841         nfs3_rename_reply(cs->req, stat, NULL, NULL, NULL, NULL, NULL);
 3842         nfs3_call_state_wipe(cs);
 3843     }
 3844 
 3845     return ret;
 3846 }
 3847 
 3848 int
 3849 nfs3_rename(rpcsvc_request_t *req, struct nfs3_fh *olddirfh, char *oldname,
 3850             struct nfs3_fh *newdirfh, char *newname)
 3851 {
 3852     xlator_t *vol = NULL;
 3853     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3854     int ret = -EFAULT;
 3855     struct nfs3_state *nfs3 = NULL;
 3856     nfs3_call_state_t *cs = NULL;
 3857 
 3858     if ((!req) || (!olddirfh) || (!oldname) || (!newdirfh) || (!newname)) {
 3859         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 3860                "Bad arguments");
 3861         return -1;
 3862     }
 3863 
 3864     nfs3_log_rename_call(rpcsvc_request_xid(req), olddirfh, oldname, newdirfh,
 3865                          newname);
 3866     nfs3_validate_gluster_fh(olddirfh, stat, nfs3err);
 3867     nfs3_validate_gluster_fh(newdirfh, stat, nfs3err);
 3868     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 3869     nfs3_validate_strlen_or_goto(oldname, NFS_NAME_MAX, nfs3err, stat, ret);
 3870     nfs3_validate_strlen_or_goto(newname, NFS_NAME_MAX, nfs3err, stat, ret);
 3871     nfs3_map_fh_to_volume(nfs3, olddirfh, req, vol, stat, nfs3err);
 3872     nfs3_volume_started_check(nfs3, vol, ret, out);
 3873     nfs3_check_rw_volaccess(nfs3, olddirfh->exportid, stat, nfs3err);
 3874     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 3875 
 3876     /* While we resolve the source (fh, name) pair, we need to keep a copy
 3877      * of the dest (fh,name) pair.
 3878      */
 3879     cs->fh = *newdirfh;
 3880     cs->pathname = gf_strdup(newname);
 3881     if (!cs->pathname) {
 3882         stat = NFS3ERR_SERVERFAULT;
 3883         ret = -1;
 3884         goto nfs3err;
 3885     }
 3886 
 3887     ret = nfs3_fh_resolve_and_resume(cs, olddirfh, oldname,
 3888                                      nfs3_rename_resume_src);
 3889     if (ret < 0)
 3890         stat = nfs3_errno_to_nfsstat3(-ret);
 3891 
 3892 nfs3err:
 3893     if (ret < 0) {
 3894         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_RENAME, stat, -ret,
 3895                             cs ? cs->resolvedloc.path : NULL);
 3896         nfs3_rename_reply(req, stat, NULL, NULL, NULL, NULL, NULL);
 3897         nfs3_call_state_wipe(cs);
 3898         /* Ret must be 0 after this so that the caller does not
 3899          * also send an RPC reply.
 3900          */
 3901         ret = 0;
 3902     }
 3903 out:
 3904     return ret;
 3905 }
 3906 
 3907 int
 3908 nfs3svc_rename(rpcsvc_request_t *req)
 3909 {
 3910     char newname[NFS_PATH_MAX];
 3911     char oldname[NFS_PATH_MAX];
 3912     struct nfs3_fh olddirfh = {
 3913         {0},
 3914     };
 3915     struct nfs3_fh newdirfh = {
 3916         {0},
 3917     };
 3918     rename3args args;
 3919     int ret = RPCSVC_ACTOR_ERROR;
 3920 
 3921     if (!req)
 3922         return ret;
 3923     nfs3_prep_rename3args(&args, &olddirfh, oldname, &newdirfh, newname);
 3924     if (xdr_to_rename3args(req->msg[0], &args) <= 0) {
 3925         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 3926                "Error decoding args");
 3927         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 3928         goto rpcerr;
 3929     }
 3930 
 3931     ret = nfs3_rename(req, &olddirfh, oldname, &newdirfh, newname);
 3932     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 3933         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_RENAME_FAIL,
 3934                "RENAME procedure failed");
 3935         rpcsvc_request_seterr(req, SYSTEM_ERR);
 3936         ret = RPCSVC_ACTOR_ERROR;
 3937     }
 3938 
 3939 rpcerr:
 3940     return ret;
 3941 }
 3942 
 3943 int
 3944 nfs3_link_reply(rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf,
 3945                 struct iatt *preparent, struct iatt *postparent)
 3946 {
 3947     link3res res = {
 3948         0,
 3949     };
 3950     uint64_t deviceid = 0;
 3951 
 3952     deviceid = nfs3_request_xlator_deviceid(req);
 3953     nfs3_fill_link3res(&res, stat, buf, preparent, postparent, deviceid);
 3954     nfs3svc_submit_reply(req, (void *)&res,
 3955                          (nfs3_serializer)xdr_serialize_link3res);
 3956 
 3957     return 0;
 3958 }
 3959 
 3960 int32_t
 3961 nfs3svc_link_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 3962                  int32_t op_ret, int32_t op_errno, inode_t *inode,
 3963                  struct iatt *buf, struct iatt *preparent,
 3964                  struct iatt *postparent, dict_t *xdata)
 3965 {
 3966     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3967     nfs3_call_state_t *cs = NULL;
 3968 
 3969     cs = frame->local;
 3970     if (op_ret == -1) {
 3971         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 3972     } else
 3973         stat = NFS3_OK;
 3974 
 3975     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_LINK, stat, op_errno,
 3976                         cs->resolvedloc.path);
 3977     nfs3_link_reply(cs->req, stat, buf, preparent, postparent);
 3978     nfs3_call_state_wipe(cs);
 3979 
 3980     return 0;
 3981 }
 3982 
 3983 int
 3984 nfs3_link_resume_lnk(void *carg)
 3985 {
 3986     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 3987     int ret = -EFAULT;
 3988     nfs3_call_state_t *cs = NULL;
 3989     nfs_user_t nfu = {
 3990         0,
 3991     };
 3992 
 3993     if (!carg)
 3994         return ret;
 3995 
 3996     cs = (nfs3_call_state_t *)carg;
 3997     nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
 3998 
 3999     nfs_request_user_init(&nfu, cs->req);
 4000     ret = nfs_link(cs->nfsx, cs->vol, &nfu, &cs->oploc, &cs->resolvedloc,
 4001                    nfs3svc_link_cbk, cs);
 4002     if (ret < 0)
 4003         stat = nfs3_errno_to_nfsstat3(-ret);
 4004 
 4005 nfs3err:
 4006     if (ret < 0) {
 4007         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_LINK, stat, -ret,
 4008                             cs->resolvedloc.path);
 4009         nfs3_link_reply(cs->req, stat, NULL, NULL, NULL);
 4010         nfs3_call_state_wipe(cs);
 4011     }
 4012     return ret;
 4013 }
 4014 
 4015 int
 4016 nfs3_link_resume_tgt(void *carg)
 4017 {
 4018     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4019     int ret = -EFAULT;
 4020     nfs3_call_state_t *cs = NULL;
 4021 
 4022     if (!carg)
 4023         return ret;
 4024 
 4025     cs = (nfs3_call_state_t *)carg;
 4026     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 4027     nfs_loc_copy(&cs->oploc, &cs->resolvedloc);
 4028     nfs_loc_wipe(&cs->resolvedloc);
 4029 
 4030     ret = nfs3_fh_resolve_and_resume(cs, &cs->fh, cs->pathname,
 4031                                      nfs3_link_resume_lnk);
 4032     if (ret < 0)
 4033         stat = nfs3_errno_to_nfsstat3(-ret);
 4034 
 4035 nfs3err:
 4036     if (ret < 0) {
 4037         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_LINK, stat, -ret,
 4038                             cs->resolvedloc.path);
 4039         nfs3_link_reply(cs->req, stat, NULL, NULL, NULL);
 4040         nfs3_call_state_wipe(cs);
 4041     }
 4042 
 4043     return ret;
 4044 }
 4045 
 4046 int
 4047 nfs3_link(rpcsvc_request_t *req, struct nfs3_fh *targetfh,
 4048           struct nfs3_fh *dirfh, char *newname)
 4049 {
 4050     xlator_t *vol = NULL;
 4051     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4052     int ret = -EFAULT;
 4053     struct nfs3_state *nfs3 = NULL;
 4054     nfs3_call_state_t *cs = NULL;
 4055 
 4056     if ((!req) || (!targetfh) || (!dirfh) || (!newname)) {
 4057         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 4058                "Bad arguments");
 4059         return -1;
 4060     }
 4061 
 4062     nfs3_validate_gluster_fh(dirfh, stat, nfs3err);
 4063     nfs3_validate_gluster_fh(targetfh, stat, nfs3err);
 4064     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 4065     nfs3_validate_strlen_or_goto(newname, NFS_NAME_MAX, nfs3err, stat, ret);
 4066     nfs3_map_fh_to_volume(nfs3, dirfh, req, vol, stat, nfs3err);
 4067     nfs3_volume_started_check(nfs3, vol, ret, out);
 4068     nfs3_check_rw_volaccess(nfs3, dirfh->exportid, stat, nfs3err);
 4069     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 4070 
 4071     cs->fh = *dirfh;
 4072     cs->pathname = gf_strdup(newname);
 4073     if (!cs->pathname) {
 4074         stat = NFS3ERR_SERVERFAULT;
 4075         ret = -1;
 4076         goto nfs3err;
 4077     }
 4078 
 4079     ret = nfs3_fh_resolve_and_resume(cs, targetfh, NULL, nfs3_link_resume_tgt);
 4080     if (ret < 0)
 4081         stat = nfs3_errno_to_nfsstat3(-ret);
 4082 
 4083 nfs3err:
 4084     if (ret < 0) {
 4085         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_LINK, stat, -ret,
 4086                             cs ? cs->pathname : NULL);
 4087         nfs3_link_reply(req, stat, NULL, NULL, NULL);
 4088         nfs3_call_state_wipe(cs);
 4089         /* Ret must be 0 after this so that the caller does not
 4090          * also send an RPC reply.
 4091          */
 4092         ret = 0;
 4093     }
 4094 out:
 4095     return ret;
 4096 }
 4097 
 4098 int
 4099 nfs3svc_link(rpcsvc_request_t *req)
 4100 {
 4101     char newpath[NFS_PATH_MAX];
 4102     struct nfs3_fh dirfh = {
 4103         {0},
 4104     };
 4105     struct nfs3_fh targetfh = {
 4106         {0},
 4107     };
 4108     link3args args;
 4109     int ret = RPCSVC_ACTOR_ERROR;
 4110 
 4111     if (!req)
 4112         return ret;
 4113     nfs3_prep_link3args(&args, &targetfh, &dirfh, newpath);
 4114     if (xdr_to_link3args(req->msg[0], &args) <= 0) {
 4115         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 4116                "Error decoding args");
 4117         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 4118         goto rpcerr;
 4119     }
 4120 
 4121     ret = nfs3_link(req, &targetfh, &dirfh, newpath);
 4122     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 4123         gf_msg(GF_NFS3, GF_LOG_ERROR, EXDEV, NFS_MSG_LINK_FAIL,
 4124                "LINK procedure failed");
 4125         rpcsvc_request_seterr(req, SYSTEM_ERR);
 4126         ret = RPCSVC_ACTOR_ERROR;
 4127     }
 4128 
 4129 rpcerr:
 4130     return ret;
 4131 }
 4132 
 4133 int
 4134 nfs3_readdirp_reply(rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *dirfh,
 4135                     uint64_t cverf, struct iatt *dirstat, gf_dirent_t *entries,
 4136                     count3 dircount, count3 maxcount, int is_eof)
 4137 {
 4138     readdirp3res res = {
 4139         0,
 4140     };
 4141     uint64_t deviceid = 0;
 4142 
 4143     deviceid = nfs3_request_xlator_deviceid(req);
 4144     nfs3_fill_readdirp3res(&res, stat, dirfh, cverf, dirstat, entries, dircount,
 4145                            maxcount, is_eof, deviceid);
 4146     nfs3svc_submit_reply(req, (void *)&res,
 4147                          (nfs3_serializer)xdr_serialize_readdirp3res);
 4148     nfs3_free_readdirp3res(&res);
 4149 
 4150     return 0;
 4151 }
 4152 
 4153 int
 4154 nfs3_readdir_reply(rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *dirfh,
 4155                    uint64_t cverf, struct iatt *dirstat, gf_dirent_t *entries,
 4156                    count3 count, int is_eof)
 4157 {
 4158     readdir3res res = {
 4159         0,
 4160     };
 4161     uint64_t deviceid = 0;
 4162 
 4163     deviceid = nfs3_request_xlator_deviceid(req);
 4164     nfs3_fill_readdir3res(&res, stat, dirfh, cverf, dirstat, entries, count,
 4165                           is_eof, deviceid);
 4166     nfs3svc_submit_reply(req, (void *)&res,
 4167                          (nfs3_serializer)xdr_serialize_readdir3res);
 4168     nfs3_free_readdir3res(&res);
 4169 
 4170     return 0;
 4171 }
 4172 
 4173 int32_t
 4174 nfs3svc_readdir_fstat_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 4175                           int32_t op_ret, int32_t op_errno, struct iatt *buf,
 4176                           dict_t *xdata)
 4177 {
 4178     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4179     int is_eof = 0;
 4180     nfs3_call_state_t *cs = NULL;
 4181 
 4182     cs = frame->local;
 4183     if (op_ret == -1) {
 4184         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 4185         goto nfs3err;
 4186     }
 4187 
 4188     /* Check whether we encountered a end of directory stream while
 4189      * readdir'ing.
 4190      */
 4191     if (cs->operrno == ENOENT) {
 4192         gf_msg_trace(GF_NFS3, 0, "Reached end-of-directory");
 4193         is_eof = 1;
 4194     }
 4195 
 4196     stat = NFS3_OK;
 4197 
 4198     /* do inode linking here */
 4199     gf_link_inodes_from_dirent(this, cs->fd->inode, &cs->entries);
 4200 
 4201 nfs3err:
 4202     if (cs->maxcount == 0) {
 4203         nfs3_log_readdir_res(rpcsvc_request_xid(cs->req), stat, op_errno,
 4204                              (uintptr_t)cs->fd, cs->dircount, is_eof,
 4205                              cs->resolvedloc.path);
 4206         nfs3_readdir_reply(cs->req, stat, &cs->parent, (uintptr_t)cs->fd, buf,
 4207                            &cs->entries, cs->dircount, is_eof);
 4208     } else {
 4209         nfs3_log_readdirp_res(rpcsvc_request_xid(cs->req), stat, op_errno,
 4210                               (uintptr_t)cs->fd, cs->dircount, cs->maxcount,
 4211                               is_eof, cs->resolvedloc.path);
 4212         nfs3_readdirp_reply(cs->req, stat, &cs->parent, (uintptr_t)cs->fd, buf,
 4213                             &cs->entries, cs->dircount, cs->maxcount, is_eof);
 4214     }
 4215 
 4216     if (is_eof) {
 4217         /* do nothing */
 4218     }
 4219 
 4220     nfs3_call_state_wipe(cs);
 4221     return 0;
 4222 }
 4223 
 4224 int32_t
 4225 nfs3svc_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 4226                     int32_t op_ret, int32_t op_errno, gf_dirent_t *entries,
 4227                     dict_t *xdata)
 4228 {
 4229     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4230     int ret = -EFAULT;
 4231     nfs_user_t nfu = {
 4232         0,
 4233     };
 4234     nfs3_call_state_t *cs = NULL;
 4235 
 4236     cs = frame->local;
 4237     if (op_ret == -1) {
 4238         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 4239         goto err;
 4240     }
 4241 
 4242     cs->operrno = op_errno;
 4243     list_splice_init(&entries->list, &cs->entries.list);
 4244     nfs_request_user_init(&nfu, cs->req);
 4245     ret = nfs_fstat(cs->nfsx, cs->vol, &nfu, cs->fd, nfs3svc_readdir_fstat_cbk,
 4246                     cs);
 4247     if (ret < 0) {
 4248         op_ret = -1;
 4249         stat = nfs3_errno_to_nfsstat3(-ret);
 4250         op_errno = -ret;
 4251     }
 4252 
 4253 err:
 4254     if (op_ret >= 0)
 4255         goto ret;
 4256 
 4257     if (cs->maxcount == 0) {
 4258         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_READDIR, stat,
 4259                             op_errno, cs->resolvedloc.path);
 4260         nfs3_readdir_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0);
 4261     } else {
 4262         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_READDIRP, stat,
 4263                             op_errno, cs->resolvedloc.path);
 4264         nfs3_readdirp_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0, 0);
 4265     }
 4266 
 4267     /* For directories, we force a purge from the fd cache on close
 4268      * so that next time the dir is read, we'll get any changed directory
 4269      * entries.
 4270      */
 4271     nfs3_call_state_wipe(cs);
 4272 ret:
 4273     return 0;
 4274 }
 4275 
 4276 int
 4277 nfs3_readdir_process(nfs3_call_state_t *cs)
 4278 {
 4279     int ret = -EFAULT;
 4280     nfs_user_t nfu = {
 4281         0,
 4282     };
 4283 
 4284     if (!cs)
 4285         return ret;
 4286 
 4287     nfs_request_user_init(&nfu, cs->req);
 4288     ret = nfs_readdirp(cs->nfsx, cs->vol, &nfu, cs->fd, cs->dircount,
 4289                        cs->cookie, nfs3svc_readdir_cbk, cs);
 4290     return ret;
 4291 }
 4292 
 4293 int
 4294 nfs3_readdir_read_resume(void *carg)
 4295 {
 4296     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4297     int ret = -EFAULT;
 4298     nfs3_call_state_t *cs = NULL;
 4299     struct nfs3_state *nfs3 = NULL;
 4300 
 4301     if (!carg)
 4302         return ret;
 4303 
 4304     cs = (nfs3_call_state_t *)carg;
 4305     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 4306     nfs3 = rpcsvc_request_program_private(cs->req);
 4307     ret = nfs3_verify_dircookie(nfs3, cs->fd, cs->cookie, cs->cookieverf,
 4308                                 &stat);
 4309     if (ret < 0) /* Stat already set by verifier function above. */
 4310         goto nfs3err;
 4311 
 4312     ret = nfs3_readdir_process(cs);
 4313     if (ret < 0)
 4314         stat = nfs3_errno_to_nfsstat3(-ret);
 4315 nfs3err:
 4316     if (ret < 0) {
 4317         if (cs->maxcount == 0) {
 4318             nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_READDIR, stat,
 4319                                 -ret, cs->resolvedloc.path);
 4320             nfs3_readdir_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0);
 4321         } else {
 4322             nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_READDIRP,
 4323                                 stat, -ret, cs->resolvedloc.path);
 4324             nfs3_readdirp_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0, 0);
 4325         }
 4326         nfs3_call_state_wipe(cs);
 4327     }
 4328 
 4329     return 0;
 4330 }
 4331 
 4332 int32_t
 4333 nfs3svc_readdir_opendir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 4334                             int32_t op_ret, int32_t op_errno, fd_t *fd,
 4335                             dict_t *xdata)
 4336 {
 4337     /*
 4338      * We don't really need this, it's just an artifact of forcing the
 4339      * opendir to happen.
 4340      */
 4341     if (fd) {
 4342         fd_unref(fd);
 4343     }
 4344 
 4345     return 0;
 4346 }
 4347 
 4348 int
 4349 nfs3_readdir_open_resume(void *carg)
 4350 {
 4351     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4352     int ret = -EFAULT;
 4353     nfs3_call_state_t *cs = NULL;
 4354     nfs_user_t nfu = {
 4355         0,
 4356     };
 4357 
 4358     if (!carg)
 4359         return ret;
 4360 
 4361     cs = (nfs3_call_state_t *)carg;
 4362     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 4363     cs->fd = fd_anonymous(cs->resolvedloc.inode);
 4364     if (!cs->fd) {
 4365         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ANONYMOUS_FD_FAIL,
 4366                "Fail to create anonymous fd");
 4367         goto nfs3err;
 4368     }
 4369 
 4370     /*
 4371      * NFS client will usually send us a readdirp without an opendir,
 4372      * which would cause us to skip our usual self-heal checks which occur
 4373      * in opendir for native protocol. To make sure those checks do happen,
 4374      * our most reliable option is to do our own opendir for any readdirp
 4375      * at the beginning of the directory.
 4376      */
 4377     if (cs->cookie == 0) {
 4378         nfs_request_user_init(&nfu, cs->req);
 4379         ret = nfs_opendir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 4380                           nfs3svc_readdir_opendir_cbk, cs);
 4381         if (ret < 0) {
 4382             gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_DIR_OP_FAIL,
 4383                    "auto-opendir failed");
 4384         }
 4385     }
 4386 
 4387     ret = nfs3_readdir_read_resume(cs);
 4388     if (ret < 0)
 4389         stat = nfs3_errno_to_nfsstat3(-ret);
 4390 
 4391 nfs3err:
 4392     if (ret < 0) {
 4393         if (cs->maxcount == 0) {
 4394             nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_READDIR, stat,
 4395                                 -ret, cs->resolvedloc.path);
 4396             nfs3_readdir_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0);
 4397         } else {
 4398             nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_READDIRP,
 4399                                 stat, -ret, cs->resolvedloc.path);
 4400             nfs3_readdirp_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0, 0);
 4401         }
 4402         nfs3_call_state_wipe(cs);
 4403     }
 4404 
 4405     return ret;
 4406 }
 4407 
 4408 int
 4409 nfs3_readdir(rpcsvc_request_t *req, struct nfs3_fh *fh, cookie3 cookie,
 4410              uint64_t cverf, count3 dircount, count3 maxcount)
 4411 {
 4412     xlator_t *vol = NULL;
 4413     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4414     int ret = -EFAULT;
 4415     struct nfs3_state *nfs3 = NULL;
 4416     nfs3_call_state_t *cs = NULL;
 4417     struct nfs_state *nfs = NULL;
 4418     gf_boolean_t is_readdirp = !!maxcount;
 4419 
 4420     if ((!req) || (!fh)) {
 4421         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 4422                "Bad arguments");
 4423         return -1;
 4424     }
 4425 
 4426     nfs3_log_readdir_call(rpcsvc_request_xid(req), fh, dircount, maxcount);
 4427     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 4428     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 4429     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 4430     nfs3_volume_started_check(nfs3, vol, ret, out);
 4431     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 4432     nfs = nfs_state(nfs3->nfsx);
 4433 
 4434     if (is_readdirp && !nfs->rdirplus) {
 4435         ret = -ENOTSUP;
 4436         stat = nfs3_errno_to_nfsstat3(-ret);
 4437         goto nfs3err;
 4438     }
 4439 
 4440     cs->cookieverf = cverf;
 4441     cs->dircount = dircount;
 4442     cs->maxcount = maxcount;
 4443     cs->cookie = cookie;
 4444     cs->parent = *fh;
 4445     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_readdir_open_resume);
 4446     if (ret < 0)
 4447         stat = nfs3_errno_to_nfsstat3(-ret);
 4448 
 4449 nfs3err:
 4450     if (ret < 0) {
 4451         if (!is_readdirp) {
 4452             nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_READDIR, stat,
 4453                                 -ret, cs ? cs->resolvedloc.path : NULL);
 4454             nfs3_readdir_reply(req, stat, NULL, 0, NULL, NULL, 0, 0);
 4455         } else {
 4456             nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_READDIRP, stat,
 4457                                 -ret, cs ? cs->resolvedloc.path : NULL);
 4458             nfs3_readdirp_reply(req, stat, NULL, 0, NULL, NULL, 0, 0, 0);
 4459         }
 4460         /* Ret must be NULL after this so that the caller does not
 4461          * also send an RPC reply.
 4462          */
 4463         ret = 0;
 4464         nfs3_call_state_wipe(cs);
 4465     }
 4466 out:
 4467     return ret;
 4468 }
 4469 
 4470 int
 4471 nfs3svc_readdir(rpcsvc_request_t *req)
 4472 {
 4473     readdir3args ra;
 4474     struct nfs3_fh fh = {
 4475         {0},
 4476     };
 4477     int ret = RPCSVC_ACTOR_ERROR;
 4478     uint64_t verf = 0;
 4479     uint64_t *cval;
 4480 
 4481     if (!req)
 4482         return ret;
 4483     nfs3_prep_readdir3args(&ra, &fh);
 4484     if (xdr_to_readdir3args(req->msg[0], &ra) <= 0) {
 4485         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 4486                "Error decoding args");
 4487         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 4488         goto rpcerr;
 4489     }
 4490     cval = (uint64_t *)ra.cookieverf;
 4491     verf = *cval;
 4492 
 4493     ret = nfs3_readdir(req, &fh, ra.cookie, verf, ra.count, 0);
 4494     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 4495         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_READDIR_FAIL,
 4496                "READDIR procedure failed");
 4497         rpcsvc_request_seterr(req, SYSTEM_ERR);
 4498         ret = RPCSVC_ACTOR_ERROR;
 4499     }
 4500 
 4501 rpcerr:
 4502     return ret;
 4503 }
 4504 
 4505 int
 4506 nfs3svc_readdirp(rpcsvc_request_t *req)
 4507 {
 4508     readdirp3args ra;
 4509     struct nfs3_fh fh = {
 4510         {0},
 4511     };
 4512     int ret = RPCSVC_ACTOR_ERROR;
 4513     uint64_t cverf = 0;
 4514     uint64_t *cval;
 4515 
 4516     if (!req)
 4517         return ret;
 4518     nfs3_prep_readdirp3args(&ra, &fh);
 4519     if (xdr_to_readdirp3args(req->msg[0], &ra) <= 0) {
 4520         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 4521                "Error decoding args");
 4522         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 4523         goto rpcerr;
 4524     }
 4525     cval = (uint64_t *)ra.cookieverf;
 4526     cverf = *cval;
 4527 
 4528     ret = nfs3_readdir(req, &fh, ra.cookie, cverf, ra.dircount, ra.maxcount);
 4529     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 4530         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_READDIRP_FAIL,
 4531                "READDIRP procedure failed");
 4532         rpcsvc_request_seterr(req, SYSTEM_ERR);
 4533         ret = RPCSVC_ACTOR_ERROR;
 4534     }
 4535 
 4536 rpcerr:
 4537     return ret;
 4538 }
 4539 
 4540 int
 4541 nfs3_fsstat_reply(rpcsvc_request_t *req, nfsstat3 stat, struct statvfs *fsbuf,
 4542                   struct iatt *postbuf)
 4543 {
 4544     fsstat3res res = {
 4545         0,
 4546     };
 4547     uint64_t deviceid = 0;
 4548 
 4549     deviceid = nfs3_request_xlator_deviceid(req);
 4550     nfs3_fill_fsstat3res(&res, stat, fsbuf, postbuf, deviceid);
 4551     return nfs3svc_submit_reply(req, &res,
 4552                                 (nfs3_serializer)xdr_serialize_fsstat3res);
 4553 }
 4554 
 4555 int32_t
 4556 nfs3_fsstat_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 4557                      int32_t op_ret, int32_t op_errno, struct iatt *buf,
 4558                      dict_t *xdata)
 4559 {
 4560     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4561     nfs3_call_state_t *cs = NULL;
 4562 
 4563     cs = frame->local;
 4564     if (op_ret == -1) {
 4565         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 4566     } else
 4567         stat = NFS3_OK;
 4568 
 4569     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_FSSTAT, stat,
 4570                         op_errno, cs->resolvedloc.path);
 4571     nfs3_fsstat_reply(cs->req, stat, &cs->fsstat, buf);
 4572     nfs3_call_state_wipe(cs);
 4573     return 0;
 4574 }
 4575 
 4576 int32_t
 4577 nfs3_fsstat_statfs_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 4578                        int32_t op_ret, int32_t op_errno, struct statvfs *buf,
 4579                        dict_t *xdata)
 4580 {
 4581     nfs_user_t nfu = {
 4582         0,
 4583     };
 4584     int ret = -EFAULT;
 4585     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4586     nfs3_call_state_t *cs = NULL;
 4587 
 4588     cs = frame->local;
 4589     if (op_ret == -1) {
 4590         ret = -op_errno;
 4591         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 4592         goto err;
 4593     }
 4594 
 4595     /* Then get the stat for the fs root in order to fill in the
 4596      * post_op_attr.
 4597      */
 4598     cs->fsstat = *buf;
 4599     nfs_request_user_init(&nfu, cs->req);
 4600     ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 4601                    nfs3_fsstat_stat_cbk, cs);
 4602     if (ret < 0)
 4603         stat = nfs3_errno_to_nfsstat3(-ret);
 4604 
 4605 err:
 4606     if (ret < 0) {
 4607         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_FSSTAT, stat,
 4608                             -ret, cs->resolvedloc.path);
 4609         nfs3_fsstat_reply(cs->req, stat, NULL, NULL);
 4610         nfs3_call_state_wipe(cs);
 4611     }
 4612 
 4613     return 0;
 4614 }
 4615 
 4616 int
 4617 nfs3_fsstat_resume(void *carg)
 4618 {
 4619     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4620     int ret = -EFAULT;
 4621     nfs3_call_state_t *cs = NULL;
 4622     nfs_user_t nfu = {
 4623         0,
 4624     };
 4625 
 4626     if (!carg)
 4627         return ret;
 4628 
 4629     cs = (nfs3_call_state_t *)carg;
 4630     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 4631     nfs_request_user_init(&nfu, cs->req);
 4632     /* First, we need to get the statvfs for the subvol */
 4633     ret = nfs_statfs(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 4634                      nfs3_fsstat_statfs_cbk, cs);
 4635     if (ret < 0)
 4636         stat = nfs3_errno_to_nfsstat3(-ret);
 4637 
 4638 nfs3err:
 4639     if (ret < 0) {
 4640         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_FSSTAT, stat,
 4641                             -ret, cs->resolvedloc.path);
 4642         nfs3_fsstat_reply(cs->req, stat, NULL, NULL);
 4643         nfs3_call_state_wipe(cs);
 4644     }
 4645 
 4646     return ret;
 4647 }
 4648 
 4649 int
 4650 nfs3_fsstat(rpcsvc_request_t *req, struct nfs3_fh *fh)
 4651 {
 4652     xlator_t *vol = NULL;
 4653     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4654     int ret = -EFAULT;
 4655     struct nfs3_state *nfs3 = NULL;
 4656     nfs3_call_state_t *cs = NULL;
 4657 
 4658     if ((!req) || (!fh)) {
 4659         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 4660                "Bad arguments");
 4661         return -1;
 4662     }
 4663 
 4664     nfs3_log_common_call(rpcsvc_request_xid(req), "FSSTAT", fh);
 4665     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 4666     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 4667     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 4668     nfs3_volume_started_check(nfs3, vol, ret, out);
 4669     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 4670 
 4671     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_fsstat_resume);
 4672     if (ret < 0)
 4673         stat = nfs3_errno_to_nfsstat3(-ret);
 4674 
 4675 nfs3err:
 4676     if (ret < 0) {
 4677         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_FSSTAT, stat, -ret,
 4678                             cs ? cs->resolvedloc.path : NULL);
 4679         nfs3_fsstat_reply(req, stat, NULL, NULL);
 4680         nfs3_call_state_wipe(cs);
 4681         /* Ret must be 0 after this so that the caller does not
 4682          * also send an RPC reply.
 4683          */
 4684         ret = 0;
 4685     }
 4686 out:
 4687     return ret;
 4688 }
 4689 
 4690 int
 4691 nfs3svc_fsstat(rpcsvc_request_t *req)
 4692 {
 4693     struct nfs3_fh fh = {
 4694         {0},
 4695     };
 4696     fsstat3args args;
 4697     int ret = RPCSVC_ACTOR_ERROR;
 4698 
 4699     if (!req)
 4700         return ret;
 4701     nfs3_prep_fsstat3args(&args, &fh);
 4702     if (xdr_to_fsstat3args(req->msg[0], &args) <= 0) {
 4703         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 4704                "Error decoding args");
 4705         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 4706         goto rpcerr;
 4707     }
 4708 
 4709     ret = nfs3_fsstat(req, &fh);
 4710     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 4711         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_FSTAT_FAIL,
 4712                "FSTAT procedure failed");
 4713         rpcsvc_request_seterr(req, SYSTEM_ERR);
 4714         ret = RPCSVC_ACTOR_ERROR;
 4715     }
 4716 
 4717 rpcerr:
 4718     return ret;
 4719 }
 4720 
 4721 int
 4722 nfs3_fsinfo_reply(rpcsvc_request_t *req, nfsstat3 status, struct iatt *fsroot)
 4723 {
 4724     fsinfo3res res;
 4725     struct nfs3_state *nfs3 = NULL;
 4726     uint64_t deviceid = 0;
 4727 
 4728     deviceid = nfs3_request_xlator_deviceid(req);
 4729     nfs3 = rpcsvc_request_program_private(req);
 4730     nfs3_fill_fsinfo3res(nfs3, &res, status, fsroot, deviceid);
 4731 
 4732     nfs3svc_submit_reply(req, &res, (nfs3_serializer)xdr_serialize_fsinfo3res);
 4733     return 0;
 4734 }
 4735 
 4736 int32_t
 4737 nfs3svc_fsinfo_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 4738                    int32_t op_ret, int32_t op_errno, struct iatt *buf,
 4739                    dict_t *xdata)
 4740 {
 4741     nfsstat3 status = NFS3ERR_SERVERFAULT;
 4742     nfs3_call_state_t *cs = NULL;
 4743 
 4744     cs = frame->local;
 4745 
 4746     if (op_ret == -1) {
 4747         status = nfs3_cbk_errno_status(op_ret, op_errno);
 4748     } else
 4749         status = NFS3_OK;
 4750 
 4751     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_FSINFO, status,
 4752                         op_errno, cs->resolvedloc.path);
 4753 
 4754     nfs3_fsinfo_reply(cs->req, status, buf);
 4755     nfs3_call_state_wipe(cs);
 4756 
 4757     return 0;
 4758 }
 4759 
 4760 int
 4761 nfs3_fsinfo_resume(void *carg)
 4762 {
 4763     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4764     int ret = -EFAULT;
 4765     nfs_user_t nfu = {
 4766         0,
 4767     };
 4768     nfs3_call_state_t *cs = NULL;
 4769 
 4770     if (!carg)
 4771         return ret;
 4772 
 4773     cs = (nfs3_call_state_t *)carg;
 4774     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 4775     nfs_request_user_init(&nfu, cs->req);
 4776 
 4777     ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 4778                    nfs3svc_fsinfo_cbk, cs);
 4779     if (ret < 0)
 4780         stat = nfs3_errno_to_nfsstat3(-ret);
 4781 
 4782 nfs3err:
 4783     if (ret < 0) {
 4784         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_FSINFO, stat,
 4785                             -ret, cs->resolvedloc.path);
 4786         nfs3_fsinfo_reply(cs->req, stat, NULL);
 4787         nfs3_call_state_wipe(cs);
 4788     }
 4789 
 4790     return ret;
 4791 }
 4792 
 4793 int
 4794 nfs3_fsinfo(rpcsvc_request_t *req, struct nfs3_fh *fh)
 4795 {
 4796     xlator_t *vol = NULL;
 4797     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4798     int ret = -EFAULT;
 4799     struct nfs3_state *nfs3 = NULL;
 4800     nfs3_call_state_t *cs = NULL;
 4801 
 4802     if ((!req) || (!fh)) {
 4803         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 4804                "Bad arguments");
 4805         return -1;
 4806     }
 4807 
 4808     nfs3_log_common_call(rpcsvc_request_xid(req), "FSINFO", fh);
 4809     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 4810     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 4811     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 4812     nfs3_volume_started_check(nfs3, vol, ret, out);
 4813     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 4814 
 4815     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_fsinfo_resume);
 4816     if (ret < 0)
 4817         stat = nfs3_errno_to_nfsstat3(-ret);
 4818 
 4819 nfs3err:
 4820     if (ret < 0) {
 4821         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_FSINFO, stat, -ret,
 4822                             cs ? cs->resolvedloc.path : NULL);
 4823         nfs3_fsinfo_reply(req, stat, NULL);
 4824         nfs3_call_state_wipe(cs);
 4825         ret = 0;
 4826     }
 4827 out:
 4828     return ret;
 4829 }
 4830 
 4831 int
 4832 nfs3svc_fsinfo(rpcsvc_request_t *req)
 4833 {
 4834     int ret = RPCSVC_ACTOR_ERROR;
 4835     fsinfo3args args;
 4836     struct nfs3_fh root = {
 4837         {0},
 4838     };
 4839 
 4840     if (!req)
 4841         return ret;
 4842 
 4843     nfs3_prep_fsinfo3args(&args, &root);
 4844     if (xdr_to_fsinfo3args(req->msg[0], &args) <= 0) {
 4845         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 4846                "Error decoding arguments");
 4847         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 4848         goto rpcerr;
 4849     }
 4850 
 4851     ret = nfs3_fsinfo(req, &root);
 4852     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 4853         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_FSINFO_FAIL,
 4854                "FSINFO procedure failed");
 4855         rpcsvc_request_seterr(req, SYSTEM_ERR);
 4856         ret = RPCSVC_ACTOR_ERROR;
 4857     }
 4858 
 4859 rpcerr:
 4860     return ret;
 4861 }
 4862 
 4863 int
 4864 nfs3_pathconf_reply(rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf)
 4865 {
 4866     pathconf3res res = {
 4867         0,
 4868     };
 4869     uint64_t deviceid = 0;
 4870 
 4871     deviceid = nfs3_request_xlator_deviceid(req);
 4872     nfs3_fill_pathconf3res(&res, stat, buf, deviceid);
 4873     nfs3svc_submit_reply(req, (void *)&res,
 4874                          (nfs3_serializer)xdr_serialize_pathconf3res);
 4875     return 0;
 4876 }
 4877 
 4878 int32_t
 4879 nfs3svc_pathconf_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 4880                      int32_t op_ret, int32_t op_errno, struct iatt *buf,
 4881                      dict_t *xdata)
 4882 {
 4883     struct iatt *sbuf = NULL;
 4884     nfs3_call_state_t *cs = NULL;
 4885     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4886 
 4887     cs = frame->local;
 4888     if (op_ret == -1) {
 4889         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 4890     } else {
 4891         /* If stat fop failed, we can still send the other components
 4892          * in a pathconf reply.
 4893          */
 4894         sbuf = buf;
 4895         stat = NFS3_OK;
 4896     }
 4897 
 4898     nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_PATHCONF, stat,
 4899                         op_errno, cs->resolvedloc.path);
 4900     nfs3_pathconf_reply(cs->req, stat, sbuf);
 4901     nfs3_call_state_wipe(cs);
 4902 
 4903     return 0;
 4904 }
 4905 
 4906 int
 4907 nfs3_pathconf_resume(void *carg)
 4908 {
 4909     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4910     int ret = -EFAULT;
 4911     nfs_user_t nfu = {
 4912         0,
 4913     };
 4914     nfs3_call_state_t *cs = NULL;
 4915 
 4916     if (!carg)
 4917         return ret;
 4918 
 4919     cs = (nfs3_call_state_t *)carg;
 4920     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 4921     nfs_request_user_init(&nfu, cs->req);
 4922     ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
 4923                    nfs3svc_pathconf_cbk, cs);
 4924     if (ret < 0)
 4925         stat = nfs3_errno_to_nfsstat3(-ret);
 4926 nfs3err:
 4927     if (ret < 0) {
 4928         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_PATHCONF, stat,
 4929                             -ret, cs->resolvedloc.path);
 4930         nfs3_pathconf_reply(cs->req, stat, NULL);
 4931         nfs3_call_state_wipe(cs);
 4932     }
 4933 
 4934     return ret;
 4935 }
 4936 
 4937 int
 4938 nfs3_pathconf(rpcsvc_request_t *req, struct nfs3_fh *fh)
 4939 {
 4940     xlator_t *vol = NULL;
 4941     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 4942     int ret = -EFAULT;
 4943     struct nfs3_state *nfs3 = NULL;
 4944     nfs3_call_state_t *cs = NULL;
 4945 
 4946     if ((!req) || (!fh)) {
 4947         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 4948                "Bad arguments");
 4949         return -1;
 4950     }
 4951 
 4952     nfs3_log_common_call(rpcsvc_request_xid(req), "PATHCONF", fh);
 4953     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 4954     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 4955     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 4956     nfs3_volume_started_check(nfs3, vol, ret, out);
 4957     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 4958 
 4959     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_pathconf_resume);
 4960     if (ret < 0)
 4961         stat = nfs3_errno_to_nfsstat3(-ret);
 4962 
 4963 nfs3err:
 4964     if (ret < 0) {
 4965         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_PATHCONF, stat, -ret,
 4966                             cs ? cs->resolvedloc.path : NULL);
 4967         nfs3_pathconf_reply(req, stat, NULL);
 4968         nfs3_call_state_wipe(cs);
 4969         /* Ret must be 0 after this so that the caller does not
 4970          * also send an RPC reply.
 4971          */
 4972         ret = 0;
 4973     }
 4974 out:
 4975     return ret;
 4976 }
 4977 
 4978 int
 4979 nfs3svc_pathconf(rpcsvc_request_t *req)
 4980 {
 4981     struct nfs3_fh fh = {
 4982         {0},
 4983     };
 4984     pathconf3args args;
 4985     int ret = RPCSVC_ACTOR_ERROR;
 4986 
 4987     if (!req)
 4988         return ret;
 4989     nfs3_prep_pathconf3args(&args, &fh);
 4990     if (xdr_to_pathconf3args(req->msg[0], &args) <= 0) {
 4991         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 4992                "Error decoding args");
 4993         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 4994         goto rpcerr;
 4995     }
 4996 
 4997     ret = nfs3_pathconf(req, &fh);
 4998     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 4999         gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_PATHCONF_FAIL,
 5000                "PATHCONF procedure failed");
 5001         rpcsvc_request_seterr(req, SYSTEM_ERR);
 5002         ret = RPCSVC_ACTOR_ERROR;
 5003     }
 5004 
 5005 rpcerr:
 5006     return ret;
 5007 }
 5008 
 5009 int
 5010 nfs3_commit_reply(rpcsvc_request_t *req, nfsstat3 stat, uint64_t wverf,
 5011                   struct iatt *prestat, struct iatt *poststat)
 5012 {
 5013     commit3res res = {
 5014         0,
 5015     };
 5016     uint64_t deviceid = 0;
 5017 
 5018     deviceid = nfs3_request_xlator_deviceid(req);
 5019     nfs3_fill_commit3res(&res, stat, wverf, prestat, poststat, deviceid);
 5020     nfs3svc_submit_reply(req, (void *)&res,
 5021                          (nfs3_serializer)xdr_serialize_commit3res);
 5022 
 5023     return 0;
 5024 }
 5025 
 5026 int32_t
 5027 nfs3svc_commit_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
 5028                    int32_t op_ret, int32_t op_errno, dict_t *xdata)
 5029 {
 5030     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 5031     nfs3_call_state_t *cs = NULL;
 5032     struct nfs3_state *nfs3 = NULL;
 5033 
 5034     cs = frame->local;
 5035     if (op_ret == -1) {
 5036         stat = nfs3_cbk_errno_status(op_ret, op_errno);
 5037     } else
 5038         stat = NFS3_OK;
 5039 
 5040     nfs3 = rpcsvc_request_program_private(cs->req);
 5041     nfs3_log_commit_res(rpcsvc_request_xid(cs->req), stat, op_errno,
 5042                         nfs3->serverstart, cs->resolvedloc.path);
 5043     nfs3_commit_reply(cs->req, stat, nfs3->serverstart, NULL, NULL);
 5044     nfs3_call_state_wipe(cs);
 5045 
 5046     return 0;
 5047 }
 5048 
 5049 int
 5050 nfs3_commit_resume(void *carg)
 5051 {
 5052     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 5053     int ret = -EFAULT;
 5054     nfs_user_t nfu = {
 5055         0,
 5056     };
 5057     nfs3_call_state_t *cs = NULL;
 5058 
 5059     if (!carg)
 5060         return ret;
 5061 
 5062     cs = (nfs3_call_state_t *)carg;
 5063     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 5064 
 5065     if (nfs3_export_sync_trusted(cs->nfs3state, cs->resolvefh.exportid)) {
 5066         ret = -1;
 5067         stat = NFS3_OK;
 5068         goto nfs3err;
 5069     }
 5070 
 5071     nfs_request_user_init(&nfu, cs->req);
 5072     ret = nfs_flush(cs->nfsx, cs->vol, &nfu, cs->fd, nfs3svc_commit_cbk, cs);
 5073     if (ret < 0)
 5074         stat = nfs3_errno_to_nfsstat3(-ret);
 5075 
 5076 nfs3err:
 5077     if (ret < 0) {
 5078         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_COMMIT, stat,
 5079                             -ret, cs->resolvedloc.path);
 5080         nfs3_commit_reply(cs->req, stat, cs->nfs3state->serverstart, NULL,
 5081                           NULL);
 5082         nfs3_call_state_wipe(cs);
 5083         ret = 0;
 5084     }
 5085 
 5086     return 0;
 5087 }
 5088 
 5089 int
 5090 nfs3_commit_open_resume(void *carg)
 5091 {
 5092     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 5093     int ret = -EFAULT;
 5094     nfs3_call_state_t *cs = NULL;
 5095 
 5096     if (!carg)
 5097         return ret;
 5098 
 5099     cs = (nfs3_call_state_t *)carg;
 5100     nfs3_check_fh_resolve_status(cs, stat, nfs3err);
 5101     cs->fd = fd_anonymous(cs->resolvedloc.inode);
 5102     if (!cs->fd) {
 5103         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ANONYMOUS_FD_FAIL,
 5104                "Failed to create anonymous fd.");
 5105         goto nfs3err;
 5106     }
 5107 
 5108     ret = nfs3_commit_resume(cs);
 5109     if (ret < 0)
 5110         stat = nfs3_errno_to_nfsstat3(-ret);
 5111 nfs3err:
 5112     if (ret < 0) {
 5113         nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_COMMIT, stat,
 5114                             -ret, cs->resolvedloc.path);
 5115         nfs3_commit_reply(cs->req, stat, 0, NULL, NULL);
 5116         nfs3_call_state_wipe(cs);
 5117     }
 5118 
 5119     return ret;
 5120 }
 5121 
 5122 int
 5123 nfs3_commit(rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
 5124             count3 count)
 5125 {
 5126     xlator_t *vol = NULL;
 5127     nfsstat3 stat = NFS3ERR_SERVERFAULT;
 5128     int ret = -EFAULT;
 5129     struct nfs3_state *nfs3 = NULL;
 5130     nfs3_call_state_t *cs = NULL;
 5131 
 5132     if ((!req) || (!fh)) {
 5133         gf_msg(GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
 5134                "Bad arguments");
 5135         return -1;
 5136     }
 5137 
 5138     nfs3_log_rw_call(rpcsvc_request_xid(req), "COMMIT", fh, offset, count, -1);
 5139     nfs3_validate_gluster_fh(fh, stat, nfs3err);
 5140     nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
 5141     nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
 5142     nfs3_volume_started_check(nfs3, vol, ret, out);
 5143     nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
 5144     nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
 5145 
 5146     cs->datacount = count;
 5147     cs->dataoffset = offset;
 5148     ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_commit_open_resume);
 5149     if (ret < 0)
 5150         stat = nfs3_errno_to_nfsstat3(-ret);
 5151 
 5152 nfs3err:
 5153     if (ret < 0) {
 5154         nfs3_log_common_res(rpcsvc_request_xid(req), NFS3_COMMIT, stat, -ret,
 5155                             cs ? cs->resolvedloc.path : NULL);
 5156         nfs3_commit_reply(req, stat, 0, NULL, NULL);
 5157         nfs3_call_state_wipe(cs);
 5158         ret = 0;
 5159     }
 5160 out:
 5161     return ret;
 5162 }
 5163 
 5164 int
 5165 nfs3svc_commit(rpcsvc_request_t *req)
 5166 {
 5167     struct nfs3_fh fh = {
 5168         {0},
 5169     };
 5170     commit3args args;
 5171     int ret = RPCSVC_ACTOR_ERROR;
 5172 
 5173     if (!req)
 5174         return ret;
 5175     nfs3_prep_commit3args(&args, &fh);
 5176     if (xdr_to_commit3args(req->msg[0], &args) <= 0) {
 5177         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR,
 5178                "Error decoding args");
 5179         rpcsvc_request_seterr(req, GARBAGE_ARGS);
 5180         goto rpcerr;
 5181     }
 5182 
 5183     ret = nfs3_commit(req, &fh, args.offset, args.count);
 5184     if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
 5185         gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_COMMIT_FAIL,
 5186                "COMMIT procedure failed");
 5187         rpcsvc_request_seterr(req, SYSTEM_ERR);
 5188         ret = RPCSVC_ACTOR_ERROR;
 5189     }
 5190 
 5191 rpcerr:
 5192     return ret;
 5193 }
 5194 
 5195 static rpcsvc_actor_t nfs3svc_actors[NFS3_PROC_COUNT] = {
 5196     {"NULL", nfs3svc_null, NULL, NFS3_NULL, DRC_IDEMPOTENT, 0},
 5197     {"GETATTR", nfs3svc_getattr, NULL, NFS3_GETATTR, DRC_IDEMPOTENT, 0},
 5198     {"SETATTR", nfs3svc_setattr, NULL, NFS3_SETATTR, DRC_NON_IDEMPOTENT, 0},
 5199     {"LOOKUP", nfs3svc_lookup, NULL, NFS3_LOOKUP, DRC_IDEMPOTENT, 0},
 5200     {"ACCESS", nfs3svc_access, NULL, NFS3_ACCESS, DRC_IDEMPOTENT, 0},
 5201     {"READLINK", nfs3svc_readlink, NULL, NFS3_READLINK, DRC_IDEMPOTENT, 0},
 5202     {"READ", nfs3svc_read, NULL, NFS3_READ, DRC_IDEMPOTENT, 0},
 5203     {"WRITE", nfs3svc_write, nfs3svc_write_vecsizer, NFS3_WRITE, DRC_IDEMPOTENT,
 5204      0},
 5205     {"CREATE", nfs3svc_create, NULL, NFS3_CREATE, DRC_NON_IDEMPOTENT, 0},
 5206     {"MKDIR", nfs3svc_mkdir, NULL, NFS3_MKDIR, DRC_NON_IDEMPOTENT, 0},
 5207     {"SYMLINK", nfs3svc_symlink, NULL, NFS3_SYMLINK, DRC_NON_IDEMPOTENT, 0},
 5208     {"MKNOD", nfs3svc_mknod, NULL, NFS3_MKNOD, DRC_NON_IDEMPOTENT, 0},
 5209     {"REMOVE", nfs3svc_remove, NULL, NFS3_REMOVE, DRC_NON_IDEMPOTENT, 0},
 5210     {"RMDIR", nfs3svc_rmdir, NULL, NFS3_RMDIR, DRC_NON_IDEMPOTENT, 0},
 5211     {"RENAME", nfs3svc_rename, NULL, NFS3_RENAME, DRC_NON_IDEMPOTENT, 0},
 5212     {"LINK", nfs3svc_link, NULL, NFS3_LINK, DRC_NON_IDEMPOTENT, 0},
 5213     {"READDIR", nfs3svc_readdir, NULL, NFS3_READDIR, DRC_IDEMPOTENT, 0},
 5214     {"READDIRPLUS", nfs3svc_readdirp, NULL, NFS3_READDIRP, DRC_IDEMPOTENT, 0},
 5215     {"FSSTAT", nfs3svc_fsstat, NULL, NFS3_FSSTAT, DRC_IDEMPOTENT, 0},
 5216     {"FSINFO", nfs3svc_fsinfo, NULL, NFS3_FSINFO, DRC_IDEMPOTENT, 0},
 5217     {"PATHCONF", nfs3svc_pathconf, NULL, NFS3_PATHCONF, DRC_IDEMPOTENT, 0},
 5218     {"COMMIT", nfs3svc_commit, NULL, NFS3_COMMIT, DRC_IDEMPOTENT, 0}};
 5219 
 5220 static rpcsvc_program_t nfs3prog = {
 5221     .progname = "NFS3",
 5222     .prognum = NFS_PROGRAM,
 5223     .progver = NFS_V3,
 5224     .progport = GF_NFS3_PORT,
 5225     .actors = nfs3svc_actors,
 5226     .numactors = NFS3_PROC_COUNT,
 5227 
 5228     /* Requests like FSINFO are sent before an auth scheme
 5229      * is inited by client. See RFC 2623, Section 2.3.2. */
 5230     .min_auth = AUTH_NULL,
 5231 };
 5232 
 5233 /*
 5234  * This function rounds up the input value to multiple of 4096. Min and Max
 5235  * supported I/O size limits are 4KB (GF_NFS3_FILE_IO_SIZE_MIN) and
 5236  * 1MB (GF_NFS3_FILE_IO_SIZE_MAX).
 5237  */
 5238 void
 5239 nfs3_iosize_roundup_4KB(uint64_t *ioszptr)
 5240 {
 5241     uint64_t iosize;
 5242     uint64_t iopages;
 5243 
 5244     if (!ioszptr)
 5245         return;
 5246 
 5247     iosize = *ioszptr;
 5248     iopages = (iosize + GF_NFS3_IO_SIZE - 1) >> GF_NFS3_IO_SHIFT;
 5249     iosize = (iopages * GF_NFS3_IO_SIZE);
 5250 
 5251     /* Double check - boundary conditions */
 5252     if (iosize < GF_NFS3_FILE_IO_SIZE_MIN) {
 5253         iosize = GF_NFS3_FILE_IO_SIZE_MIN;
 5254     } else if (iosize > GF_NFS3_FILE_IO_SIZE_MAX) {
 5255         iosize = GF_NFS3_FILE_IO_SIZE_MAX;
 5256     }
 5257 
 5258     *ioszptr = iosize;
 5259 }
 5260 
 5261 int
 5262 nfs3_init_options(struct nfs3_state *nfs3, dict_t *options)
 5263 {
 5264     int ret = -1;
 5265     char *optstr = NULL;
 5266     uint64_t size64 = 0;
 5267 
 5268     if ((!nfs3) || (!options))
 5269         return -1;
 5270 
 5271     /* nfs3.read-size */
 5272     nfs3->readsize = GF_NFS3_RTPREF;
 5273     if (dict_get(options, "nfs3.read-size")) {
 5274         ret = dict_get_str(options, "nfs3.read-size", &optstr);
 5275         if (ret < 0) {
 5276             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_READ_FAIL,
 5277                    "Failed to read option: nfs3.read-size");
 5278             ret = -1;
 5279             goto err;
 5280         }
 5281 
 5282         ret = gf_string2uint64(optstr, &size64);
 5283         if (ret == -1) {
 5284             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_FORMAT_FAIL,
 5285                    "Failed to format option: nfs3.read-size");
 5286             ret = -1;
 5287             goto err;
 5288         }
 5289 
 5290         nfs3_iosize_roundup_4KB(&size64);
 5291         nfs3->readsize = size64;
 5292     }
 5293 
 5294     /* nfs3.write-size */
 5295     nfs3->writesize = GF_NFS3_WTPREF;
 5296     if (dict_get(options, "nfs3.write-size")) {
 5297         ret = dict_get_str(options, "nfs3.write-size", &optstr);
 5298         if (ret < 0) {
 5299             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_READ_FAIL,
 5300                    "Failed to read  option: nfs3.write-size");
 5301             ret = -1;
 5302             goto err;
 5303         }
 5304 
 5305         ret = gf_string2uint64(optstr, &size64);
 5306         if (ret == -1) {
 5307             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_FORMAT_FAIL,
 5308                    "Failed to format option: nfs3.write-size");
 5309             ret = -1;
 5310             goto err;
 5311         }
 5312 
 5313         nfs3_iosize_roundup_4KB(&size64);
 5314         nfs3->writesize = size64;
 5315     }
 5316 
 5317     /* nfs3.readdir.size */
 5318     nfs3->readdirsize = GF_NFS3_DTPREF;
 5319     if (dict_get(options, "nfs3.readdir-size")) {
 5320         ret = dict_get_str(options, "nfs3.readdir-size", &optstr);
 5321         if (ret < 0) {
 5322             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_READ_FAIL,
 5323                    "Failed to read option: nfs3.readdir-size");
 5324             ret = -1;
 5325             goto err;
 5326         }
 5327 
 5328         ret = gf_string2uint64(optstr, &size64);
 5329         if (ret == -1) {
 5330             gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_FORMAT_FAIL,
 5331                    "Failed to format option: nfs3.readdir-size");
 5332             ret = -1;
 5333             goto err;
 5334         }
 5335 
 5336         nfs3_iosize_roundup_4KB(&size64);
 5337         nfs3->readdirsize = size64;
 5338     }
 5339 
 5340     /* We want to use the size of the biggest param for the io buffer size.
 5341      */
 5342     nfs3->iobsize = nfs3->readsize;
 5343     if (nfs3->iobsize < nfs3->writesize)
 5344         nfs3->iobsize = nfs3->writesize;
 5345     if (nfs3->iobsize < nfs3->readdirsize)
 5346         nfs3->iobsize = nfs3->readdirsize;
 5347 
 5348     /* But this is the true size of each iobuf. We need this size to
 5349      * accommodate the NFS headers also in the same buffer. */
 5350     nfs3->iobsize = nfs3->iobsize * 2;
 5351 
 5352     ret = 0;
 5353 err:
 5354     return ret;
 5355 }
 5356 
 5357 int
 5358