"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/xlators/features/gfid-access/src/gfid-access.c" (16 Sep 2020, 36281 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 "gfid-access.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2    Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com>
    3    This file is part of GlusterFS.
    4 
    5    This file is licensed to you under your choice of the GNU Lesser
    6    General Public License, version 3 or any later version (LGPLv3 or
    7    later), or the GNU General Public License, version 2 (GPLv2), in all
    8    cases as published by the Free Software Foundation.
    9 */
   10 #include "gfid-access.h"
   11 #include <glusterfs/inode.h>
   12 #include <glusterfs/byte-order.h>
   13 #include <glusterfs/statedump.h>
   14 
   15 int
   16 ga_valid_inode_loc_copy(loc_t *dst, loc_t *src, xlator_t *this)
   17 {
   18     int ret = 0;
   19     uint64_t value = 0;
   20 
   21     /* if its an entry operation, on the virtual */
   22     /* directory inode as parent, we need to handle */
   23     /* it properly */
   24     ret = loc_copy(dst, src);
   25     if (ret < 0)
   26         goto out;
   27 
   28     /*
   29      * Change ALL virtual inodes with real-inodes in loc
   30      */
   31     if (dst->parent) {
   32         ret = inode_ctx_get(dst->parent, this, &value);
   33         if (ret < 0) {
   34             ret = 0;  // real-inode
   35             goto out;
   36         }
   37         inode_unref(dst->parent);
   38         dst->parent = inode_ref((inode_t *)(uintptr_t)value);
   39         gf_uuid_copy(dst->pargfid, dst->parent->gfid);
   40     }
   41 
   42     if (dst->inode) {
   43         ret = inode_ctx_get(dst->inode, this, &value);
   44         if (ret < 0) {
   45             ret = 0;  // real-inode
   46             goto out;
   47         }
   48         inode_unref(dst->inode);
   49         dst->inode = inode_ref((inode_t *)(uintptr_t)value);
   50         gf_uuid_copy(dst->gfid, dst->inode->gfid);
   51     }
   52 out:
   53 
   54     return ret;
   55 }
   56 
   57 void
   58 ga_newfile_args_free(ga_newfile_args_t *args)
   59 {
   60     if (!args)
   61         goto out;
   62 
   63     GF_FREE(args->bname);
   64 
   65     if (S_ISLNK(args->st_mode) && args->args.symlink.linkpath) {
   66         GF_FREE(args->args.symlink.linkpath);
   67         args->args.symlink.linkpath = NULL;
   68     }
   69 
   70     mem_put(args);
   71 out:
   72     return;
   73 }
   74 
   75 void
   76 ga_heal_args_free(ga_heal_args_t *args)
   77 {
   78     if (!args)
   79         goto out;
   80 
   81     GF_FREE(args->bname);
   82 
   83     mem_put(args);
   84 out:
   85     return;
   86 }
   87 
   88 ga_newfile_args_t *
   89 ga_newfile_parse_args(xlator_t *this, data_t *data)
   90 {
   91     ga_newfile_args_t *args = NULL;
   92     ga_private_t *priv = NULL;
   93     int len = 0;
   94     int blob_len = 0;
   95     int min_len = 0;
   96     void *blob = NULL;
   97 
   98     priv = this->private;
   99 
  100     blob = data->data;
  101     blob_len = data->len;
  102 
  103     min_len = sizeof(args->uid) + sizeof(args->gid) + sizeof(args->gfid) +
  104               sizeof(args->st_mode) + 2 + 2;
  105     if (blob_len < min_len) {
  106         gf_log(this->name, GF_LOG_ERROR,
  107                "Invalid length: Total length is less "
  108                "than minimum length.");
  109         goto err;
  110     }
  111 
  112     args = mem_get0(priv->newfile_args_pool);
  113     if (args == NULL)
  114         goto err;
  115 
  116     args->uid = ntoh32(*(uint32_t *)blob);
  117     blob += sizeof(uint32_t);
  118     blob_len -= sizeof(uint32_t);
  119 
  120     args->gid = ntoh32(*(uint32_t *)blob);
  121     blob += sizeof(uint32_t);
  122     blob_len -= sizeof(uint32_t);
  123 
  124     memcpy(args->gfid, blob, sizeof(args->gfid));
  125     blob += sizeof(args->gfid);
  126     blob_len -= sizeof(args->gfid);
  127 
  128     args->st_mode = ntoh32(*(uint32_t *)blob);
  129     blob += sizeof(uint32_t);
  130     blob_len -= sizeof(uint32_t);
  131 
  132     len = strnlen(blob, blob_len);
  133     if (len == blob_len) {
  134         gf_log(this->name, GF_LOG_ERROR, "gfid: %s. No null byte present.",
  135                args->gfid);
  136         goto err;
  137     }
  138 
  139     args->bname = GF_MALLOC(len + 1, gf_common_mt_char);
  140     if (args->bname == NULL)
  141         goto err;
  142 
  143     memcpy(args->bname, blob, (len + 1));
  144     blob += (len + 1);
  145     blob_len -= (len + 1);
  146 
  147     if (S_ISDIR(args->st_mode)) {
  148         if (blob_len < sizeof(uint32_t)) {
  149             gf_log(this->name, GF_LOG_ERROR, "gfid: %s. Invalid length",
  150                    args->gfid);
  151             goto err;
  152         }
  153         args->args.mkdir.mode = ntoh32(*(uint32_t *)blob);
  154         blob += sizeof(uint32_t);
  155         blob_len -= sizeof(uint32_t);
  156 
  157         if (blob_len < sizeof(uint32_t)) {
  158             gf_log(this->name, GF_LOG_ERROR, "gfid: %s. Invalid length",
  159                    args->gfid);
  160             goto err;
  161         }
  162         args->args.mkdir.umask = ntoh32(*(uint32_t *)blob);
  163         blob_len -= sizeof(uint32_t);
  164         if (blob_len < 0) {
  165             gf_log(this->name, GF_LOG_ERROR, "gfid: %s. Invalid length",
  166                    args->gfid);
  167             goto err;
  168         }
  169     } else if (S_ISLNK(args->st_mode)) {
  170         len = strnlen(blob, blob_len);
  171         if (len == blob_len) {
  172             gf_log(this->name, GF_LOG_ERROR, "gfid: %s. Invalid length",
  173                    args->gfid);
  174             goto err;
  175         }
  176         args->args.symlink.linkpath = GF_MALLOC(len + 1, gf_common_mt_char);
  177         if (args->args.symlink.linkpath == NULL)
  178             goto err;
  179 
  180         memcpy(args->args.symlink.linkpath, blob, (len + 1));
  181         blob_len -= (len + 1);
  182     } else {
  183         if (blob_len < sizeof(uint32_t)) {
  184             gf_log(this->name, GF_LOG_ERROR, "gfid: %s. Invalid length",
  185                    args->gfid);
  186             goto err;
  187         }
  188         args->args.mknod.mode = ntoh32(*(uint32_t *)blob);
  189         blob += sizeof(uint32_t);
  190         blob_len -= sizeof(uint32_t);
  191 
  192         if (blob_len < sizeof(uint32_t)) {
  193             gf_log(this->name, GF_LOG_ERROR, "gfid: %s. Invalid length",
  194                    args->gfid);
  195             goto err;
  196         }
  197         args->args.mknod.rdev = ntoh32(*(uint32_t *)blob);
  198         blob += sizeof(uint32_t);
  199         blob_len -= sizeof(uint32_t);
  200 
  201         if (blob_len < sizeof(uint32_t)) {
  202             gf_log(this->name, GF_LOG_ERROR, "gfid: %s. Invalid length",
  203                    args->gfid);
  204             goto err;
  205         }
  206         args->args.mknod.umask = ntoh32(*(uint32_t *)blob);
  207         blob_len -= sizeof(uint32_t);
  208     }
  209 
  210     if (blob_len) {
  211         gf_log(this->name, GF_LOG_ERROR, "gfid: %s. Invalid length",
  212                args->gfid);
  213         goto err;
  214     }
  215 
  216     return args;
  217 
  218 err:
  219     if (args)
  220         ga_newfile_args_free(args);
  221 
  222     return NULL;
  223 }
  224 
  225 ga_heal_args_t *
  226 ga_heal_parse_args(xlator_t *this, data_t *data)
  227 {
  228     ga_heal_args_t *args = NULL;
  229     ga_private_t *priv = NULL;
  230     void *blob = NULL;
  231     int len = 0;
  232     int blob_len = 0;
  233 
  234     blob = data->data;
  235     blob_len = data->len;
  236 
  237     priv = this->private;
  238 
  239     /* bname should at least contain a character */
  240     if (blob_len < (sizeof(args->gfid) + 2))
  241         goto err;
  242 
  243     args = mem_get0(priv->heal_args_pool);
  244     if (!args)
  245         goto err;
  246 
  247     memcpy(args->gfid, blob, sizeof(args->gfid));
  248     blob += sizeof(args->gfid);
  249     blob_len -= sizeof(args->gfid);
  250 
  251     len = strnlen(blob, blob_len);
  252     if (len == blob_len)
  253         goto err;
  254 
  255     args->bname = GF_MALLOC(len + 1, gf_common_mt_char);
  256     if (!args->bname)
  257         goto err;
  258 
  259     memcpy(args->bname, blob, len);
  260     args->bname[len] = '\0';
  261     blob_len -= (len + 1);
  262 
  263     if (blob_len)
  264         goto err;
  265 
  266     return args;
  267 
  268 err:
  269     if (args)
  270         ga_heal_args_free(args);
  271 
  272     return NULL;
  273 }
  274 
  275 static int32_t
  276 ga_fill_tmp_loc(loc_t *loc, xlator_t *this, uuid_t gfid, char *bname,
  277                 dict_t *xdata, loc_t *new_loc)
  278 {
  279     int ret = -1;
  280     uint64_t value = 0;
  281     inode_t *parent = NULL;
  282     unsigned char *gfid_ptr = NULL;
  283 
  284     parent = loc->inode;
  285     ret = inode_ctx_get(loc->inode, this, &value);
  286     if (!ret) {
  287         parent = (void *)(uintptr_t)value;
  288         if (gf_uuid_is_null(parent->gfid))
  289             parent = loc->inode;
  290     }
  291 
  292     /* parent itself should be looked up */
  293     gf_uuid_copy(new_loc->pargfid, parent->gfid);
  294     new_loc->parent = inode_ref(parent);
  295 
  296     new_loc->inode = inode_grep(parent->table, parent, bname);
  297     if (!new_loc->inode) {
  298         new_loc->inode = inode_new(parent->table);
  299         gf_uuid_copy(new_loc->inode->gfid, gfid);
  300     }
  301 
  302     loc_path(new_loc, bname);
  303     if (new_loc->path) {
  304         new_loc->name = strrchr(new_loc->path, '/');
  305         if (new_loc->name)
  306             new_loc->name++;
  307     }
  308 
  309     gfid_ptr = GF_MALLOC(sizeof(uuid_t), gf_common_mt_uuid_t);
  310     if (!gfid_ptr) {
  311         ret = -1;
  312         goto out;
  313     }
  314     gf_uuid_copy(gfid_ptr, gfid);
  315     ret = dict_set_gfuuid(xdata, "gfid-req", gfid_ptr, false);
  316     if (ret < 0)
  317         goto out;
  318 
  319     ret = 0;
  320 
  321 out:
  322     if (ret && gfid_ptr)
  323         GF_FREE(gfid_ptr);
  324     return ret;
  325 }
  326 
  327 static gf_boolean_t
  328 __is_gfid_access_dir(uuid_t gfid)
  329 {
  330     static uuid_t aux_gfid = {0, 0, 0, 0, 0, 0, 0, 0,
  331                               0, 0, 0, 0, 0, 0, 0, GF_AUX_GFID};
  332 
  333     if (gf_uuid_compare(gfid, aux_gfid) == 0)
  334         return _gf_true;
  335 
  336     return _gf_false;
  337 }
  338 
  339 int32_t
  340 ga_forget(xlator_t *this, inode_t *inode)
  341 {
  342     int ret = -1;
  343     uint64_t value = 0;
  344     inode_t *tmp_inode = NULL;
  345 
  346     ret = inode_ctx_del(inode, this, &value);
  347     if (ret)
  348         goto out;
  349 
  350     tmp_inode = (void *)(uintptr_t)value;
  351     inode_unref(tmp_inode);
  352 
  353 out:
  354     return 0;
  355 }
  356 
  357 static int
  358 ga_heal_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
  359             int32_t op_errno, inode_t *inode, struct iatt *stat, dict_t *dict,
  360             struct iatt *postparent)
  361 {
  362     call_frame_t *orig_frame = NULL;
  363 
  364     orig_frame = frame->local;
  365     frame->local = NULL;
  366 
  367     /* don't worry about inode linking and other stuff. They'll happen on
  368      * the next lookup.
  369      */
  370     STACK_DESTROY(frame->root);
  371 
  372     STACK_UNWIND_STRICT(setxattr, orig_frame, op_ret, op_errno, dict);
  373 
  374     return 0;
  375 }
  376 
  377 static int
  378 ga_newentry_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  379                 int32_t op_ret, int32_t op_errno, inode_t *inode,
  380                 struct iatt *buf, struct iatt *preparent,
  381                 struct iatt *postparent, dict_t *xdata)
  382 {
  383     ga_local_t *local = NULL;
  384 
  385     local = frame->local;
  386 
  387     /* don't worry about inode linking and other stuff. They'll happen on
  388      * the next lookup.
  389      */
  390     frame->local = NULL;
  391     STACK_DESTROY(frame->root);
  392 
  393     STACK_UNWIND_STRICT(setxattr, local->orig_frame, op_ret, op_errno, xdata);
  394 
  395     if (local->xdata)
  396         dict_unref(local->xdata);
  397     loc_wipe(&local->loc);
  398     mem_put(local);
  399 
  400     return 0;
  401 }
  402 
  403 static int
  404 ga_newentry_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  405                        int32_t op_ret, int32_t op_errno, inode_t *inode,
  406                        struct iatt *stat, dict_t *xdata,
  407                        struct iatt *postparent)
  408 
  409 {
  410     ga_local_t *local = NULL;
  411 
  412     local = frame->local;
  413 
  414     if ((op_ret < 0) && ((op_errno != ENOENT) && (op_errno != ESTALE)))
  415         goto err;
  416 
  417     STACK_WIND(frame, ga_newentry_cbk, FIRST_CHILD(this),
  418                FIRST_CHILD(this)->fops->mknod, &local->loc, local->mode,
  419                local->rdev, local->umask, local->xdata);
  420     return 0;
  421 
  422 err:
  423     frame->local = NULL;
  424     STACK_DESTROY(frame->root);
  425     STACK_UNWIND_STRICT(setxattr, local->orig_frame, op_ret, op_errno, xdata);
  426     if (local->xdata)
  427         dict_unref(local->xdata);
  428     loc_wipe(&local->loc);
  429     mem_put(local);
  430 
  431     return 0;
  432 }
  433 
  434 int32_t
  435 ga_new_entry(call_frame_t *frame, xlator_t *this, loc_t *loc, data_t *data,
  436              dict_t *xdata)
  437 {
  438     int ret = -1;
  439     ga_newfile_args_t *args = NULL;
  440     loc_t tmp_loc = {
  441         0,
  442     };
  443     call_frame_t *new_frame = NULL;
  444     ga_local_t *local = NULL;
  445     uuid_t gfid = {
  446         0,
  447     };
  448 
  449     if (!xdata) {
  450         xdata = dict_new();
  451     } else {
  452         xdata = dict_ref(xdata);
  453     }
  454 
  455     if (!xdata) {
  456         ret = -1;
  457         goto out;
  458     }
  459 
  460     args = ga_newfile_parse_args(this, data);
  461     if (!args)
  462         goto out;
  463 
  464     ret = gf_uuid_parse(args->gfid, gfid);
  465     if (ret)
  466         goto out;
  467 
  468     ret = ga_fill_tmp_loc(loc, this, gfid, args->bname, xdata, &tmp_loc);
  469     if (ret)
  470         goto out;
  471 
  472     new_frame = copy_frame(frame);
  473     if (!new_frame)
  474         goto out;
  475 
  476     local = mem_get0(this->local_pool);
  477     local->orig_frame = frame;
  478 
  479     loc_copy(&local->loc, &tmp_loc);
  480 
  481     new_frame->local = local;
  482     new_frame->root->uid = args->uid;
  483     new_frame->root->gid = args->gid;
  484 
  485     if (S_ISDIR(args->st_mode)) {
  486         STACK_WIND(new_frame, ga_newentry_cbk, FIRST_CHILD(this),
  487                    FIRST_CHILD(this)->fops->mkdir, &tmp_loc,
  488                    args->args.mkdir.mode, args->args.mkdir.umask, xdata);
  489     } else if (S_ISLNK(args->st_mode)) {
  490         STACK_WIND(new_frame, ga_newentry_cbk, FIRST_CHILD(this),
  491                    FIRST_CHILD(this)->fops->symlink,
  492                    args->args.symlink.linkpath, &tmp_loc, 0, xdata);
  493     } else {
  494         /* use 07777 (4 7s) for considering the Sticky bits etc) */
  495         ((ga_local_t *)new_frame->local)->mode = (S_IFMT & args->st_mode) |
  496                                                  (07777 &
  497                                                   args->args.mknod.mode);
  498 
  499         ((ga_local_t *)new_frame->local)->umask = args->args.mknod.umask;
  500         ((ga_local_t *)new_frame->local)->rdev = args->args.mknod.rdev;
  501         ((ga_local_t *)new_frame->local)->xdata = dict_ref(xdata);
  502 
  503         /* send a named lookup, so that dht can cleanup up stale linkto
  504          * files etc.
  505          */
  506         STACK_WIND(new_frame, ga_newentry_lookup_cbk, FIRST_CHILD(this),
  507                    FIRST_CHILD(this)->fops->lookup, &tmp_loc, NULL);
  508     }
  509 
  510     ret = 0;
  511 out:
  512     ga_newfile_args_free(args);
  513 
  514     if (xdata)
  515         dict_unref(xdata);
  516 
  517     loc_wipe(&tmp_loc);
  518 
  519     return ret;
  520 }
  521 
  522 int32_t
  523 ga_heal_entry(call_frame_t *frame, xlator_t *this, loc_t *loc, data_t *data,
  524               dict_t *xdata)
  525 {
  526     int ret = -1;
  527     ga_heal_args_t *args = NULL;
  528     loc_t tmp_loc = {
  529         0,
  530     };
  531     call_frame_t *new_frame = NULL;
  532     uuid_t gfid = {
  533         0,
  534     };
  535 
  536     args = ga_heal_parse_args(this, data);
  537     if (!args)
  538         goto out;
  539 
  540     ret = gf_uuid_parse(args->gfid, gfid);
  541     if (ret)
  542         goto out;
  543 
  544     if (!xdata)
  545         xdata = dict_new();
  546     else
  547         xdata = dict_ref(xdata);
  548 
  549     if (!xdata) {
  550         ret = -1;
  551         goto out;
  552     }
  553 
  554     ret = ga_fill_tmp_loc(loc, this, gfid, args->bname, xdata, &tmp_loc);
  555     if (ret)
  556         goto out;
  557 
  558     new_frame = copy_frame(frame);
  559     if (!new_frame)
  560         goto out;
  561 
  562     new_frame->local = (void *)frame;
  563 
  564     STACK_WIND(new_frame, ga_heal_cbk, FIRST_CHILD(this),
  565                FIRST_CHILD(this)->fops->lookup, &tmp_loc, xdata);
  566 
  567     ret = 0;
  568 out:
  569     if (args)
  570         ga_heal_args_free(args);
  571 
  572     loc_wipe(&tmp_loc);
  573 
  574     if (xdata)
  575         dict_unref(xdata);
  576 
  577     return ret;
  578 }
  579 
  580 int32_t
  581 ga_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  582                 int32_t op_ret, int32_t op_errno, dict_t *xdata)
  583 {
  584     STACK_UNWIND_STRICT(setxattr, frame, op_ret, op_errno, xdata);
  585     return 0;
  586 }
  587 
  588 int32_t
  589 ga_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict,
  590             int32_t flags, dict_t *xdata)
  591 {
  592     data_t *data = NULL;
  593     int op_errno = ENOMEM;
  594     int ret = 0;
  595     loc_t ga_loc = {
  596         0,
  597     };
  598 
  599     GFID_ACCESS_INODE_OP_CHECK(loc, op_errno, err);
  600 
  601     data = dict_get(dict, GF_FUSE_AUX_GFID_NEWFILE);
  602     if (data) {
  603         ret = ga_new_entry(frame, this, loc, data, xdata);
  604         if (ret)
  605             goto err;
  606         return 0;
  607     }
  608 
  609     data = dict_get(dict, GF_FUSE_AUX_GFID_HEAL);
  610     if (data) {
  611         ret = ga_heal_entry(frame, this, loc, data, xdata);
  612         if (ret)
  613             goto err;
  614         return 0;
  615     }
  616 
  617     // If the inode is a virtual inode change the inode otherwise perform
  618     // the operation on same inode
  619     ret = ga_valid_inode_loc_copy(&ga_loc, loc, this);
  620     if (ret < 0)
  621         goto err;
  622 
  623     STACK_WIND(frame, ga_setxattr_cbk, FIRST_CHILD(this),
  624                FIRST_CHILD(this)->fops->setxattr, &ga_loc, dict, flags, xdata);
  625 
  626     loc_wipe(&ga_loc);
  627     return 0;
  628 err:
  629     STACK_UNWIND_STRICT(setxattr, frame, -1, op_errno, xdata);
  630     return 0;
  631 }
  632 
  633 int32_t
  634 ga_virtual_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  635                       int32_t op_ret, int32_t op_errno, inode_t *inode,
  636                       struct iatt *buf, dict_t *xdata, struct iatt *postparent)
  637 {
  638     int ret = 0;
  639     inode_t *cbk_inode = NULL;
  640     inode_t *true_inode = NULL;
  641     uuid_t random_gfid = {
  642         0,
  643     };
  644     inode_t *linked_inode = NULL;
  645 
  646     if (frame->local)
  647         cbk_inode = frame->local;
  648     else
  649         cbk_inode = inode_ref(inode);
  650 
  651     frame->local = NULL;
  652     if (op_ret)
  653         goto unwind;
  654 
  655     if (!IA_ISDIR(buf->ia_type))
  656         goto unwind;
  657 
  658     /* need to send back a different inode for linking in itable */
  659     if (cbk_inode == inode) {
  660         /* check if the inode is in the 'itable' or
  661            if its just previously discover()'d inode */
  662         true_inode = inode_find(inode->table, buf->ia_gfid);
  663         if (!true_inode) {
  664             /* This unref is for 'inode_ref()' done in beginning.
  665                This is needed as cbk_inode is allocated new inode
  666                whose unref is taken at the end*/
  667             inode_unref(cbk_inode);
  668             cbk_inode = inode_new(inode->table);
  669 
  670             if (!cbk_inode) {
  671                 op_ret = -1;
  672                 op_errno = ENOMEM;
  673                 goto unwind;
  674             }
  675             /* the inode is not present in itable, ie, the actual
  676                path is not yet looked up. Use the current inode
  677                itself for now */
  678 
  679             linked_inode = inode_link(inode, NULL, NULL, buf);
  680             inode = linked_inode;
  681         } else {
  682             /* 'inode_ref()' has been done in inode_find() */
  683             inode = true_inode;
  684         }
  685 
  686         ret = inode_ctx_put(cbk_inode, this, (uint64_t)(uintptr_t)inode);
  687         if (ret) {
  688             gf_log(this->name, GF_LOG_WARNING,
  689                    "failed to set the inode ctx with"
  690                    "the actual inode");
  691             if (inode)
  692                 inode_unref(inode);
  693         }
  694         inode = NULL;
  695     }
  696 
  697     if (!gf_uuid_is_null(cbk_inode->gfid)) {
  698         /* if the previous linked inode is used, use the
  699            same gfid */
  700         gf_uuid_copy(random_gfid, cbk_inode->gfid);
  701     } else {
  702         /* replace the buf->ia_gfid to a random gfid
  703            for directory, for files, what we received is fine */
  704         gf_uuid_generate(random_gfid);
  705     }
  706 
  707     gf_uuid_copy(buf->ia_gfid, random_gfid);
  708 
  709     buf->ia_ino = gfid_to_ino(buf->ia_gfid);
  710 
  711 unwind:
  712     /* Lookup on non-existing gfid returns ESTALE.
  713        Convert into ENOENT for virtual lookup*/
  714     if (op_errno == ESTALE)
  715         op_errno = ENOENT;
  716 
  717     STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, cbk_inode, buf, xdata,
  718                         postparent);
  719 
  720     /* Also handles inode_unref of frame->local if done in ga_lookup */
  721     if (cbk_inode)
  722         inode_unref(cbk_inode);
  723 
  724     return 0;
  725 }
  726 
  727 int32_t
  728 ga_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
  729               int32_t op_errno, inode_t *inode, struct iatt *buf, dict_t *xdata,
  730               struct iatt *postparent)
  731 {
  732     ga_private_t *priv = NULL;
  733 
  734     /* if the entry in question is not 'root',
  735        then follow the normal path */
  736     if (op_ret || !__is_root_gfid(buf->ia_gfid))
  737         goto unwind;
  738 
  739     priv = this->private;
  740 
  741     /* do we need to copy root stbuf every time? */
  742     /* mostly yes, as we want to have the 'stat' info show latest
  743        in every _cbk() */
  744 
  745     /* keep the reference for root stat buf */
  746     priv->root_stbuf = *buf;
  747     priv->gfiddir_stbuf = priv->root_stbuf;
  748     priv->gfiddir_stbuf.ia_gfid[15] = GF_AUX_GFID;
  749     priv->gfiddir_stbuf.ia_ino = GF_AUX_GFID;
  750 
  751 unwind:
  752     STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, inode, buf, xdata,
  753                         postparent);
  754     return 0;
  755 }
  756 
  757 int32_t
  758 ga_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)
  759 {
  760     ga_private_t *priv = NULL;
  761     int ret = -1;
  762     uuid_t tmp_gfid = {
  763         0,
  764     };
  765     loc_t tmp_loc = {
  766         0,
  767     };
  768     uint64_t value = 0;
  769     inode_t *inode = NULL;
  770     inode_t *true_inode = NULL;
  771     int32_t op_errno = ENOENT;
  772 
  773     priv = this->private;
  774 
  775     /* Handle nameless lookup on ".gfid" */
  776     if (!loc->parent && __is_gfid_access_dir(loc->gfid)) {
  777         STACK_UNWIND_STRICT(lookup, frame, 0, 0, loc->inode,
  778                             &priv->gfiddir_stbuf, xdata, &priv->root_stbuf);
  779         return 0;
  780     }
  781 
  782     /* if its discover(), no need for any action here */
  783     if (!loc->name)
  784         goto wind;
  785 
  786     /* if its revalidate, and inode is not of type directory,
  787        proceed with 'wind' */
  788     if (loc->inode && loc->inode->ia_type && !IA_ISDIR(loc->inode->ia_type)) {
  789         /* a revalidate on ".gfid/<dentry>" is possible, check for it */
  790         if (((loc->parent && __is_gfid_access_dir(loc->parent->gfid)) ||
  791              __is_gfid_access_dir(loc->pargfid))) {
  792             /* here, just send 'loc->gfid' and 'loc->inode' */
  793             tmp_loc.inode = inode_ref(loc->inode);
  794             gf_uuid_copy(tmp_loc.gfid, loc->inode->gfid);
  795 
  796             STACK_WIND(frame, default_lookup_cbk, FIRST_CHILD(this),
  797                        FIRST_CHILD(this)->fops->lookup, &tmp_loc, xdata);
  798 
  799             inode_unref(tmp_loc.inode);
  800 
  801             return 0;
  802         }
  803 
  804         /* not something to bother, continue the flow */
  805         goto wind;
  806     }
  807 
  808     /* need to check if the lookup is on virtual dir */
  809     if ((loc->name && !strcmp(GF_GFID_DIR, loc->name)) &&
  810         ((loc->parent && __is_root_gfid(loc->parent->gfid)) ||
  811          __is_root_gfid(loc->pargfid))) {
  812         /* this means, the query is on '/.gfid', return the fake stat,
  813            and say success */
  814 
  815         STACK_UNWIND_STRICT(lookup, frame, 0, 0, loc->inode,
  816                             &priv->gfiddir_stbuf, xdata, &priv->root_stbuf);
  817         return 0;
  818     }
  819 
  820     /* now, check if the lookup() is on an existing entry,
  821        but on gfid-path */
  822     if (!((loc->parent && __is_gfid_access_dir(loc->parent->gfid)) ||
  823           __is_gfid_access_dir(loc->pargfid))) {
  824         if (!loc->parent)
  825             goto wind;
  826 
  827         ret = inode_ctx_get(loc->parent, this, &value);
  828         if (ret)
  829             goto wind;
  830 
  831         inode = (inode_t *)(uintptr_t)value;
  832 
  833         ret = loc_copy_overload_parent(&tmp_loc, loc, inode);
  834         if (ret)
  835             goto err;
  836 
  837         STACK_WIND(frame, ga_lookup_cbk, FIRST_CHILD(this),
  838                    FIRST_CHILD(this)->fops->lookup, &tmp_loc, xdata);
  839 
  840         loc_wipe(&tmp_loc);
  841         return 0;
  842     }
  843 
  844     /* make sure the 'basename' is actually a 'canonical-gfid',
  845        otherwise, return error */
  846     ret = gf_uuid_parse(loc->name, tmp_gfid);
  847     if (ret)
  848         goto err;
  849 
  850     /* if its fresh lookup, go ahead and send it down, if not,
  851        for directory, we need indirection to actual dir inode */
  852     if (!(loc->inode && loc->inode->ia_type))
  853         goto discover;
  854 
  855     /* revalidate on directory */
  856     ret = inode_ctx_get(loc->inode, this, &value);
  857     if (ret)
  858         goto err;
  859 
  860     inode = (void *)(uintptr_t)value;
  861 
  862     /* valid inode, already looked up, work on that */
  863     if (inode->ia_type)
  864         goto discover;
  865 
  866     /* check if the inode is in the 'itable' or
  867        if its just previously discover()'d inode */
  868     true_inode = inode_find(loc->inode->table, tmp_gfid);
  869     if (true_inode) {
  870         /* time do another lookup and update the context
  871            with proper inode */
  872         op_errno = ESTALE;
  873         /* 'inode_ref()' done in inode_find */
  874         inode_unref(true_inode);
  875         goto err;
  876     }
  877 
  878 discover:
  879     /* for the virtual entries, we don't need to send 'gfid-req' key, as
  880        for these entries, we don't want to 'set' a new gfid */
  881     if (xdata)
  882         dict_del(xdata, "gfid-req");
  883 
  884     gf_uuid_copy(tmp_loc.gfid, tmp_gfid);
  885 
  886     /* if revalidate, then we need to have the proper reference */
  887     if (inode) {
  888         tmp_loc.inode = inode_ref(inode);
  889         frame->local = inode_ref(loc->inode);
  890     } else {
  891         tmp_loc.inode = inode_ref(loc->inode);
  892     }
  893 
  894     STACK_WIND(frame, ga_virtual_lookup_cbk, FIRST_CHILD(this),
  895                FIRST_CHILD(this)->fops->lookup, &tmp_loc, xdata);
  896 
  897     inode_unref(tmp_loc.inode);
  898 
  899     return 0;
  900 
  901 wind:
  902     /* used for all the normal lookup path */
  903     STACK_WIND(frame, ga_lookup_cbk, FIRST_CHILD(this),
  904                FIRST_CHILD(this)->fops->lookup, loc, xdata);
  905 
  906     return 0;
  907 
  908 err:
  909     STACK_UNWIND_STRICT(lookup, frame, -1, op_errno, loc->inode,
  910                         &priv->gfiddir_stbuf, xdata, &priv->root_stbuf);
  911     return 0;
  912 }
  913 
  914 int
  915 ga_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
  916          mode_t umask, dict_t *xdata)
  917 {
  918     int op_errno = ENOMEM;
  919 
  920     GFID_ACCESS_ENTRY_OP_CHECK(loc, op_errno, err);
  921 
  922     STACK_WIND(frame, default_mkdir_cbk, FIRST_CHILD(this),
  923                FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata);
  924 
  925     return 0;
  926 
  927 err:
  928     STACK_UNWIND_STRICT(mkdir, frame, -1, op_errno, loc->inode, NULL, NULL,
  929                         NULL, xdata);
  930     return 0;
  931 }
  932 
  933 int
  934 ga_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags,
  935           mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata)
  936 {
  937     int op_errno = ENOMEM;
  938 
  939     GFID_ACCESS_ENTRY_OP_CHECK(loc, op_errno, err);
  940 
  941     STACK_WIND(frame, default_create_cbk, FIRST_CHILD(this),
  942                FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, fd,
  943                xdata);
  944     return 0;
  945 err:
  946     STACK_UNWIND_STRICT(create, frame, -1, op_errno, NULL, NULL, NULL, NULL,
  947                         NULL, xdata);
  948 
  949     return 0;
  950 }
  951 
  952 int
  953 ga_symlink(call_frame_t *frame, xlator_t *this, const char *linkname,
  954            loc_t *loc, mode_t umask, dict_t *xdata)
  955 {
  956     int op_errno = ENOMEM;
  957 
  958     GFID_ACCESS_ENTRY_OP_CHECK(loc, op_errno, err);
  959 
  960     STACK_WIND(frame, default_symlink_cbk, FIRST_CHILD(this),
  961                FIRST_CHILD(this)->fops->symlink, linkname, loc, umask, xdata);
  962     return 0;
  963 err:
  964     STACK_UNWIND_STRICT(symlink, frame, -1, op_errno, NULL, NULL, NULL, NULL,
  965                         xdata);
  966 
  967     return 0;
  968 }
  969 
  970 int
  971 ga_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
  972          dev_t rdev, mode_t umask, dict_t *xdata)
  973 {
  974     int op_errno = ENOMEM;
  975 
  976     GFID_ACCESS_ENTRY_OP_CHECK(loc, op_errno, err);
  977 
  978     STACK_WIND(frame, default_mknod_cbk, FIRST_CHILD(this),
  979                FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, xdata);
  980 
  981     return 0;
  982 err:
  983     STACK_UNWIND_STRICT(mknod, frame, -1, op_errno, NULL, NULL, NULL, NULL,
  984                         xdata);
  985 
  986     return 0;
  987 }
  988 
  989 int
  990 ga_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int flag,
  991          dict_t *xdata)
  992 {
  993     int op_errno = ENOMEM;
  994     int ret = -1;
  995     loc_t ga_loc = {
  996         0,
  997     };
  998 
  999     GFID_ACCESS_ENTRY_OP_CHECK(loc, op_errno, err);
 1000 
 1001     ret = ga_valid_inode_loc_copy(&ga_loc, loc, this);
 1002     if (ret < 0)
 1003         goto err;
 1004 
 1005     STACK_WIND(frame, default_rmdir_cbk, FIRST_CHILD(this),
 1006                FIRST_CHILD(this)->fops->rmdir, &ga_loc, flag, xdata);
 1007 
 1008     loc_wipe(&ga_loc);
 1009     return 0;
 1010 err:
 1011     STACK_UNWIND_STRICT(rmdir, frame, -1, op_errno, NULL, NULL, xdata);
 1012 
 1013     return 0;
 1014 }
 1015 
 1016 int
 1017 ga_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t xflag,
 1018           dict_t *xdata)
 1019 {
 1020     int op_errno = ENOMEM;
 1021     int ret = -1;
 1022     loc_t ga_loc = {
 1023         0,
 1024     };
 1025 
 1026     GFID_ACCESS_ENTRY_OP_CHECK(loc, op_errno, err);
 1027 
 1028     ret = ga_valid_inode_loc_copy(&ga_loc, loc, this);
 1029     if (ret < 0)
 1030         goto err;
 1031 
 1032     STACK_WIND(frame, default_unlink_cbk, FIRST_CHILD(this),
 1033                FIRST_CHILD(this)->fops->unlink, &ga_loc, xflag, xdata);
 1034 
 1035     loc_wipe(&ga_loc);
 1036     return 0;
 1037 err:
 1038     STACK_UNWIND_STRICT(unlink, frame, -1, op_errno, NULL, NULL, xdata);
 1039 
 1040     return 0;
 1041 }
 1042 
 1043 int
 1044 ga_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
 1045           dict_t *xdata)
 1046 {
 1047     int op_errno = ENOMEM;
 1048     int ret = 0;
 1049     loc_t ga_oldloc = {
 1050         0,
 1051     };
 1052     loc_t ga_newloc = {
 1053         0,
 1054     };
 1055 
 1056     GFID_ACCESS_ENTRY_OP_CHECK(oldloc, op_errno, err);
 1057     GFID_ACCESS_ENTRY_OP_CHECK(newloc, op_errno, err);
 1058 
 1059     ret = ga_valid_inode_loc_copy(&ga_oldloc, oldloc, this);
 1060     if (ret < 0)
 1061         goto err;
 1062 
 1063     ret = ga_valid_inode_loc_copy(&ga_newloc, newloc, this);
 1064     if (ret < 0) {
 1065         loc_wipe(&ga_oldloc);
 1066         goto err;
 1067     }
 1068 
 1069     STACK_WIND(frame, default_rename_cbk, FIRST_CHILD(this),
 1070                FIRST_CHILD(this)->fops->rename, &ga_oldloc, &ga_newloc, xdata);
 1071 
 1072     loc_wipe(&ga_newloc);
 1073     loc_wipe(&ga_oldloc);
 1074     return 0;
 1075 err:
 1076     STACK_UNWIND_STRICT(rename, frame, -1, op_errno, NULL, NULL, NULL, NULL,
 1077                         NULL, xdata);
 1078 
 1079     return 0;
 1080 }
 1081 
 1082 int
 1083 ga_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
 1084         dict_t *xdata)
 1085 {
 1086     int op_errno = ENOMEM;
 1087     int ret = 0;
 1088     loc_t ga_oldloc = {
 1089         0,
 1090     };
 1091     loc_t ga_newloc = {
 1092         0,
 1093     };
 1094 
 1095     GFID_ACCESS_ENTRY_OP_CHECK(oldloc, op_errno, err);
 1096     GFID_ACCESS_ENTRY_OP_CHECK(newloc, op_errno, err);
 1097 
 1098     ret = ga_valid_inode_loc_copy(&ga_oldloc, oldloc, this);
 1099     if (ret < 0)
 1100         goto err;
 1101 
 1102     ret = ga_valid_inode_loc_copy(&ga_newloc, newloc, this);
 1103     if (ret < 0) {
 1104         loc_wipe(&ga_oldloc);
 1105         goto err;
 1106     }
 1107 
 1108     STACK_WIND(frame, default_link_cbk, FIRST_CHILD(this),
 1109                FIRST_CHILD(this)->fops->link, &ga_oldloc, &ga_newloc, xdata);
 1110 
 1111     loc_wipe(&ga_newloc);
 1112     loc_wipe(&ga_oldloc);
 1113     return 0;
 1114 
 1115 err:
 1116     STACK_UNWIND_STRICT(link, frame, -1, op_errno, NULL, NULL, NULL, NULL,
 1117                         xdata);
 1118 
 1119     return 0;
 1120 }
 1121 
 1122 int32_t
 1123 ga_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd,
 1124            dict_t *xdata)
 1125 {
 1126     int op_errno = ENOMEM;
 1127 
 1128     GFID_ACCESS_INODE_OP_CHECK(loc, op_errno, err);
 1129 
 1130     /* also check if the loc->inode itself is virtual
 1131        inode, if yes, return with failure, mainly because we
 1132        can't handle all the readdirp and other things on it. */
 1133     if (inode_ctx_get(loc->inode, this, NULL) == 0) {
 1134         op_errno = ENOTSUP;
 1135         goto err;
 1136     }
 1137 
 1138     STACK_WIND(frame, default_opendir_cbk, FIRST_CHILD(this),
 1139                FIRST_CHILD(this)->fops->opendir, loc, fd, xdata);
 1140     return 0;
 1141 err:
 1142     STACK_UNWIND_STRICT(opendir, frame, -1, op_errno, NULL, xdata);
 1143 
 1144     return 0;
 1145 }
 1146 
 1147 int32_t
 1148 ga_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
 1149             dict_t *xdata)
 1150 {
 1151     int op_errno = ENOMEM;
 1152     int ret = -1;
 1153     loc_t ga_loc = {
 1154         0,
 1155     };
 1156 
 1157     GFID_ACCESS_INODE_OP_CHECK(loc, op_errno, err);
 1158     ret = ga_valid_inode_loc_copy(&ga_loc, loc, this);
 1159     if (ret < 0)
 1160         goto err;
 1161 
 1162     STACK_WIND(frame, default_getxattr_cbk, FIRST_CHILD(this),
 1163                FIRST_CHILD(this)->fops->getxattr, &ga_loc, name, xdata);
 1164 
 1165     loc_wipe(&ga_loc);
 1166 
 1167     return 0;
 1168 err:
 1169     STACK_UNWIND_STRICT(getxattr, frame, -1, op_errno, NULL, xdata);
 1170 
 1171     return 0;
 1172 }
 1173 
 1174 int32_t
 1175 ga_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)
 1176 {
 1177     int op_errno = ENOMEM;
 1178     int ret = -1;
 1179     loc_t ga_loc = {
 1180         0,
 1181     };
 1182     ga_private_t *priv = NULL;
 1183 
 1184     priv = this->private;
 1185     /* If stat is on ".gfid" itself, do not wind further,
 1186      * return fake stat and return success.
 1187      */
 1188     if (__is_gfid_access_dir(loc->gfid))
 1189         goto out;
 1190 
 1191     ret = ga_valid_inode_loc_copy(&ga_loc, loc, this);
 1192     if (ret < 0)
 1193         goto err;
 1194 
 1195     STACK_WIND(frame, default_stat_cbk, FIRST_CHILD(this),
 1196                FIRST_CHILD(this)->fops->stat, &ga_loc, xdata);
 1197 
 1198     loc_wipe(&ga_loc);
 1199     return 0;
 1200 
 1201 err:
 1202     STACK_UNWIND_STRICT(stat, frame, -1, op_errno, NULL, xdata);
 1203 
 1204     return 0;
 1205 
 1206 out:
 1207     STACK_UNWIND_STRICT(stat, frame, 0, 0, &priv->gfiddir_stbuf, xdata);
 1208     return 0;
 1209 }
 1210 
 1211 int32_t
 1212 ga_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *stbuf,
 1213            int32_t valid, dict_t *xdata)
 1214 {
 1215     int op_errno = ENOMEM;
 1216     int ret = -1;
 1217     loc_t ga_loc = {
 1218         0,
 1219     };
 1220 
 1221     GFID_ACCESS_INODE_OP_CHECK(loc, op_errno, err);
 1222     ret = ga_valid_inode_loc_copy(&ga_loc, loc, this);
 1223     if (ret < 0)
 1224         goto err;
 1225 
 1226     STACK_WIND(frame, default_setattr_cbk, FIRST_CHILD(this),
 1227                FIRST_CHILD(this)->fops->setattr, &ga_loc, stbuf, valid, xdata);
 1228 
 1229     loc_wipe(&ga_loc);
 1230     return 0;
 1231 err:
 1232     STACK_UNWIND_STRICT(setattr, frame, -1, op_errno, NULL, NULL, xdata);
 1233 
 1234     return 0;
 1235 }
 1236 
 1237 int32_t
 1238 ga_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc,
 1239                const char *name, dict_t *xdata)
 1240 {
 1241     int op_errno = ENOMEM;
 1242     int ret = -1;
 1243     loc_t ga_loc = {
 1244         0,
 1245     };
 1246 
 1247     GFID_ACCESS_INODE_OP_CHECK(loc, op_errno, err);
 1248     ret = ga_valid_inode_loc_copy(&ga_loc, loc, this);
 1249     if (ret < 0)
 1250         goto err;
 1251 
 1252     STACK_WIND(frame, default_removexattr_cbk, FIRST_CHILD(this),
 1253                FIRST_CHILD(this)->fops->removexattr, &ga_loc, name, xdata);
 1254 
 1255     loc_wipe(&ga_loc);
 1256     return 0;
 1257 
 1258 err:
 1259     STACK_UNWIND_STRICT(removexattr, frame, -1, op_errno, xdata);
 1260 
 1261     return 0;
 1262 }
 1263 
 1264 int32_t
 1265 mem_acct_init(xlator_t *this)
 1266 {
 1267     int ret = -1;
 1268 
 1269     if (!this)
 1270         return ret;
 1271 
 1272     ret = xlator_mem_acct_init(this, gf_gfid_access_mt_end + 1);
 1273 
 1274     if (ret != 0) {
 1275         gf_log(this->name, GF_LOG_WARNING,
 1276                "Memory accounting"
 1277                " init failed");
 1278         return ret;
 1279     }
 1280 
 1281     return ret;
 1282 }
 1283 
 1284 int32_t
 1285 init(xlator_t *this)
 1286 {
 1287     ga_private_t *priv = NULL;
 1288     int ret = -1;
 1289 
 1290     if (!this->children || this->children->next) {
 1291         gf_log(this->name, GF_LOG_ERROR,
 1292                "not configured with exactly one child. exiting");
 1293         goto out;
 1294     }
 1295 
 1296     /* This can be the top of graph in certain cases */
 1297     if (!this->parents) {
 1298         gf_log(this->name, GF_LOG_DEBUG, "dangling volume. check volfile ");
 1299     }
 1300 
 1301     /* TODO: define a mem-type structure */
 1302     priv = GF_CALLOC(1, sizeof(*priv), gf_gfid_access_mt_priv_t);
 1303     if (!priv)
 1304         goto out;
 1305 
 1306     priv->newfile_args_pool = mem_pool_new(ga_newfile_args_t, 512);
 1307     if (!priv->newfile_args_pool)
 1308         goto out;
 1309 
 1310     priv->heal_args_pool = mem_pool_new(ga_heal_args_t, 512);
 1311     if (!priv->heal_args_pool)
 1312         goto out;
 1313 
 1314     this->local_pool = mem_pool_new(ga_local_t, 16);
 1315     if (!this->local_pool) {
 1316         gf_log(this->name, GF_LOG_ERROR,
 1317                "failed to create local_t's memory pool");
 1318         goto out;
 1319     }
 1320 
 1321     this->private = priv;
 1322 
 1323     ret = 0;
 1324 out:
 1325     if (ret && priv) {
 1326         if (priv->newfile_args_pool)
 1327             mem_pool_destroy(priv->newfile_args_pool);
 1328         GF_FREE(priv);
 1329     }
 1330 
 1331     return ret;
 1332 }
 1333 
 1334 void
 1335 fini(xlator_t *this)
 1336 {
 1337     ga_private_t *priv = NULL;
 1338     priv = this->private;
 1339     this->private = NULL;
 1340 
 1341     if (priv) {
 1342         if (priv->newfile_args_pool)
 1343             mem_pool_destroy(priv->newfile_args_pool);
 1344         if (priv->heal_args_pool)
 1345             mem_pool_destroy(priv->heal_args_pool);
 1346         GF_FREE(priv);
 1347     }
 1348 
 1349     return;
 1350 }
 1351 
 1352 int32_t
 1353 ga_dump_inodectx(xlator_t *this, inode_t *inode)
 1354 {
 1355     int ret = -1;
 1356     uint64_t value = 0;
 1357     inode_t *tmp_inode = NULL;
 1358     char key_prefix[GF_DUMP_MAX_BUF_LEN] = {
 1359         0,
 1360     };
 1361 
 1362     ret = inode_ctx_get(inode, this, &value);
 1363     if (ret == 0) {
 1364         tmp_inode = (void *)(uintptr_t)value;
 1365         gf_proc_dump_build_key(key_prefix, this->name, "inode");
 1366         gf_proc_dump_add_section("%s", key_prefix);
 1367         gf_proc_dump_write("real-gfid", "%s", uuid_utoa(tmp_inode->gfid));
 1368     }
 1369 
 1370     return 0;
 1371 }
 1372 
 1373 struct xlator_fops fops = {
 1374     .lookup = ga_lookup,
 1375 
 1376     /* entry fops */
 1377     .mkdir = ga_mkdir,
 1378     .mknod = ga_mknod,
 1379     .create = ga_create,
 1380     .symlink = ga_symlink,
 1381     .link = ga_link,
 1382     .unlink = ga_unlink,
 1383     .rmdir = ga_rmdir,
 1384     .rename = ga_rename,
 1385 
 1386     /* handle any other directory operations here */
 1387     .opendir = ga_opendir,
 1388     .stat = ga_stat,
 1389     .setattr = ga_setattr,
 1390     .getxattr = ga_getxattr,
 1391     .removexattr = ga_removexattr,
 1392 
 1393     /* special fop to handle more entry creations */
 1394     .setxattr = ga_setxattr,
 1395 };
 1396 
 1397 struct xlator_cbks cbks = {
 1398     .forget = ga_forget,
 1399 };
 1400 
 1401 struct xlator_dumpops dumpops = {
 1402     .inodectx = ga_dump_inodectx,
 1403 };
 1404 
 1405 struct volume_options options[] = {
 1406     /* This translator doesn't take any options, or provide any options */
 1407     {.key = {NULL}},
 1408 };
 1409 
 1410 xlator_api_t xlator_api = {
 1411     .init = init,
 1412     .fini = fini,
 1413     .mem_acct_init = mem_acct_init,
 1414     .op_version = {1},
 1415     .fops = &fops,
 1416     .cbks = &cbks,
 1417     .options = options,
 1418     .identifier = "gfid-access",
 1419     .category = GF_MAINTAINED,
 1420 };