"Fossies" - the Fresh Open Source Software Archive

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

    1 /*
    2    Copyright (c) 2014 Red Hat, Inc. <http://www.redhat.com>
    3    This file is part of GlusterFS.
    4 
    5    This file is licensed to you under your choice of the GNU Lesser
    6    General Public License, version 3 or any later version (LGPLv3 or
    7    later), or the GNU General Public License, version 2 (GPLv2), in all
    8    cases as published by the Free Software Foundation.
    9 */
   10 #include "snapview-server.h"
   11 #include "snapview-server-mem-types.h"
   12 #include <pthread.h>
   13 
   14 int
   15 mgmt_cbk_snap(struct rpc_clnt *rpc, void *mydata, void *data)
   16 {
   17     xlator_t *this = NULL;
   18 
   19     this = mydata;
   20     GF_ASSERT(this);
   21 
   22     gf_msg("mgmt", GF_LOG_INFO, 0, SVS_MSG_SNAPSHOT_LIST_CHANGED,
   23            "list of snapshots changed");
   24 
   25     svs_get_snapshot_list(this);
   26     return 0;
   27 }
   28 
   29 static rpcclnt_cb_actor_t svs_cbk_actors[GF_CBK_MAXVALUE] = {
   30     [GF_CBK_GET_SNAPS] = {"GETSNAPS", mgmt_cbk_snap, GF_CBK_GET_SNAPS},
   31 };
   32 
   33 static struct rpcclnt_cb_program svs_cbk_prog = {
   34     .progname = "GlusterFS Callback",
   35     .prognum = GLUSTER_CBK_PROGRAM,
   36     .progver = GLUSTER_CBK_VERSION,
   37     .actors = svs_cbk_actors,
   38     .numactors = GF_CBK_MAXVALUE,
   39 };
   40 
   41 static char *clnt_handshake_procs[GF_HNDSK_MAXVALUE] = {
   42     [GF_HNDSK_NULL] = "NULL",
   43     [GF_HNDSK_EVENT_NOTIFY] = "EVENTNOTIFY",
   44 };
   45 
   46 static rpc_clnt_prog_t svs_clnt_handshake_prog = {
   47     .progname = "GlusterFS Handshake",
   48     .prognum = GLUSTER_HNDSK_PROGRAM,
   49     .progver = GLUSTER_HNDSK_VERSION,
   50     .procnames = clnt_handshake_procs,
   51 };
   52 
   53 static int
   54 svs_rpc_notify(struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event,
   55                void *data)
   56 {
   57     xlator_t *this = NULL;
   58     int ret = 0;
   59 
   60     this = mydata;
   61 
   62     switch (event) {
   63         case RPC_CLNT_CONNECT:
   64             ret = svs_get_snapshot_list(this);
   65             if (ret) {
   66                 gf_msg(this->name, GF_LOG_ERROR, EINVAL,
   67                        SVS_MSG_GET_SNAPSHOT_LIST_FAILED,
   68                        "Error in refreshing the snaplist "
   69                        "infrastructure");
   70                 ret = -1;
   71             }
   72             break;
   73         default:
   74             break;
   75     }
   76     return ret;
   77 }
   78 
   79 int
   80 svs_mgmt_init(xlator_t *this)
   81 {
   82     int ret = -1;
   83     svs_private_t *priv = NULL;
   84     dict_t *options = NULL;
   85     int port = GF_DEFAULT_BASE_PORT;
   86     char *host = NULL;
   87     cmd_args_t *cmd_args = NULL;
   88     glusterfs_ctx_t *ctx = NULL;
   89     xlator_cmdline_option_t *opt = NULL;
   90 
   91     GF_VALIDATE_OR_GOTO("snapview-server", this, out);
   92     GF_VALIDATE_OR_GOTO(this->name, this->private, out);
   93     GF_VALIDATE_OR_GOTO(this->name, this->ctx, out);
   94 
   95     priv = this->private;
   96 
   97     ctx = this->ctx;
   98     cmd_args = &ctx->cmd_args;
   99 
  100     host = "localhost";
  101     if (cmd_args->volfile_server)
  102         host = cmd_args->volfile_server;
  103 
  104     options = dict_new();
  105     if (!options)
  106         goto out;
  107 
  108     opt = find_xlator_option_in_cmd_args_t("address-family", cmd_args);
  109     ret = rpc_transport_inet_options_build(options, host, port,
  110                                            (opt != NULL ? opt->value : NULL));
  111     if (ret) {
  112         gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_BUILD_TRNSPRT_OPT_FAILED,
  113                "failed to build the "
  114                "transport options");
  115         goto out;
  116     }
  117 
  118     priv->rpc = rpc_clnt_new(options, this, this->name, 8);
  119     if (!priv->rpc) {
  120         gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_RPC_INIT_FAILED,
  121                "failed to initialize RPC");
  122         goto out;
  123     }
  124 
  125     ret = rpc_clnt_register_notify(priv->rpc, svs_rpc_notify, this);
  126     if (ret) {
  127         gf_msg(this->name, GF_LOG_WARNING, 0, SVS_MSG_REG_NOTIFY_FAILED,
  128                "failed to register notify function");
  129         goto out;
  130     }
  131 
  132     ret = rpcclnt_cbk_program_register(priv->rpc, &svs_cbk_prog, this);
  133     if (ret) {
  134         gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_REG_CBK_PRGM_FAILED,
  135                "failed to register callback program");
  136         goto out;
  137     }
  138 
  139     ret = rpc_clnt_start(priv->rpc);
  140     if (ret) {
  141         gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_RPC_CLNT_START_FAILED,
  142                "failed to start the rpc "
  143                "client");
  144         goto out;
  145     }
  146 
  147     ret = 0;
  148 
  149     gf_msg_debug(this->name, 0, "svs mgmt init successful");
  150 
  151 out:
  152     if (options)
  153         dict_unref(options);
  154     if (ret)
  155         if (priv) {
  156             rpc_clnt_connection_cleanup(&priv->rpc->conn);
  157             rpc_clnt_unref(priv->rpc);
  158             priv->rpc = NULL;
  159         }
  160 
  161     return ret;
  162 }
  163 
  164 int
  165 svs_mgmt_submit_request(void *req, call_frame_t *frame, glusterfs_ctx_t *ctx,
  166                         rpc_clnt_prog_t *prog, int procnum, fop_cbk_fn_t cbkfn,
  167                         xdrproc_t xdrproc)
  168 {
  169     int ret = -1;
  170     int count = 0;
  171     struct iovec iov = {
  172         0,
  173     };
  174     struct iobuf *iobuf = NULL;
  175     struct iobref *iobref = NULL;
  176     ssize_t xdr_size = 0;
  177 
  178     GF_VALIDATE_OR_GOTO("snapview-server", frame, out);
  179     GF_VALIDATE_OR_GOTO("snapview-server", req, out);
  180     GF_VALIDATE_OR_GOTO("snapview-server", ctx, out);
  181     GF_VALIDATE_OR_GOTO("snapview-server", prog, out);
  182 
  183     GF_ASSERT(frame->this);
  184 
  185     iobref = iobref_new();
  186     if (!iobref) {
  187         gf_msg(frame->this->name, GF_LOG_WARNING, ENOMEM, SVS_MSG_NO_MEMORY,
  188                "failed to allocate "
  189                "new iobref");
  190         goto out;
  191     }
  192 
  193     if (req) {
  194         xdr_size = xdr_sizeof(xdrproc, req);
  195 
  196         iobuf = iobuf_get2(ctx->iobuf_pool, xdr_size);
  197         if (!iobuf) {
  198             goto out;
  199         }
  200 
  201         iobref_add(iobref, iobuf);
  202 
  203         iov.iov_base = iobuf->ptr;
  204         iov.iov_len = iobuf_pagesize(iobuf);
  205 
  206         /* Create the xdr payload */
  207         ret = xdr_serialize_generic(iov, req, xdrproc);
  208         if (ret == -1) {
  209             gf_msg(frame->this->name, GF_LOG_WARNING, 0,
  210                    SVS_MSG_XDR_PAYLOAD_FAILED, "Failed to create XDR payload");
  211             goto out;
  212         }
  213         iov.iov_len = ret;
  214         count = 1;
  215     }
  216 
  217     ret = rpc_clnt_submit(ctx->mgmt, prog, procnum, cbkfn, &iov, count, NULL, 0,
  218                           iobref, frame, NULL, 0, NULL, 0, NULL);
  219 
  220 out:
  221     if (iobref)
  222         iobref_unref(iobref);
  223 
  224     if (iobuf)
  225         iobuf_unref(iobuf);
  226     return ret;
  227 }
  228 
  229 int
  230 mgmt_get_snapinfo_cbk(struct rpc_req *req, struct iovec *iov, int count,
  231                       void *myframe)
  232 {
  233     gf_getsnap_name_uuid_rsp rsp = {
  234         0,
  235     };
  236     call_frame_t *frame = NULL;
  237     glusterfs_ctx_t *ctx = NULL;
  238     int ret = -1;
  239     dict_t *dict = NULL;
  240     char key[32] = {0};
  241     int len;
  242     int snapcount = 0;
  243     svs_private_t *priv = NULL;
  244     xlator_t *this = NULL;
  245     int i = 0;
  246     int j = 0;
  247     char *value = NULL;
  248     snap_dirent_t *dirents = NULL;
  249     snap_dirent_t *old_dirents = NULL;
  250     int oldcount = 0;
  251 
  252     GF_VALIDATE_OR_GOTO("snapview-server", req, error_out);
  253     GF_VALIDATE_OR_GOTO("snapview-server", myframe, error_out);
  254     GF_VALIDATE_OR_GOTO("snapview-server", iov, error_out);
  255 
  256     frame = myframe;
  257     this = frame->this;
  258     ctx = frame->this->ctx;
  259     priv = this->private;
  260 
  261     if (!ctx) {
  262         errno = EINVAL;
  263         gf_msg(frame->this->name, GF_LOG_ERROR, errno, SVS_MSG_NULL_CTX,
  264                "NULL context");
  265         goto out;
  266     }
  267 
  268     if (-1 == req->rpc_status) {
  269         errno = EINVAL;
  270         gf_msg(frame->this->name, GF_LOG_ERROR, errno, SVS_MSG_RPC_CALL_FAILED,
  271                "RPC call is not successful");
  272         goto out;
  273     }
  274 
  275     ret = xdr_to_generic(*iov, &rsp, (xdrproc_t)xdr_gf_getsnap_name_uuid_rsp);
  276     if (ret < 0) {
  277         gf_msg(frame->this->name, GF_LOG_ERROR, 0, SVS_MSG_XDR_DECODE_FAILED,
  278                "Failed to decode xdr response, rsp.op_ret = %d", rsp.op_ret);
  279         goto out;
  280     }
  281 
  282     if (rsp.op_ret == -1) {
  283         errno = rsp.op_errno;
  284         ret = -1;
  285         goto out;
  286     }
  287 
  288     if (!rsp.dict.dict_len) {
  289         ret = -1;
  290         errno = EINVAL;
  291         gf_msg(frame->this->name, GF_LOG_ERROR, errno, SVS_MSG_RSP_DICT_EMPTY,
  292                "Response dict is not populated");
  293         goto out;
  294     }
  295 
  296     dict = dict_new();
  297     if (!dict) {
  298         ret = -1;
  299         errno = ENOMEM;
  300         goto out;
  301     }
  302 
  303     ret = dict_unserialize(rsp.dict.dict_val, rsp.dict.dict_len, &dict);
  304     if (ret) {
  305         errno = EINVAL;
  306         gf_msg(frame->this->name, GF_LOG_ERROR, errno,
  307                LG_MSG_DICT_UNSERIAL_FAILED, "Failed to unserialize dictionary");
  308         goto out;
  309     }
  310 
  311     ret = dict_get_int32(dict, "snap-count", (int32_t *)&snapcount);
  312     if (ret) {
  313         errno = EINVAL;
  314         ret = -1;
  315         gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_DICT_GET_FAILED,
  316                "Error retrieving snapcount");
  317         goto out;
  318     }
  319 
  320     if (snapcount > 0) {
  321         /* first time we are fetching snap list */
  322         dirents = GF_CALLOC(snapcount, sizeof(snap_dirent_t),
  323                             gf_svs_mt_dirents_t);
  324         if (!dirents) {
  325             errno = ENOMEM;
  326             ret = -1;
  327             gf_msg(frame->this->name, GF_LOG_ERROR, errno, SVS_MSG_NO_MEMORY,
  328                    "Unable to allocate memory");
  329             goto out;
  330         }
  331     }
  332 
  333     for (i = 0; i < snapcount; i++) {
  334         len = snprintf(key, sizeof(key), "snap-volname.%d", i + 1);
  335         ret = dict_get_strn(dict, key, len, &value);
  336         if (ret) {
  337             errno = EINVAL;
  338             ret = -1;
  339             gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_DICT_GET_FAILED,
  340                    "Error retrieving snap volname %d", i + 1);
  341             goto out;
  342         }
  343 
  344         strncpy(dirents[i].snap_volname, value,
  345                 sizeof(dirents[i].snap_volname));
  346 
  347         len = snprintf(key, sizeof(key), "snap-id.%d", i + 1);
  348         ret = dict_get_strn(dict, key, len, &value);
  349         if (ret) {
  350             errno = EINVAL;
  351             ret = -1;
  352             gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_DICT_GET_FAILED,
  353                    "Error retrieving snap uuid %d", i + 1);
  354             goto out;
  355         }
  356         strncpy(dirents[i].uuid, value, sizeof(dirents[i].uuid));
  357 
  358         len = snprintf(key, sizeof(key), "snapname.%d", i + 1);
  359         ret = dict_get_strn(dict, key, len, &value);
  360         if (ret) {
  361             errno = EINVAL;
  362             ret = -1;
  363             gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_DICT_GET_FAILED,
  364                    "Error retrieving snap name %d", i + 1);
  365             goto out;
  366         }
  367         strncpy(dirents[i].name, value, sizeof(dirents[i].name));
  368     }
  369 
  370     /*
  371      * Got the new snap list populated in dirents
  372      * The new snap list is either a subset or a superset of
  373      * the existing snaplist old_dirents which has priv->num_snaps
  374      * number of entries.
  375      *
  376      * If subset, then clean up the fs for entries which are
  377      * no longer relevant.
  378      *
  379      * For other overlapping entries set the fs for new dirents
  380      * entries which have a fs assigned already in old_dirents
  381      *
  382      * We do this as we don't want to do new glfs_init()s repeatedly
  383      * as the dirents entries for snapshot volumes get repatedly
  384      * cleaned up and allocated. And if we don't then that will lead
  385      * to memleaks
  386      */
  387 
  388     LOCK(&priv->snaplist_lock);
  389     {
  390         oldcount = priv->num_snaps;
  391         old_dirents = priv->dirents;
  392         for (i = 0; i < priv->num_snaps; i++) {
  393             for (j = 0; j < snapcount; j++) {
  394                 if ((!strcmp(old_dirents[i].name, dirents[j].name)) &&
  395                     (!strcmp(old_dirents[i].uuid, dirents[j].uuid))) {
  396                     dirents[j].fs = old_dirents[i].fs;
  397                     old_dirents[i].fs = NULL;
  398                     break;
  399                 }
  400             }
  401         }
  402 
  403         priv->dirents = dirents;
  404         priv->num_snaps = snapcount;
  405     }
  406     UNLOCK(&priv->snaplist_lock);
  407 
  408     if (old_dirents) {
  409         for (i = 0; i < oldcount; i++) {
  410             if (old_dirents[i].fs)
  411                 gf_msg_debug(this->name, 0,
  412                              "calling glfs_fini on "
  413                              "name: %s, snap_volname: %s, uuid: %s",
  414                              old_dirents[i].name, old_dirents[i].snap_volname,
  415                              old_dirents[i].uuid);
  416             glfs_fini(old_dirents[i].fs);
  417         }
  418     }
  419 
  420     GF_FREE(old_dirents);
  421 
  422     ret = 0;
  423 
  424 out:
  425     if (dict) {
  426         dict_unref(dict);
  427     }
  428     free(rsp.dict.dict_val);
  429     free(rsp.op_errstr);
  430 
  431     if (ret && dirents) {
  432         gf_msg(this->name, GF_LOG_WARNING, 0, SVS_MSG_SNAP_LIST_REFRESH_FAILED,
  433                "Could not update dirents with refreshed snap list");
  434         GF_FREE(dirents);
  435     }
  436 
  437     if (myframe)
  438         SVS_STACK_DESTROY(myframe);
  439 
  440 error_out:
  441     return ret;
  442 }
  443 
  444 int
  445 svs_get_snapshot_list(xlator_t *this)
  446 {
  447     gf_getsnap_name_uuid_req req = {{
  448         0,
  449     }};
  450     int ret = -1;
  451     dict_t *dict = NULL;
  452     glusterfs_ctx_t *ctx = NULL;
  453     call_frame_t *frame = NULL;
  454     svs_private_t *priv = NULL;
  455     gf_boolean_t frame_cleanup = _gf_true;
  456 
  457     GF_VALIDATE_OR_GOTO("snapview-server", this, out);
  458 
  459     ctx = this->ctx;
  460     if (!ctx) {
  461         gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_NULL_CTX, "ctx is NULL");
  462         goto out;
  463     }
  464 
  465     frame = create_frame(this, ctx->pool);
  466     if (!frame) {
  467         gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_FRAME_ERROR,
  468                "Error allocating frame");
  469         goto out;
  470     }
  471 
  472     priv = this->private;
  473 
  474     dict = dict_new();
  475     if (!dict) {
  476         gf_msg(this->name, GF_LOG_ERROR, ENOMEM, SVS_MSG_NO_MEMORY,
  477                "Error allocating dictionary");
  478         goto out;
  479     }
  480 
  481     ret = dict_set_str(dict, "volname", priv->volname);
  482     if (ret) {
  483         gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_DICT_SET_FAILED,
  484                "Error setting volname in dict");
  485         goto out;
  486     }
  487 
  488     ret = dict_allocate_and_serialize(dict, &req.dict.dict_val,
  489                                       &req.dict.dict_len);
  490     if (ret) {
  491         gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_DICT_UNSERIAL_FAILED,
  492                "Failed to serialize dictionary");
  493         ret = -1;
  494         goto out;
  495     }
  496 
  497     ret = svs_mgmt_submit_request(
  498         &req, frame, ctx, &svs_clnt_handshake_prog, GF_HNDSK_GET_SNAPSHOT_INFO,
  499         mgmt_get_snapinfo_cbk, (xdrproc_t)xdr_gf_getsnap_name_uuid_req);
  500 
  501     if (ret) {
  502         gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_RPC_REQ_FAILED,
  503                "Error sending snapshot names RPC request");
  504     }
  505 
  506     frame_cleanup = _gf_false;
  507 
  508 out:
  509     if (dict) {
  510         dict_unref(dict);
  511     }
  512     GF_FREE(req.dict.dict_val);
  513 
  514     if (frame_cleanup && frame) {
  515         /*
  516          * Destroy the frame if we encountered an error
  517          * Else we need to clean it up in
  518          * mgmt_get_snapinfo_cbk
  519          */
  520         SVS_STACK_DESTROY(frame);
  521     }
  522 
  523     return ret;
  524 }