diff options
Diffstat (limited to 'xlators/debug/error-gen/src/error-gen.c')
| -rw-r--r-- | xlators/debug/error-gen/src/error-gen.c | 260 |
1 files changed, 171 insertions, 89 deletions
diff --git a/xlators/debug/error-gen/src/error-gen.c b/xlators/debug/error-gen/src/error-gen.c index 6ecca2ee5..ec0874b35 100644 --- a/xlators/debug/error-gen/src/error-gen.c +++ b/xlators/debug/error-gen/src/error-gen.c @@ -1,22 +1,12 @@ /* - Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.com> - This file is part of GlusterFS. - - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ #ifndef _CONFIG_H #define _CONFIG_H #include "config.h" @@ -24,6 +14,7 @@ #include "xlator.h" #include "error-gen.h" +#include "statedump.h" sys_error_t error_no_list[] = { [GF_FOP_LOOKUP] = { .error_no_count = 4, @@ -91,9 +82,10 @@ sys_error_t error_no_list[] = { [GF_FOP_READ] = { .error_no_count = 5, .error_no = {EINVAL,EBADF,EFAULT,EISDIR, ENAMETOOLONG}}, - [GF_FOP_WRITE] = { .error_no_count = 5, + [GF_FOP_WRITE] = { .error_no_count = 7, .error_no = {EINVAL,EBADF,EFAULT,EISDIR, - ENAMETOOLONG}}, + ENAMETOOLONG,ENOSPC, + GF_ERROR_SHORT_WRITE}}, [GF_FOP_STATFS] = {.error_no_count = 10, .error_no = {EACCES,EBADF,EFAULT,EINTR, EIO,ENAMETOOLONG,ENOENT, @@ -246,6 +238,8 @@ conv_errno_to_int (char **error_no) return EINTR; else if (!strcmp ((*error_no), "EFBIG")) return EFBIG; + else if (!strcmp((*error_no), "GF_ERROR_SHORT_WRITE")) + return GF_ERROR_SHORT_WRITE; else return EAGAIN; } @@ -1114,10 +1108,26 @@ error_gen_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, if (enable) op_errno = error_gen (this, GF_FOP_WRITE); - if (op_errno) { + if (op_errno == GF_ERROR_SHORT_WRITE) { + struct iovec *shortvec; + + /* + * A short write error returns some value less than what was + * requested from a write. To simulate this, replace the vector + * with one half the size; + */ + shortvec = iov_dup(vector, 1); + shortvec->iov_len /= 2; + + STACK_WIND(frame, error_gen_writev_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->writev, fd, shortvec, count, + off, flags, iobref, xdata); + GF_FREE(shortvec); + return 0; + } else if (op_errno) { GF_ERROR(this, "unwind(-1, %s)", strerror (op_errno)); STACK_UNWIND_STRICT (writev, frame, -1, op_errno, NULL, NULL, xdata); - return 0; + return 0; } STACK_WIND (frame, error_gen_writev_cbk, @@ -1944,6 +1954,85 @@ error_gen_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, return 0; } +static void +error_gen_set_failure (eg_t *pvt, int percent) +{ + GF_ASSERT (pvt); + + if (percent) + pvt->failure_iter_no = 100/percent; + else + pvt->failure_iter_no = 100/GF_FAILURE_DEFAULT; +} + +static void +error_gen_parse_fill_fops (eg_t *pvt, char *enable_fops) +{ + char *op_no_str = NULL; + int op_no = -1; + int i = 0; + xlator_t *this = THIS; + char *saveptr = NULL; + + GF_ASSERT (pvt); + GF_ASSERT (this); + + for (i = 0; i < GF_FOP_MAXVALUE; i++) + pvt->enable[i] = 0; + + if (!enable_fops) { + gf_log (this->name, GF_LOG_WARNING, + "All fops are enabled."); + for (i = 0; i < GF_FOP_MAXVALUE; i++) + pvt->enable[i] = 1; + } else { + op_no_str = strtok_r (enable_fops, ",", &saveptr); + while (op_no_str) { + op_no = get_fop_int (&op_no_str); + if (op_no == -1) { + gf_log (this->name, GF_LOG_WARNING, + "Wrong option value %s", op_no_str); + } else + pvt->enable[op_no] = 1; + + op_no_str = strtok_r (NULL, ",", &saveptr); + } + } +} + +int32_t +error_gen_priv_dump (xlator_t *this) +{ + char key_prefix[GF_DUMP_MAX_BUF_LEN]; + int ret = -1; + eg_t *conf = NULL; + + if (!this) + goto out; + + conf = this->private; + if (!conf) + goto out; + + ret = TRY_LOCK(&conf->lock); + if (ret != 0) { + return ret; + } + + gf_proc_dump_add_section("xlator.debug.error-gen.%s.priv", this->name); + gf_proc_dump_build_key(key_prefix,"xlator.debug.error-gen","%s.priv", + this->name); + + gf_proc_dump_write("op_count", "%d", conf->op_count); + gf_proc_dump_write("failure_iter_no", "%d", conf->failure_iter_no); + gf_proc_dump_write("error_no", "%s", conf->error_no); + gf_proc_dump_write("random_failure", "%d", conf->random_failure); + + UNLOCK(&conf->lock); +out: + return ret; +} + int32_t mem_acct_init (xlator_t *this) { @@ -1964,18 +2053,43 @@ mem_acct_init (xlator_t *this) } int +reconfigure (xlator_t *this, dict_t *options) +{ + eg_t *pvt = NULL; + int32_t ret = 0; + char *error_enable_fops = NULL; + int32_t failure_percent_int = 0; + + if (!this || !this->private) + goto out; + + pvt = this->private; + + GF_OPTION_RECONF ("error-no", pvt->error_no, options, str, out); + + GF_OPTION_RECONF ("failure", failure_percent_int, options, int32, + out); + + GF_OPTION_RECONF ("enable", error_enable_fops, options, str, out); + + GF_OPTION_RECONF ("random-failure", pvt->random_failure, options, + bool, out); + + error_gen_parse_fill_fops (pvt, error_enable_fops); + error_gen_set_failure (pvt, failure_percent_int); + + ret = 0; +out: + gf_log (this->name, GF_LOG_DEBUG, "reconfigure returning %d", ret); + return ret; +} + +int init (xlator_t *this) { eg_t *pvt = NULL; - data_t *error_no = NULL; - data_t *failure_percent = NULL; - data_t *enable = NULL; - gf_boolean_t random_failure = _gf_false; int32_t ret = 0; char *error_enable_fops = NULL; - char *op_no_str = NULL; - int op_no = -1; - int i = 0; int32_t failure_percent_int = 0; if (!this->children || this->children->next) { @@ -1990,79 +2104,34 @@ init (xlator_t *this) "dangling volume. check volfile "); } - error_no = dict_get (this->options, "error-no"); - failure_percent = dict_get (this->options, "failure"); - enable = dict_get (this->options, "enable"); - pvt = GF_CALLOC (1, sizeof (eg_t), gf_error_gen_mt_eg_t); if (!pvt) { - gf_log (this->name, GF_LOG_ERROR, - "out of memory."); ret = -1; goto out; } LOCK_INIT (&pvt->lock); - for (i = 0; i < GF_FOP_MAXVALUE; i++) - pvt->enable[i] = 0; - if (!error_no) { - gf_log (this->name, GF_LOG_DEBUG, - "error-no not specified."); - } else { - pvt->error_no = data_to_str (error_no); - } + GF_OPTION_INIT ("error-no", pvt->error_no, str, out); - if (!failure_percent) { - gf_log (this->name, GF_LOG_DEBUG, - "failure percent not specified."); - pvt->failure_iter_no = 100/GF_FAILURE_DEFAULT; - } else { - failure_percent_int = data_to_int32 (failure_percent); - if (failure_percent_int) - pvt->failure_iter_no = 100/failure_percent_int; - else - pvt->failure_iter_no = 100/GF_FAILURE_DEFAULT; - } + GF_OPTION_INIT ("failure", failure_percent_int, int32, out); - if (!enable) { - gf_log (this->name, GF_LOG_WARNING, - "All fops are enabled."); - for (i = 0; i < GF_FOP_MAXVALUE; i++) - pvt->enable[i] = 1; - } else { - error_enable_fops = data_to_str (enable); - op_no_str = error_enable_fops; - while ((*error_enable_fops) != '\0') { - error_enable_fops++; - if (((*error_enable_fops) == ',') || - ((*error_enable_fops) == '\0')) { - if ((*error_enable_fops) != '\0') { - (*error_enable_fops) = '\0'; - error_enable_fops++; - } - op_no = get_fop_int (&op_no_str); - if (op_no == -1) { - gf_log (this->name, GF_LOG_WARNING, - "Wrong option value %s", - op_no_str); - } else - pvt->enable[op_no] = 1; - op_no_str = error_enable_fops; - } - } - } + GF_OPTION_INIT ("enable", error_enable_fops, str, out); - random_failure = dict_get_str_boolean (this->options, "random-failure", - _gf_false); - pvt->random_failure = random_failure; + GF_OPTION_INIT ("random-failure", pvt->random_failure, bool, out); + + + error_gen_parse_fill_fops (pvt, error_enable_fops); + error_gen_set_failure (pvt, failure_percent_int); this->private = pvt; /* Give some seed value here */ srand (time(NULL)); out: + if (ret) + GF_FREE (pvt); return ret; } @@ -2084,9 +2153,12 @@ fini (xlator_t *this) return; } -struct xlator_fops cbks = { +struct xlator_dumpops dumpops = { + .priv = error_gen_priv_dump, }; +struct xlator_fops cbks; + struct xlator_fops fops = { .lookup = error_gen_lookup, .stat = error_gen_stat, @@ -2134,17 +2206,27 @@ struct xlator_fops fops = { struct volume_options options[] = { { .key = {"failure"}, - .type = GF_OPTION_TYPE_INT }, + .type = GF_OPTION_TYPE_INT, + .description = "Percentage failure of operations when enabled.", + }, + { .key = {"error-no"}, .value = {"ENOENT","ENOTDIR","ENAMETOOLONG","EACCES","EBADF", "EFAULT","ENOMEM","EINVAL","EIO","EEXIST","ENOSPC", "EPERM","EROFS","EBUSY","EISDIR","ENOTEMPTY","EMLINK" "ENODEV","EXDEV","EMFILE","ENFILE","ENOSYS","EINTR", - "EFBIG","EAGAIN"}, - .type = GF_OPTION_TYPE_STR }, + "EFBIG","EAGAIN","GF_ERROR_SHORT_WRITE"}, + .type = GF_OPTION_TYPE_STR, + }, + { .key = {"random-failure"}, - .type = GF_OPTION_TYPE_BOOL}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + }, + { .key = {"enable"}, - .type = GF_OPTION_TYPE_STR }, + .type = GF_OPTION_TYPE_STR, + }, + { .key = {NULL} } }; |
