"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/libglusterfs/src/xlator.c" (16 Sep 2020, 36964 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 "xlator.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2   Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
    3   This file is part of GlusterFS.
    4 
    5   This file is licensed to you under your choice of the GNU Lesser
    6   General Public License, version 3 or any later version (LGPLv3 or
    7   later), or the GNU General Public License, version 2 (GPLv2), in all
    8   cases as published by the Free Software Foundation.
    9 */
   10 
   11 #include "glusterfs/xlator.h"
   12 #include <dlfcn.h>
   13 #include <netdb.h>
   14 #include <fnmatch.h>
   15 #include "glusterfs/defaults.h"
   16 #include "glusterfs/libglusterfs-messages.h"
   17 
   18 #define SET_DEFAULT_FOP(fn)                                                    \
   19     do {                                                                       \
   20         if (!xl->fops->fn)                                                     \
   21             xl->fops->fn = default_##fn;                                       \
   22         if (!xl->pass_through_fops->fn)                                        \
   23             xl->pass_through_fops->fn = default_##fn;                          \
   24     } while (0)
   25 
   26 #define SET_DEFAULT_CBK(fn)                                                    \
   27     do {                                                                       \
   28         if (!xl->cbks->fn)                                                     \
   29             xl->cbks->fn = default_##fn;                                       \
   30     } while (0)
   31 
   32 pthread_mutex_t xlator_init_mutex = PTHREAD_MUTEX_INITIALIZER;
   33 
   34 void
   35 xlator_init_lock(void)
   36 {
   37     (void)pthread_mutex_lock(&xlator_init_mutex);
   38 }
   39 
   40 void
   41 xlator_init_unlock(void)
   42 {
   43     (void)pthread_mutex_unlock(&xlator_init_mutex);
   44 }
   45 
   46 static struct xlator_cbks default_cbks = {};
   47 struct volume_options default_options[] = {
   48     {
   49         .key = {"log-level"},
   50         .type = GF_OPTION_TYPE_STR,
   51         .op_version = {GD_OP_VERSION_6_0},
   52         .flags = OPT_FLAG_SETTABLE,
   53         .tags = {"generic"},
   54         .value = {"DEBUG", "WARNING", "ERROR", "INFO", "CRITICAL", "NONE",
   55                   "TRACE"},
   56         .description = "Option to set log-level of given translator",
   57     },
   58     {
   59         .key = {NULL},
   60     },
   61 };
   62 
   63 /* Handle the common options in each translator */
   64 void
   65 handle_default_options(xlator_t *xl, dict_t *options)
   66 {
   67     int ret;
   68     char *value;
   69 
   70     /* log-level */
   71     ret = dict_get_str(options, "log-level", &value);
   72     if (!ret) {
   73         int log_level = glusterd_check_log_level(value);
   74         if (log_level != -1) {
   75             xl->loglevel = log_level;
   76         }
   77     }
   78 }
   79 
   80 static void
   81 fill_defaults(xlator_t *xl)
   82 {
   83     if (xl == NULL) {
   84         gf_msg_callingfn("xlator", GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
   85                          "invalid argument");
   86         return;
   87     }
   88 
   89     if (!xl->pass_through_fops)
   90         xl->pass_through_fops = default_fops;
   91 
   92     SET_DEFAULT_FOP(create);
   93     SET_DEFAULT_FOP(open);
   94     SET_DEFAULT_FOP(stat);
   95     SET_DEFAULT_FOP(readlink);
   96     SET_DEFAULT_FOP(mknod);
   97     SET_DEFAULT_FOP(mkdir);
   98     SET_DEFAULT_FOP(unlink);
   99     SET_DEFAULT_FOP(rmdir);
  100     SET_DEFAULT_FOP(symlink);
  101     SET_DEFAULT_FOP(rename);
  102     SET_DEFAULT_FOP(link);
  103     SET_DEFAULT_FOP(truncate);
  104     SET_DEFAULT_FOP(readv);
  105     SET_DEFAULT_FOP(writev);
  106     SET_DEFAULT_FOP(statfs);
  107     SET_DEFAULT_FOP(flush);
  108     SET_DEFAULT_FOP(fsync);
  109     SET_DEFAULT_FOP(setxattr);
  110     SET_DEFAULT_FOP(getxattr);
  111     SET_DEFAULT_FOP(fsetxattr);
  112     SET_DEFAULT_FOP(fgetxattr);
  113     SET_DEFAULT_FOP(removexattr);
  114     SET_DEFAULT_FOP(fremovexattr);
  115     SET_DEFAULT_FOP(opendir);
  116     SET_DEFAULT_FOP(readdir);
  117     SET_DEFAULT_FOP(readdirp);
  118     SET_DEFAULT_FOP(fsyncdir);
  119     SET_DEFAULT_FOP(access);
  120     SET_DEFAULT_FOP(ftruncate);
  121     SET_DEFAULT_FOP(fstat);
  122     SET_DEFAULT_FOP(lk);
  123     SET_DEFAULT_FOP(inodelk);
  124     SET_DEFAULT_FOP(finodelk);
  125     SET_DEFAULT_FOP(entrylk);
  126     SET_DEFAULT_FOP(fentrylk);
  127     SET_DEFAULT_FOP(lookup);
  128     SET_DEFAULT_FOP(rchecksum);
  129     SET_DEFAULT_FOP(xattrop);
  130     SET_DEFAULT_FOP(fxattrop);
  131     SET_DEFAULT_FOP(setattr);
  132     SET_DEFAULT_FOP(fsetattr);
  133     SET_DEFAULT_FOP(fallocate);
  134     SET_DEFAULT_FOP(discard);
  135     SET_DEFAULT_FOP(zerofill);
  136     SET_DEFAULT_FOP(ipc);
  137     SET_DEFAULT_FOP(seek);
  138     SET_DEFAULT_FOP(lease);
  139     SET_DEFAULT_FOP(getactivelk);
  140     SET_DEFAULT_FOP(setactivelk);
  141     SET_DEFAULT_FOP(put);
  142 
  143     SET_DEFAULT_FOP(getspec);
  144     SET_DEFAULT_FOP(icreate);
  145     SET_DEFAULT_FOP(namelink);
  146     SET_DEFAULT_FOP(copy_file_range);
  147 
  148     if (!xl->cbks)
  149         xl->cbks = &default_cbks;
  150 
  151     SET_DEFAULT_CBK(release);
  152     SET_DEFAULT_CBK(releasedir);
  153     SET_DEFAULT_CBK(forget);
  154 
  155     if (!xl->fini)
  156         xl->fini = default_fini;
  157 
  158     if (!xl->notify)
  159         xl->notify = default_notify;
  160 
  161     if (!xl->mem_acct_init)
  162         xl->mem_acct_init = default_mem_acct_init;
  163 
  164     return;
  165 }
  166 
  167 int
  168 xlator_set_type_virtual(xlator_t *xl, const char *type)
  169 {
  170     GF_VALIDATE_OR_GOTO("xlator", xl, out);
  171     GF_VALIDATE_OR_GOTO("xlator", type, out);
  172 
  173     xl->type = gf_strdup(type);
  174 
  175     if (xl->type)
  176         return 0;
  177 
  178 out:
  179     return -1;
  180 }
  181 
  182 int
  183 xlator_volopt_dynload(char *xlator_type, void **dl_handle,
  184                       volume_opt_list_t *opt_list)
  185 {
  186     int ret = -1;
  187     char *name = NULL;
  188     void *handle = NULL;
  189     xlator_api_t *xlapi = NULL;
  190 
  191     GF_VALIDATE_OR_GOTO("xlator", xlator_type, out);
  192 
  193     /* socket.so doesn't fall under the default xlator directory, hence we
  194      * need this check */
  195     if (!strstr(xlator_type, "rpc-transport"))
  196         ret = gf_asprintf(&name, "%s/%s.so", XLATORDIR, xlator_type);
  197     else
  198         ret = gf_asprintf(&name, "%s/%s.so", XLATORPARENTDIR, xlator_type);
  199     if (-1 == ret) {
  200         goto out;
  201     }
  202 
  203     ret = -1;
  204 
  205     gf_msg_trace("xlator", 0, "attempt to load file %s", name);
  206 
  207     handle = dlopen(name, RTLD_NOW);
  208     if (!handle) {
  209         gf_smsg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED, "error=%s",
  210                 dlerror(), NULL);
  211         goto out;
  212     }
  213 
  214     /* check new struct first, and then check this */
  215     xlapi = dlsym(handle, "xlator_api");
  216     if (!xlapi) {
  217         gf_smsg("xlator", GF_LOG_ERROR, 0, LG_MSG_DLSYM_ERROR, "error=%s",
  218                 dlerror(), NULL);
  219         goto out;
  220     }
  221 
  222     opt_list->given_opt = xlapi->options;
  223     if (!opt_list->given_opt) {
  224         gf_smsg("xlator", GF_LOG_ERROR, 0, LG_MSG_LOAD_FAILED, NULL);
  225         goto out;
  226     }
  227 
  228     *dl_handle = handle;
  229     handle = NULL;
  230 
  231     ret = 0;
  232 out:
  233     GF_FREE(name);
  234     if (handle)
  235         dlclose(handle);
  236 
  237     gf_msg_debug("xlator", 0, "Returning %d", ret);
  238     return ret;
  239 }
  240 
  241 static int
  242 xlator_dynload_apis(xlator_t *xl)
  243 {
  244     int ret = -1;
  245     void *handle = NULL;
  246     volume_opt_list_t *vol_opt = NULL;
  247     xlator_api_t *xlapi = NULL;
  248 
  249     handle = xl->dlhandle;
  250 
  251     xlapi = dlsym(handle, "xlator_api");
  252     if (!xlapi) {
  253         gf_smsg("xlator", GF_LOG_ERROR, 0, LG_MSG_DLSYM_ERROR, "dlsym=%s",
  254                 dlerror(), NULL);
  255         ret = -1;
  256         goto out;
  257     }
  258 
  259     xl->fops = xlapi->fops;
  260     if (!xl->fops) {
  261         gf_smsg("xlator", GF_LOG_WARNING, 0, LG_MSG_STRUCT_MISS, "name=%s",
  262                 xl->name, NULL);
  263         goto out;
  264     }
  265 
  266     xl->cbks = xlapi->cbks;
  267     if (!xl->cbks) {
  268         gf_msg_trace("xlator", 0, "%s: struct missing (cbks)", xl->name);
  269     }
  270 
  271     xl->init = xlapi->init;
  272     if (!xl->init) {
  273         gf_smsg("xlator", GF_LOG_WARNING, 0, LG_MSG_METHOD_MISS, "name=%s",
  274                 xl->name, NULL);
  275         goto out;
  276     }
  277 
  278     xl->fini = xlapi->fini;
  279     if (!xl->fini) {
  280         gf_msg_trace("xlator", 0, "%s: method missing (fini)", xl->name);
  281     }
  282 
  283     xl->reconfigure = xlapi->reconfigure;
  284     if (!xl->reconfigure) {
  285         gf_msg_trace("xlator", 0, "%s: method missing (reconfigure)", xl->name);
  286     }
  287     xl->notify = xlapi->notify;
  288     if (!xl->notify) {
  289         gf_msg_trace("xlator", 0, "%s: method missing (notify)", xl->name);
  290     }
  291     xl->dumpops = xlapi->dumpops;
  292     if (!xl->dumpops) {
  293         gf_msg_trace("xlator", 0, "%s: method missing (dumpops)", xl->name);
  294     }
  295     xl->mem_acct_init = xlapi->mem_acct_init;
  296     if (!xl->mem_acct_init) {
  297         gf_msg_trace("xlator", 0, "%s: method missing (mem_acct_init)",
  298                      xl->name);
  299     }
  300 
  301     xl->dump_metrics = xlapi->dump_metrics;
  302     if (!xl->dump_metrics) {
  303         gf_msg_trace("xlator", 0, "%s: method missing (dump_metrics)",
  304                      xl->name);
  305     }
  306 
  307     xl->pass_through_fops = xlapi->pass_through_fops;
  308     if (!xl->pass_through_fops) {
  309         gf_msg_trace("xlator", 0,
  310                      "%s: method missing (pass_through_fops), "
  311                      "falling back to default",
  312                      xl->name);
  313     }
  314 
  315     vol_opt = GF_CALLOC(1, sizeof(volume_opt_list_t),
  316                         gf_common_mt_volume_opt_list_t);
  317     if (!vol_opt) {
  318         goto out;
  319     }
  320     INIT_LIST_HEAD(&vol_opt->list);
  321 
  322     vol_opt->given_opt = default_options;
  323     list_add_tail(&vol_opt->list, &xl->volume_options);
  324 
  325     if (xlapi->options) {
  326         vol_opt = GF_CALLOC(1, sizeof(volume_opt_list_t),
  327                             gf_common_mt_volume_opt_list_t);
  328         if (!vol_opt) {
  329             goto out;
  330         }
  331         INIT_LIST_HEAD(&vol_opt->list);
  332 
  333         vol_opt->given_opt = xlapi->options;
  334         list_add_tail(&vol_opt->list, &xl->volume_options);
  335     }
  336 
  337     xl->id = xlapi->xlator_id;
  338     xl->flags = xlapi->flags;
  339     xl->identifier = xlapi->identifier;
  340     xl->category = xlapi->category;
  341 
  342     memcpy(xl->op_version, xlapi->op_version,
  343            sizeof(uint32_t) * GF_MAX_RELEASES);
  344 
  345     ret = 0;
  346 out:
  347     return ret;
  348 }
  349 
  350 int
  351 xlator_dynload(xlator_t *xl)
  352 {
  353     int ret = -1;
  354     char *name = NULL;
  355     void *handle = NULL;
  356 
  357     GF_VALIDATE_OR_GOTO("xlator", xl, out);
  358 
  359     INIT_LIST_HEAD(&xl->volume_options);
  360 
  361     ret = gf_asprintf(&name, "%s/%s.so", XLATORDIR, xl->type);
  362     if (-1 == ret) {
  363         goto out;
  364     }
  365 
  366     ret = -1;
  367 
  368     gf_msg_trace("xlator", 0, "attempt to load file %s", name);
  369 
  370     handle = dlopen(name, RTLD_NOW);
  371     if (!handle) {
  372         gf_smsg("xlator", GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED, "error=%s",
  373                 dlerror(), NULL);
  374         goto out;
  375     }
  376     xl->dlhandle = handle;
  377 
  378     ret = xlator_dynload_apis(xl);
  379     if (-1 == ret)
  380         goto out;
  381 
  382     fill_defaults(xl);
  383 
  384     ret = 0;
  385 
  386 out:
  387     GF_FREE(name);
  388     return ret;
  389 }
  390 
  391 int
  392 xlator_set_type(xlator_t *xl, const char *type)
  393 {
  394     int ret = 0;
  395 
  396     /* Handle 'global' translator differently */
  397     if (!strncmp(GF_GLOBAL_XLATOR_NAME, type, SLEN(GF_GLOBAL_XLATOR_NAME))) {
  398         volume_opt_list_t *vol_opt = NULL;
  399 
  400         /* set the required values from Global xlator */
  401         xl->type = gf_strdup(GF_GLOBAL_XLATOR_NAME);
  402         xl->cbks = global_xlator.cbks;
  403         xl->fops = global_xlator.fops;
  404         xl->init = global_xlator.init;
  405         xl->fini = global_xlator.fini;
  406         xl->reconfigure = global_xlator.reconfigure;
  407 
  408         vol_opt = GF_CALLOC(1, sizeof(volume_opt_list_t),
  409                             gf_common_mt_volume_opt_list_t);
  410         if (!vol_opt) {
  411             ret = -1;
  412             goto out;
  413         }
  414 
  415         vol_opt->given_opt = global_xl_options;
  416 
  417         INIT_LIST_HEAD(&xl->volume_options);
  418         INIT_LIST_HEAD(&vol_opt->list);
  419         list_add_tail(&vol_opt->list, &xl->volume_options);
  420 
  421         fill_defaults(xl);
  422         ret = 0;
  423         goto out;
  424     }
  425 
  426     ret = xlator_set_type_virtual(xl, type);
  427     if (!ret)
  428         ret = xlator_dynload(xl);
  429 out:
  430     return ret;
  431 }
  432 
  433 void
  434 xlator_set_inode_lru_limit(xlator_t *this, void *data)
  435 {
  436     int inode_lru_limit = 0;
  437 
  438     if (this->itable) {
  439         if (!data) {
  440             gf_smsg(this->name, GF_LOG_WARNING, 0, LG_MSG_INPUT_DATA_NULL,
  441                     NULL);
  442             goto out;
  443         }
  444         inode_lru_limit = *(int *)data;
  445         inode_table_set_lru_limit(this->itable, inode_lru_limit);
  446     }
  447 
  448 out:
  449     return;
  450 }
  451 
  452 void
  453 xlator_foreach(xlator_t *this, void (*fn)(xlator_t *each, void *data),
  454                void *data)
  455 {
  456     xlator_t *first = NULL;
  457     xlator_t *old_THIS = NULL;
  458 
  459     GF_VALIDATE_OR_GOTO("xlator", this, out);
  460     GF_VALIDATE_OR_GOTO("xlator", fn, out);
  461 
  462     first = this;
  463 
  464     while (first->prev)
  465         first = first->prev;
  466 
  467     while (first) {
  468         old_THIS = THIS;
  469         THIS = first;
  470 
  471         fn(first, data);
  472 
  473         THIS = old_THIS;
  474         first = first->next;
  475     }
  476 
  477 out:
  478     return;
  479 }
  480 
  481 void
  482 xlator_foreach_depth_first(xlator_t *this,
  483                            void (*fn)(xlator_t *each, void *data), void *data)
  484 {
  485     xlator_list_t *subv = NULL;
  486 
  487     subv = this->children;
  488 
  489     while (subv) {
  490         xlator_foreach_depth_first(subv->xlator, fn, data);
  491         subv = subv->next;
  492     }
  493 
  494     fn(this, data);
  495 }
  496 
  497 xlator_t *
  498 xlator_search_by_name(xlator_t *any, const char *name)
  499 {
  500     xlator_t *search = NULL;
  501 
  502     GF_VALIDATE_OR_GOTO("xlator", any, out);
  503     GF_VALIDATE_OR_GOTO("xlator", name, out);
  504 
  505     search = any;
  506 
  507     while (search->prev)
  508         search = search->prev;
  509 
  510     while (search) {
  511         if (!strcmp(search->name, name))
  512             break;
  513         search = search->next;
  514     }
  515 
  516 out:
  517     return search;
  518 }
  519 
  520 /*
  521  * With brick multiplexing, we sort of have multiple graphs, so
  522  * xlator_search_by_name might not find what we want.  Also, the translator
  523  * we're looking for might not be a direct child if something else was put in
  524  * between (as already happened with decompounder before that was fixed) and
  525  * it's hard to debug why our translator wasn't found.  Using a recursive tree
  526  * search instead of a linear search works around both problems.
  527  */
  528 static xlator_t *
  529 get_xlator_by_name_or_type(xlator_t *this, char *target, int is_name)
  530 {
  531     xlator_list_t *trav;
  532     xlator_t *child_xl;
  533     char *value;
  534 
  535     for (trav = this->children; trav; trav = trav->next) {
  536         value = is_name ? trav->xlator->name : trav->xlator->type;
  537         if (!strcmp(value, target) && !trav->xlator->cleanup_starting) {
  538             return trav->xlator;
  539         }
  540         child_xl = get_xlator_by_name_or_type(trav->xlator, target, is_name);
  541         if (child_xl) {
  542             /*
  543              * If the xlator we're looking for is somewhere down
  544              * the stack, get_xlator_by_name expects to get a
  545              * pointer to the top of its subtree (child of "this")
  546              * while get_xlator_by_type expects a pointer to what
  547              * we actually found.  Handle both cases here.
  548              *
  549              * TBD: rename the functions and fix callers to better
  550              * reflect the difference in semantics.
  551              */
  552             return is_name ? trav->xlator : child_xl;
  553         }
  554     }
  555 
  556     return NULL;
  557 }
  558 
  559 xlator_t *
  560 get_xlator_by_name(xlator_t *this, char *target)
  561 {
  562     return get_xlator_by_name_or_type(this, target, 1);
  563 }
  564 
  565 xlator_t *
  566 get_xlator_by_type(xlator_t *this, char *target)
  567 {
  568     return get_xlator_by_name_or_type(this, target, 0);
  569 }
  570 
  571 static int
  572 __xlator_init(xlator_t *xl)
  573 {
  574     xlator_t *old_THIS = NULL;
  575     int ret = 0;
  576     int fop_idx = 0;
  577 
  578     old_THIS = THIS;
  579     THIS = xl;
  580 
  581     /* initialize the metrics related locks */
  582     for (fop_idx = 0; fop_idx < GF_FOP_MAXVALUE; fop_idx++) {
  583         GF_ATOMIC_INIT(xl->stats.total.metrics[fop_idx].fop, 0);
  584         GF_ATOMIC_INIT(xl->stats.total.metrics[fop_idx].cbk, 0);
  585 
  586         GF_ATOMIC_INIT(xl->stats.interval.metrics[fop_idx].fop, 0);
  587         GF_ATOMIC_INIT(xl->stats.interval.metrics[fop_idx].cbk, 0);
  588     }
  589     GF_ATOMIC_INIT(xl->stats.total.count, 0);
  590     GF_ATOMIC_INIT(xl->stats.interval.count, 0);
  591 
  592     xlator_init_lock();
  593     handle_default_options(xl, xl->options);
  594     ret = xl->init(xl);
  595     xlator_init_unlock();
  596 
  597     THIS = old_THIS;
  598 
  599     return ret;
  600 }
  601 
  602 int
  603 xlator_init(xlator_t *xl)
  604 {
  605     int32_t ret = -1;
  606 
  607     GF_VALIDATE_OR_GOTO("xlator", xl, out);
  608 
  609     if (xl->mem_acct_init)
  610         xl->mem_acct_init(xl);
  611 
  612     xl->instance_name = NULL;
  613     GF_ATOMIC_INIT(xl->xprtrefcnt, 0);
  614     if (!xl->init) {
  615         gf_smsg(xl->name, GF_LOG_WARNING, 0, LG_MSG_INIT_FAILED, NULL);
  616         goto out;
  617     }
  618 
  619     ret = __xlator_init(xl);
  620 
  621     if (ret) {
  622         gf_smsg(xl->name, GF_LOG_ERROR, 0, LG_MSG_VOLUME_ERROR, "name=%s",
  623                 xl->name, NULL);
  624         goto out;
  625     }
  626 
  627     xl->init_succeeded = 1;
  628     /*xl->cleanup_starting = 0;
  629       xl->call_cleanup = 0;
  630     */
  631     ret = 0;
  632 out:
  633     return ret;
  634 }
  635 
  636 static void
  637 xlator_fini_rec(xlator_t *xl)
  638 {
  639     xlator_list_t *trav = NULL;
  640     xlator_t *old_THIS = NULL;
  641 
  642     GF_VALIDATE_OR_GOTO("xlator", xl, out);
  643 
  644     trav = xl->children;
  645 
  646     while (trav) {
  647         if (!trav->xlator->init_succeeded) {
  648             break;
  649         }
  650 
  651         xlator_fini_rec(trav->xlator);
  652         gf_msg_debug(trav->xlator->name, 0, "fini done");
  653         trav = trav->next;
  654     }
  655 
  656     xl->cleanup_starting = 1;
  657     if (xl->init_succeeded) {
  658         if (xl->fini) {
  659             old_THIS = THIS;
  660             THIS = xl;
  661 
  662             xl->fini(xl);
  663 
  664             if (xl->local_pool) {
  665                 mem_pool_destroy(xl->local_pool);
  666                 xl->local_pool = NULL;
  667             }
  668             if (xl->itable) {
  669                 inode_table_destroy(xl->itable);
  670                 xl->itable = NULL;
  671             }
  672 
  673             THIS = old_THIS;
  674         } else {
  675             gf_msg_debug(xl->name, 0, "No fini() found");
  676         }
  677         xl->init_succeeded = 0;
  678     }
  679 
  680 out:
  681     return;
  682 }
  683 
  684 int
  685 xlator_notify(xlator_t *xl, int event, void *data, ...)
  686 {
  687     xlator_t *old_THIS = NULL;
  688     int ret = 0;
  689 
  690     old_THIS = THIS;
  691     THIS = xl;
  692 
  693     ret = xl->notify(xl, event, data);
  694 
  695     THIS = old_THIS;
  696 
  697     return ret;
  698 }
  699 
  700 int
  701 xlator_mem_acct_init(xlator_t *xl, int num_types)
  702 {
  703     int i = 0;
  704     int ret = 0;
  705 
  706     if (!xl)
  707         return -1;
  708 
  709     if (!xl->ctx)
  710         return -1;
  711 
  712     if (!xl->ctx->mem_acct_enable)
  713         return 0;
  714 
  715     xl->mem_acct = MALLOC(sizeof(struct mem_acct) +
  716                           sizeof(struct mem_acct_rec) * num_types);
  717 
  718     if (!xl->mem_acct) {
  719         return -1;
  720     }
  721 
  722     xl->mem_acct->num_types = num_types;
  723     GF_ATOMIC_INIT(xl->mem_acct->refcnt, 1);
  724 
  725     for (i = 0; i < num_types; i++) {
  726         memset(&xl->mem_acct->rec[i], 0, sizeof(struct mem_acct_rec));
  727         ret = LOCK_INIT(&(xl->mem_acct->rec[i].lock));
  728         if (ret) {
  729             fprintf(stderr, "Unable to lock..errno : %d", errno);
  730         }
  731 #ifdef DEBUG
  732         INIT_LIST_HEAD(&(xl->mem_acct->rec[i].obj_list));
  733 #endif
  734     }
  735 
  736     return 0;
  737 }
  738 
  739 void
  740 xlator_mem_acct_unref(struct mem_acct *mem_acct)
  741 {
  742     uint32_t i;
  743 
  744     if (GF_ATOMIC_DEC(mem_acct->refcnt) == 0) {
  745         for (i = 0; i < mem_acct->num_types; i++) {
  746             LOCK_DESTROY(&(mem_acct->rec[i].lock));
  747         }
  748         FREE(mem_acct);
  749     }
  750 }
  751 
  752 void
  753 xlator_tree_fini(xlator_t *xl)
  754 {
  755     xlator_t *top = NULL;
  756 
  757     GF_VALIDATE_OR_GOTO("xlator", xl, out);
  758 
  759     top = xl;
  760     xlator_fini_rec(top);
  761 
  762 out:
  763     return;
  764 }
  765 
  766 int
  767 xlator_list_destroy(xlator_list_t *list)
  768 {
  769     xlator_list_t *next = NULL;
  770 
  771     while (list) {
  772         next = list->next;
  773         GF_FREE(list);
  774         list = next;
  775     }
  776 
  777     return 0;
  778 }
  779 
  780 int
  781 xlator_memrec_free(xlator_t *xl)
  782 {
  783     struct mem_acct *mem_acct = NULL;
  784 
  785     if (!xl) {
  786         return 0;
  787     }
  788     mem_acct = xl->mem_acct;
  789 
  790     if (mem_acct) {
  791         xlator_mem_acct_unref(mem_acct);
  792         xl->mem_acct = NULL;
  793     }
  794 
  795     return 0;
  796 }
  797 
  798 static int
  799 xlator_members_free(xlator_t *xl)
  800 {
  801     volume_opt_list_t *vol_opt = NULL;
  802     volume_opt_list_t *tmp = NULL;
  803 
  804     if (!xl)
  805         return 0;
  806 
  807     GF_FREE(xl->name);
  808     GF_FREE(xl->type);
  809     if (!(xl->ctx && xl->ctx->cmd_args.valgrind) && xl->dlhandle)
  810         dlclose(xl->dlhandle);
  811     if (xl->options)
  812         dict_unref(xl->options);
  813 
  814     xlator_list_destroy(xl->children);
  815 
  816     xlator_list_destroy(xl->parents);
  817 
  818     list_for_each_entry_safe(vol_opt, tmp, &xl->volume_options, list)
  819     {
  820         list_del_init(&vol_opt->list);
  821         GF_FREE(vol_opt);
  822     }
  823 
  824     return 0;
  825 }
  826 
  827 /* This function destroys all the xlator members except for the
  828  * xlator strcuture and its mem accounting field.
  829  *
  830  * If otherwise, it would destroy the master xlator object as well
  831  * its mem accounting, which would mean after calling glusterfs_graph_destroy()
  832  * there cannot be any reference to GF_FREE() from the master xlator, this is
  833  * not possible because of the following dependencies:
  834  * - glusterfs_ctx_t will have mem pools allocated by the master xlators
  835  * - xlator objects will have references to those mem pools(g: dict)
  836  *
  837  * Ordering the freeing in any of the order will also not solve the dependency:
  838  * - Freeing xlator objects(including memory accounting) before mem pools
  839  *   destruction will mean not use GF_FREE while destroying mem pools.
  840  * - Freeing mem pools and then destroying xlator objects would lead to crashes
  841  *   when xlator tries to unref dict or other mem pool objects.
  842  *
  843  * Hence the way chosen out of this interdependency is to split xlator object
  844  * free into two stages:
  845  * - Free all the xlator members excpet for its mem accounting structure
  846  * - Free all the mem accouting structures of xlator along with the xlator
  847  *   object itself.
  848  *
  849  * This two stages of destruction, is mainly required for glfs_fini().
  850  */
  851 
  852 int
  853 xlator_tree_free_members(xlator_t *tree)
  854 {
  855     xlator_t *trav = tree;
  856     xlator_t *prev = tree;
  857 
  858     if (!tree) {
  859         gf_smsg("parser", GF_LOG_ERROR, 0, LG_MSG_TREE_NOT_FOUND, NULL);
  860         return -1;
  861     }
  862 
  863     while (prev) {
  864         trav = prev->next;
  865         xlator_members_free(prev);
  866         prev = trav;
  867     }
  868 
  869     return 0;
  870 }
  871 
  872 int
  873 xlator_tree_free_memacct(xlator_t *tree)
  874 {
  875     xlator_t *trav = tree;
  876     xlator_t *prev = tree;
  877 
  878     if (!tree) {
  879         gf_smsg("parser", GF_LOG_ERROR, 0, LG_MSG_TREE_NOT_FOUND, NULL);
  880         return -1;
  881     }
  882 
  883     while (prev) {
  884         trav = prev->next;
  885         xlator_memrec_free(prev);
  886         GF_FREE(prev);
  887         prev = trav;
  888     }
  889 
  890     return 0;
  891 }
  892 
  893 static int
  894 xlator_mem_free(xlator_t *xl)
  895 {
  896     volume_opt_list_t *vol_opt = NULL;
  897     volume_opt_list_t *tmp = NULL;
  898 
  899     if (!xl)
  900         return 0;
  901 
  902     if (xl->options) {
  903         dict_unref(xl->options);
  904         xl->options = NULL;
  905     }
  906 
  907     list_for_each_entry_safe(vol_opt, tmp, &xl->volume_options, list)
  908     {
  909         list_del_init(&vol_opt->list);
  910         GF_FREE(vol_opt);
  911     }
  912 
  913     xlator_memrec_free(xl);
  914 
  915     return 0;
  916 }
  917 
  918 static void
  919 xlator_call_fini(xlator_t *this)
  920 {
  921     if (!this || this->call_cleanup)
  922         return;
  923     this->cleanup_starting = 1;
  924     this->call_cleanup = 1;
  925     xlator_call_fini(this->next);
  926     this->fini(this);
  927 }
  928 
  929 void
  930 xlator_mem_cleanup(xlator_t *this)
  931 {
  932     xlator_list_t *list = this->children;
  933     xlator_t *trav = list->xlator;
  934     inode_table_t *inode_table = NULL;
  935     xlator_t *prev = trav;
  936     glusterfs_ctx_t *ctx = NULL;
  937     xlator_list_t **trav_p = NULL;
  938     xlator_t *top = NULL;
  939     xlator_t *victim = NULL;
  940     glusterfs_graph_t *graph = NULL;
  941     gf_boolean_t graph_cleanup = _gf_false;
  942 
  943     if (this->call_cleanup || !this->ctx)
  944         return;
  945 
  946     this->call_cleanup = 1;
  947     ctx = this->ctx;
  948 
  949     inode_table = this->itable;
  950     if (inode_table) {
  951         inode_table_destroy(inode_table);
  952         this->itable = NULL;
  953     }
  954 
  955     xlator_call_fini(trav);
  956 
  957     while (prev) {
  958         trav = prev->next;
  959         xlator_mem_free(prev);
  960         prev = trav;
  961     }
  962 
  963     if (this->fini) {
  964         this->fini(this);
  965     }
  966 
  967     xlator_mem_free(this);
  968 
  969     if (ctx->active) {
  970         top = ctx->active->first;
  971         LOCK(&ctx->volfile_lock);
  972         for (trav_p = &top->children; *trav_p; trav_p = &(*trav_p)->next) {
  973             victim = (*trav_p)->xlator;
  974             if (victim->call_cleanup && !strcmp(victim->name, this->name)) {
  975                 graph_cleanup = _gf_true;
  976                 (*trav_p) = (*trav_p)->next;
  977                 break;
  978             }
  979         }
  980         UNLOCK(&ctx->volfile_lock);
  981     }
  982 
  983     if (graph_cleanup) {
  984         prev = this;
  985         graph = ctx->active;
  986         pthread_mutex_lock(&graph->mutex);
  987         while (prev) {
  988             trav = prev->next;
  989             GF_FREE(prev);
  990             prev = trav;
  991         }
  992         pthread_mutex_unlock(&graph->mutex);
  993     }
  994 }
  995 
  996 void
  997 loc_wipe(loc_t *loc)
  998 {
  999     if (loc->inode) {
 1000         inode_unref(loc->inode);
 1001         loc->inode = NULL;
 1002     }
 1003     if (loc->path) {
 1004         GF_FREE((char *)loc->path);
 1005         loc->path = NULL;
 1006     }
 1007 
 1008     if (loc->parent) {
 1009         inode_unref(loc->parent);
 1010         loc->parent = NULL;
 1011     }
 1012 
 1013     memset(loc, 0, sizeof(*loc));
 1014 }
 1015 
 1016 int
 1017 loc_path(loc_t *loc, const char *bname)
 1018 {
 1019     int ret = 0;
 1020 
 1021     if (loc->path)
 1022         goto out;
 1023 
 1024     ret = -1;
 1025 
 1026     if (bname && !strlen(bname))
 1027         bname = NULL;
 1028 
 1029     if (!bname)
 1030         goto inode_path;
 1031 
 1032     if (loc->parent && !gf_uuid_is_null(loc->parent->gfid)) {
 1033         ret = inode_path(loc->parent, bname, (char **)&loc->path);
 1034     } else if (!gf_uuid_is_null(loc->pargfid)) {
 1035         ret = gf_asprintf((char **)&loc->path, INODE_PATH_FMT "/%s",
 1036                           uuid_utoa(loc->pargfid), bname);
 1037     }
 1038 
 1039     if (loc->path)
 1040         goto out;
 1041 
 1042 inode_path:
 1043     if (loc->inode && !gf_uuid_is_null(loc->inode->gfid)) {
 1044         ret = inode_path(loc->inode, NULL, (char **)&loc->path);
 1045     } else if (!gf_uuid_is_null(loc->gfid)) {
 1046         ret = gf_asprintf((char **)&loc->path, INODE_PATH_FMT,
 1047                           uuid_utoa(loc->gfid));
 1048     }
 1049 out:
 1050     return ret;
 1051 }
 1052 
 1053 void
 1054 loc_gfid(loc_t *loc, uuid_t gfid)
 1055 {
 1056     if (!gfid)
 1057         goto out;
 1058     gf_uuid_clear(gfid);
 1059 
 1060     if (!loc)
 1061         goto out;
 1062     else if (!gf_uuid_is_null(loc->gfid))
 1063         gf_uuid_copy(gfid, loc->gfid);
 1064     else if (loc->inode && (!gf_uuid_is_null(loc->inode->gfid)))
 1065         gf_uuid_copy(gfid, loc->inode->gfid);
 1066 out:
 1067     return;
 1068 }
 1069 
 1070 void
 1071 loc_pargfid(loc_t *loc, uuid_t gfid)
 1072 {
 1073     if (!gfid)
 1074         goto out;
 1075     gf_uuid_clear(gfid);
 1076 
 1077     if (!loc)
 1078         goto out;
 1079     else if (!gf_uuid_is_null(loc->pargfid))
 1080         gf_uuid_copy(gfid, loc->pargfid);
 1081     else if (loc->parent && (!gf_uuid_is_null(loc->parent->gfid)))
 1082         gf_uuid_copy(gfid, loc->parent->gfid);
 1083 out:
 1084     return;
 1085 }
 1086 
 1087 char *
 1088 loc_gfid_utoa(loc_t *loc)
 1089 {
 1090     uuid_t gfid = {
 1091         0,
 1092     };
 1093     loc_gfid(loc, gfid);
 1094     return uuid_utoa(gfid);
 1095 }
 1096 
 1097 int
 1098 loc_touchup(loc_t *loc, const char *name)
 1099 {
 1100     char *path = NULL;
 1101     int ret = 0;
 1102 
 1103     if (loc->path)
 1104         goto out;
 1105 
 1106     if (loc->parent && name && strlen(name)) {
 1107         ret = inode_path(loc->parent, name, &path);
 1108         if (path) /*Guaranteed to have trailing '/' */
 1109             loc->name = strrchr(path, '/') + 1;
 1110 
 1111         if (gf_uuid_is_null(loc->pargfid))
 1112             gf_uuid_copy(loc->pargfid, loc->parent->gfid);
 1113     } else if (loc->inode) {
 1114         ret = inode_path(loc->inode, 0, &path);
 1115         if (gf_uuid_is_null(loc->gfid))
 1116             gf_uuid_copy(loc->gfid, loc->inode->gfid);
 1117     }
 1118 
 1119     if (ret < 0 || !path) {
 1120         ret = -ENOMEM;
 1121         goto out;
 1122     }
 1123 
 1124     loc->path = path;
 1125     ret = 0;
 1126 out:
 1127     return ret;
 1128 }
 1129 
 1130 int
 1131 loc_copy_overload_parent(loc_t *dst, loc_t *src, inode_t *parent)
 1132 {
 1133     int ret = -1;
 1134 
 1135     GF_VALIDATE_OR_GOTO("xlator", dst, err);
 1136     GF_VALIDATE_OR_GOTO("xlator", src, err);
 1137     GF_VALIDATE_OR_GOTO("xlator", parent, err);
 1138 
 1139     gf_uuid_copy(dst->gfid, src->gfid);
 1140     gf_uuid_copy(dst->pargfid, parent->gfid);
 1141 
 1142     if (src->inode)
 1143         dst->inode = inode_ref(src->inode);
 1144 
 1145     if (parent)
 1146         dst->parent = inode_ref(parent);
 1147 
 1148     if (src->path) {
 1149         dst->path = gf_strdup(src->path);
 1150 
 1151         if (!dst->path)
 1152             goto out;
 1153 
 1154         if (src->name)
 1155             dst->name = strrchr(dst->path, '/');
 1156         if (dst->name)
 1157             dst->name++;
 1158     } else if (src->name) {
 1159         dst->name = src->name;
 1160     }
 1161 
 1162     ret = 0;
 1163 out:
 1164     if (ret == -1)
 1165         loc_wipe(dst);
 1166 
 1167 err:
 1168     return ret;
 1169 }
 1170 
 1171 int
 1172 loc_copy(loc_t *dst, loc_t *src)
 1173 {
 1174     int ret = -1;
 1175 
 1176     GF_VALIDATE_OR_GOTO("xlator", dst, err);
 1177     GF_VALIDATE_OR_GOTO("xlator", src, err);
 1178 
 1179     if (!gf_uuid_is_null(src->gfid))
 1180         gf_uuid_copy(dst->gfid, src->gfid);
 1181     else if (src->inode && !gf_uuid_is_null(src->inode->gfid))
 1182         gf_uuid_copy(dst->gfid, src->inode->gfid);
 1183 
 1184     gf_uuid_copy(dst->pargfid, src->pargfid);
 1185 
 1186     if (src->inode)
 1187         dst->inode = inode_ref(src->inode);
 1188 
 1189     if (src->parent)
 1190         dst->parent = inode_ref(src->parent);
 1191 
 1192     if (src->path) {
 1193         dst->path = gf_strdup(src->path);
 1194 
 1195         if (!dst->path)
 1196             goto out;
 1197 
 1198         if (src->name)
 1199             dst->name = strrchr(dst->path, '/');
 1200         if (dst->name)
 1201             dst->name++;
 1202     } else if (src->name) {
 1203         dst->name = src->name;
 1204     }
 1205 
 1206     ret = 0;
 1207 out:
 1208     if (ret == -1)
 1209         loc_wipe(dst);
 1210 
 1211 err:
 1212     return ret;
 1213 }
 1214 
 1215 gf_boolean_t
 1216 loc_is_root(loc_t *loc)
 1217 {
 1218     if (loc && __is_root_gfid(loc->gfid)) {
 1219         return _gf_true;
 1220     } else if (loc && loc->inode && __is_root_gfid(loc->inode->gfid)) {
 1221         return _gf_true;
 1222     }
 1223 
 1224     return _gf_false;
 1225 }
 1226 
 1227 int32_t
 1228 loc_build_child(loc_t *child, loc_t *parent, char *name)
 1229 {
 1230     int32_t ret = -1;
 1231 
 1232     GF_VALIDATE_OR_GOTO("xlator", child, out);
 1233     GF_VALIDATE_OR_GOTO("xlator", parent, out);
 1234     GF_VALIDATE_OR_GOTO("xlator", name, out);
 1235 
 1236     loc_gfid(parent, child->pargfid);
 1237 
 1238     if (strcmp(parent->path, "/") == 0)
 1239         ret = gf_asprintf((char **)&child->path, "/%s", name);
 1240     else
 1241         ret = gf_asprintf((char **)&child->path, "%s/%s", parent->path, name);
 1242 
 1243     if (ret < 0 || !child->path) {
 1244         ret = -1;
 1245         goto out;
 1246     }
 1247 
 1248     child->name = strrchr(child->path, '/') + 1;
 1249 
 1250     child->parent = inode_ref(parent->inode);
 1251     child->inode = inode_new(parent->inode->table);
 1252 
 1253     if (!child->inode) {
 1254         ret = -1;
 1255         goto out;
 1256     }
 1257 
 1258     ret = 0;
 1259 
 1260 out:
 1261     if ((ret < 0) && child)
 1262         loc_wipe(child);
 1263 
 1264     return ret;
 1265 }
 1266 
 1267 gf_boolean_t
 1268 loc_is_nameless(loc_t *loc)
 1269 {
 1270     gf_boolean_t ret = _gf_false;
 1271 
 1272     GF_VALIDATE_OR_GOTO("xlator", loc, out);
 1273 
 1274     if ((!loc->parent && gf_uuid_is_null(loc->pargfid)) || !loc->name)
 1275         ret = _gf_true;
 1276 out:
 1277     return ret;
 1278 }
 1279 
 1280 int
 1281 xlator_destroy(xlator_t *xl)
 1282 {
 1283     if (!xl)
 1284         return 0;
 1285 
 1286     xlator_members_free(xl);
 1287     xlator_memrec_free(xl);
 1288     GF_FREE(xl);
 1289 
 1290     return 0;
 1291 }
 1292 
 1293 static int32_t
 1294 gf_bin_to_string(char *dst, size_t size, void *src, size_t len)
 1295 {
 1296     if (len >= size) {
 1297         return EINVAL;
 1298     }
 1299 
 1300     memcpy(dst, src, len);
 1301     dst[len] = 0;
 1302 
 1303     return 0;
 1304 }
 1305 
 1306 int
 1307 is_gf_log_command(xlator_t *this, const char *name, char *value, size_t size)
 1308 {
 1309     xlator_t *trav = NULL;
 1310     char key[1024] = {
 1311         0,
 1312     };
 1313     int ret = -1;
 1314     int log_level = -1;
 1315     gf_boolean_t syslog_flag = 0;
 1316     glusterfs_ctx_t *ctx = NULL;
 1317 
 1318     if (!strcmp("trusted.glusterfs.syslog", name)) {
 1319         ret = gf_bin_to_string(key, sizeof(key), value, size);
 1320         if (ret != 0) {
 1321             goto out;
 1322         }
 1323         ret = gf_string2boolean(key, &syslog_flag);
 1324         if (ret) {
 1325             ret = EOPNOTSUPP;
 1326             goto out;
 1327         }
 1328         if (syslog_flag)
 1329             gf_log_enable_syslog();
 1330         else
 1331             gf_log_disable_syslog();
 1332 
 1333         goto out;
 1334     }
 1335 
 1336     if (fnmatch("trusted.glusterfs*set-log-level", name, FNM_NOESCAPE))
 1337         goto out;
 1338 
 1339     ret = gf_bin_to_string(key, sizeof(key), value, size);
 1340     if (ret != 0) {
 1341         goto out;
 1342     }
 1343 
 1344     log_level = glusterd_check_log_level(key);
 1345     if (log_level == -1) {
 1346         ret = EOPNOTSUPP;
 1347         goto out;
 1348     }
 1349 
 1350     /* Some crude way to change the log-level of process */
 1351     if (!strcmp(name, "trusted.glusterfs.set-log-level")) {
 1352         gf_smsg("glusterfs", gf_log_get_loglevel(), 0, LG_MSG_SET_LOG_LEVEL,
 1353                 "new-value=%d", log_level, "old-value=%d",
 1354                 gf_log_get_loglevel(), NULL);
 1355         gf_log_set_loglevel(this->ctx, log_level);
 1356         ret = 0;
 1357         goto out;
 1358     }
 1359 
 1360     if (!strcmp(name, "trusted.glusterfs.fuse.set-log-level")) {
 1361         /* */
 1362         gf_smsg(this->name, gf_log_get_xl_loglevel(this), 0,
 1363                 LG_MSG_SET_LOG_LEVEL, "new-value=%d", log_level, "old-value=%d",
 1364                 gf_log_get_xl_loglevel(this), NULL);
 1365         gf_log_set_xl_loglevel(this, log_level);
 1366         ret = 0;
 1367         goto out;
 1368     }
 1369 
 1370     ctx = this->ctx;
 1371     if (!ctx)
 1372         goto out;
 1373     if (!ctx->active)
 1374         goto out;
 1375     trav = ctx->active->top;
 1376 
 1377     while (trav) {
 1378         snprintf(key, 1024, "trusted.glusterfs.%s.set-log-level", trav->name);
 1379         if (fnmatch(name, key, FNM_NOESCAPE) == 0) {
 1380             gf_smsg(trav->name, gf_log_get_xl_loglevel(trav), 0,
 1381                     LG_MSG_SET_LOG_LEVEL, "new-value%d", log_level,
 1382                     "old-value=%d", gf_log_get_xl_loglevel(trav), NULL);
 1383             gf_log_set_xl_loglevel(trav, log_level);
 1384             ret = 0;
 1385         }
 1386         trav = trav->next;
 1387     }
 1388 out:
 1389     return ret;
 1390 }
 1391 
 1392 int
 1393 glusterd_check_log_level(const char *value)
 1394 {
 1395     int log_level = -1;
 1396 
 1397     if (!strcasecmp(value, "CRITICAL")) {
 1398         log_level = GF_LOG_CRITICAL;
 1399     } else if (!strcasecmp(value, "ERROR")) {
 1400         log_level = GF_LOG_ERROR;
 1401     } else if (!strcasecmp(value, "WARNING")) {
 1402         log_level = GF_LOG_WARNING;
 1403     } else if (!strcasecmp(value, "INFO")) {
 1404         log_level = GF_LOG_INFO;
 1405     } else if (!strcasecmp(value, "DEBUG")) {
 1406         log_level = GF_LOG_DEBUG;
 1407     } else if (!strcasecmp(value, "TRACE")) {
 1408         log_level = GF_LOG_TRACE;
 1409     } else if (!strcasecmp(value, "NONE")) {
 1410         log_level = GF_LOG_NONE;
 1411     }
 1412 
 1413     if (log_level == -1)
 1414         gf_smsg(THIS->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_INIT, NULL);
 1415 
 1416     return log_level;
 1417 }
 1418 
 1419 int
 1420 xlator_subvolume_count(xlator_t *this)
 1421 {
 1422     int i = 0;
 1423     xlator_list_t *list = NULL;
 1424 
 1425     for (list = this->children; list; list = list->next)
 1426         i++;
 1427     return i;
 1428 }
 1429 
 1430 static int
 1431 _copy_opt_to_child(dict_t *options, char *key, data_t *value, void *data)
 1432 {
 1433     xlator_t *child = data;
 1434 
 1435     gf_log(__func__, GF_LOG_DEBUG, "copying %s to child %s", key, child->name);
 1436     dict_set(child->options, key, value);
 1437 
 1438     return 0;
 1439 }
 1440 
 1441 int
 1442 copy_opts_to_child(xlator_t *src, xlator_t *dst, char *glob)
 1443 {
 1444     return dict_foreach_fnmatch(src->options, glob, _copy_opt_to_child, dst);
 1445 }
 1446 
 1447 int
 1448 glusterfs_delete_volfile_checksum(glusterfs_ctx_t *ctx, const char *volfile_id)
 1449 {
 1450     gf_volfile_t *volfile_tmp = NULL;
 1451     gf_volfile_t *volfile_obj = NULL;
 1452 
 1453     list_for_each_entry(volfile_tmp, &ctx->volfile_list, volfile_list)
 1454     {
 1455         if (!strcmp(volfile_id, volfile_tmp->vol_id)) {
 1456             list_del_init(&volfile_tmp->volfile_list);
 1457             volfile_obj = volfile_tmp;
 1458             break;
 1459         }
 1460     }
 1461 
 1462     if (volfile_obj) {
 1463         GF_FREE(volfile_obj);
 1464     } else {
 1465         gf_log(THIS->name, GF_LOG_ERROR,
 1466                "failed to get volfile "
 1467                "checksum for volfile id %s.",
 1468                volfile_id);
 1469     }
 1470 
 1471     return 0;
 1472 }
 1473 
 1474 /*
 1475    The function is required to take dict ref for every xlator at graph.
 1476    At the time of compare graph topology create a graph and populate
 1477    key values in the dictionary, after finished graph comparison we do destroy
 1478    the new graph.At the time of construct graph we don't take any reference
 1479    so to avoid dict leak at the of destroying graph due to ref counter underflow
 1480    we need to call dict_ref here.
 1481 
 1482 */
 1483 
 1484 void
 1485 gluster_graph_take_reference(xlator_t *tree)
 1486 {
 1487     xlator_t *trav = tree;
 1488     xlator_t *prev = tree;
 1489 
 1490     if (!tree) {
 1491         gf_smsg("parser", GF_LOG_ERROR, 0, LG_MSG_TREE_NOT_FOUND, NULL);
 1492         return;
 1493     }
 1494 
 1495     while (prev) {
 1496         trav = prev->next;
 1497         if (prev->options)
 1498             dict_ref(prev->options);
 1499         prev = trav;
 1500     }
 1501     return;
 1502 }
 1503 
 1504 gf_boolean_t
 1505 mgmt_is_multiplexed_daemon(char *name)
 1506 {
 1507     const char *mux_daemons[] = {"glustershd", NULL};
 1508     int i;
 1509 
 1510     if (!name)
 1511         return _gf_false;
 1512 
 1513     for (i = 0; mux_daemons[i]; i++) {
 1514         if (!strcmp(name, mux_daemons[i]))
 1515             return _gf_true;
 1516     }
 1517     return _gf_false;
 1518 }
 1519 
 1520 gf_boolean_t
 1521 xlator_is_cleanup_starting(xlator_t *this)
 1522 {
 1523     gf_boolean_t cleanup = _gf_false;
 1524     glusterfs_graph_t *graph = NULL;
 1525     xlator_t *xl = NULL;
 1526 
 1527     if (!this) {
 1528         gf_smsg("xlator", GF_LOG_WARNING, EINVAL, LG_MSG_OBJECT_NULL, "xlator",
 1529                 NULL);
 1530         goto out;
 1531     }
 1532 
 1533     graph = this->graph;
 1534     if (!graph) {
 1535         gf_smsg("xlator", GF_LOG_WARNING, EINVAL, LG_MSG_GRAPH_NOT_SET,
 1536                 "name=%s", this->name, NULL);
 1537         goto out;
 1538     }
 1539 
 1540     xl = graph->first;
 1541     if (xl && xl->cleanup_starting)
 1542         cleanup = _gf_true;
 1543 out:
 1544     return cleanup;
 1545 }
 1546 
 1547 int
 1548 graph_total_client_xlator(glusterfs_graph_t *graph)
 1549 {
 1550     xlator_t *xl = NULL;
 1551     int count = 0;
 1552 
 1553     if (!graph) {
 1554         gf_smsg("xlator", GF_LOG_WARNING, EINVAL, LG_MSG_OBJECT_NULL, "graph",
 1555                 NULL);
 1556         goto out;
 1557     }
 1558 
 1559     xl = graph->first;
 1560     if (!strcmp(xl->type, "protocol/server")) {
 1561         gf_msg_debug(xl->name, 0, "Return because it is a server graph");
 1562         return 0;
 1563     }
 1564 
 1565     while (xl) {
 1566         if (strcmp(xl->type, "protocol/client") == 0) {
 1567             count++;
 1568         }
 1569         xl = xl->next;
 1570     }
 1571 out:
 1572     return count;
 1573 }