"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/api/src/glfs-mgmt.c" (16 Sep 2020, 28115 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-mgmt.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 #include <stdio.h>
   12 #include <sys/types.h>
   13 #include <sys/wait.h>
   14 #include <stdlib.h>
   15 #include <signal.h>
   16 #include <pthread.h>
   17 
   18 #include <glusterfs/glusterfs.h>
   19 #include "glfs.h"
   20 #include <glusterfs/dict.h>
   21 
   22 #include "rpc-clnt.h"
   23 #include "protocol-common.h"
   24 #include "xdr-generic.h"
   25 #include "rpc-common-xdr.h"
   26 
   27 #include <glusterfs/syncop.h>
   28 
   29 #include "glfs-internal.h"
   30 #include "gfapi-messages.h"
   31 #include <glusterfs/syscall.h>
   32 
   33 int
   34 glfs_volfile_fetch(struct glfs *fs);
   35 int32_t
   36 glfs_get_volume_info_rpc(call_frame_t *frame, xlator_t *this, struct glfs *fs);
   37 
   38 int
   39 glfs_process_volfp(struct glfs *fs, FILE *fp)
   40 {
   41     glusterfs_graph_t *graph = NULL;
   42     int ret = -1;
   43     xlator_t *trav = NULL;
   44     glusterfs_ctx_t *ctx = NULL;
   45 
   46     ctx = fs->ctx;
   47     graph = glusterfs_graph_construct(fp);
   48     if (!graph) {
   49         gf_smsg("glfs", GF_LOG_ERROR, errno, API_MSG_GRAPH_CONSTRUCT_FAILED,
   50                 NULL);
   51         goto out;
   52     }
   53 
   54     for (trav = graph->first; trav; trav = trav->next) {
   55         if (strcmp(trav->type, "mount/api") == 0) {
   56             gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_API_XLATOR_ERROR,
   57                     NULL);
   58             goto out;
   59         }
   60     }
   61 
   62     ret = glusterfs_graph_prepare(graph, ctx, fs->volname);
   63     if (ret) {
   64         glusterfs_graph_destroy(graph);
   65         goto out;
   66     }
   67 
   68     ret = glusterfs_graph_activate(graph, ctx);
   69 
   70     if (ret) {
   71         glusterfs_graph_destroy(graph);
   72         goto out;
   73     }
   74 
   75     gf_log_dump_graph(fp, graph);
   76 
   77     ret = 0;
   78 out:
   79     if (fp)
   80         fclose(fp);
   81 
   82     if (!ctx->active) {
   83         ret = -1;
   84     }
   85 
   86     return ret;
   87 }
   88 
   89 int
   90 mgmt_cbk_spec(struct rpc_clnt *rpc, void *mydata, void *data)
   91 {
   92     struct glfs *fs = NULL;
   93     xlator_t *this = NULL;
   94 
   95     this = mydata;
   96     fs = this->private;
   97 
   98     glfs_volfile_fetch(fs);
   99 
  100     return 0;
  101 }
  102 
  103 int
  104 mgmt_cbk_event(struct rpc_clnt *rpc, void *mydata, void *data)
  105 {
  106     return 0;
  107 }
  108 
  109 static int
  110 mgmt_cbk_statedump(struct rpc_clnt *rpc, void *mydata, void *data)
  111 {
  112     struct glfs *fs = NULL;
  113     xlator_t *this = NULL;
  114     gf_statedump target_pid = {
  115         0,
  116     };
  117     struct iovec *iov = NULL;
  118     int ret = -1;
  119 
  120     this = mydata;
  121     if (!this) {
  122         gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_NULL, "mydata", NULL);
  123         errno = EINVAL;
  124         goto out;
  125     }
  126 
  127     fs = this->private;
  128     if (!fs) {
  129         gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_NULL, "glfs", NULL);
  130         errno = EINVAL;
  131         goto out;
  132     }
  133 
  134     iov = (struct iovec *)data;
  135     if (!iov) {
  136         gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_NULL, "iovec data", NULL);
  137         errno = EINVAL;
  138         goto out;
  139     }
  140 
  141     ret = xdr_to_generic(*iov, &target_pid, (xdrproc_t)xdr_gf_statedump);
  142     if (ret < 0) {
  143         gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_DECODE_XDR_FAILED, NULL);
  144         goto out;
  145     }
  146 
  147     gf_msg_trace("glfs", 0, "statedump requested for pid: %d", target_pid.pid);
  148 
  149     if ((uint64_t)getpid() == target_pid.pid) {
  150         gf_msg_debug("glfs", 0, "Taking statedump for pid: %d", target_pid.pid);
  151 
  152         ret = glfs_sysrq(fs, GLFS_SYSRQ_STATEDUMP);
  153         if (ret < 0) {
  154             gf_smsg("glfs", GF_LOG_INFO, 0, API_MSG_STATEDUMP_FAILED, NULL);
  155         }
  156     }
  157 out:
  158     return ret;
  159 }
  160 
  161 static rpcclnt_cb_actor_t mgmt_cbk_actors[GF_CBK_MAXVALUE] = {
  162     [GF_CBK_FETCHSPEC] = {"FETCHSPEC", mgmt_cbk_spec, GF_CBK_FETCHSPEC},
  163     [GF_CBK_EVENT_NOTIFY] = {"EVENTNOTIFY", mgmt_cbk_event,
  164                              GF_CBK_EVENT_NOTIFY},
  165     [GF_CBK_STATEDUMP] = {"STATEDUMP", mgmt_cbk_statedump, GF_CBK_STATEDUMP},
  166 };
  167 
  168 static struct rpcclnt_cb_program mgmt_cbk_prog = {
  169     .progname = "GlusterFS Callback",
  170     .prognum = GLUSTER_CBK_PROGRAM,
  171     .progver = GLUSTER_CBK_VERSION,
  172     .actors = mgmt_cbk_actors,
  173     .numactors = GF_CBK_MAXVALUE,
  174 };
  175 
  176 static char *clnt_handshake_procs[GF_HNDSK_MAXVALUE] = {
  177     [GF_HNDSK_NULL] = "NULL",
  178     [GF_HNDSK_SETVOLUME] = "SETVOLUME",
  179     [GF_HNDSK_GETSPEC] = "GETSPEC",
  180     [GF_HNDSK_PING] = "PING",
  181     [GF_HNDSK_EVENT_NOTIFY] = "EVENTNOTIFY",
  182     [GF_HNDSK_GET_VOLUME_INFO] = "GETVOLUMEINFO",
  183 };
  184 
  185 static rpc_clnt_prog_t clnt_handshake_prog = {
  186     .progname = "GlusterFS Handshake",
  187     .prognum = GLUSTER_HNDSK_PROGRAM,
  188     .progver = GLUSTER_HNDSK_VERSION,
  189     .procnames = clnt_handshake_procs,
  190 };
  191 
  192 int
  193 mgmt_submit_request(void *req, call_frame_t *frame, glusterfs_ctx_t *ctx,
  194                     rpc_clnt_prog_t *prog, int procnum, fop_cbk_fn_t cbkfn,
  195                     xdrproc_t xdrproc)
  196 {
  197     int ret = -1;
  198     int count = 0;
  199     struct iovec iov = {
  200         0,
  201     };
  202     struct iobuf *iobuf = NULL;
  203     struct iobref *iobref = NULL;
  204     ssize_t xdr_size = 0;
  205 
  206     iobref = iobref_new();
  207     if (!iobref) {
  208         goto out;
  209     }
  210 
  211     if (req) {
  212         xdr_size = xdr_sizeof(xdrproc, req);
  213 
  214         iobuf = iobuf_get2(ctx->iobuf_pool, xdr_size);
  215         if (!iobuf) {
  216             goto out;
  217         };
  218 
  219         iobref_add(iobref, iobuf);
  220 
  221         iov.iov_base = iobuf->ptr;
  222         iov.iov_len = iobuf_pagesize(iobuf);
  223 
  224         /* Create the xdr payload */
  225         ret = xdr_serialize_generic(iov, req, xdrproc);
  226         if (ret == -1) {
  227             gf_smsg(THIS->name, GF_LOG_WARNING, 0, API_MSG_XDR_PAYLOAD_FAILED,
  228                     NULL);
  229             goto out;
  230         }
  231         iov.iov_len = ret;
  232         count = 1;
  233     }
  234 
  235     /* Send the msg */
  236     ret = rpc_clnt_submit(ctx->mgmt, prog, procnum, cbkfn, &iov, count, NULL, 0,
  237                           iobref, frame, NULL, 0, NULL, 0, NULL);
  238 
  239 out:
  240     if (iobref)
  241         iobref_unref(iobref);
  242 
  243     if (iobuf)
  244         iobuf_unref(iobuf);
  245     return ret;
  246 }
  247 
  248 /*
  249  * Callback routine for 'GF_HNDSK_GET_VOLUME_INFO' rpc request
  250  */
  251 int
  252 mgmt_get_volinfo_cbk(struct rpc_req *req, struct iovec *iov, int count,
  253                      void *myframe)
  254 {
  255     int ret = 0;
  256     char *volume_id_str = NULL;
  257     dict_t *dict = NULL;
  258     gf_get_volume_info_rsp rsp = {
  259         0,
  260     };
  261     call_frame_t *frame = NULL;
  262     glusterfs_ctx_t *ctx = NULL;
  263     struct glfs *fs = NULL;
  264     struct syncargs *args;
  265 
  266     frame = myframe;
  267     ctx = frame->this->ctx;
  268     args = frame->local;
  269 
  270     if (!ctx) {
  271         gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL, API_MSG_NULL,
  272                 "context", NULL);
  273         errno = EINVAL;
  274         ret = -1;
  275         goto out;
  276     }
  277 
  278     fs = ((xlator_t *)ctx->master)->private;
  279 
  280     if (-1 == req->rpc_status) {
  281         gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL,
  282                 API_MSG_CALL_NOT_SUCCESSFUL, NULL);
  283         errno = EINVAL;
  284         ret = -1;
  285         goto out;
  286     }
  287 
  288     ret = xdr_to_generic(*iov, &rsp, (xdrproc_t)xdr_gf_get_volume_info_rsp);
  289 
  290     if (ret < 0) {
  291         gf_smsg(frame->this->name, GF_LOG_ERROR, 0,
  292                 API_MSG_XDR_RESPONSE_DECODE_FAILED, NULL);
  293         goto out;
  294     }
  295 
  296     gf_msg_debug(frame->this->name, 0,
  297                  "Received resp to GET_VOLUME_INFO "
  298                  "RPC: %d",
  299                  rsp.op_ret);
  300 
  301     if (rsp.op_ret == -1) {
  302         errno = rsp.op_errno;
  303         ret = -1;
  304         goto out;
  305     }
  306 
  307     if (!rsp.dict.dict_len) {
  308         gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL, API_MSG_CALL_NOT_VALID,
  309                 NULL);
  310         ret = -1;
  311         errno = EINVAL;
  312         goto out;
  313     }
  314 
  315     dict = dict_new();
  316 
  317     if (!dict) {
  318         ret = -1;
  319         errno = ENOMEM;
  320         goto out;
  321     }
  322 
  323     ret = dict_unserialize(rsp.dict.dict_val, rsp.dict.dict_len, &dict);
  324 
  325     if (ret) {
  326         errno = ENOMEM;
  327         goto out;
  328     }
  329 
  330     ret = dict_get_str_sizen(dict, "volume_id", &volume_id_str);
  331     if (ret) {
  332         errno = EINVAL;
  333         goto out;
  334     }
  335 
  336     ret = 0;
  337 out:
  338     if (volume_id_str) {
  339         gf_msg_debug(frame->this->name, 0, "Volume Id: %s", volume_id_str);
  340         pthread_mutex_lock(&fs->mutex);
  341         gf_uuid_parse(volume_id_str, fs->vol_uuid);
  342         pthread_mutex_unlock(&fs->mutex);
  343     }
  344 
  345     if (ret) {
  346         gf_smsg(frame->this->name, GF_LOG_ERROR, errno,
  347                 API_MSG_GET_VOLINFO_CBK_FAILED, "error=%s", strerror(errno),
  348                 NULL);
  349     }
  350 
  351     if (dict)
  352         dict_unref(dict);
  353 
  354     if (rsp.dict.dict_val)
  355         free(rsp.dict.dict_val);
  356 
  357     if (rsp.op_errstr)
  358         free(rsp.op_errstr);
  359 
  360     gf_msg_debug(frame->this->name, 0, "Returning: %d", ret);
  361 
  362     __wake(args);
  363 
  364     return ret;
  365 }
  366 
  367 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_get_volumeid, 3.5.0)
  368 int
  369 pub_glfs_get_volumeid(struct glfs *fs, char *volid, size_t size)
  370 {
  371     /* TODO: Define a global macro to store UUID size */
  372     size_t uuid_size = 16;
  373 
  374     DECLARE_OLD_THIS;
  375     __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
  376 
  377     pthread_mutex_lock(&fs->mutex);
  378     {
  379         /* check if the volume uuid is initialized */
  380         if (!gf_uuid_is_null(fs->vol_uuid)) {
  381             pthread_mutex_unlock(&fs->mutex);
  382             goto done;
  383         }
  384     }
  385     pthread_mutex_unlock(&fs->mutex);
  386 
  387     /* Need to fetch volume_uuid */
  388     glfs_get_volume_info(fs);
  389 
  390     if (gf_uuid_is_null(fs->vol_uuid)) {
  391         gf_smsg(THIS->name, GF_LOG_ERROR, EINVAL, API_MSG_FETCH_VOLUUID_FAILED,
  392                 NULL);
  393         goto out;
  394     }
  395 
  396 done:
  397     if (!volid || !size) {
  398         gf_msg_debug(THIS->name, 0, "volumeid/size is null");
  399         __GLFS_EXIT_FS;
  400         return uuid_size;
  401     }
  402 
  403     if (size < uuid_size) {
  404         gf_smsg(THIS->name, GF_LOG_ERROR, ERANGE, API_MSG_INSUFF_SIZE, NULL);
  405         errno = ERANGE;
  406         goto out;
  407     }
  408 
  409     memcpy(volid, fs->vol_uuid, uuid_size);
  410 
  411     __GLFS_EXIT_FS;
  412 
  413     return uuid_size;
  414 
  415 out:
  416     __GLFS_EXIT_FS;
  417 
  418 invalid_fs:
  419     return -1;
  420 }
  421 
  422 int
  423 glfs_get_volume_info(struct glfs *fs)
  424 {
  425     call_frame_t *frame = NULL;
  426     glusterfs_ctx_t *ctx = NULL;
  427     struct syncargs args = {
  428         0,
  429     };
  430     int ret = 0;
  431 
  432     ctx = fs->ctx;
  433     frame = create_frame(THIS, ctx->pool);
  434     if (!frame) {
  435         gf_smsg("glfs", GF_LOG_ERROR, ENOMEM, API_MSG_FRAME_CREAT_FAILED, NULL);
  436         ret = -1;
  437         goto out;
  438     }
  439 
  440     frame->local = &args;
  441 
  442     __yawn((&args));
  443 
  444     ret = glfs_get_volume_info_rpc(frame, THIS, fs);
  445     if (ret)
  446         goto out;
  447 
  448     __yield((&args));
  449 
  450     frame->local = NULL;
  451     STACK_DESTROY(frame->root);
  452 
  453 out:
  454     return ret;
  455 }
  456 
  457 int32_t
  458 glfs_get_volume_info_rpc(call_frame_t *frame, xlator_t *this, struct glfs *fs)
  459 {
  460     gf_get_volume_info_req req = {{
  461         0,
  462     }};
  463     int ret = 0;
  464     glusterfs_ctx_t *ctx = NULL;
  465     dict_t *dict = NULL;
  466     int32_t flags = 0;
  467 
  468     if (!frame || !this || !fs) {
  469         ret = -1;
  470         goto out;
  471     }
  472 
  473     ctx = fs->ctx;
  474 
  475     dict = dict_new();
  476     if (!dict) {
  477         ret = -1;
  478         goto out;
  479     }
  480 
  481     if (fs->volname) {
  482         ret = dict_set_str(dict, "volname", fs->volname);
  483         if (ret)
  484             goto out;
  485     }
  486 
  487     // Set the flags for the fields which we are interested in
  488     flags = (int32_t)GF_GET_VOLUME_UUID;  // ctx->flags;
  489     ret = dict_set_int32(dict, "flags", flags);
  490     if (ret) {
  491         gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL,
  492                 API_MSG_DICT_SET_FAILED, "flags", NULL);
  493         goto out;
  494     }
  495 
  496     ret = dict_allocate_and_serialize(dict, &req.dict.dict_val,
  497                                       &req.dict.dict_len);
  498 
  499     ret = mgmt_submit_request(&req, frame, ctx, &clnt_handshake_prog,
  500                               GF_HNDSK_GET_VOLUME_INFO, mgmt_get_volinfo_cbk,
  501                               (xdrproc_t)xdr_gf_get_volume_info_req);
  502 out:
  503     if (dict) {
  504         dict_unref(dict);
  505     }
  506 
  507     GF_FREE(req.dict.dict_val);
  508 
  509     return ret;
  510 }
  511 
  512 static int
  513 glusterfs_oldvolfile_update(struct glfs *fs, char *volfile, ssize_t size)
  514 {
  515     int ret = -1;
  516 
  517     pthread_mutex_lock(&fs->mutex);
  518 
  519     fs->oldvollen = size;
  520     if (!fs->oldvolfile) {
  521         fs->oldvolfile = CALLOC(1, size + 1);
  522     } else {
  523         fs->oldvolfile = REALLOC(fs->oldvolfile, size + 1);
  524     }
  525 
  526     if (!fs->oldvolfile) {
  527         fs->oldvollen = 0;
  528     } else {
  529         memcpy(fs->oldvolfile, volfile, size);
  530         fs->oldvollen = size;
  531         ret = 0;
  532     }
  533 
  534     pthread_mutex_unlock(&fs->mutex);
  535 
  536     return ret;
  537 }
  538 
  539 int
  540 glfs_mgmt_getspec_cbk(struct rpc_req *req, struct iovec *iov, int count,
  541                       void *myframe)
  542 {
  543     gf_getspec_rsp rsp = {
  544         0,
  545     };
  546     call_frame_t *frame = NULL;
  547     glusterfs_ctx_t *ctx = NULL;
  548     int ret = 0;
  549     ssize_t size = 0;
  550     FILE *tmpfp = NULL;
  551     int need_retry = 0;
  552     struct glfs *fs = NULL;
  553     dict_t *dict = NULL;
  554     char *servers_list = NULL;
  555     int tmp_fd = -1;
  556     char template[] = "/tmp/gfapi.volfile.XXXXXX";
  557 
  558     frame = myframe;
  559     ctx = frame->this->ctx;
  560 
  561     if (!ctx) {
  562         gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL, API_MSG_NULL,
  563                 "context", NULL);
  564         errno = EINVAL;
  565         ret = -1;
  566         goto out;
  567     }
  568 
  569     fs = ((xlator_t *)ctx->master)->private;
  570 
  571     if (-1 == req->rpc_status) {
  572         ret = -1;
  573         need_retry = 1;
  574         goto out;
  575     }
  576 
  577     ret = xdr_to_generic(*iov, &rsp, (xdrproc_t)xdr_gf_getspec_rsp);
  578     if (ret < 0) {
  579         gf_smsg(frame->this->name, GF_LOG_ERROR, 0, API_MSG_XDR_DECODE_FAILED,
  580                 NULL);
  581         ret = -1;
  582         goto out;
  583     }
  584 
  585     if (-1 == rsp.op_ret) {
  586         gf_smsg(frame->this->name, GF_LOG_ERROR, rsp.op_errno,
  587                 API_MSG_GET_VOLFILE_FAILED, "from server", NULL);
  588         ret = -1;
  589         errno = rsp.op_errno;
  590         goto out;
  591     }
  592 
  593     if (!rsp.xdata.xdata_len) {
  594         goto volfile;
  595     }
  596 
  597     dict = dict_new();
  598     if (!dict) {
  599         ret = -1;
  600         errno = ENOMEM;
  601         goto out;
  602     }
  603 
  604     ret = dict_unserialize(rsp.xdata.xdata_val, rsp.xdata.xdata_len, &dict);
  605     if (ret) {
  606         gf_log(frame->this->name, GF_LOG_ERROR,
  607                "failed to unserialize xdata to dictionary");
  608         goto out;
  609     }
  610     dict->extra_stdfree = rsp.xdata.xdata_val;
  611 
  612     /* glusterd2 only */
  613     ret = dict_get_str(dict, "servers-list", &servers_list);
  614     if (ret) {
  615         goto volfile;
  616     }
  617 
  618     gf_log(frame->this->name, GF_LOG_INFO,
  619            "Received list of available volfile servers: %s", servers_list);
  620 
  621     ret = gf_process_getspec_servers_list(&ctx->cmd_args, servers_list);
  622     if (ret) {
  623         gf_log(frame->this->name, GF_LOG_ERROR,
  624                "Failed (%s) to process servers list: %s", strerror(errno),
  625                servers_list);
  626     }
  627 
  628 volfile:
  629     ret = 0;
  630     size = rsp.op_ret;
  631 
  632     pthread_mutex_lock(&fs->mutex);
  633     if ((size == fs->oldvollen) &&
  634         (memcmp(fs->oldvolfile, rsp.spec, size) == 0)) {
  635         pthread_mutex_unlock(&fs->mutex);
  636         gf_smsg(frame->this->name, GF_LOG_INFO, 0, API_MSG_VOLFILE_INFO, NULL);
  637         goto out;
  638     }
  639     pthread_mutex_unlock(&fs->mutex);
  640 
  641     /* coverity[secure_temp] mkstemp uses 0600 as the mode and is safe */
  642     tmp_fd = mkstemp(template);
  643     if (-1 == tmp_fd) {
  644         ret = -1;
  645         goto out;
  646     }
  647 
  648     /* Calling unlink so that when the file is closed or program
  649      * terminates the temporary file is deleted.
  650      */
  651     ret = sys_unlink(template);
  652     if (ret < 0) {
  653         gf_smsg(frame->this->name, GF_LOG_INFO, 0, API_MSG_UNABLE_TO_DEL,
  654                 "template=%s", template, NULL);
  655         ret = 0;
  656     }
  657 
  658     tmpfp = fdopen(tmp_fd, "w+b");
  659     if (!tmpfp) {
  660         ret = -1;
  661         goto out;
  662     }
  663 
  664     fwrite(rsp.spec, size, 1, tmpfp);
  665     fflush(tmpfp);
  666     if (ferror(tmpfp)) {
  667         ret = -1;
  668         goto out;
  669     }
  670 
  671     /*  Check if only options have changed. No need to reload the
  672      *  volfile if topology hasn't changed.
  673      *  glusterfs_volfile_reconfigure returns 3 possible return states
  674      *  return 0         =======> reconfiguration of options has succeeded
  675      *  return 1         =======> the graph has to be reconstructed and all
  676      * the xlators should be inited return -1(or -ve) =======> Some Internal
  677      * Error occurred during the operation
  678      */
  679 
  680     pthread_mutex_lock(&fs->mutex);
  681     ret = gf_volfile_reconfigure(fs->oldvollen, tmpfp, fs->ctx, fs->oldvolfile);
  682     pthread_mutex_unlock(&fs->mutex);
  683 
  684     if (ret == 0) {
  685         gf_msg_debug("glusterfsd-mgmt", 0,
  686                      "No need to re-load "
  687                      "volfile, reconfigure done");
  688         ret = glusterfs_oldvolfile_update(fs, rsp.spec, size);
  689         goto out;
  690     }
  691 
  692     if (ret < 0) {
  693         gf_msg_debug("glusterfsd-mgmt", 0, "Reconfigure failed !!");
  694         goto out;
  695     }
  696 
  697     ret = glfs_process_volfp(fs, tmpfp);
  698     /* tmpfp closed */
  699     tmpfp = NULL;
  700     tmp_fd = -1;
  701     if (ret)
  702         goto out;
  703 
  704     ret = glusterfs_oldvolfile_update(fs, rsp.spec, size);
  705 out:
  706     STACK_DESTROY(frame->root);
  707 
  708     if (rsp.spec)
  709         free(rsp.spec);
  710 
  711     if (dict)
  712         dict_unref(dict);
  713 
  714     // Stop if server is running at an unsupported op-version
  715     if (ENOTSUP == ret) {
  716         gf_smsg("mgmt", GF_LOG_ERROR, ENOTSUP, API_MSG_WRONG_OPVERSION, NULL);
  717         errno = ENOTSUP;
  718         glfs_init_done(fs, -1);
  719     }
  720 
  721     if (ret && ctx && !ctx->active) {
  722         /* Do it only for the first time */
  723         /* Failed to get the volume file, something wrong,
  724            restart the process */
  725         gf_smsg("glfs-mgmt", GF_LOG_ERROR, EINVAL, API_MSG_GET_VOLFILE_FAILED,
  726                 "key=%s", ctx->cmd_args.volfile_id, NULL);
  727         if (!need_retry) {
  728             if (!errno)
  729                 errno = EINVAL;
  730             glfs_init_done(fs, -1);
  731         }
  732     }
  733 
  734     if (tmpfp)
  735         fclose(tmpfp);
  736     else if (tmp_fd != -1)
  737         sys_close(tmp_fd);
  738 
  739     return 0;
  740 }
  741 
  742 int
  743 glfs_volfile_fetch(struct glfs *fs)
  744 {
  745     cmd_args_t *cmd_args = NULL;
  746     gf_getspec_req req = {
  747         0,
  748     };
  749     int ret = -1;
  750     call_frame_t *frame = NULL;
  751     glusterfs_ctx_t *ctx = NULL;
  752     dict_t *dict = NULL;
  753 
  754     ctx = fs->ctx;
  755     cmd_args = &ctx->cmd_args;
  756 
  757     req.key = cmd_args->volfile_id;
  758     req.flags = 0;
  759 
  760     dict = dict_new();
  761     if (!dict) {
  762         goto out;
  763     }
  764 
  765     // Set the supported min and max op-versions, so glusterd can make a
  766     // decision
  767     ret = dict_set_int32(dict, "min-op-version", GD_OP_VERSION_MIN);
  768     if (ret) {
  769         gf_smsg(THIS->name, GF_LOG_ERROR, EINVAL, API_MSG_DICT_SET_FAILED,
  770                 "min-op-version", NULL);
  771         goto out;
  772     }
  773 
  774     ret = dict_set_int32(dict, "max-op-version", GD_OP_VERSION_MAX);
  775     if (ret) {
  776         gf_smsg(THIS->name, GF_LOG_ERROR, EINVAL, API_MSG_DICT_SET_FAILED,
  777                 "max-op-version", NULL);
  778         goto out;
  779     }
  780 
  781     /* Ask for a list of volfile (glusterd2 only) servers */
  782     if (GF_CLIENT_PROCESS == ctx->process_mode) {
  783         req.flags = req.flags | GF_GETSPEC_FLAG_SERVERS_LIST;
  784     }
  785 
  786     ret = dict_allocate_and_serialize(dict, &req.xdata.xdata_val,
  787                                       &req.xdata.xdata_len);
  788     if (ret < 0) {
  789         gf_smsg(THIS->name, GF_LOG_ERROR, 0, API_MSG_DICT_SERIALIZE_FAILED,
  790                 NULL);
  791         goto out;
  792     }
  793 
  794     frame = create_frame(THIS, ctx->pool);
  795     if (!frame) {
  796         ret = -1;
  797         goto out;
  798     }
  799 
  800     ret = mgmt_submit_request(&req, frame, ctx, &clnt_handshake_prog,
  801                               GF_HNDSK_GETSPEC, glfs_mgmt_getspec_cbk,
  802                               (xdrproc_t)xdr_gf_getspec_req);
  803 out:
  804     if (req.xdata.xdata_val)
  805         GF_FREE(req.xdata.xdata_val);
  806     if (dict)
  807         dict_unref(dict);
  808 
  809     return ret;
  810 }
  811 
  812 static int
  813 mgmt_rpc_notify(struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event,
  814                 void *data)
  815 {
  816     xlator_t *this = NULL;
  817     glusterfs_ctx_t *ctx = NULL;
  818     server_cmdline_t *server = NULL;
  819     rpc_transport_t *rpc_trans = NULL;
  820     struct glfs *fs = NULL;
  821     int ret = 0;
  822     struct dnscache6 *dnscache = NULL;
  823 
  824     this = mydata;
  825     rpc_trans = rpc->conn.trans;
  826 
  827     ctx = this->ctx;
  828     if (!ctx)
  829         goto out;
  830 
  831     fs = ((xlator_t *)ctx->master)->private;
  832 
  833     switch (event) {
  834         case RPC_CLNT_DISCONNECT:
  835             if (!ctx->active) {
  836                 if (rpc_trans->connect_failed)
  837                     gf_smsg("glfs-mgmt", GF_LOG_ERROR, 0,
  838                             API_MSG_REMOTE_HOST_CONN_FAILED, "server=%s",
  839                             ctx->cmd_args.volfile_server, NULL);
  840                 else
  841                     gf_smsg("glfs-mgmt", GF_LOG_INFO, 0,
  842                             API_MSG_REMOTE_HOST_CONN_FAILED, "server=%s",
  843                             ctx->cmd_args.volfile_server, NULL);
  844 
  845                 if (!rpc->disabled) {
  846                     /*
  847                      * Check if dnscache is exhausted for current server
  848                      * and continue until cache is exhausted
  849                      */
  850                     dnscache = rpc_trans->dnscache;
  851                     if (dnscache && dnscache->next) {
  852                         break;
  853                     }
  854                 }
  855                 server = ctx->cmd_args.curr_server;
  856                 if (server->list.next == &ctx->cmd_args.volfile_servers) {
  857                     errno = ENOTCONN;
  858                     gf_smsg("glfs-mgmt", GF_LOG_INFO, ENOTCONN,
  859                             API_MSG_VOLFILE_SERVER_EXHAUST, NULL);
  860                     glfs_init_done(fs, -1);
  861                     break;
  862                 }
  863                 server = list_entry(server->list.next, typeof(*server), list);
  864                 ctx->cmd_args.curr_server = server;
  865                 ctx->cmd_args.volfile_server_port = server->port;
  866                 ctx->cmd_args.volfile_server = server->volfile_server;
  867                 ctx->cmd_args.volfile_server_transport = server->transport;
  868 
  869                 ret = dict_set_str(rpc_trans->options, "transport-type",
  870                                    server->transport);
  871                 if (ret != 0) {
  872                     gf_smsg("glfs-mgmt", GF_LOG_ERROR, ENOTCONN,
  873                             API_MSG_DICT_SET_FAILED, "transport-type=%s",
  874                             server->transport, NULL);
  875                     errno = ENOTCONN;
  876                     glfs_init_done(fs, -1);
  877                     break;
  878                 }
  879 
  880                 if (strcmp(server->transport, "unix") == 0) {
  881                     ret = dict_set_str(rpc_trans->options,
  882                                        "transport.socket.connect-path",
  883                                        server->volfile_server);
  884                     if (ret != 0) {
  885                         gf_smsg("glfs-mgmt", GF_LOG_ERROR, ENOTCONN,
  886                                 API_MSG_DICT_SET_FAILED,
  887                                 "socket.connect-path=%s",
  888                                 server->volfile_server, NULL);
  889                         errno = ENOTCONN;
  890                         glfs_init_done(fs, -1);
  891                         break;
  892                     }
  893                     /* delete the remote-host and remote-port keys
  894                      * in case they were set while looping through
  895                      * list of volfile servers previously
  896                      */
  897                     dict_del(rpc_trans->options, "remote-host");
  898                     dict_del(rpc_trans->options, "remote-port");
  899                 } else {
  900                     ret = dict_set_int32(rpc_trans->options, "remote-port",
  901                                          server->port);
  902                     if (ret != 0) {
  903                         gf_smsg("glfs-mgmt", GF_LOG_ERROR, ENOTCONN,
  904                                 API_MSG_DICT_SET_FAILED, "remote-port=%d",
  905                                 server->port, NULL);
  906                         errno = ENOTCONN;
  907                         glfs_init_done(fs, -1);
  908                         break;
  909                     }
  910 
  911                     ret = dict_set_str(rpc_trans->options, "remote-host",
  912                                        server->volfile_server);
  913                     if (ret != 0) {
  914                         gf_smsg("glfs-mgmt", GF_LOG_ERROR, ENOTCONN,
  915                                 API_MSG_DICT_SET_FAILED, "remote-host=%s",
  916                                 server->volfile_server, NULL);
  917                         errno = ENOTCONN;
  918                         glfs_init_done(fs, -1);
  919                         break;
  920                     }
  921                     /* delete the "transport.socket.connect-path"
  922                      * key in case if it was set while looping
  923                      * through list of volfile servers previously
  924                      */
  925                     dict_del(rpc_trans->options,
  926                              "transport.socket.connect-path");
  927                 }
  928 
  929                 gf_smsg("glfs-mgmt", GF_LOG_INFO, 0, API_MSG_VOLFILE_CONNECTING,
  930                         "server=%s", server->volfile_server, "port=%d",
  931                         server->port, "transport=%s", server->transport, NULL);
  932             }
  933             break;
  934         case RPC_CLNT_CONNECT:
  935             ret = glfs_volfile_fetch(fs);
  936             if (ret && (ctx->active == NULL)) {
  937                 /* Do it only for the first time */
  938                 /* Exit the process.. there are some wrong options */
  939                 gf_smsg("glfs-mgmt", GF_LOG_ERROR, EINVAL,
  940                         API_MSG_GET_VOLFILE_FAILED, "key=%s",
  941                         ctx->cmd_args.volfile_id, NULL);
  942                 errno = EINVAL;
  943                 glfs_init_done(fs, -1);
  944             }
  945 
  946             break;
  947         default:
  948             break;
  949     }
  950 out:
  951     return 0;
  952 }
  953 
  954 int
  955 glusterfs_mgmt_notify(int32_t op, void *data, ...)
  956 {
  957     int ret = 0;
  958 
  959     switch (op) {
  960         case GF_EN_DEFRAG_STATUS:
  961             break;
  962 
  963         default:
  964             break;
  965     }
  966 
  967     return ret;
  968 }
  969 
  970 int
  971 glfs_mgmt_init(struct glfs *fs)
  972 {
  973     cmd_args_t *cmd_args = NULL;
  974     struct rpc_clnt *rpc = NULL;
  975     dict_t *options = NULL;
  976     int ret = -1;
  977     int port = GF_DEFAULT_BASE_PORT;
  978     char *host = NULL;
  979     glusterfs_ctx_t *ctx = NULL;
  980 
  981     ctx = fs->ctx;
  982     cmd_args = &ctx->cmd_args;
  983 
  984     if (ctx->mgmt)
  985         return 0;
  986 
  987     options = dict_new();
  988     if (!options)
  989         goto out;
  990 
  991     if (cmd_args->volfile_server_port)
  992         port = cmd_args->volfile_server_port;
  993 
  994     if (cmd_args->volfile_server) {
  995         host = cmd_args->volfile_server;
  996     } else if (cmd_args->volfile_server_transport &&
  997                !strcmp(cmd_args->volfile_server_transport, "unix")) {
  998         host = DEFAULT_GLUSTERD_SOCKFILE;
  999     } else {
 1000         host = "localhost";
 1001     }
 1002 
 1003     if (cmd_args->volfile_server_transport &&
 1004         !strcmp(cmd_args->volfile_server_transport, "unix")) {
 1005         ret = rpc_transport_unix_options_build(options, host, 0);
 1006     } else {
 1007         xlator_cmdline_option_t *opt = find_xlator_option_in_cmd_args_t(
 1008             "address-family", cmd_args);
 1009         ret = rpc_transport_inet_options_build(options, host, port,
 1010                                                (opt ? opt->value : NULL));
 1011     }
 1012 
 1013     if (ret)
 1014         goto out;
 1015 
 1016     if (sys_access(SECURE_ACCESS_FILE, F_OK) == 0) {
 1017         ctx->secure_mgmt = 1;
 1018         ctx->ssl_cert_depth = glusterfs_read_secure_access_file();
 1019     }
 1020 
 1021     rpc = rpc_clnt_new(options, THIS, THIS->name, 8);
 1022     if (!rpc) {
 1023         ret = -1;
 1024         gf_smsg(THIS->name, GF_LOG_WARNING, 0, API_MSG_CREATE_RPC_CLIENT_FAILED,
 1025                 NULL);
 1026         goto out;
 1027     }
 1028 
 1029     ret = rpc_clnt_register_notify(rpc, mgmt_rpc_notify, THIS);
 1030     if (ret) {
 1031         gf_smsg(THIS->name, GF_LOG_WARNING, 0, API_MSG_REG_NOTIFY_FUNC_FAILED,
 1032                 NULL);
 1033         goto out;
 1034     }
 1035 
 1036     ret = rpcclnt_cbk_program_register(rpc, &mgmt_cbk_prog, THIS);
 1037     if (ret) {
 1038         gf_smsg(THIS->name, GF_LOG_WARNING, 0, API_MSG_REG_CBK_FUNC_FAILED,
 1039                 NULL);
 1040         goto out;
 1041     }
 1042 
 1043     ctx->notify = glusterfs_mgmt_notify;
 1044 
 1045     /* This value should be set before doing the 'rpc_clnt_start()' as
 1046        the notify function uses this variable */
 1047     ctx->mgmt = rpc;
 1048 
 1049     ret = rpc_clnt_start(rpc);
 1050 out:
 1051     if (options)
 1052         dict_unref(options);
 1053     return ret;
 1054 }