Blame libglusterfs/src/options.c

Packit b2c0d9
/*
Packit b2c0d9
  Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
Packit b2c0d9
  This file is part of GlusterFS.
Packit b2c0d9
Packit b2c0d9
  This file is licensed to you under your choice of the GNU Lesser
Packit b2c0d9
  General Public License, version 3 or any later version (LGPLv3 or
Packit b2c0d9
  later), or the GNU General Public License, version 2 (GPLv2), in all
Packit b2c0d9
  cases as published by the Free Software Foundation.
Packit b2c0d9
*/
Packit b2c0d9
Packit b2c0d9
#include <fnmatch.h>
Packit b2c0d9
Packit b2c0d9
#include "glusterfs/xlator.h"
Packit b2c0d9
#include "glusterfs/defaults.h"
Packit b2c0d9
#include "glusterfs/libglusterfs-messages.h"
Packit b2c0d9
Packit b2c0d9
#define GF_OPTION_LIST_EMPTY(_opt) (_opt->value[0] == NULL)
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_path(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                            volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
Packit b2c0d9
    if (strstr(value, "../")) {
Packit b2c0d9
        snprintf(errstr, 256, "invalid path given '%s'", value);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    /* Make sure the given path is valid */
Packit b2c0d9
    if (value[0] != '/') {
Packit b2c0d9
        snprintf(errstr, 256,
Packit b2c0d9
                 "option %s %s: '%s' is not an "
Packit b2c0d9
                 "absolute path name",
Packit b2c0d9
                 key, value, value);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    if (ret && op_errstr)
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_int(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                           volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    long long inputll = 0;
Packit b2c0d9
    unsigned long long uinputll = 0;
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
Packit b2c0d9
    /* Check the range */
Packit b2c0d9
    if (gf_string2longlong(value, &inputll) != 0) {
Packit b2c0d9
        snprintf(errstr, 256, "invalid number format \"%s\" in option \"%s\"",
Packit b2c0d9
                 value, key);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    /* Handle '-0' */
Packit b2c0d9
    if ((inputll == 0) && (gf_string2ulonglong(value, &uinputll) != 0)) {
Packit b2c0d9
        snprintf(errstr, 256, "invalid number format \"%s\" in option \"%s\"",
Packit b2c0d9
                 value, key);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if ((opt->min == 0) && (opt->max == 0) &&
Packit b2c0d9
        (opt->validate == GF_OPT_VALIDATE_BOTH)) {
Packit b2c0d9
        gf_msg_trace(xl->name, 0,
Packit b2c0d9
                     "no range check required for "
Packit b2c0d9
                     "'option %s %s'",
Packit b2c0d9
                     key, value);
Packit b2c0d9
        ret = 0;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if (opt->validate == GF_OPT_VALIDATE_MIN) {
Packit b2c0d9
        if (inputll < opt->min) {
Packit b2c0d9
            snprintf(errstr, 256,
Packit b2c0d9
                     "'%lld' in 'option %s %s' is smaller than "
Packit b2c0d9
                     "minimum value '%.0f'",
Packit b2c0d9
                     inputll, key, value, opt->min);
Packit b2c0d9
            gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s",
Packit b2c0d9
                   errstr);
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
    } else if (opt->validate == GF_OPT_VALIDATE_MAX) {
Packit b2c0d9
        if (inputll > opt->max) {
Packit b2c0d9
            snprintf(errstr, 256,
Packit b2c0d9
                     "'%lld' in 'option %s %s' is greater than "
Packit b2c0d9
                     "maximum value '%.0f'",
Packit b2c0d9
                     inputll, key, value, opt->max);
Packit b2c0d9
            gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s",
Packit b2c0d9
                   errstr);
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
    } else if ((inputll < opt->min) || (inputll > opt->max)) {
Packit b2c0d9
        snprintf(errstr, 256,
Packit b2c0d9
                 "'%lld' in 'option %s %s' is out of range "
Packit b2c0d9
                 "[%.0f - %.0f]",
Packit b2c0d9
                 inputll, key, value, opt->min, opt->max);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_OUT_OF_RANGE, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    if (ret && op_errstr)
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_sizet(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                             volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    uint64_t size = 0;
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
Packit b2c0d9
    /* Check the range */
Packit b2c0d9
    if (gf_string2bytesize_uint64(value, &size) != 0) {
Packit b2c0d9
        snprintf(errstr, 256, "invalid number format \"%s\" in option \"%s\"",
Packit b2c0d9
                 value, key);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        ret = -1;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if ((opt->min == 0) && (opt->max == 0)) {
Packit b2c0d9
        gf_msg_trace(xl->name, 0,
Packit b2c0d9
                     "no range check required for "
Packit b2c0d9
                     "'option %s %s'",
Packit b2c0d9
                     key, value);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if ((size < opt->min) || (size > opt->max)) {
Packit b2c0d9
        snprintf(errstr, 256,
Packit b2c0d9
                 "'%" PRIu64
Packit b2c0d9
                 "' in 'option %s %s' is out of range [%.0f - %.0f]",
Packit b2c0d9
                 size, key, value, opt->min, opt->max);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_OUT_OF_RANGE, "%s", errstr);
Packit b2c0d9
        ret = -1;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
out:
Packit b2c0d9
    if (ret && op_errstr)
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_bool(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                            volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
    gf_boolean_t is_valid;
Packit b2c0d9
Packit b2c0d9
    /* Check if the value is one of
Packit b2c0d9
       '0|1|on|off|no|yes|true|false|enable|disable' */
Packit b2c0d9
Packit b2c0d9
    if (gf_string2boolean(value, &is_valid) != 0) {
Packit b2c0d9
        snprintf(errstr, 256, "option %s %s: '%s' is not a valid boolean value",
Packit b2c0d9
                 key, value, value);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    if (ret && op_errstr)
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_xlator(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                              volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
    xlator_t *xlopt = NULL;
Packit b2c0d9
Packit b2c0d9
    /* Check if the value is one of the xlators */
Packit b2c0d9
    xlopt = xl;
Packit b2c0d9
    while (xlopt->prev)
Packit b2c0d9
        xlopt = xlopt->prev;
Packit b2c0d9
Packit b2c0d9
    while (xlopt) {
Packit b2c0d9
        if (strcmp(value, xlopt->name) == 0) {
Packit b2c0d9
            ret = 0;
Packit b2c0d9
            break;
Packit b2c0d9
        }
Packit b2c0d9
        xlopt = xlopt->next;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if (!xlopt) {
Packit b2c0d9
        snprintf(errstr, 256, "option %s %s: '%s' is not a valid volume name",
Packit b2c0d9
                 key, value, value);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    if (ret && op_errstr)
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
void
Packit b2c0d9
set_error_str(char *errstr, size_t len, volume_option_t *opt, const char *key,
Packit b2c0d9
              const char *value)
Packit b2c0d9
{
Packit b2c0d9
    int i = 0;
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
Packit b2c0d9
    ret = snprintf(errstr, len,
Packit b2c0d9
                   "option %s %s: '%s' is not valid "
Packit b2c0d9
                   "(possible options are ",
Packit b2c0d9
                   key, value, value);
Packit b2c0d9
Packit b2c0d9
    for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && opt->value[i];) {
Packit b2c0d9
        ret += snprintf(errstr + ret, len - ret, "%s", opt->value[i]);
Packit b2c0d9
        if (((++i) < ZR_OPTION_MAX_ARRAY_SIZE) && (opt->value[i]))
Packit b2c0d9
            ret += snprintf(errstr + ret, len - ret, ", ");
Packit b2c0d9
        else
Packit b2c0d9
            ret += snprintf(errstr + ret, len - ret, ".)");
Packit b2c0d9
    }
Packit b2c0d9
    return;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
int
Packit b2c0d9
is_all_whitespaces(const char *value)
Packit b2c0d9
{
Packit b2c0d9
    int i = 0;
Packit b2c0d9
    size_t len = 0;
Packit b2c0d9
Packit b2c0d9
    if (value == NULL)
Packit b2c0d9
        return -1;
Packit b2c0d9
Packit b2c0d9
    len = strlen(value);
Packit b2c0d9
Packit b2c0d9
    for (i = 0; i < len; i++) {
Packit b2c0d9
        if (value[i] == ' ')
Packit b2c0d9
            continue;
Packit b2c0d9
        else
Packit b2c0d9
            return 0;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    return 1;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_str(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                           volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    int i = 0;
Packit b2c0d9
    char errstr[4096] = {
Packit b2c0d9
        0,
Packit b2c0d9
    };
Packit b2c0d9
Packit b2c0d9
    /* Check if the '*str' is valid */
Packit b2c0d9
    if (GF_OPTION_LIST_EMPTY(opt)) {
Packit b2c0d9
        ret = 0;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if (is_all_whitespaces(value) == 1)
Packit b2c0d9
        goto out;
Packit b2c0d9
Packit b2c0d9
    for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && opt->value[i]; i++) {
Packit b2c0d9
#ifdef GF_DARWIN_HOST_OS
Packit b2c0d9
        if (fnmatch(opt->value[i], value, 0) == 0) {
Packit b2c0d9
            ret = 0;
Packit b2c0d9
            break;
Packit b2c0d9
        }
Packit b2c0d9
#else
Packit b2c0d9
        if (fnmatch(opt->value[i], value, FNM_EXTMATCH) == 0) {
Packit b2c0d9
            ret = 0;
Packit b2c0d9
            break;
Packit b2c0d9
        }
Packit b2c0d9
#endif
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if ((i == ZR_OPTION_MAX_ARRAY_SIZE) || (!opt->value[i]))
Packit b2c0d9
        goto out;
Packit b2c0d9
    /* enter here only if
Packit b2c0d9
     * 1. reached end of opt->value array and haven't
Packit b2c0d9
     *    validated input
Packit b2c0d9
     *                      OR
Packit b2c0d9
     * 2. valid input list is less than
Packit b2c0d9
     *    ZR_OPTION_MAX_ARRAY_SIZE and input has not
Packit b2c0d9
     *    matched all possible input values.
Packit b2c0d9
     */
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
Packit b2c0d9
out:
Packit b2c0d9
    if (ret) {
Packit b2c0d9
        set_error_str(errstr, sizeof(errstr), opt, key, value);
Packit b2c0d9
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        if (op_errstr)
Packit b2c0d9
            *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    }
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_percent(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                               volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    double percent = 0;
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
Packit b2c0d9
    /* Check if the value is valid percentage */
Packit b2c0d9
    if (gf_string2percent(value, &percent) != 0) {
Packit b2c0d9
        snprintf(errstr, 256, "invalid percent format \"%s\" in \"option %s\"",
Packit b2c0d9
                 value, key);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if ((percent < 0.0) || (percent > 100.0)) {
Packit b2c0d9
        snprintf(errstr, 256,
Packit b2c0d9
                 "'%lf' in 'option %s %s' is out of range [0 - 100]", percent,
Packit b2c0d9
                 key, value);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_OUT_OF_RANGE, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    if (ret && op_errstr)
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_fractional_value(const char *value)
Packit b2c0d9
{
Packit b2c0d9
    const char *s = NULL;
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
Packit b2c0d9
    s = strchr(value, '.');
Packit b2c0d9
    if (s) {
Packit b2c0d9
        for (s = s + 1; *s != '\0'; s++) {
Packit b2c0d9
            if (*s != '0') {
Packit b2c0d9
                return -1;
Packit b2c0d9
            }
Packit b2c0d9
        }
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_percent_or_sizet(xlator_t *xl, const char *key,
Packit b2c0d9
                                        const char *value, volume_option_t *opt,
Packit b2c0d9
                                        char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
    double size = 0;
Packit b2c0d9
    gf_boolean_t is_percent = _gf_false;
Packit b2c0d9
Packit b2c0d9
    if (gf_string2percent_or_bytesize(value, &size, &is_percent) == 0) {
Packit b2c0d9
        if (is_percent) {
Packit b2c0d9
            if ((size < 0.0) || (size > 100.0)) {
Packit b2c0d9
                snprintf(errstr, sizeof(errstr),
Packit b2c0d9
                         "'%lf' in 'option %s %s' is out"
Packit b2c0d9
                         " of range [0 - 100]",
Packit b2c0d9
                         size, key, value);
Packit b2c0d9
                gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_OUT_OF_RANGE, "%s",
Packit b2c0d9
                       errstr);
Packit b2c0d9
                goto out;
Packit b2c0d9
            }
Packit b2c0d9
            ret = 0;
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
Packit b2c0d9
        /*Input value of size(in byte) should not be fractional*/
Packit b2c0d9
        ret = xlator_option_validate_fractional_value(value);
Packit b2c0d9
        if (ret) {
Packit b2c0d9
            snprintf(errstr, sizeof(errstr),
Packit b2c0d9
                     "'%lf' in 'option %s"
Packit b2c0d9
                     " %s' should not be fractional value. Use "
Packit b2c0d9
                     "valid unsigned integer value.",
Packit b2c0d9
                     size, key, value);
Packit b2c0d9
            gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s",
Packit b2c0d9
                   errstr);
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
Packit b2c0d9
        /* Check the range */
Packit b2c0d9
        if ((opt->min == 0) && (opt->max == 0)) {
Packit b2c0d9
            gf_msg_trace(xl->name, 0,
Packit b2c0d9
                         "no range check required "
Packit b2c0d9
                         "for 'option %s %s'",
Packit b2c0d9
                         key, value);
Packit b2c0d9
            ret = 0;
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
        if ((size < opt->min) || (size > opt->max)) {
Packit b2c0d9
            snprintf(errstr, 256,
Packit b2c0d9
                     "'%lf' in 'option %s %s'"
Packit b2c0d9
                     " is out of range [%.0f - %.0f]",
Packit b2c0d9
                     size, key, value, opt->min, opt->max);
Packit b2c0d9
            gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_OUT_OF_RANGE, "%s",
Packit b2c0d9
                   errstr);
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
        ret = 0;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    /* If control reaches here, invalid argument */
Packit b2c0d9
Packit b2c0d9
    snprintf(errstr, 256, "invalid number format \"%s\" in \"option %s\"",
Packit b2c0d9
             value, key);
Packit b2c0d9
    gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
Packit b2c0d9
out:
Packit b2c0d9
    if (ret && op_errstr)
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_time(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                            volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
    uint32_t input_time = 0;
Packit b2c0d9
Packit b2c0d9
    /* Check if the value is valid time */
Packit b2c0d9
    if (gf_string2time(value, &input_time) != 0) {
Packit b2c0d9
        snprintf(errstr, 256,
Packit b2c0d9
                 "invalid time format \"%s\" in "
Packit b2c0d9
                 "\"option %s\"",
Packit b2c0d9
                 value, key);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if ((opt->min == 0) && (opt->max == 0)) {
Packit b2c0d9
        gf_msg_trace(xl->name, 0,
Packit b2c0d9
                     "no range check required for "
Packit b2c0d9
                     "'option %s %s'",
Packit b2c0d9
                     key, value);
Packit b2c0d9
        ret = 0;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if ((input_time < opt->min) || (input_time > opt->max)) {
Packit b2c0d9
        snprintf(errstr, 256,
Packit b2c0d9
                 "'%" PRIu32
Packit b2c0d9
                 "' in 'option %s %s' is "
Packit b2c0d9
                 "out of range [%.0f - %.0f]",
Packit b2c0d9
                 input_time, key, value, opt->min, opt->max);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_OUT_OF_RANGE, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    if (ret && op_errstr)
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_double(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                              volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    double input = 0.0;
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
Packit b2c0d9
    /* Check the range */
Packit b2c0d9
    if (gf_string2double(value, &input) != 0) {
Packit b2c0d9
        snprintf(errstr, 256, "invalid number format \"%s\" in option \"%s\"",
Packit b2c0d9
                 value, key);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if ((opt->min == 0) && (opt->max == 0) &&
Packit b2c0d9
        (opt->validate == GF_OPT_VALIDATE_BOTH)) {
Packit b2c0d9
        gf_msg_trace(xl->name, 0,
Packit b2c0d9
                     "no range check required for "
Packit b2c0d9
                     "'option %s %s'",
Packit b2c0d9
                     key, value);
Packit b2c0d9
        ret = 0;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if (opt->validate == GF_OPT_VALIDATE_MIN) {
Packit b2c0d9
        if (input < opt->min) {
Packit b2c0d9
            snprintf(errstr, 256,
Packit b2c0d9
                     "'%f' in 'option %s %s' is smaller than "
Packit b2c0d9
                     "minimum value '%f'",
Packit b2c0d9
                     input, key, value, opt->min);
Packit b2c0d9
            gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s",
Packit b2c0d9
                   errstr);
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
    } else if (opt->validate == GF_OPT_VALIDATE_MAX) {
Packit b2c0d9
        if (input > opt->max) {
Packit b2c0d9
            snprintf(errstr, 256,
Packit b2c0d9
                     "'%f' in 'option %s %s' is greater than "
Packit b2c0d9
                     "maximum value '%f'",
Packit b2c0d9
                     input, key, value, opt->max);
Packit b2c0d9
            gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s",
Packit b2c0d9
                   errstr);
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
    } else if ((input < opt->min) || (input > opt->max)) {
Packit b2c0d9
        snprintf(errstr, 256,
Packit b2c0d9
                 "'%f' in 'option %s %s' is out of range "
Packit b2c0d9
                 "[%f - %f]",
Packit b2c0d9
                 input, key, value, opt->min, opt->max);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_OUT_OF_RANGE, "%s", errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    if (ret && op_errstr)
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_addr(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                            volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char errstr[256];
Packit b2c0d9
Packit b2c0d9
    if (!valid_internet_address((char *)value, _gf_false, _gf_false)) {
Packit b2c0d9
        snprintf(errstr, 256, "option %s %s: Can not parse %s address", key,
Packit b2c0d9
                 value, value);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        if (op_errstr)
Packit b2c0d9
            *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
int
Packit b2c0d9
xlator_option_validate_addr_list(xlator_t *xl, const char *key,
Packit b2c0d9
                                 const char *value, volume_option_t *opt,
Packit b2c0d9
                                 char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char *dup_val = NULL;
Packit b2c0d9
    char *addr_tok = NULL;
Packit b2c0d9
    char *save_ptr = NULL;
Packit b2c0d9
    char *entry = NULL;
Packit b2c0d9
    char *entry_ptr = NULL;
Packit b2c0d9
    char *dir_and_addr = NULL;
Packit b2c0d9
    char *addr_ptr = NULL;
Packit b2c0d9
    char *addr_list = NULL;
Packit b2c0d9
    char *addr = NULL;
Packit b2c0d9
    char *dir = NULL;
Packit b2c0d9
    char errstr[4096] = {
Packit b2c0d9
        0,
Packit b2c0d9
    };
Packit b2c0d9
Packit b2c0d9
    dup_val = gf_strdup(value);
Packit b2c0d9
    if (!dup_val)
Packit b2c0d9
        goto out;
Packit b2c0d9
Packit b2c0d9
    if (dup_val[0] != '/' && !strchr(dup_val, '(')) {
Packit b2c0d9
        /* Possible old format, handle it for back-ward compatibility */
Packit b2c0d9
        addr_tok = strtok_r(dup_val, ",", &save_ptr);
Packit b2c0d9
        while (addr_tok) {
Packit b2c0d9
            if (!valid_internet_address(addr_tok, _gf_true, _gf_true))
Packit b2c0d9
                goto out;
Packit b2c0d9
Packit b2c0d9
            addr_tok = strtok_r(NULL, ",", &save_ptr);
Packit b2c0d9
        }
Packit b2c0d9
        ret = 0;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    /* Lets handle the value with new format */
Packit b2c0d9
    entry = strtok_r(dup_val, ",", &entry_ptr);
Packit b2c0d9
    while (entry) {
Packit b2c0d9
        dir_and_addr = gf_strdup(entry);
Packit b2c0d9
        if (!dir_and_addr)
Packit b2c0d9
            goto out;
Packit b2c0d9
Packit b2c0d9
        dir = strtok_r(dir_and_addr, "(", &addr_ptr);
Packit b2c0d9
        if (dir[0] != '/') {
Packit b2c0d9
            /* Valid format should be starting from '/' */
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
        /* dir = strtok_r (NULL, " =", &addr_tmp); */
Packit b2c0d9
        addr = strtok_r(NULL, ")", &addr_ptr);
Packit b2c0d9
        if (!addr)
Packit b2c0d9
            goto out;
Packit b2c0d9
Packit b2c0d9
        addr_list = gf_strdup(addr);
Packit b2c0d9
        if (!addr_list)
Packit b2c0d9
            goto out;
Packit b2c0d9
Packit b2c0d9
        /* This format be separated by '|' */
Packit b2c0d9
        addr_tok = strtok_r(addr_list, "|", &save_ptr);
Packit b2c0d9
        if (addr_tok == NULL)
Packit b2c0d9
            goto out;
Packit b2c0d9
        while (addr_tok) {
Packit b2c0d9
            if (!valid_internet_address(addr_tok, _gf_true, _gf_true))
Packit b2c0d9
                goto out;
Packit b2c0d9
Packit b2c0d9
            addr_tok = strtok_r(NULL, "|", &save_ptr);
Packit b2c0d9
        }
Packit b2c0d9
        entry = strtok_r(NULL, ",", &entry_ptr);
Packit b2c0d9
        GF_FREE(dir_and_addr);
Packit b2c0d9
        GF_FREE(addr_list);
Packit b2c0d9
        addr_list = NULL;
Packit b2c0d9
        dir_and_addr = NULL;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
Packit b2c0d9
out:
Packit b2c0d9
    if (ret) {
Packit b2c0d9
        snprintf(errstr, sizeof(errstr),
Packit b2c0d9
                 "option %s %s: '%s' is not "
Packit b2c0d9
                 "a valid internet-address-list",
Packit b2c0d9
                 key, value, value);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        if (op_errstr)
Packit b2c0d9
            *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    }
Packit b2c0d9
    GF_FREE(dup_val);
Packit b2c0d9
    GF_FREE(dir_and_addr);
Packit b2c0d9
    GF_FREE(addr_list);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_mntauth(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                               volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    char *dup_val = NULL;
Packit b2c0d9
    char *addr_tok = NULL;
Packit b2c0d9
    char *save_ptr = NULL;
Packit b2c0d9
    char errstr[4096] = {
Packit b2c0d9
        0,
Packit b2c0d9
    };
Packit b2c0d9
Packit b2c0d9
    dup_val = gf_strdup(value);
Packit b2c0d9
    if (!dup_val)
Packit b2c0d9
        goto out;
Packit b2c0d9
Packit b2c0d9
    addr_tok = strtok_r(dup_val, ",", &save_ptr);
Packit b2c0d9
    if (addr_tok == NULL)
Packit b2c0d9
        goto out;
Packit b2c0d9
    while (addr_tok) {
Packit b2c0d9
        if (!valid_mount_auth_address(addr_tok))
Packit b2c0d9
            goto out;
Packit b2c0d9
Packit b2c0d9
        addr_tok = strtok_r(NULL, ",", &save_ptr);
Packit b2c0d9
    }
Packit b2c0d9
    ret = 0;
Packit b2c0d9
Packit b2c0d9
out:
Packit b2c0d9
    if (ret) {
Packit b2c0d9
        snprintf(errstr, sizeof(errstr),
Packit b2c0d9
                 "option %s %s: '%s' is not "
Packit b2c0d9
                 "a valid mount-auth-address",
Packit b2c0d9
                 key, value, value);
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY, "%s", errstr);
Packit b2c0d9
        if (op_errstr)
Packit b2c0d9
            *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    }
Packit b2c0d9
    GF_FREE(dup_val);
Packit b2c0d9
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
/*XXX: the rules to validate are as per block-size required for stripe xlator */
Packit b2c0d9
static int
Packit b2c0d9
gf_validate_size(const char *sizestr, volume_option_t *opt)
Packit b2c0d9
{
Packit b2c0d9
    uint64_t value = 0;
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
Packit b2c0d9
    GF_ASSERT(opt);
Packit b2c0d9
Packit b2c0d9
    if (gf_string2bytesize_uint64(sizestr, &value) != 0 || value < opt->min ||
Packit b2c0d9
        value % 512) {
Packit b2c0d9
        ret = -1;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
out:
Packit b2c0d9
    gf_msg_debug(THIS->name, 0, "Returning %d", ret);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
gf_validate_number(const char *numstr, volume_option_t *opt)
Packit b2c0d9
{
Packit b2c0d9
    int32_t value;
Packit b2c0d9
    return gf_string2int32(numstr, &value);
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
/*  Parses the string to be of the form <key1>:<value1>,<key2>:<value2>...  *
Packit b2c0d9
 *  takes two optional validaters key_validator and value_validator         */
Packit b2c0d9
static int
Packit b2c0d9
validate_list_elements(const char *string, volume_option_t *opt,
Packit b2c0d9
                       int(key_validator)(const char *),
Packit b2c0d9
                       int(value_validator)(const char *, volume_option_t *))
Packit b2c0d9
{
Packit b2c0d9
    char *dup_string = NULL;
Packit b2c0d9
    char *str_sav = NULL;
Packit b2c0d9
    char *substr_sav = NULL;
Packit b2c0d9
    char *str_ptr = NULL;
Packit b2c0d9
    char *key = NULL;
Packit b2c0d9
    char *value = NULL;
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
Packit b2c0d9
    GF_ASSERT(string);
Packit b2c0d9
Packit b2c0d9
    dup_string = gf_strdup(string);
Packit b2c0d9
    if (NULL == dup_string)
Packit b2c0d9
        goto out;
Packit b2c0d9
Packit b2c0d9
    str_ptr = strtok_r(dup_string, ",", &str_sav);
Packit b2c0d9
    if (str_ptr == NULL) {
Packit b2c0d9
        ret = -1;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
    while (str_ptr) {
Packit b2c0d9
        key = strtok_r(str_ptr, ":", &substr_sav);
Packit b2c0d9
        if (!key || (key_validator && key_validator(key))) {
Packit b2c0d9
            ret = -1;
Packit b2c0d9
            gf_msg(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INVALID_ENTRY,
Packit b2c0d9
                   "invalid list '%s', key "
Packit b2c0d9
                   "'%s' not valid.",
Packit b2c0d9
                   string, key);
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
Packit b2c0d9
        value = strtok_r(NULL, ":", &substr_sav);
Packit b2c0d9
        if (!value || (value_validator && value_validator(value, opt))) {
Packit b2c0d9
            ret = -1;
Packit b2c0d9
            gf_msg(THIS->name, GF_LOG_WARNING, 0, LG_MSG_INVALID_ENTRY,
Packit b2c0d9
                   "invalid list '%s', "
Packit b2c0d9
                   "value '%s' not valid.",
Packit b2c0d9
                   string, key);
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
Packit b2c0d9
        str_ptr = strtok_r(NULL, ",", &str_sav);
Packit b2c0d9
        substr_sav = NULL;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
out:
Packit b2c0d9
    GF_FREE(dup_string);
Packit b2c0d9
    gf_msg_debug(THIS->name, 0, "Returning %d", ret);
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_priority_list(xlator_t *xl, const char *key,
Packit b2c0d9
                                     const char *value, volume_option_t *opt,
Packit b2c0d9
                                     char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
    char errstr[1024] = {
Packit b2c0d9
        0,
Packit b2c0d9
    };
Packit b2c0d9
Packit b2c0d9
    GF_ASSERT(value);
Packit b2c0d9
Packit b2c0d9
    ret = validate_list_elements(value, opt, NULL, &gf_validate_number);
Packit b2c0d9
    if (ret) {
Packit b2c0d9
        snprintf(errstr, 1024,
Packit b2c0d9
                 "option %s %s: '%s' is not a valid "
Packit b2c0d9
                 "priority-list",
Packit b2c0d9
                 key, value, value);
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_size_list(xlator_t *xl, const char *key,
Packit b2c0d9
                                 const char *value, volume_option_t *opt,
Packit b2c0d9
                                 char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
    char errstr[1024] = {
Packit b2c0d9
        0,
Packit b2c0d9
    };
Packit b2c0d9
Packit b2c0d9
    GF_ASSERT(value);
Packit b2c0d9
Packit b2c0d9
    ret = gf_validate_size(value, opt);
Packit b2c0d9
    if (ret)
Packit b2c0d9
        ret = validate_list_elements(value, opt, NULL, &gf_validate_size);
Packit b2c0d9
Packit b2c0d9
    if (ret) {
Packit b2c0d9
        snprintf(errstr, 1024,
Packit b2c0d9
                 "option %s %s: '%s' is not a valid "
Packit b2c0d9
                 "size-list",
Packit b2c0d9
                 key, value, value);
Packit b2c0d9
        *op_errstr = gf_strdup(errstr);
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_option_validate_any(xlator_t *xl, const char *key, const char *value,
Packit b2c0d9
                           volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    return 0;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
typedef int(xlator_option_validator_t)(xlator_t *xl, const char *key,
Packit b2c0d9
                                       const char *value, volume_option_t *opt,
Packit b2c0d9
                                       char **operrstr);
Packit b2c0d9
Packit b2c0d9
int
Packit b2c0d9
xlator_option_validate(xlator_t *xl, char *key, char *value,
Packit b2c0d9
                       volume_option_t *opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    xlator_option_validator_t *validate;
Packit b2c0d9
    xlator_option_validator_t *validators[] = {
Packit b2c0d9
        [GF_OPTION_TYPE_PATH] = xlator_option_validate_path,
Packit b2c0d9
        [GF_OPTION_TYPE_INT] = xlator_option_validate_int,
Packit b2c0d9
        [GF_OPTION_TYPE_SIZET] = xlator_option_validate_sizet,
Packit b2c0d9
        [GF_OPTION_TYPE_BOOL] = xlator_option_validate_bool,
Packit b2c0d9
        [GF_OPTION_TYPE_XLATOR] = xlator_option_validate_xlator,
Packit b2c0d9
        [GF_OPTION_TYPE_STR] = xlator_option_validate_str,
Packit b2c0d9
        [GF_OPTION_TYPE_PERCENT] = xlator_option_validate_percent,
Packit b2c0d9
        [GF_OPTION_TYPE_PERCENT_OR_SIZET] =
Packit b2c0d9
            xlator_option_validate_percent_or_sizet,
Packit b2c0d9
        [GF_OPTION_TYPE_TIME] = xlator_option_validate_time,
Packit b2c0d9
        [GF_OPTION_TYPE_DOUBLE] = xlator_option_validate_double,
Packit b2c0d9
        [GF_OPTION_TYPE_INTERNET_ADDRESS] = xlator_option_validate_addr,
Packit b2c0d9
        [GF_OPTION_TYPE_INTERNET_ADDRESS_LIST] =
Packit b2c0d9
            xlator_option_validate_addr_list,
Packit b2c0d9
        [GF_OPTION_TYPE_PRIORITY_LIST] = xlator_option_validate_priority_list,
Packit b2c0d9
        [GF_OPTION_TYPE_SIZE_LIST] = xlator_option_validate_size_list,
Packit b2c0d9
        [GF_OPTION_TYPE_ANY] = xlator_option_validate_any,
Packit b2c0d9
        [GF_OPTION_TYPE_CLIENT_AUTH_ADDR] = xlator_option_validate_mntauth,
Packit b2c0d9
        [GF_OPTION_TYPE_MAX] = NULL,
Packit b2c0d9
    };
Packit b2c0d9
Packit b2c0d9
    if (opt->type > GF_OPTION_TYPE_MAX) {
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY,
Packit b2c0d9
               "unknown option type '%d'", opt->type);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    validate = validators[opt->type];
Packit b2c0d9
Packit b2c0d9
    ret = validate(xl, key, value, opt, op_errstr);
Packit b2c0d9
out:
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
volume_option_t *
Packit b2c0d9
xlator_volume_option_get_list(volume_opt_list_t *vol_list, const char *key)
Packit b2c0d9
{
Packit b2c0d9
    volume_option_t *opt = NULL;
Packit b2c0d9
    volume_opt_list_t *opt_list = NULL;
Packit b2c0d9
    volume_option_t *found = NULL;
Packit b2c0d9
    int index = 0;
Packit b2c0d9
    int i = 0;
Packit b2c0d9
    char *cmp_key = NULL;
Packit b2c0d9
Packit b2c0d9
    if (!vol_list->given_opt) {
Packit b2c0d9
        opt_list = list_entry(vol_list->list.next, volume_opt_list_t, list);
Packit b2c0d9
        opt = opt_list->given_opt;
Packit b2c0d9
    } else
Packit b2c0d9
        opt = vol_list->given_opt;
Packit b2c0d9
Packit b2c0d9
    for (index = 0; opt[index].key[0]; index++) {
Packit b2c0d9
        for (i = 0; i < ZR_VOLUME_MAX_NUM_KEY; i++) {
Packit b2c0d9
            cmp_key = opt[index].key[i];
Packit b2c0d9
            if (!cmp_key)
Packit b2c0d9
                break;
Packit b2c0d9
            if (fnmatch(cmp_key, key, FNM_NOESCAPE) == 0) {
Packit b2c0d9
                found = &opt[index];
Packit b2c0d9
                goto out;
Packit b2c0d9
            }
Packit b2c0d9
        }
Packit b2c0d9
    }
Packit b2c0d9
out:
Packit b2c0d9
    return found;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
volume_option_t *
Packit b2c0d9
xlator_volume_option_get(xlator_t *xl, const char *key)
Packit b2c0d9
{
Packit b2c0d9
    volume_opt_list_t *vol_list = NULL;
Packit b2c0d9
    volume_option_t *found = NULL;
Packit b2c0d9
Packit b2c0d9
    list_for_each_entry(vol_list, &xl->volume_options, list)
Packit b2c0d9
    {
Packit b2c0d9
        found = xlator_volume_option_get_list(vol_list, key);
Packit b2c0d9
        if (found)
Packit b2c0d9
            break;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    return found;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xl_opt_validate(dict_t *dict, char *key, data_t *value, void *data)
Packit b2c0d9
{
Packit b2c0d9
    xlator_t *xl = NULL;
Packit b2c0d9
    volume_opt_list_t *vol_opt = NULL;
Packit b2c0d9
    volume_option_t *opt = NULL;
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
    char *errstr = NULL;
Packit b2c0d9
Packit b2c0d9
    struct {
Packit b2c0d9
        xlator_t *this;
Packit b2c0d9
        volume_opt_list_t *vol_opt;
Packit b2c0d9
        char *errstr;
Packit b2c0d9
    } * stub;
Packit b2c0d9
Packit b2c0d9
    stub = data;
Packit b2c0d9
    xl = stub->this;
Packit b2c0d9
    vol_opt = stub->vol_opt;
Packit b2c0d9
Packit b2c0d9
    opt = xlator_volume_option_get_list(vol_opt, key);
Packit b2c0d9
    if (!opt)
Packit b2c0d9
        return 0;
Packit b2c0d9
Packit b2c0d9
    ret = xlator_option_validate(xl, key, value->data, opt, &errstr);
Packit b2c0d9
    if (ret)
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_WARNING, 0, LG_MSG_VALIDATE_RETURNS,
Packit b2c0d9
               "validate of %s returned %d", key, ret);
Packit b2c0d9
Packit b2c0d9
    if (errstr)
Packit b2c0d9
        /* possible small leak of previously set stub->errstr */
Packit b2c0d9
        stub->errstr = errstr;
Packit b2c0d9
Packit b2c0d9
    if (fnmatch(opt->key[0], key, FNM_NOESCAPE) != 0) {
Packit b2c0d9
        gf_msg(xl->name, GF_LOG_DEBUG, 0, LG_MSG_INVALID_ENTRY,
Packit b2c0d9
               "option '%s' is deprecated, preferred is '%s', "
Packit b2c0d9
               "continuing with correction",
Packit b2c0d9
               key, opt->key[0]);
Packit b2c0d9
        dict_set(dict, opt->key[0], value);
Packit b2c0d9
        dict_del(dict, key);
Packit b2c0d9
    }
Packit b2c0d9
    return 0;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
int
Packit b2c0d9
xlator_options_validate_list(xlator_t *xl, dict_t *options,
Packit b2c0d9
                             volume_opt_list_t *vol_opt, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
    struct {
Packit b2c0d9
        xlator_t *this;
Packit b2c0d9
        volume_opt_list_t *vol_opt;
Packit b2c0d9
        char *errstr;
Packit b2c0d9
    } stub;
Packit b2c0d9
Packit b2c0d9
    stub.this = xl;
Packit b2c0d9
    stub.vol_opt = vol_opt;
Packit b2c0d9
    stub.errstr = NULL;
Packit b2c0d9
Packit b2c0d9
    dict_foreach(options, xl_opt_validate, &stub);
Packit b2c0d9
    if (stub.errstr) {
Packit b2c0d9
        ret = -1;
Packit b2c0d9
        if (op_errstr)
Packit b2c0d9
            *op_errstr = stub.errstr;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
int
Packit b2c0d9
xlator_options_validate(xlator_t *xl, dict_t *options, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
    volume_opt_list_t *vol_opt = NULL;
Packit b2c0d9
Packit b2c0d9
    if (!xl) {
Packit b2c0d9
        gf_msg_debug(THIS->name, 0, "'this' not a valid ptr");
Packit b2c0d9
        ret = -1;
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if (list_empty(&xl->volume_options))
Packit b2c0d9
        goto out;
Packit b2c0d9
Packit b2c0d9
    list_for_each_entry(vol_opt, &xl->volume_options, list)
Packit b2c0d9
    {
Packit b2c0d9
        ret = xlator_options_validate_list(xl, options, vol_opt, op_errstr);
Packit b2c0d9
    }
Packit b2c0d9
out:
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
int
Packit b2c0d9
xlator_validate_rec(xlator_t *xlator, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    xlator_list_t *trav = NULL;
Packit b2c0d9
    xlator_t *old_THIS = NULL;
Packit b2c0d9
Packit b2c0d9
    GF_VALIDATE_OR_GOTO("xlator", xlator, out);
Packit b2c0d9
Packit b2c0d9
    trav = xlator->children;
Packit b2c0d9
Packit b2c0d9
    while (trav) {
Packit b2c0d9
        if (xlator_validate_rec(trav->xlator, op_errstr)) {
Packit b2c0d9
            gf_msg("xlator", GF_LOG_WARNING, 0, LG_MSG_VALIDATE_REC_FAILED,
Packit b2c0d9
                   "validate_rec "
Packit b2c0d9
                   "failed");
Packit b2c0d9
            goto out;
Packit b2c0d9
        }
Packit b2c0d9
Packit b2c0d9
        trav = trav->next;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if (xlator_dynload(xlator))
Packit b2c0d9
        gf_msg_debug(xlator->name, 0, "Did not load the symbols");
Packit b2c0d9
Packit b2c0d9
    old_THIS = THIS;
Packit b2c0d9
    THIS = xlator;
Packit b2c0d9
Packit b2c0d9
    /* Need this here, as this graph has not yet called init() */
Packit b2c0d9
    if (!xlator->mem_acct) {
Packit b2c0d9
        if (!xlator->mem_acct_init)
Packit b2c0d9
            xlator->mem_acct_init = default_mem_acct_init;
Packit b2c0d9
        xlator->mem_acct_init(xlator);
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = xlator_options_validate(xlator, xlator->options, op_errstr);
Packit b2c0d9
    THIS = old_THIS;
Packit b2c0d9
Packit b2c0d9
    if (ret) {
Packit b2c0d9
        gf_msg(xlator->name, GF_LOG_INFO, 0, LG_MSG_INVALID_ENTRY, "%s",
Packit b2c0d9
               *op_errstr);
Packit b2c0d9
        goto out;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    gf_msg_debug(xlator->name, 0, "Validated options");
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
int
Packit b2c0d9
graph_reconf_validateopt(glusterfs_graph_t *graph, char **op_errstr)
Packit b2c0d9
{
Packit b2c0d9
    xlator_t *xlator = NULL;
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
Packit b2c0d9
    GF_ASSERT(graph);
Packit b2c0d9
Packit b2c0d9
    xlator = graph->first;
Packit b2c0d9
Packit b2c0d9
    ret = xlator_validate_rec(xlator, op_errstr);
Packit b2c0d9
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xlator_reconfigure_rec(xlator_t *old_xl, xlator_t *new_xl)
Packit b2c0d9
{
Packit b2c0d9
    xlator_list_t *trav1 = NULL;
Packit b2c0d9
    xlator_list_t *trav2 = NULL;
Packit b2c0d9
    int32_t ret = -1;
Packit b2c0d9
    xlator_t *old_THIS = NULL;
Packit b2c0d9
Packit b2c0d9
    GF_VALIDATE_OR_GOTO("xlator", old_xl, out);
Packit b2c0d9
    GF_VALIDATE_OR_GOTO("xlator", new_xl, out);
Packit b2c0d9
Packit b2c0d9
    trav1 = old_xl->children;
Packit b2c0d9
    trav2 = new_xl->children;
Packit b2c0d9
Packit b2c0d9
    while (trav1 && trav2) {
Packit b2c0d9
        ret = xlator_reconfigure_rec(trav1->xlator, trav2->xlator);
Packit b2c0d9
        if (ret)
Packit b2c0d9
            goto out;
Packit b2c0d9
Packit b2c0d9
        gf_msg_debug(trav1->xlator->name, 0, "reconfigured");
Packit b2c0d9
Packit b2c0d9
        trav1 = trav1->next;
Packit b2c0d9
        trav2 = trav2->next;
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    if (old_xl->reconfigure) {
Packit b2c0d9
        old_THIS = THIS;
Packit b2c0d9
        THIS = old_xl;
Packit b2c0d9
Packit b2c0d9
        xlator_init_lock();
Packit b2c0d9
        handle_default_options(old_xl, new_xl->options);
Packit b2c0d9
        ret = old_xl->reconfigure(old_xl, new_xl->options);
Packit b2c0d9
        xlator_init_unlock();
Packit b2c0d9
Packit b2c0d9
        THIS = old_THIS;
Packit b2c0d9
Packit b2c0d9
        if (ret)
Packit b2c0d9
            goto out;
Packit b2c0d9
    } else {
Packit b2c0d9
        gf_msg_debug(old_xl->name, 0, "No reconfigure() found");
Packit b2c0d9
    }
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
int
Packit b2c0d9
xlator_tree_reconfigure(xlator_t *old_xl, xlator_t *new_xl)
Packit b2c0d9
{
Packit b2c0d9
    xlator_t *new_top = NULL;
Packit b2c0d9
    xlator_t *old_top = NULL;
Packit b2c0d9
Packit b2c0d9
    GF_ASSERT(old_xl);
Packit b2c0d9
    GF_ASSERT(new_xl);
Packit b2c0d9
Packit b2c0d9
    old_top = old_xl;
Packit b2c0d9
    new_top = new_xl;
Packit b2c0d9
Packit b2c0d9
    return xlator_reconfigure_rec(old_top, new_top);
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
int
Packit b2c0d9
xlator_option_info_list(volume_opt_list_t *list, char *key, char **def_val,
Packit b2c0d9
                        char **descr)
Packit b2c0d9
{
Packit b2c0d9
    int ret = -1;
Packit b2c0d9
    volume_option_t *opt = NULL;
Packit b2c0d9
Packit b2c0d9
    opt = xlator_volume_option_get_list(list, key);
Packit b2c0d9
    if (!opt)
Packit b2c0d9
        goto out;
Packit b2c0d9
Packit b2c0d9
    if (def_val)
Packit b2c0d9
        *def_val = opt->default_value;
Packit b2c0d9
    if (descr)
Packit b2c0d9
        *descr = opt->description;
Packit b2c0d9
Packit b2c0d9
    ret = 0;
Packit b2c0d9
out:
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
pass(char *in, char **out)
Packit b2c0d9
{
Packit b2c0d9
    *out = in;
Packit b2c0d9
    return 0;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
xl_by_name(char *in, xlator_t **out)
Packit b2c0d9
{
Packit b2c0d9
    xlator_t *xl = NULL;
Packit b2c0d9
Packit b2c0d9
    xl = xlator_search_by_name(THIS, in);
Packit b2c0d9
Packit b2c0d9
    if (!xl)
Packit b2c0d9
        return -1;
Packit b2c0d9
    *out = xl;
Packit b2c0d9
    return 0;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
static int
Packit b2c0d9
pc_or_size(char *in, double *out)
Packit b2c0d9
{
Packit b2c0d9
    double pc = 0;
Packit b2c0d9
    int ret = 0;
Packit b2c0d9
    uint64_t size = 0;
Packit b2c0d9
Packit b2c0d9
    if (gf_string2percent(in, &pc) == 0) {
Packit b2c0d9
        if (pc > 100.0) {
Packit b2c0d9
            ret = gf_string2bytesize_uint64(in, &size);
Packit b2c0d9
            if (!ret)
Packit b2c0d9
                *out = size;
Packit b2c0d9
        } else {
Packit b2c0d9
            *out = pc;
Packit b2c0d9
        }
Packit b2c0d9
    } else {
Packit b2c0d9
        ret = gf_string2bytesize_uint64(in, &size);
Packit b2c0d9
        if (!ret)
Packit b2c0d9
            *out = size;
Packit b2c0d9
    }
Packit b2c0d9
    return ret;
Packit b2c0d9
}
Packit b2c0d9
Packit b2c0d9
DEFINE_INIT_OPT(char *, str, pass);
Packit b2c0d9
DEFINE_INIT_OPT(uint64_t, uint64, gf_string2uint64);
Packit b2c0d9
DEFINE_INIT_OPT(int64_t, int64, gf_string2int64);
Packit b2c0d9
DEFINE_INIT_OPT(uint32_t, uint32, gf_string2uint32);
Packit b2c0d9
DEFINE_INIT_OPT(int32_t, int32, gf_string2int32);
Packit b2c0d9
DEFINE_INIT_OPT(uint64_t, size, gf_string2bytesize_uint64);
Packit b2c0d9
DEFINE_INIT_OPT(uint64_t, size_uint64, gf_string2bytesize_uint64);
Packit b2c0d9
DEFINE_INIT_OPT(double, percent, gf_string2percent);
Packit b2c0d9
DEFINE_INIT_OPT(double, percent_or_size, pc_or_size);
Packit b2c0d9
DEFINE_INIT_OPT(gf_boolean_t, bool, gf_string2boolean);
Packit b2c0d9
DEFINE_INIT_OPT(xlator_t *, xlator, xl_by_name);
Packit b2c0d9
DEFINE_INIT_OPT(char *, path, pass);
Packit b2c0d9
DEFINE_INIT_OPT(double, double, gf_string2double);
Packit b2c0d9
DEFINE_INIT_OPT(uint32_t, time, gf_string2time);
Packit b2c0d9
Packit b2c0d9
DEFINE_RECONF_OPT(char *, str, pass);
Packit b2c0d9
DEFINE_RECONF_OPT(uint64_t, uint64, gf_string2uint64);
Packit b2c0d9
DEFINE_RECONF_OPT(int64_t, int64, gf_string2int64);
Packit b2c0d9
DEFINE_RECONF_OPT(uint32_t, uint32, gf_string2uint32);
Packit b2c0d9
DEFINE_RECONF_OPT(int32_t, int32, gf_string2int32);
Packit b2c0d9
DEFINE_RECONF_OPT(uint64_t, size, gf_string2bytesize_uint64);
Packit b2c0d9
DEFINE_RECONF_OPT(uint64_t, size_uint64, gf_string2bytesize_uint64);
Packit b2c0d9
DEFINE_RECONF_OPT(double, percent, gf_string2percent);
Packit b2c0d9
DEFINE_RECONF_OPT(double, percent_or_size, pc_or_size);
Packit b2c0d9
DEFINE_RECONF_OPT(gf_boolean_t, bool, gf_string2boolean);
Packit b2c0d9
DEFINE_RECONF_OPT(xlator_t *, xlator, xl_by_name);
Packit b2c0d9
DEFINE_RECONF_OPT(char *, path, pass);
Packit b2c0d9
DEFINE_RECONF_OPT(double, double, gf_string2double);
Packit b2c0d9
DEFINE_RECONF_OPT(uint32_t, time, gf_string2time);