"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/api/src/glfs.c" (16 Sep 2020, 42971 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 "glfs.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 8.0_vs_8.1.

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