"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-7.6/api/src/glfs.c" (18 May 2020, 43107 Bytes) of package /linux/misc/glusterfs-7.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "glfs.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 7.5_vs_7.6.

    1 /*
    2   Copyright (c) 2012-2018 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 /*
   12   TODO:
   13   - set proper pid/lk_owner to call frames (currently buried in syncop)
   14   - fix logging.c/h to store logfp and loglevel in glusterfs_ctx_t and
   15     reach it via THIS.
   16   - update syncop functions to accept/return xdata. ???
   17   - protocol/client to reconnect immediately after portmap disconnect.
   18   - handle SEEK_END failure in _lseek()
   19   - handle umask (per filesystem?)
   20   - make itables LRU based
   21   - 0-copy for readv/writev
   22   - reconcile the open/creat mess
   23 */
   24 
   25 #include <unistd.h>
   26 #include <string.h>
   27 #include <stdlib.h>
   28 #include <stdio.h>
   29 #include <inttypes.h>
   30 #include <sys/types.h>
   31 #include <unistd.h>
   32 #include <limits.h>
   33 #ifdef GF_LINUX_HOST_OS
   34 #include <sys/prctl.h>
   35 #endif
   36 
   37 #include <glusterfs/glusterfs.h>
   38 #include <glusterfs/logging.h>
   39 #include <glusterfs/stack.h>
   40 #include <glusterfs/gf-event.h>
   41 #include "glfs-mem-types.h"
   42 #include <glusterfs/common-utils.h>
   43 #include <glusterfs/syncop.h>
   44 #include <glusterfs/call-stub.h>
   45 #include <glusterfs/hashfn.h>
   46 #include "rpc-clnt.h"
   47 #include <glusterfs/statedump.h>
   48 #include <glusterfs/syscall.h>
   49 
   50 #include "gfapi-messages.h"
   51 #include "glfs.h"
   52 #include "glfs-internal.h"
   53 
   54 static gf_boolean_t
   55 vol_assigned(cmd_args_t *args)
   56 {
   57     return args->volfile || args->volfile_server;
   58 }
   59 
   60 static int
   61 glusterfs_ctx_defaults_init(glusterfs_ctx_t *ctx)
   62 {
   63     call_pool_t *pool = NULL;
   64     int ret = -1;
   65 
   66     if (!ctx) {
   67         goto err;
   68     }
   69 
   70     ret = xlator_mem_acct_init(THIS, glfs_mt_end + 1);
   71     if (ret != 0) {
   72         gf_msg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_MEM_ACCT_INIT_FAILED,
   73                "Memory accounting init failed");
   74         return ret;
   75     }
   76 
   77     /* reset ret to -1 so that we don't need to explicitly
   78      * set it in all error paths before "goto err"
   79      */
   80 
   81     ret = -1;
   82 
   83     ctx->process_uuid = generate_glusterfs_ctx_id();
   84     if (!ctx->process_uuid) {
   85         goto err;
   86     }
   87 
   88     ctx->page_size = 128 * GF_UNIT_KB;
   89 
   90     ctx->iobuf_pool = iobuf_pool_new();
   91     if (!ctx->iobuf_pool) {
   92         goto err;
   93     }
   94 
   95     ctx->event_pool = gf_event_pool_new(DEFAULT_EVENT_POOL_SIZE,
   96                                         STARTING_EVENT_THREADS);
   97     if (!ctx->event_pool) {
   98         goto err;
   99     }
  100 
  101     ctx->env = syncenv_new(0, 0, 0);
  102     if (!ctx->env) {
  103         goto err;
  104     }
  105 
  106     pool = GF_CALLOC(1, sizeof(call_pool_t), glfs_mt_call_pool_t);
  107     if (!pool) {
  108         goto err;
  109     }
  110 
  111     /* frame_mem_pool size 112 * 4k */
  112     pool->frame_mem_pool = mem_pool_new(call_frame_t, 4096);
  113     if (!pool->frame_mem_pool) {
  114         goto err;
  115     }
  116     /* stack_mem_pool size 256 * 1024 */
  117     pool->stack_mem_pool = mem_pool_new(call_stack_t, 1024);
  118     if (!pool->stack_mem_pool) {
  119         goto err;
  120     }
  121 
  122     ctx->stub_mem_pool = mem_pool_new(call_stub_t, 1024);
  123     if (!ctx->stub_mem_pool) {
  124         goto err;
  125     }
  126 
  127     ctx->dict_pool = mem_pool_new(dict_t, GF_MEMPOOL_COUNT_OF_DICT_T);
  128     if (!ctx->dict_pool)
  129         goto err;
  130 
  131     ctx->dict_pair_pool = mem_pool_new(data_pair_t,
  132                                        GF_MEMPOOL_COUNT_OF_DATA_PAIR_T);
  133     if (!ctx->dict_pair_pool)
  134         goto err;
  135 
  136     ctx->dict_data_pool = mem_pool_new(data_t, GF_MEMPOOL_COUNT_OF_DATA_T);
  137     if (!ctx->dict_data_pool)
  138         goto err;
  139 
  140     ctx->logbuf_pool = mem_pool_new(log_buf_t, GF_MEMPOOL_COUNT_OF_LRU_BUF_T);
  141     if (!ctx->logbuf_pool)
  142         goto err;
  143 
  144     INIT_LIST_HEAD(&pool->all_frames);
  145     INIT_LIST_HEAD(&ctx->cmd_args.xlator_options);
  146     INIT_LIST_HEAD(&ctx->cmd_args.volfile_servers);
  147 
  148     LOCK_INIT(&pool->lock);
  149     ctx->pool = pool;
  150 
  151     ret = 0;
  152 err:
  153     if (ret && pool) {
  154         if (pool->frame_mem_pool)
  155             mem_pool_destroy(pool->frame_mem_pool);
  156         if (pool->stack_mem_pool)
  157             mem_pool_destroy(pool->stack_mem_pool);
  158         GF_FREE(pool);
  159     }
  160 
  161     if (ret && ctx) {
  162         if (ctx->stub_mem_pool)
  163             mem_pool_destroy(ctx->stub_mem_pool);
  164         if (ctx->dict_pool)
  165             mem_pool_destroy(ctx->dict_pool);
  166         if (ctx->dict_data_pool)
  167             mem_pool_destroy(ctx->dict_data_pool);
  168         if (ctx->dict_pair_pool)
  169             mem_pool_destroy(ctx->dict_pair_pool);
  170         if (ctx->logbuf_pool)
  171             mem_pool_destroy(ctx->logbuf_pool);
  172     }
  173 
  174     return ret;
  175 }
  176 
  177 static int
  178 create_master(struct glfs *fs)
  179 {
  180     int ret = 0;
  181     xlator_t *master = NULL;
  182 
  183     master = GF_CALLOC(1, sizeof(*master), glfs_mt_xlator_t);
  184     if (!master)
  185         goto err;
  186 
  187     master->name = gf_strdup("gfapi");
  188     if (!master->name)
  189         goto err;
  190 
  191     if (xlator_set_type(master, "mount/api") == -1) {
  192         gf_msg("glfs", GF_LOG_ERROR, 0, API_MSG_MASTER_XLATOR_INIT_FAILED,
  193                "master xlator "
  194                "for %s initialization failed",
  195                fs->volname);
  196         goto err;
  197     }
  198 
  199     master->ctx = fs->ctx;
  200     master->private = fs;
  201     master->options = dict_new();
  202     if (!master->options)
  203         goto err;
  204 
  205     ret = xlator_init(master);
  206     if (ret) {
  207         gf_msg("glfs", GF_LOG_ERROR, 0, API_MSG_GFAPI_XLATOR_INIT_FAILED,
  208                "failed to initialize gfapi translator");
  209         goto err;
  210     }
  211 
  212     fs->ctx->master = master;
  213     THIS = master;
  214 
  215     return 0;
  216 
  217 err:
  218     if (master) {
  219         xlator_destroy(master);
  220     }
  221 
  222     return -1;
  223 }
  224 
  225 static FILE *
  226 get_volfp(struct glfs *fs)
  227 {
  228     cmd_args_t *cmd_args = NULL;
  229     FILE *specfp = NULL;
  230 
  231     cmd_args = &fs->ctx->cmd_args;
  232 
  233     if ((specfp = fopen(cmd_args->volfile, "r")) == NULL) {
  234         gf_msg("glfs", GF_LOG_ERROR, errno, API_MSG_VOLFILE_OPEN_FAILED,
  235                "volume file %s open failed: %s", cmd_args->volfile,
  236                strerror(errno));
  237         return NULL;
  238     }
  239 
  240     gf_msg_debug("glfs", 0, "loading volume file %s", cmd_args->volfile);
  241 
  242     return specfp;
  243 }
  244 
  245 int
  246 glfs_volumes_init(struct glfs *fs)
  247 {
  248     FILE *fp = NULL;
  249     cmd_args_t *cmd_args = NULL;
  250     int ret = 0;
  251 
  252     cmd_args = &fs->ctx->cmd_args;
  253 
  254     if (!vol_assigned(cmd_args))
  255         return -1;
  256 
  257     if (cmd_args->volfile_server) {
  258         ret = glfs_mgmt_init(fs);
  259         goto out;
  260     }
  261 
  262     fp = get_volfp(fs);
  263 
  264     if (!fp) {
  265         gf_msg("glfs", GF_LOG_ERROR, ENOENT, API_MSG_VOL_SPEC_FILE_ERROR,
  266                "Cannot reach volume specification file");
  267         ret = -1;
  268         goto out;
  269     }
  270 
  271     ret = glfs_process_volfp(fs, fp);
  272     if (ret)
  273         goto out;
  274 
  275 out:
  276     return ret;
  277 }
  278 
  279 ///////////////////////////////////////////////////////////////////////////////
  280 
  281 int
  282 pub_glfs_set_xlator_option(struct glfs *fs, const char *xlator, const char *key,
  283                            const char *value)
  284 {
  285     xlator_cmdline_option_t *option = NULL;
  286 
  287     DECLARE_OLD_THIS;
  288     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
  289 
  290     option = GF_CALLOC(1, sizeof(*option), glfs_mt_xlator_cmdline_option_t);
  291     if (!option)
  292         goto enomem;
  293 
  294     INIT_LIST_HEAD(&option->cmd_args);
  295 
  296     option->volume = gf_strdup(xlator);
  297     if (!option->volume)
  298         goto enomem;
  299     option->key = gf_strdup(key);
  300     if (!option->key)
  301         goto enomem;
  302     option->value = gf_strdup(value);
  303     if (!option->value)
  304         goto enomem;
  305 
  306     list_add(&option->cmd_args, &fs->ctx->cmd_args.xlator_options);
  307 
  308     __GLFS_EXIT_FS;
  309 
  310     return 0;
  311 enomem:
  312     errno = ENOMEM;
  313 
  314     if (!option) {
  315         __GLFS_EXIT_FS;
  316         return -1;
  317     }
  318 
  319     GF_FREE(option->volume);
  320     GF_FREE(option->key);
  321     GF_FREE(option->value);
  322     GF_FREE(option);
  323 
  324     __GLFS_EXIT_FS;
  325 
  326 invalid_fs:
  327     return -1;
  328 }
  329 
  330 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_xlator_option, 3.4.0);
  331 
  332 int
  333 pub_glfs_unset_volfile_server(struct glfs *fs, const char *transport,
  334                               const char *host, const int port)
  335 {
  336     cmd_args_t *cmd_args = NULL;
  337     server_cmdline_t *server = NULL;
  338     server_cmdline_t *tmp = NULL;
  339     char *transport_val = NULL;
  340     int port_val = 0;
  341     int ret = -1;
  342 
  343     if (!fs || !host) {
  344         errno = EINVAL;
  345         return ret;
  346     }
  347 
  348     DECLARE_OLD_THIS;
  349     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
  350 
  351     cmd_args = &fs->ctx->cmd_args;
  352 
  353     if (transport) {
  354         transport_val = gf_strdup(transport);
  355     } else {
  356         transport_val = gf_strdup(GF_DEFAULT_VOLFILE_TRANSPORT);
  357     }
  358 
  359     if (!transport_val) {
  360         errno = ENOMEM;
  361         goto out;
  362     }
  363 
  364     if (port) {
  365         port_val = port;
  366     } else {
  367         port_val = GF_DEFAULT_BASE_PORT;
  368     }
  369 
  370     list_for_each_entry_safe(server, tmp, &cmd_args->curr_server->list, list)
  371     {
  372         if ((!strcmp(server->volfile_server, host) &&
  373              !strcmp(server->transport, transport_val) &&
  374              (server->port == port_val))) {
  375             list_del(&server->list);
  376             ret = 0;
  377             goto out;
  378         }
  379     }
  380 
  381 out:
  382     GF_FREE(transport_val);
  383     __GLFS_EXIT_FS;
  384 
  385 invalid_fs:
  386     return ret;
  387 }
  388 
  389 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_unset_volfile_server, 3.5.1);
  390 
  391 int
  392 pub_glfs_set_volfile_server(struct glfs *fs, const char *transport,
  393                             const char *host, int port)
  394 {
  395     cmd_args_t *cmd_args = NULL;
  396     int ret = -1;
  397     char *server_host = NULL;
  398     char *server_transport = NULL;
  399 
  400     if (!fs || !host) {
  401         errno = EINVAL;
  402         return ret;
  403     }
  404 
  405     DECLARE_OLD_THIS;
  406     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
  407 
  408     cmd_args = &fs->ctx->cmd_args;
  409     cmd_args->max_connect_attempts = 1;
  410 
  411     server_host = gf_strdup(host);
  412     if (!server_host) {
  413         errno = ENOMEM;
  414         goto out;
  415     }
  416 
  417     if (transport) {
  418         /* volfile fetch support over tcp|unix only */
  419         if (!strcmp(transport, "tcp") || !strcmp(transport, "unix")) {
  420             server_transport = gf_strdup(transport);
  421         } else if (!strcmp(transport, "rdma")) {
  422             server_transport = gf_strdup(GF_DEFAULT_VOLFILE_TRANSPORT);
  423             gf_msg("glfs", GF_LOG_WARNING, EINVAL, API_MSG_INVALID_ENTRY,
  424                    "transport RDMA is deprecated, "
  425                    "falling back to tcp");
  426         } else {
  427             gf_msg("glfs", GF_LOG_TRACE, EINVAL, API_MSG_INVALID_ENTRY,
  428                    "transport %s is not supported, "
  429                    "possible values tcp|unix",
  430                    transport);
  431             goto out;
  432         }
  433     } else {
  434         server_transport = gf_strdup(GF_DEFAULT_VOLFILE_TRANSPORT);
  435     }
  436 
  437     if (!server_transport) {
  438         errno = ENOMEM;
  439         goto out;
  440     }
  441 
  442     if (!port) {
  443         port = GF_DEFAULT_BASE_PORT;
  444     }
  445 
  446     if (!strcmp(server_transport, "unix")) {
  447         port = 0;
  448     }
  449 
  450     ret = gf_set_volfile_server_common(cmd_args, server_host, server_transport,
  451                                        port);
  452     if (ret) {
  453         gf_log("glfs", GF_LOG_ERROR, "failed to set volfile server: %s",
  454                strerror(errno));
  455     }
  456 
  457 out:
  458     if (server_host) {
  459         GF_FREE(server_host);
  460     }
  461 
  462     if (server_transport) {
  463         GF_FREE(server_transport);
  464     }
  465 
  466     __GLFS_EXIT_FS;
  467 
  468 invalid_fs:
  469     return ret;
  470 }
  471 
  472 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_volfile_server, 3.4.0);
  473 
  474 /* *
  475  * Used to free the arguments allocated by glfs_set_volfile_server()
  476  */
  477 static void
  478 glfs_free_volfile_servers(cmd_args_t *cmd_args)
  479 {
  480     server_cmdline_t *server = NULL;
  481     server_cmdline_t *tmp = NULL;
  482 
  483     GF_VALIDATE_OR_GOTO(THIS->name, cmd_args, out);
  484 
  485     list_for_each_entry_safe(server, tmp, &cmd_args->volfile_servers, list)
  486     {
  487         list_del_init(&server->list);
  488         GF_FREE(server->volfile_server);
  489         GF_FREE(server->transport);
  490         GF_FREE(server);
  491     }
  492     cmd_args->curr_server = NULL;
  493 out:
  494     return;
  495 }
  496 
  497 static void
  498 glfs_free_xlator_options(cmd_args_t *cmd_args)
  499 {
  500     xlator_cmdline_option_t *xo = NULL;
  501     xlator_cmdline_option_t *tmp_xo = NULL;
  502 
  503     if (!&(cmd_args->xlator_options))
  504         return;
  505 
  506     list_for_each_entry_safe(xo, tmp_xo, &cmd_args->xlator_options, cmd_args)
  507     {
  508         list_del_init(&xo->cmd_args);
  509         GF_FREE(xo->volume);
  510         GF_FREE(xo->key);
  511         GF_FREE(xo->value);
  512         GF_FREE(xo);
  513     }
  514 }
  515 
  516 int
  517 pub_glfs_setfsuid(uid_t fsuid)
  518 {
  519     /* TODO:
  520      * - Set the THIS and restore it appropriately
  521      */
  522     return syncopctx_setfsuid(&fsuid);
  523 }
  524 
  525 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setfsuid, 3.4.2);
  526 
  527 int
  528 pub_glfs_setfsgid(gid_t fsgid)
  529 {
  530     /* TODO:
  531      * - Set the THIS and restore it appropriately
  532      */
  533     return syncopctx_setfsgid(&fsgid);
  534 }
  535 
  536 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setfsgid, 3.4.2);
  537 
  538 int
  539 pub_glfs_setfsgroups(size_t size, const gid_t *list)
  540 {
  541     /* TODO:
  542      * - Set the THIS and restore it appropriately
  543      */
  544     return syncopctx_setfsgroups(size, list);
  545 }
  546 
  547 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setfsgroups, 3.4.2);
  548 
  549 int
  550 pub_glfs_setfsleaseid(glfs_leaseid_t leaseid)
  551 {
  552     int ret = -1;
  553     char *gleaseid = NULL;
  554 
  555     gleaseid = gf_leaseid_get();
  556     if (gleaseid) {
  557         if (leaseid)
  558             memcpy(gleaseid, leaseid, LEASE_ID_SIZE);
  559         else /* reset leaseid */
  560             memset(gleaseid, 0, LEASE_ID_SIZE);
  561         ret = 0;
  562     }
  563 
  564     if (ret)
  565         gf_log("glfs", GF_LOG_ERROR, "failed to set leaseid: %s",
  566                strerror(errno));
  567     return ret;
  568 }
  569 
  570 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setfsleaseid, 4.0.0);
  571 
  572 int
  573 get_fop_attr_glfd(dict_t **fop_attr, struct glfs_fd *glfd)
  574 {
  575     char *leaseid = NULL;
  576     int ret = 0;
  577     gf_boolean_t dict_create = _gf_false;
  578 
  579     leaseid = GF_MALLOC(LEASE_ID_SIZE, gf_common_mt_char);
  580     GF_CHECK_ALLOC_AND_LOG("gfapi", leaseid, ret, "lease id alloc failed", out);
  581     memcpy(leaseid, glfd->lease_id, LEASE_ID_SIZE);
  582     if (*fop_attr == NULL) {
  583         *fop_attr = dict_new();
  584         dict_create = _gf_true;
  585     }
  586     GF_CHECK_ALLOC_AND_LOG("gfapi", *fop_attr, ret, "dict_new failed", out);
  587     ret = dict_set_bin(*fop_attr, "lease-id", leaseid, LEASE_ID_SIZE);
  588 out:
  589     if (ret) {
  590         GF_FREE(leaseid);
  591         if (dict_create) {
  592             if (*fop_attr)
  593                 dict_unref(*fop_attr);
  594             *fop_attr = NULL;
  595         }
  596     }
  597     return ret;
  598 }
  599 
  600 int
  601 set_fop_attr_glfd(struct glfs_fd *glfd)
  602 {
  603     char *lease_id = NULL;
  604     int ret = -1;
  605 
  606     lease_id = gf_existing_leaseid();
  607     if (lease_id) {
  608         memcpy(glfd->lease_id, lease_id, LEASE_ID_SIZE);
  609         ret = 0;
  610     }
  611     return ret;
  612 }
  613 
  614 int
  615 get_fop_attr_thrd_key(dict_t **fop_attr)
  616 {
  617     char *existing_leaseid = NULL, *leaseid = NULL;
  618     int ret = 0;
  619     gf_boolean_t dict_create = _gf_false;
  620 
  621     existing_leaseid = gf_existing_leaseid();
  622     if (existing_leaseid) {
  623         leaseid = GF_MALLOC(LEASE_ID_SIZE, gf_common_mt_char);
  624         GF_CHECK_ALLOC_AND_LOG("gfapi", leaseid, ret, "lease id alloc failed",
  625                                out);
  626         memcpy(leaseid, existing_leaseid, LEASE_ID_SIZE);
  627         if (*fop_attr == NULL) {
  628             *fop_attr = dict_new();
  629             dict_create = _gf_true;
  630         }
  631         GF_CHECK_ALLOC_AND_LOG("gfapi", *fop_attr, ret, "dict_new failed", out);
  632         ret = dict_set_bin(*fop_attr, "lease-id", leaseid, LEASE_ID_SIZE);
  633     }
  634 
  635 out:
  636     if (ret) {
  637         GF_FREE(leaseid);
  638         if (dict_create) {
  639             if (*fop_attr)
  640                 dict_unref(*fop_attr);
  641             *fop_attr = NULL;
  642         }
  643     }
  644     return ret;
  645 }
  646 
  647 void
  648 unset_fop_attr(dict_t **fop_attr)
  649 {
  650     char *lease_id = NULL;
  651     lease_id = gf_existing_leaseid();
  652     if (lease_id)
  653         memset(lease_id, 0, LEASE_ID_SIZE);
  654     if (*fop_attr) {
  655         dict_unref(*fop_attr);
  656         *fop_attr = NULL;
  657     }
  658 }
  659 struct glfs *
  660 pub_glfs_from_glfd(struct glfs_fd *glfd)
  661 {
  662     return glfd->fs;
  663 }
  664 
  665 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_from_glfd, 3.4.0);
  666 
  667 static void
  668 glfs_fd_destroy(struct glfs_fd *glfd)
  669 {
  670     if (!glfd)
  671         return;
  672 
  673     glfs_lock(glfd->fs, _gf_true);
  674     {
  675         list_del_init(&glfd->openfds);
  676     }
  677     glfs_unlock(glfd->fs);
  678 
  679     if (glfd->fd) {
  680         fd_unref(glfd->fd);
  681         glfd->fd = NULL;
  682     }
  683 
  684     GF_FREE(glfd->readdirbuf);
  685 
  686     GF_FREE(glfd);
  687 }
  688 
  689 struct glfs_fd *
  690 glfs_fd_new(struct glfs *fs)
  691 {
  692     struct glfs_fd *glfd = NULL;
  693 
  694     glfd = GF_CALLOC(1, sizeof(*glfd), glfs_mt_glfs_fd_t);
  695     if (!glfd)
  696         return NULL;
  697 
  698     glfd->fs = fs;
  699 
  700     INIT_LIST_HEAD(&glfd->openfds);
  701 
  702     GF_REF_INIT(glfd, glfs_fd_destroy);
  703 
  704     return glfd;
  705 }
  706 
  707 void
  708 glfs_fd_bind(struct glfs_fd *glfd)
  709 {
  710     struct glfs *fs = NULL;
  711 
  712     fs = glfd->fs;
  713 
  714     glfs_lock(fs, _gf_true);
  715     {
  716         list_add_tail(&glfd->openfds, &fs->openfds);
  717     }
  718     glfs_unlock(fs);
  719 }
  720 
  721 static void *
  722 glfs_poller(void *data)
  723 {
  724     struct glfs *fs = NULL;
  725 
  726     fs = data;
  727 
  728     gf_event_dispatch(fs->ctx->event_pool);
  729 
  730     return NULL;
  731 }
  732 
  733 static struct glfs *
  734 glfs_new_fs(const char *volname)
  735 {
  736     struct glfs *fs = NULL;
  737 
  738     fs = CALLOC(1, sizeof(*fs));
  739     if (!fs)
  740         return NULL;
  741 
  742     INIT_LIST_HEAD(&fs->openfds);
  743     INIT_LIST_HEAD(&fs->upcall_list);
  744     INIT_LIST_HEAD(&fs->waitq);
  745 
  746     PTHREAD_MUTEX_INIT(&fs->mutex, NULL, fs->pthread_flags, GLFS_INIT_MUTEX,
  747                        err);
  748 
  749     PTHREAD_COND_INIT(&fs->cond, NULL, fs->pthread_flags, GLFS_INIT_COND, err);
  750 
  751     PTHREAD_COND_INIT(&fs->child_down_cond, NULL, fs->pthread_flags,
  752                       GLFS_INIT_COND_CHILD, err);
  753 
  754     PTHREAD_MUTEX_INIT(&fs->upcall_list_mutex, NULL, fs->pthread_flags,
  755                        GLFS_INIT_MUTEX_UPCALL, err);
  756 
  757     fs->volname = strdup(volname);
  758     if (!fs->volname)
  759         goto err;
  760 
  761     fs->pin_refcnt = 0;
  762     fs->upcall_events = 0;
  763     fs->up_cbk = NULL;
  764     fs->up_data = NULL;
  765 
  766     return fs;
  767 
  768 err:
  769     glfs_free_from_ctx(fs);
  770     return NULL;
  771 }
  772 
  773 extern xlator_t global_xlator;
  774 extern glusterfs_ctx_t *global_ctx;
  775 extern pthread_mutex_t global_ctx_mutex;
  776 
  777 static int
  778 glfs_init_global_ctx()
  779 {
  780     int ret = 0;
  781     glusterfs_ctx_t *ctx = NULL;
  782 
  783     pthread_mutex_lock(&global_ctx_mutex);
  784     {
  785         if (global_xlator.ctx)
  786             goto unlock;
  787 
  788         ctx = glusterfs_ctx_new();
  789         if (!ctx) {
  790             ret = -1;
  791             goto unlock;
  792         }
  793 
  794         gf_log_globals_init(ctx, GF_LOG_NONE);
  795 
  796         global_ctx = ctx;
  797         global_xlator.ctx = global_ctx;
  798 
  799         ret = glusterfs_ctx_defaults_init(ctx);
  800         if (ret) {
  801             global_ctx = NULL;
  802             global_xlator.ctx = NULL;
  803             goto unlock;
  804         }
  805     }
  806 unlock:
  807     pthread_mutex_unlock(&global_ctx_mutex);
  808 
  809     if (ret)
  810         FREE(ctx);
  811 
  812     return ret;
  813 }
  814 
  815 struct glfs *
  816 pub_glfs_new(const char *volname)
  817 {
  818     struct glfs *fs = NULL;
  819     int ret = -1;
  820     glusterfs_ctx_t *ctx = NULL;
  821     xlator_t *old_THIS = NULL;
  822     char pname[16] = "";
  823     char msg[32] = "";
  824 
  825     if (!volname) {
  826         errno = EINVAL;
  827         return NULL;
  828     }
  829 
  830     /*
  831      * Do this as soon as possible in case something else depends on
  832      * pool allocations.
  833      */
  834     mem_pools_init();
  835 
  836     fs = glfs_new_fs(volname);
  837     if (!fs)
  838         goto out;
  839 
  840     ctx = glusterfs_ctx_new();
  841     if (!ctx)
  842         goto out;
  843 
  844     /* first globals init, for gf_mem_acct_enable_set () */
  845 
  846     ret = glusterfs_globals_init(ctx);
  847     if (ret)
  848         goto out;
  849 
  850     old_THIS = THIS;
  851     ret = glfs_init_global_ctx();
  852     if (ret)
  853         goto out;
  854 
  855     /* then ctx_defaults_init, for xlator_mem_acct_init(THIS) */
  856 
  857     ret = glusterfs_ctx_defaults_init(ctx);
  858     if (ret)
  859         goto out;
  860 
  861     fs->ctx = ctx;
  862     fs->ctx->process_mode = GF_CLIENT_PROCESS;
  863 
  864     ret = glfs_set_logging(fs, "/dev/null", 0);
  865     if (ret)
  866         goto out;
  867 
  868     fs->ctx->cmd_args.volfile_id = gf_strdup(volname);
  869     if (!(fs->ctx->cmd_args.volfile_id)) {
  870         ret = -1;
  871         goto out;
  872     }
  873 
  874     ret = -1;
  875 #ifdef GF_LINUX_HOST_OS
  876     ret = prctl(PR_GET_NAME, (unsigned long)pname, 0, 0, 0);
  877 #endif
  878     if (ret)
  879         fs->ctx->cmd_args.process_name = gf_strdup("gfapi");
  880     else {
  881         snprintf(msg, sizeof(msg), "gfapi.%s", pname);
  882         fs->ctx->cmd_args.process_name = gf_strdup(msg);
  883     }
  884     ret = 0;
  885 
  886 out:
  887     if (ret) {
  888         if (fs) {
  889             glfs_fini(fs);
  890             fs = NULL;
  891         } else {
  892             /* glfs_fini() calls mem_pools_fini() too */
  893             mem_pools_fini();
  894         }
  895     }
  896 
  897     if (old_THIS)
  898         THIS = old_THIS;
  899 
  900     return fs;
  901 }
  902 
  903 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_new, 3.4.0);
  904 
  905 struct glfs *
  906 priv_glfs_new_from_ctx(glusterfs_ctx_t *ctx)
  907 {
  908     struct glfs *fs = NULL;
  909 
  910     if (!ctx)
  911         goto out;
  912 
  913     fs = glfs_new_fs("");
  914     if (!fs)
  915         goto out;
  916 
  917     fs->ctx = ctx;
  918 
  919 out:
  920     return fs;
  921 }
  922 
  923 GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_new_from_ctx, 3.7.0);
  924 
  925 void
  926 priv_glfs_free_from_ctx(struct glfs *fs)
  927 {
  928     upcall_entry *u_list = NULL;
  929     upcall_entry *tmp = NULL;
  930 
  931     if (!fs)
  932         return;
  933 
  934     /* cleanup upcall structures */
  935     list_for_each_entry_safe(u_list, tmp, &fs->upcall_list, upcall_list)
  936     {
  937         list_del_init(&u_list->upcall_list);
  938         GF_FREE(u_list->upcall_data.data);
  939         GF_FREE(u_list);
  940     }
  941 
  942     PTHREAD_MUTEX_DESTROY(&fs->mutex, fs->pthread_flags, GLFS_INIT_MUTEX);
  943 
  944     PTHREAD_COND_DESTROY(&fs->cond, fs->pthread_flags, GLFS_INIT_COND);
  945 
  946     PTHREAD_COND_DESTROY(&fs->child_down_cond, fs->pthread_flags,
  947                          GLFS_INIT_COND_CHILD);
  948 
  949     PTHREAD_MUTEX_DESTROY(&fs->upcall_list_mutex, fs->pthread_flags,
  950                           GLFS_INIT_MUTEX_UPCALL);
  951 
  952     if (fs->oldvolfile)
  953         FREE(fs->oldvolfile);
  954 
  955     FREE(fs->volname);
  956 
  957     FREE(fs);
  958 }
  959 
  960 GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_free_from_ctx, 3.7.0);
  961 
  962 int
  963 pub_glfs_set_volfile(struct glfs *fs, const char *volfile)
  964 {
  965     cmd_args_t *cmd_args = NULL;
  966 
  967     cmd_args = &fs->ctx->cmd_args;
  968 
  969     if (vol_assigned(cmd_args))
  970         return -1;
  971 
  972     cmd_args->volfile = gf_strdup(volfile);
  973     if (!cmd_args->volfile)
  974         return -1;
  975     return 0;
  976 }
  977 
  978 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_volfile, 3.4.0);
  979 
  980 int
  981 pub_glfs_set_logging(struct glfs *fs, const char *logfile, int loglevel)
  982 {
  983     int ret = -1;
  984     char *tmplog = NULL;
  985 
  986     DECLARE_OLD_THIS;
  987     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
  988 
  989     if (!logfile) {
  990         ret = gf_set_log_file_path(&fs->ctx->cmd_args, fs->ctx);
  991         if (ret)
  992             goto out;
  993         tmplog = fs->ctx->cmd_args.log_file;
  994     } else {
  995         tmplog = (char *)logfile;
  996     }
  997 
  998     /* finish log set parameters before init */
  999     if (loglevel >= 0)
 1000         gf_log_set_loglevel(fs->ctx, loglevel);
 1001 
 1002     ret = gf_log_init(fs->ctx, tmplog, NULL);
 1003     if (ret)
 1004         goto out;
 1005 
 1006     ret = gf_log_inject_timer_event(fs->ctx);
 1007     if (ret)
 1008         goto out;
 1009 
 1010 out:
 1011     __GLFS_EXIT_FS;
 1012 
 1013 invalid_fs:
 1014     return ret;
 1015 }
 1016 
 1017 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_logging, 3.4.0);
 1018 
 1019 int
 1020 glfs_init_wait(struct glfs *fs)
 1021 {
 1022     int ret = -1;
 1023 
 1024     /* Always a top-down call, use glfs_lock() */
 1025     glfs_lock(fs, _gf_true);
 1026     {
 1027         while (!fs->init)
 1028             pthread_cond_wait(&fs->cond, &fs->mutex);
 1029         ret = fs->ret;
 1030         errno = fs->err;
 1031     }
 1032     glfs_unlock(fs);
 1033 
 1034     return ret;
 1035 }
 1036 
 1037 void
 1038 priv_glfs_init_done(struct glfs *fs, int ret)
 1039 {
 1040     glfs_init_cbk init_cbk;
 1041 
 1042     if (!fs) {
 1043         gf_msg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_GLFS_FSOBJ_NULL,
 1044                "fs is NULL");
 1045         goto out;
 1046     }
 1047 
 1048     init_cbk = fs->init_cbk;
 1049 
 1050     /* Always a bottom-up call, use mutex_lock() */
 1051     pthread_mutex_lock(&fs->mutex);
 1052     {
 1053         fs->init = 1;
 1054         fs->ret = ret;
 1055         fs->err = errno;
 1056 
 1057         if (!init_cbk)
 1058             pthread_cond_broadcast(&fs->cond);
 1059     }
 1060     pthread_mutex_unlock(&fs->mutex);
 1061 
 1062     if (init_cbk)
 1063         init_cbk(fs, ret);
 1064 out:
 1065     return;
 1066 }
 1067 
 1068 GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_init_done, 3.4.0);
 1069 
 1070 int
 1071 glfs_init_common(struct glfs *fs)
 1072 {
 1073     int ret = -1;
 1074 
 1075     ret = create_master(fs);
 1076     if (ret)
 1077         return ret;
 1078 
 1079     ret = gf_thread_create(&fs->poller, NULL, glfs_poller, fs, "glfspoll");
 1080     if (ret)
 1081         return ret;
 1082 
 1083     ret = glfs_volumes_init(fs);
 1084     if (ret)
 1085         return ret;
 1086 
 1087     fs->dev_id = gf_dm_hashfn(fs->volname, strlen(fs->volname));
 1088     return ret;
 1089 }
 1090 
 1091 int
 1092 glfs_init_async(struct glfs *fs, glfs_init_cbk cbk)
 1093 {
 1094     int ret = -1;
 1095 
 1096     if (!fs || !fs->ctx) {
 1097         gf_msg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_INVALID_ENTRY,
 1098                "fs is not properly initialized.");
 1099         errno = EINVAL;
 1100         return ret;
 1101     }
 1102 
 1103     fs->init_cbk = cbk;
 1104 
 1105     ret = glfs_init_common(fs);
 1106 
 1107     return ret;
 1108 }
 1109 
 1110 int
 1111 pub_glfs_init(struct glfs *fs)
 1112 {
 1113     int ret = -1;
 1114 
 1115     DECLARE_OLD_THIS;
 1116 
 1117     if (!fs || !fs->ctx) {
 1118         gf_msg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_INVALID_ENTRY,
 1119                "fs is not properly initialized.");
 1120         errno = EINVAL;
 1121         return ret;
 1122     }
 1123 
 1124     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
 1125 
 1126     ret = glfs_init_common(fs);
 1127     if (ret)
 1128         goto out;
 1129 
 1130     ret = glfs_init_wait(fs);
 1131 out:
 1132     __GLFS_EXIT_FS;
 1133 
 1134     /* Set the initial current working directory to "/" */
 1135     if (ret >= 0) {
 1136         ret = glfs_chdir(fs, "/");
 1137     }
 1138 
 1139 invalid_fs:
 1140     return ret;
 1141 }
 1142 
 1143 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_init, 3.4.0);
 1144 
 1145 static int
 1146 glusterfs_ctx_destroy(glusterfs_ctx_t *ctx)
 1147 {
 1148     call_pool_t *pool = NULL;
 1149     int ret = 0;
 1150     glusterfs_graph_t *trav_graph = NULL;
 1151     glusterfs_graph_t *tmp = NULL;
 1152 
 1153     if (ctx == NULL)
 1154         return 0;
 1155 
 1156     if (ctx->cmd_args.curr_server)
 1157         glfs_free_volfile_servers(&ctx->cmd_args);
 1158 
 1159     glfs_free_xlator_options(&ctx->cmd_args);
 1160 
 1161     /* For all the graphs, crawl through the xlator_t structs and free
 1162      * all its members except for the mem_acct member,
 1163      * as GF_FREE will be referencing it.
 1164      */
 1165     list_for_each_entry_safe(trav_graph, tmp, &ctx->graphs, list)
 1166     {
 1167         xlator_tree_free_members(trav_graph->first);
 1168     }
 1169 
 1170     /* Free the memory pool */
 1171     if (ctx->stub_mem_pool)
 1172         mem_pool_destroy(ctx->stub_mem_pool);
 1173     if (ctx->dict_pool)
 1174         mem_pool_destroy(ctx->dict_pool);
 1175     if (ctx->dict_data_pool)
 1176         mem_pool_destroy(ctx->dict_data_pool);
 1177     if (ctx->dict_pair_pool)
 1178         mem_pool_destroy(ctx->dict_pair_pool);
 1179     if (ctx->logbuf_pool)
 1180         mem_pool_destroy(ctx->logbuf_pool);
 1181 
 1182     pool = ctx->pool;
 1183     if (pool) {
 1184         if (pool->frame_mem_pool)
 1185             mem_pool_destroy(pool->frame_mem_pool);
 1186         if (pool->stack_mem_pool)
 1187             mem_pool_destroy(pool->stack_mem_pool);
 1188         LOCK_DESTROY(&pool->lock);
 1189         GF_FREE(pool);
 1190     }
 1191 
 1192     /* Free the event pool */
 1193     ret = gf_event_pool_destroy(ctx->event_pool);
 1194 
 1195     /* Free the iobuf pool */
 1196     iobuf_pool_destroy(ctx->iobuf_pool);
 1197 
 1198     GF_FREE(ctx->process_uuid);
 1199     GF_FREE(ctx->cmd_args.volfile_id);
 1200     GF_FREE(ctx->cmd_args.process_name);
 1201 
 1202     LOCK_DESTROY(&ctx->lock);
 1203     pthread_mutex_destroy(&ctx->notify_lock);
 1204     pthread_cond_destroy(&ctx->notify_cond);
 1205 
 1206     /* Free all the graph structs and its containing xlator_t structs
 1207      * from this point there should be no reference to GF_FREE/GF_CALLOC
 1208      * as it will try to access mem_acct and the below function would
 1209      * have freed the same.
 1210      */
 1211     list_for_each_entry_safe(trav_graph, tmp, &ctx->graphs, list)
 1212     {
 1213         glusterfs_graph_destroy_residual(trav_graph);
 1214     }
 1215 
 1216     GF_FREE(ctx->statedump_path);
 1217     FREE(ctx);
 1218 
 1219     return ret;
 1220 }
 1221 
 1222 int
 1223 pub_glfs_fini(struct glfs *fs)
 1224 {
 1225     int ret = -1;
 1226     int countdown = 100;
 1227     xlator_t *subvol = NULL;
 1228     glusterfs_ctx_t *ctx = NULL;
 1229     glusterfs_graph_t *graph = NULL;
 1230     call_pool_t *call_pool = NULL;
 1231     int fs_init = 0;
 1232     int err = -1;
 1233     struct synctask *waittask = NULL;
 1234 
 1235     DECLARE_OLD_THIS;
 1236 
 1237     if (!fs) {
 1238         errno = EINVAL;
 1239         goto invalid_fs;
 1240     }
 1241 
 1242     ctx = fs->ctx;
 1243     if (!ctx) {
 1244         goto free_fs;
 1245     }
 1246 
 1247     THIS = fs->ctx->master;
 1248 
 1249     if (ctx->mgmt) {
 1250         rpc_clnt_disable(ctx->mgmt);
 1251     }
 1252 
 1253     call_pool = fs->ctx->pool;
 1254 
 1255     /* Wake up any suspended synctasks */
 1256     while (!list_empty(&fs->waitq)) {
 1257         waittask = list_entry(fs->waitq.next, struct synctask, waitq);
 1258         list_del_init(&waittask->waitq);
 1259         synctask_wake(waittask);
 1260     }
 1261 
 1262     while (countdown--) {
 1263         /* give some time for background frames to finish */
 1264         pthread_mutex_lock(&fs->mutex);
 1265         {
 1266             /* Do we need to increase countdown? */
 1267             if ((!call_pool->cnt) && (!fs->pin_refcnt)) {
 1268                 gf_msg_trace("glfs", 0,
 1269                              "call_pool_cnt - %" PRId64
 1270                              ","
 1271                              "pin_refcnt - %d",
 1272                              call_pool->cnt, fs->pin_refcnt);
 1273 
 1274                 ctx->cleanup_started = 1;
 1275                 pthread_mutex_unlock(&fs->mutex);
 1276                 break;
 1277             }
 1278         }
 1279         pthread_mutex_unlock(&fs->mutex);
 1280         usleep(100000);
 1281     }
 1282 
 1283     /* leaked frames may exist, we ignore */
 1284 
 1285     /*We deem glfs_fini as successful if there are no pending frames in the call
 1286      *pool*/
 1287     ret = (call_pool->cnt == 0) ? 0 : -1;
 1288 
 1289     pthread_mutex_lock(&fs->mutex);
 1290     {
 1291         fs_init = fs->init;
 1292     }
 1293     pthread_mutex_unlock(&fs->mutex);
 1294 
 1295     if (fs_init != 0) {
 1296         subvol = glfs_active_subvol(fs);
 1297         if (subvol) {
 1298             /* PARENT_DOWN within glfs_subvol_done() is issued
 1299                only on graph switch (new graph should activiate
 1300                and decrement the extra @winds count taken in
 1301                glfs_graph_setup()
 1302 
 1303                Since we are explicitly destroying,
 1304                PARENT_DOWN is necessary
 1305             */
 1306             xlator_notify(subvol, GF_EVENT_PARENT_DOWN, subvol, 0);
 1307             /* Here we wait for GF_EVENT_CHILD_DOWN before exiting,
 1308                in case of asynchrnous cleanup
 1309             */
 1310             graph = subvol->graph;
 1311             err = pthread_mutex_lock(&fs->mutex);
 1312             if (err != 0) {
 1313                 gf_msg("glfs", GF_LOG_ERROR, err, API_MSG_FSMUTEX_LOCK_FAILED,
 1314                        "pthread lock on glfs mutex, "
 1315                        "returned error: (%s)",
 1316                        strerror(err));
 1317                 goto fail;
 1318             }
 1319             /* check and wait for CHILD_DOWN for active subvol*/
 1320             {
 1321                 while (graph->used) {
 1322                     err = pthread_cond_wait(&fs->child_down_cond, &fs->mutex);
 1323                     if (err != 0)
 1324                         gf_msg("glfs", GF_LOG_INFO, err,
 1325                                API_MSG_COND_WAIT_FAILED,
 1326                                "%s cond wait failed %s", subvol->name,
 1327                                strerror(err));
 1328                 }
 1329             }
 1330 
 1331             err = pthread_mutex_unlock(&fs->mutex);
 1332             if (err != 0) {
 1333                 gf_msg("glfs", GF_LOG_ERROR, err, API_MSG_FSMUTEX_UNLOCK_FAILED,
 1334                        "pthread unlock on glfs mutex, "
 1335                        "returned error: (%s)",
 1336                        strerror(err));
 1337                 goto fail;
 1338             }
 1339         }
 1340         glfs_subvol_done(fs, subvol);
 1341     }
 1342 
 1343     ctx->cleanup_started = 1;
 1344 
 1345     if (fs_init != 0) {
 1346         /* Destroy all the inode tables of all the graphs.
 1347          * NOTE:
 1348          * - inode objects should be destroyed before calling fini()
 1349          *   of each xlator, as fini() and forget() of the xlators
 1350          *   can share few common locks or data structures, calling
 1351          *   fini first might destroy those required by forget
 1352          *   ( eg: in quick-read)
 1353          * - The call to inode_table_destroy_all is not required when
 1354          *   the cleanup during graph switch is implemented to perform
 1355          *   inode table destroy.
 1356          */
 1357         inode_table_destroy_all(ctx);
 1358 
 1359         /* Call fini() of all the xlators in the active graph
 1360          * NOTE:
 1361          * - xlator fini() should be called before destroying any of
 1362          *   the threads. (eg: fini() in protocol-client uses timer
 1363          *   thread) */
 1364         glusterfs_graph_deactivate(ctx->active);
 1365 
 1366         /* Join the syncenv_processor threads and cleanup
 1367          * syncenv resources*/
 1368         syncenv_destroy(ctx->env);
 1369 
 1370         /* Join the poller thread */
 1371         if (gf_event_dispatch_destroy(ctx->event_pool) < 0)
 1372             ret = -1;
 1373     }
 1374 
 1375     /* Avoid dispatching events to mgmt after freed,
 1376      * unreference mgmt after the event_dispatch_destroy */
 1377     if (ctx->mgmt) {
 1378         rpc_clnt_unref(ctx->mgmt);
 1379         ctx->mgmt = NULL;
 1380     }
 1381 
 1382     /* log infra has to be brought down before destroying
 1383      * timer registry, as logging uses timer infra
 1384      */
 1385     if (gf_log_fini(ctx) != 0)
 1386         ret = -1;
 1387 
 1388     /* Join the timer thread */
 1389     if (fs_init != 0) {
 1390         gf_timer_registry_destroy(ctx);
 1391     }
 1392 
 1393     /* Destroy the context and the global pools */
 1394     if (glusterfs_ctx_destroy(ctx) != 0)
 1395         ret = -1;
 1396 
 1397 free_fs:
 1398     glfs_free_from_ctx(fs);
 1399 
 1400     /*
 1401      * Do this as late as possible in case anything else has (or
 1402      * grows) a dependency on mem-pool allocations.
 1403      */
 1404     mem_pools_fini();
 1405 
 1406 fail:
 1407     if (!ret)
 1408         ret = err;
 1409 
 1410     __GLFS_EXIT_FS;
 1411 
 1412 invalid_fs:
 1413     return ret;
 1414 }
 1415 
 1416 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fini, 3.4.0);
 1417 
 1418 ssize_t
 1419 pub_glfs_get_volfile(struct glfs *fs, void *buf, size_t len)
 1420 {
 1421     ssize_t res = -1;
 1422 
 1423     DECLARE_OLD_THIS;
 1424     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
 1425 
 1426     glfs_lock(fs, _gf_true);
 1427     if (len >= fs->oldvollen) {
 1428         gf_msg_trace("glfs", 0, "copying %zu to %p", len, buf);
 1429         memcpy(buf, fs->oldvolfile, len);
 1430         res = len;
 1431     } else {
 1432         res = len - fs->oldvollen;
 1433         gf_msg_trace("glfs", 0, "buffer is %zd too short", -res);
 1434     }
 1435     glfs_unlock(fs);
 1436 
 1437     __GLFS_EXIT_FS;
 1438 
 1439 invalid_fs:
 1440     return res;
 1441 }
 1442 
 1443 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_get_volfile, 3.6.0);
 1444 
 1445 int
 1446 priv_glfs_ipc(struct glfs *fs, int opcode, void *xd_in, void **xd_out)
 1447 {
 1448     xlator_t *subvol = NULL;
 1449     int ret = -1;
 1450 
 1451     DECLARE_OLD_THIS;
 1452     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
 1453 
 1454     subvol = glfs_active_subvol(fs);
 1455     if (!subvol) {
 1456         ret = -1;
 1457         errno = EIO;
 1458         goto out;
 1459     }
 1460 
 1461     ret = syncop_ipc(subvol, opcode, (dict_t *)xd_in, (dict_t **)xd_out);
 1462     DECODE_SYNCOP_ERR(ret);
 1463 
 1464 out:
 1465     glfs_subvol_done(fs, subvol);
 1466     __GLFS_EXIT_FS;
 1467 
 1468 invalid_fs:
 1469     return ret;
 1470 }
 1471 
 1472 GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_ipc, 3.12.0);
 1473 
 1474 int
 1475 priv_glfs_setfspid(struct glfs *fs, pid_t pid)
 1476 {
 1477     cmd_args_t *cmd_args = NULL;
 1478     int ret = 0;
 1479 
 1480     cmd_args = &fs->ctx->cmd_args;
 1481     cmd_args->client_pid = pid;
 1482     cmd_args->client_pid_set = 1;
 1483     ret = syncopctx_setfspid(&pid);
 1484 
 1485     return ret;
 1486 }
 1487 GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_setfspid, 6.1);
 1488 
 1489 void
 1490 pub_glfs_free(void *ptr)
 1491 {
 1492     GLFS_FREE(ptr);
 1493 }
 1494 
 1495 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_free, 3.7.16);
 1496 
 1497 struct glfs *
 1498 pub_glfs_upcall_get_fs(struct glfs_upcall *arg)
 1499 {
 1500     return arg->fs;
 1501 }
 1502 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_fs, 3.7.16);
 1503 
 1504 enum glfs_upcall_reason
 1505 pub_glfs_upcall_get_reason(struct glfs_upcall *arg)
 1506 {
 1507     return arg->reason;
 1508 }
 1509 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_reason, 3.7.16);
 1510 
 1511 void *
 1512 pub_glfs_upcall_get_event(struct glfs_upcall *arg)
 1513 {
 1514     return arg->event;
 1515 }
 1516 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_event, 3.7.16);
 1517 
 1518 struct glfs_object *
 1519 pub_glfs_upcall_inode_get_object(struct glfs_upcall_inode *arg)
 1520 {
 1521     return arg->object;
 1522 }
 1523 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_object, 3.7.16);
 1524 
 1525 uint64_t
 1526 pub_glfs_upcall_inode_get_flags(struct glfs_upcall_inode *arg)
 1527 {
 1528     return arg->flags;
 1529 }
 1530 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_flags, 3.7.16);
 1531 
 1532 struct stat *
 1533 pub_glfs_upcall_inode_get_stat(struct glfs_upcall_inode *arg)
 1534 {
 1535     return &arg->buf;
 1536 }
 1537 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_stat, 3.7.16);
 1538 
 1539 uint64_t
 1540 pub_glfs_upcall_inode_get_expire(struct glfs_upcall_inode *arg)
 1541 {
 1542     return arg->expire_time_attr;
 1543 }
 1544 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_expire, 3.7.16);
 1545 
 1546 struct glfs_object *
 1547 pub_glfs_upcall_inode_get_pobject(struct glfs_upcall_inode *arg)
 1548 {
 1549     return arg->p_object;
 1550 }
 1551 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_pobject, 3.7.16);
 1552 
 1553 struct stat *
 1554 pub_glfs_upcall_inode_get_pstat(struct glfs_upcall_inode *arg)
 1555 {
 1556     return &arg->p_buf;
 1557 }
 1558 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_pstat, 3.7.16);
 1559 
 1560 struct glfs_object *
 1561 pub_glfs_upcall_inode_get_oldpobject(struct glfs_upcall_inode *arg)
 1562 {
 1563     return arg->oldp_object;
 1564 }
 1565 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_oldpobject, 3.7.16);
 1566 
 1567 struct stat *
 1568 pub_glfs_upcall_inode_get_oldpstat(struct glfs_upcall_inode *arg)
 1569 {
 1570     return &arg->oldp_buf;
 1571 }
 1572 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_oldpstat, 3.7.16);
 1573 
 1574 struct glfs_object *
 1575 pub_glfs_upcall_lease_get_object(struct glfs_upcall_lease *arg)
 1576 {
 1577     return arg->object;
 1578 }
 1579 
 1580 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_lease_get_object, 4.1.6);
 1581 
 1582 uint32_t
 1583 pub_glfs_upcall_lease_get_lease_type(struct glfs_upcall_lease *arg)
 1584 {
 1585     return arg->lease_type;
 1586 }
 1587 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_lease_get_lease_type, 4.1.6);
 1588 
 1589 /* definitions of the GLFS_SYSRQ_* chars are in glfs.h */
 1590 static struct glfs_sysrq_help {
 1591     char sysrq;
 1592     char *msg;
 1593 } glfs_sysrq_help[] = {{GLFS_SYSRQ_HELP, "(H)elp"},
 1594                        {GLFS_SYSRQ_STATEDUMP, "(S)tatedump"},
 1595                        {0, NULL}};
 1596 
 1597 int
 1598 pub_glfs_sysrq(struct glfs *fs, char sysrq)
 1599 {
 1600     glusterfs_ctx_t *ctx = NULL;
 1601     int ret = 0;
 1602     int msg_len;
 1603     char msg[1024] = {
 1604         0,
 1605     }; /* should not exceed 1024 chars */
 1606 
 1607     if (!fs || !fs->ctx) {
 1608         ret = -1;
 1609         errno = EINVAL;
 1610         goto out;
 1611     }
 1612 
 1613     ctx = fs->ctx;
 1614 
 1615     switch (sysrq) {
 1616         case GLFS_SYSRQ_HELP: {
 1617             struct glfs_sysrq_help *usage = NULL;
 1618 
 1619             for (usage = glfs_sysrq_help; usage->sysrq; usage++) {
 1620                 msg_len = strlen(msg);
 1621                 snprintf(msg + msg_len, /* append to msg */
 1622                          sizeof(msg) - msg_len - 2,
 1623                          /* - 2 for the " " + terminating \0 */
 1624                          " %s", usage->msg);
 1625             }
 1626 
 1627             /* not really an 'error', but make sure it gets logged */
 1628             gf_log("glfs", GF_LOG_ERROR, "available events: %s", msg);
 1629 
 1630             break;
 1631         }
 1632         case GLFS_SYSRQ_STATEDUMP:
 1633             gf_proc_dump_info(SIGUSR1, ctx);
 1634             break;
 1635         default:
 1636             gf_msg("glfs", GF_LOG_ERROR, ENOTSUP, API_MSG_INVALID_ENTRY,
 1637                    "'%c' is not a valid sysrq", sysrq);
 1638             errno = ENOTSUP;
 1639             ret = -1;
 1640     }
 1641 out:
 1642     return ret;
 1643 }
 1644 
 1645 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_sysrq, 3.10.0);
 1646 
 1647 int
 1648 pub_glfs_upcall_register(struct glfs *fs, uint32_t event_list,
 1649                          glfs_upcall_cbk cbk, void *data)
 1650 {
 1651     int ret = 0;
 1652 
 1653     /* list of supported upcall events */
 1654     uint32_t up_events = (GLFS_EVENT_INODE_INVALIDATE |
 1655                           GLFS_EVENT_RECALL_LEASE);
 1656 
 1657     DECLARE_OLD_THIS;
 1658     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
 1659 
 1660     GF_VALIDATE_OR_GOTO(THIS->name, cbk, out);
 1661 
 1662     /* Event list should be either GLFS_EVENT_ANY
 1663      * or list of supported individual events (up_events)
 1664      */
 1665     if ((event_list != GLFS_EVENT_ANY) && (event_list & ~up_events)) {
 1666         errno = EINVAL;
 1667         ret = -1;
 1668         gf_msg(THIS->name, GF_LOG_ERROR, errno, LG_MSG_INVALID_ARG,
 1669                "invalid event_list (0x%08x)", event_list);
 1670         goto out;
 1671     }
 1672 
 1673     /* in case other thread does unregister */
 1674     pthread_mutex_lock(&fs->mutex);
 1675     {
 1676         if (event_list & GLFS_EVENT_INODE_INVALIDATE) {
 1677             /* @todo: Check if features.cache-invalidation is
 1678              * enabled.
 1679              */
 1680             fs->upcall_events |= GF_UPCALL_CACHE_INVALIDATION;
 1681             ret |= GLFS_EVENT_INODE_INVALIDATE;
 1682         }
 1683         if (event_list & GLFS_EVENT_RECALL_LEASE) {
 1684             /* @todo: Check if features.leases is enabled */
 1685             fs->upcall_events |= GF_UPCALL_RECALL_LEASE;
 1686             ret |= GLFS_EVENT_RECALL_LEASE;
 1687         }
 1688         /* Override cbk function if existing */
 1689         fs->up_cbk = cbk;
 1690         fs->up_data = data;
 1691         fs->cache_upcalls = _gf_true;
 1692     }
 1693     pthread_mutex_unlock(&fs->mutex);
 1694 
 1695 out:
 1696     __GLFS_EXIT_FS;
 1697 
 1698 invalid_fs:
 1699     return ret;
 1700 }
 1701 
 1702 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_register, 3.13.0);
 1703 
 1704 int
 1705 pub_glfs_upcall_unregister(struct glfs *fs, uint32_t event_list)
 1706 {
 1707     int ret = 0;
 1708     /* list of supported upcall events */
 1709     uint32_t up_events = (GLFS_EVENT_INODE_INVALIDATE |
 1710                           GLFS_EVENT_RECALL_LEASE);
 1711 
 1712     DECLARE_OLD_THIS;
 1713     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
 1714 
 1715     /* Event list should be either GLFS_EVENT_ANY
 1716      * or list of supported individual events (up_events)
 1717      */
 1718     if ((event_list != GLFS_EVENT_ANY) && (event_list & ~up_events)) {
 1719         errno = EINVAL;
 1720         ret = -1;
 1721         gf_msg(THIS->name, GF_LOG_ERROR, errno, LG_MSG_INVALID_ARG,
 1722                "invalid event_list (0x%08x)", event_list);
 1723         goto out;
 1724     }
 1725 
 1726     pthread_mutex_lock(&fs->mutex);
 1727     {
 1728         /* We already checked if event_list contains list of supported
 1729          * upcall events. No other specific checks needed as of now for
 1730          * unregister */
 1731         fs->upcall_events &= ~(event_list);
 1732         ret |= ((event_list == GLFS_EVENT_ANY) ? up_events : event_list);
 1733 
 1734         /* If there are no upcall events registered, reset cbk */
 1735         if (fs->upcall_events == 0) {
 1736             fs->up_cbk = NULL;
 1737             fs->up_data = NULL;
 1738             fs->cache_upcalls = _gf_false;
 1739         }
 1740     }
 1741     pthread_mutex_unlock(&fs->mutex);
 1742 
 1743 out:
 1744     __GLFS_EXIT_FS;
 1745 
 1746 invalid_fs:
 1747     return ret;
 1748 }
 1749 
 1750 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_unregister, 3.13.0);
 1751 
 1752 int
 1753 pub_glfs_set_statedump_path(struct glfs *fs, const char *path)
 1754 {
 1755     struct stat st;
 1756     int ret;
 1757     DECLARE_OLD_THIS;
 1758     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
 1759 
 1760     if (!path) {
 1761         gf_log("glfs", GF_LOG_ERROR, "path is NULL");
 1762         errno = EINVAL;
 1763         goto err;
 1764     }
 1765 
 1766     /* If path is not present OR, if it is directory AND has enough permission
 1767      * to create files, then proceed */
 1768     ret = sys_stat(path, &st);
 1769     if (ret && errno != ENOENT) {
 1770         gf_log("glfs", GF_LOG_ERROR, "%s: not a valid path (%s)", path,
 1771                strerror(errno));
 1772         errno = EINVAL;
 1773         goto err;
 1774     }
 1775 
 1776     if (!ret) {
 1777         /* file is present, now check other things */
 1778         if (!S_ISDIR(st.st_mode)) {
 1779             gf_log("glfs", GF_LOG_ERROR, "%s: path is not directory", path);
 1780             errno = EINVAL;
 1781             goto err;
 1782         }
 1783         if (sys_access(path, W_OK | X_OK) < 0) {
 1784             gf_log("glfs", GF_LOG_ERROR,
 1785                    "%s: path doesn't have write permission", path);
 1786             errno = EPERM;
 1787             goto err;
 1788         }
 1789     }
 1790 
 1791     /* If set, it needs to be freed, so we don't have leak */
 1792     GF_FREE(fs->ctx->statedump_path);
 1793 
 1794     fs->ctx->statedump_path = gf_strdup(path);
 1795     if (!fs->ctx->statedump_path) {
 1796         gf_log("glfs", GF_LOG_ERROR,
 1797                "%s: failed to set statedump path, no memory", path);
 1798         errno = ENOMEM;
 1799         goto err;
 1800     }
 1801 
 1802     __GLFS_EXIT_FS;
 1803 
 1804     return 0;
 1805 err:
 1806     __GLFS_EXIT_FS;
 1807 
 1808 invalid_fs:
 1809     return -1;
 1810 }
 1811 
 1812 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_statedump_path, 7.0);