"Fossies" - the Fresh Open Source Software Archive

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

    1 /*
    2    Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
    3    This file is part of GlusterFS.
    4 
    5    This file is licensed to you under your choice of the GNU Lesser
    6    General Public License, version 3 or any later version (LGPLv3 or
    7    later), or the GNU General Public License, version 2 (GPLv2), in all
    8    cases as published by the Free Software Foundation.
    9 */
   10 
   11 #include "libxlator.h"
   12 
   13 int marker_xtime_default_gauge[] = {
   14     [MCNT_FOUND] = 1,     [MCNT_NOTFOUND] = -1, [MCNT_ENODATA] = -1,
   15     [MCNT_ENOTCONN] = -1, [MCNT_ENOENT] = -1,   [MCNT_EOTHER] = -1,
   16 };
   17 
   18 int marker_uuid_default_gauge[] = {
   19     [MCNT_FOUND] = 1,    [MCNT_NOTFOUND] = 0, [MCNT_ENODATA] = 0,
   20     [MCNT_ENOTCONN] = 0, [MCNT_ENOENT] = 0,   [MCNT_EOTHER] = 0,
   21 };
   22 
   23 static int marker_idx_errno_map[] = {
   24     [MCNT_FOUND] = EINVAL,    [MCNT_NOTFOUND] = EINVAL,
   25     [MCNT_ENOENT] = ENOENT,   [MCNT_ENOTCONN] = ENOTCONN,
   26     [MCNT_ENODATA] = ENODATA, [MCNT_EOTHER] = EINVAL,
   27     [MCNT_MAX] = 0,
   28 };
   29 
   30 /*Copy the contents of oldtimebuf to newtimbuf*/
   31 static void
   32 update_timebuf(uint32_t *oldtimbuf, uint32_t *newtimebuf)
   33 {
   34     newtimebuf[0] = (oldtimbuf[0]);
   35     newtimebuf[1] = (oldtimbuf[1]);
   36 }
   37 
   38 /* Convert Timebuf in network order to host order */
   39 static void
   40 get_hosttime(uint32_t *oldtimbuf, uint32_t *newtimebuf)
   41 {
   42     newtimebuf[0] = ntohl(oldtimbuf[0]);
   43     newtimebuf[1] = ntohl(oldtimbuf[1]);
   44 }
   45 
   46 /* Match the Incoming trusted.glusterfs.<uuid>.xtime against volume uuid */
   47 int
   48 match_uuid_local(const char *name, char *uuid)
   49 {
   50     if (!uuid || !*uuid)
   51         return -1;
   52 
   53     name = strtail((char *)name, MARKER_XATTR_PREFIX);
   54     if (!name || name++ [0] != '.')
   55         return -1;
   56 
   57     name = strtail((char *)name, uuid);
   58     if (!name || strcmp(name, ".xtime") != 0)
   59         return -1;
   60 
   61     return 0;
   62 }
   63 
   64 static void
   65 marker_local_incr_errcount(xl_marker_local_t *local, int op_errno)
   66 {
   67     marker_result_idx_t i = -1;
   68 
   69     if (!local)
   70         return;
   71 
   72     switch (op_errno) {
   73         case ENODATA:
   74             i = MCNT_ENODATA;
   75             break;
   76         case ENOENT:
   77             i = MCNT_ENOENT;
   78             break;
   79         case ENOTCONN:
   80             i = MCNT_ENOTCONN;
   81             break;
   82         default:
   83             i = MCNT_EOTHER;
   84             break;
   85     }
   86 
   87     local->count[i]++;
   88 }
   89 
   90 static int
   91 evaluate_marker_results(int *gauge, int *count)
   92 {
   93     int i = 0;
   94     int op_errno = 0;
   95     gf_boolean_t sane = _gf_true;
   96 
   97     /* check if the policy of the gauge is violated;
   98      * if yes, try to get the best errno, ie. look
   99      * for the first position where there is a more
  100      * specific kind of vioilation than the generic EINVAL
  101      */
  102     for (i = 0; i < MCNT_MAX; i++) {
  103         if (sane) {
  104             if ((gauge[i] > 0 && count[i] < gauge[i]) ||
  105                 (gauge[i] < 0 && count[i] >= -gauge[i])) {
  106                 sane = _gf_false;
  107                 /* generic action: adopt corresponding errno */
  108                 op_errno = marker_idx_errno_map[i];
  109             }
  110         } else {
  111             /* already insane; trying to get a more informative
  112              * errno by checking subsequent counters
  113              */
  114             if (count[i] > 0)
  115                 op_errno = marker_idx_errno_map[i];
  116         }
  117         if (op_errno && op_errno != EINVAL)
  118             break;
  119     }
  120 
  121     return op_errno;
  122 }
  123 
  124 static void
  125 cluster_marker_unwind(call_frame_t *frame, char *key, void *value, size_t size,
  126                       dict_t *dict)
  127 {
  128     xl_marker_local_t *local = frame->local;
  129     int ret = 0;
  130     int32_t op_ret = 0;
  131     int32_t op_errno = 0;
  132     gf_boolean_t unref = _gf_false;
  133 
  134     frame->local = local->xl_local;
  135 
  136     if (local->count[MCNT_FOUND]) {
  137         if (!dict) {
  138             dict = dict_new();
  139             if (dict) {
  140                 unref = _gf_true;
  141             } else {
  142                 op_ret = -1;
  143                 op_errno = ENOMEM;
  144                 goto out;
  145             }
  146         }
  147 
  148         ret = dict_set_static_bin(dict, key, value, size);
  149         if (ret) {
  150             op_ret = -1;
  151             op_errno = ENOMEM;
  152             goto out;
  153         }
  154     }
  155 
  156     op_errno = evaluate_marker_results(local->gauge, local->count);
  157     if (op_errno)
  158         op_ret = -1;
  159 
  160 out:
  161     if (local->xl_specf_unwind) {
  162         local->xl_specf_unwind(frame, op_ret, op_errno, dict, NULL);
  163     } else {
  164         STACK_UNWIND_STRICT(getxattr, frame, op_ret, op_errno, dict, NULL);
  165     }
  166 
  167     GF_FREE(local);
  168     if (unref)
  169         dict_unref(dict);
  170 }
  171 
  172 /* Aggregate all the <volid>.xtime attrs of the cluster and send the max*/
  173 int32_t
  174 cluster_markerxtime_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  175                         int op_ret, int op_errno, dict_t *dict, dict_t *xdata)
  176 
  177 {
  178     int32_t callcnt = 0;
  179     uint32_t *net_timebuf = NULL;
  180     uint32_t host_timebuf[2] = {
  181         0,
  182     };
  183     char marker_xattr[128] = {0};
  184     xl_marker_local_t *local = NULL;
  185 
  186     local = frame->local;
  187 
  188     snprintf(marker_xattr, sizeof(marker_xattr), "%s.%s.%s",
  189              MARKER_XATTR_PREFIX, local->vol_uuid, XTIME);
  190 
  191     LOCK(&frame->lock);
  192     {
  193         callcnt = --local->call_count;
  194 
  195         if (op_ret) {
  196             marker_local_incr_errcount(local, op_errno);
  197             goto unlock;
  198         }
  199 
  200         if (dict_get_ptr(dict, marker_xattr, (void **)&net_timebuf)) {
  201             local->count[MCNT_NOTFOUND]++;
  202             UNLOCK(&frame->lock);
  203             gf_log(this->name, GF_LOG_WARNING,
  204                    "Unable to get <uuid>.xtime attr");
  205             goto post_unlock;
  206         }
  207 
  208         if (local->count[MCNT_FOUND]) {
  209             get_hosttime(net_timebuf, host_timebuf);
  210             if ((host_timebuf[0] > local->host_timebuf[0]) ||
  211                 (host_timebuf[0] == local->host_timebuf[0] &&
  212                  host_timebuf[1] >= local->host_timebuf[1])) {
  213                 update_timebuf(net_timebuf, local->net_timebuf);
  214                 update_timebuf(host_timebuf, local->host_timebuf);
  215             }
  216 
  217         } else {
  218             get_hosttime(net_timebuf, local->host_timebuf);
  219             update_timebuf(net_timebuf, local->net_timebuf);
  220             local->count[MCNT_FOUND]++;
  221         }
  222     }
  223 unlock:
  224     UNLOCK(&frame->lock);
  225 post_unlock:
  226     if (callcnt == 0)
  227         cluster_marker_unwind(frame, marker_xattr, local->net_timebuf, 8, dict);
  228 
  229     return 0;
  230 }
  231 
  232 int32_t
  233 cluster_markeruuid_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  234                        int op_ret, int op_errno, dict_t *dict, dict_t *xdata)
  235 {
  236     int32_t callcnt = 0;
  237     struct volume_mark *volmark = NULL;
  238     xl_marker_local_t *local = NULL;
  239     int32_t ret = -1;
  240     char *vol_uuid = NULL;
  241 
  242     local = frame->local;
  243 
  244     LOCK(&frame->lock);
  245     {
  246         callcnt = --local->call_count;
  247         vol_uuid = local->vol_uuid;
  248 
  249         if (op_ret) {
  250             marker_local_incr_errcount(local, op_errno);
  251             goto unlock;
  252         }
  253 
  254         ret = dict_get_bin(dict, GF_XATTR_MARKER_KEY, (void *)&volmark);
  255         if (ret)
  256             goto unlock;
  257 
  258         if (local->count[MCNT_FOUND]) {
  259             if ((local->volmark->major != volmark->major) ||
  260                 (local->volmark->minor != volmark->minor)) {
  261                 op_ret = -1;
  262                 op_errno = EINVAL;
  263                 goto unlock;
  264             }
  265 
  266             if (local->retval) {
  267                 goto unlock;
  268             } else if (volmark->retval) {
  269                 GF_FREE(local->volmark);
  270                 local->volmark = gf_memdup(volmark, sizeof(*volmark));
  271                 local->retval = volmark->retval;
  272             } else if ((volmark->sec > local->volmark->sec) ||
  273                        ((volmark->sec == local->volmark->sec) &&
  274                         (volmark->usec >= local->volmark->usec))) {
  275                 GF_FREE(local->volmark);
  276                 local->volmark = gf_memdup(volmark, sizeof(*volmark));
  277             }
  278 
  279         } else {
  280             local->volmark = gf_memdup(volmark, sizeof(*volmark));
  281             VALIDATE_OR_GOTO(local->volmark, unlock);
  282             gf_uuid_unparse(volmark->uuid, vol_uuid);
  283             if (volmark->retval)
  284                 local->retval = volmark->retval;
  285             local->count[MCNT_FOUND]++;
  286         }
  287     }
  288 unlock:
  289     UNLOCK(&frame->lock);
  290 
  291     if (callcnt == 0)
  292         cluster_marker_unwind(frame, GF_XATTR_MARKER_KEY, local->volmark,
  293                               sizeof(*local->volmark), dict);
  294 
  295     return 0;
  296 }
  297 
  298 int
  299 gf_get_min_stime(xlator_t *this, dict_t *dst, char *key, data_t *value)
  300 {
  301     int ret = -1;
  302     uint32_t *net_timebuf = NULL;
  303     uint32_t *value_timebuf = NULL;
  304     uint32_t host_timebuf[2] = {
  305         0,
  306     };
  307     uint32_t host_value_timebuf[2] = {
  308         0,
  309     };
  310 
  311     /* stime should be minimum of all the other nodes */
  312     ret = dict_get_bin(dst, key, (void **)&net_timebuf);
  313     if (ret < 0) {
  314         net_timebuf = GF_CALLOC(1, sizeof(int64_t), gf_common_mt_char);
  315         if (!net_timebuf)
  316             goto out;
  317 
  318         ret = dict_set_bin(dst, key, net_timebuf, sizeof(int64_t));
  319         if (ret < 0) {
  320             gf_log(this->name, GF_LOG_WARNING, "key=%s: dict set failed", key);
  321             goto error;
  322         }
  323     }
  324 
  325     value_timebuf = data_to_bin(value);
  326     if (!value_timebuf) {
  327         gf_log(this->name, GF_LOG_WARNING,
  328                "key=%s: getting value of stime failed", key);
  329         ret = -1;
  330         goto out;
  331     }
  332 
  333     get_hosttime(value_timebuf, host_value_timebuf);
  334     get_hosttime(net_timebuf, host_timebuf);
  335 
  336     /* can't use 'min()' macro here as we need to compare two fields
  337        in the array, selectively */
  338     if ((host_value_timebuf[0] < host_timebuf[0]) ||
  339         ((host_value_timebuf[0] == host_timebuf[0]) &&
  340          (host_value_timebuf[1] < host_timebuf[1]))) {
  341         update_timebuf(value_timebuf, net_timebuf);
  342     }
  343 
  344     ret = 0;
  345 out:
  346     return ret;
  347 error:
  348     /* To be used only when net_timebuf is not set in the dict */
  349     if (net_timebuf)
  350         GF_FREE(net_timebuf);
  351 
  352     return ret;
  353 }
  354 
  355 int
  356 gf_get_max_stime(xlator_t *this, dict_t *dst, char *key, data_t *value)
  357 {
  358     int ret = -ENOMEM;
  359     uint32_t *net_timebuf = NULL;
  360     uint32_t *value_timebuf = NULL;
  361     uint32_t host_timebuf[2] = {
  362         0,
  363     };
  364     uint32_t host_value_timebuf[2] = {
  365         0,
  366     };
  367 
  368     /* stime should be maximum of all the other nodes */
  369     ret = dict_get_bin(dst, key, (void **)&net_timebuf);
  370     if (ret < 0) {
  371         net_timebuf = GF_CALLOC(1, sizeof(int64_t), gf_common_mt_char);
  372         if (!net_timebuf)
  373             goto out;
  374 
  375         ret = dict_set_bin(dst, key, net_timebuf, sizeof(int64_t));
  376         if (ret < 0) {
  377             gf_log(this->name, GF_LOG_WARNING, "key=%s: dict set failed", key);
  378             goto error;
  379         }
  380     }
  381 
  382     value_timebuf = data_to_bin(value);
  383     if (!value_timebuf) {
  384         gf_log(this->name, GF_LOG_WARNING,
  385                "key=%s: getting value of stime failed", key);
  386         ret = -EINVAL;
  387         goto out;
  388     }
  389 
  390     get_hosttime(value_timebuf, host_value_timebuf);
  391     get_hosttime(net_timebuf, host_timebuf);
  392 
  393     /* can't use 'max()' macro here as we need to compare two fields
  394        in the array, selectively */
  395     if ((host_value_timebuf[0] > host_timebuf[0]) ||
  396         ((host_value_timebuf[0] == host_timebuf[0]) &&
  397          (host_value_timebuf[1] > host_timebuf[1]))) {
  398         update_timebuf(value_timebuf, net_timebuf);
  399     }
  400 
  401     ret = 0;
  402 out:
  403     return ret;
  404 error:
  405     /* To be used only when net_timebuf is not set in the dict */
  406     if (net_timebuf)
  407         GF_FREE(net_timebuf);
  408 
  409     return ret;
  410 }
  411 
  412 static int
  413 _get_children_count(xlator_t *xl)
  414 {
  415     int i = 0;
  416     xlator_list_t *trav = NULL;
  417     for (i = 0, trav = xl->children; trav; trav = trav->next, i++) {
  418         /*'i' will have the value */
  419     }
  420 
  421     return i;
  422 }
  423 
  424 int
  425 cluster_handle_marker_getxattr(call_frame_t *frame, loc_t *loc,
  426                                const char *name, char *vol_uuid,
  427                                xlator_specf_unwind_t unwind,
  428                                int (*populate_args)(call_frame_t *frame,
  429                                                     int type, int *gauge,
  430                                                     xlator_t **subvols))
  431 {
  432     xlator_t *this = frame->this;
  433     xlator_t **subvols = NULL;
  434     int num_subvols = 0;
  435     int type = 0;
  436     int i = 0;
  437     int gauge[MCNT_MAX] = {0};
  438     xl_marker_local_t *local = NULL;
  439 
  440     if (GF_CLIENT_PID_GSYNCD != frame->root->pid)
  441         return -EINVAL;
  442 
  443     if (name == NULL)
  444         return -EINVAL;
  445 
  446     if (strcmp(GF_XATTR_MARKER_KEY, name) == 0) {
  447         type = MARKER_UUID_TYPE;
  448         memcpy(gauge, marker_uuid_default_gauge, sizeof(gauge));
  449     } else if (match_uuid_local(name, vol_uuid) == 0) {
  450         type = MARKER_XTIME_TYPE;
  451         memcpy(gauge, marker_xtime_default_gauge, sizeof(gauge));
  452     } else {
  453         return -EINVAL;
  454     }
  455 
  456     num_subvols = _get_children_count(this);
  457     subvols = alloca(num_subvols * sizeof(*subvols));
  458     num_subvols = populate_args(frame, type, gauge, subvols);
  459 
  460     local = GF_CALLOC(sizeof(struct marker_str), 1,
  461                       gf_common_mt_libxl_marker_local);
  462 
  463     if (!local)
  464         goto fail;
  465 
  466     local->xl_local = frame->local;
  467     local->call_count = num_subvols;
  468     local->xl_specf_unwind = unwind;
  469     local->vol_uuid = vol_uuid;
  470     memcpy(local->gauge, gauge, sizeof(local->gauge));
  471 
  472     frame->local = local;
  473 
  474     for (i = 0; i < num_subvols; i++) {
  475         if (MARKER_UUID_TYPE == type)
  476             STACK_WIND(frame, cluster_markeruuid_cbk, subvols[i],
  477                        subvols[i]->fops->getxattr, loc, name, NULL);
  478         else if (MARKER_XTIME_TYPE == type)
  479             STACK_WIND(frame, cluster_markerxtime_cbk, subvols[i],
  480                        subvols[i]->fops->getxattr, loc, name, NULL);
  481     }
  482 
  483     return 0;
  484 fail:
  485     if (unwind)
  486         unwind(frame, -1, ENOMEM, NULL, NULL);
  487     else
  488         default_getxattr_failure_cbk(frame, ENOMEM);
  489     return 0;
  490 }