diff --git a/lib/bdev/Makefile b/lib/bdev/Makefile index d872b7e7d..4e93af215 100644 --- a/lib/bdev/Makefile +++ b/lib/bdev/Makefile @@ -38,7 +38,7 @@ CFLAGS += $(ENV_CFLAGS) -I. C_SRCS = bdev.c scsi_nvme.c LIBNAME = bdev -DIRS-y += malloc null nvme rpc split +DIRS-y += error malloc null nvme rpc split ifeq ($(OS),Linux) DIRS-y += aio diff --git a/lib/bdev/error/Makefile b/lib/bdev/error/Makefile new file mode 100644 index 000000000..a4eee5986 --- /dev/null +++ b/lib/bdev/error/Makefile @@ -0,0 +1,41 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..) +include $(SPDK_ROOT_DIR)/mk/spdk.common.mk + +CFLAGS += $(ENV_CFLAGS) -I$(SPDK_ROOT_DIR)/lib/bdev/ +C_SRCS = vbdev_error.c vbdev_error_rpc.c +LIBNAME = vbdev_error + +include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk diff --git a/lib/bdev/error/vbdev_error.c b/lib/bdev/error/vbdev_error.c new file mode 100644 index 000000000..aa03e037f --- /dev/null +++ b/lib/bdev/error/vbdev_error.c @@ -0,0 +1,285 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This is a module for test purpose which will simulate error cases for bdev. + */ + +#include "spdk/stdinc.h" +#include "spdk/rpc.h" +#include "spdk/conf.h" +#include "spdk/endian.h" +#include "spdk/nvme_spec.h" + +#include "spdk_internal/bdev.h" +#include "spdk_internal/log.h" + +#include "vbdev_error.h" + +/* Context for each error bdev */ +struct vbdev_error_disk { + struct spdk_bdev disk; + struct spdk_bdev *base_bdev; + TAILQ_ENTRY(vbdev_error_disk) tailq; +}; + +static uint32_t g_io_type_mask; +static uint32_t g_error_num; +static pthread_mutex_t g_vbdev_error_mutex = PTHREAD_MUTEX_INITIALIZER; +static TAILQ_HEAD(, vbdev_error_disk) g_vbdev_error_disks = TAILQ_HEAD_INITIALIZER( + g_vbdev_error_disks); + +void +spdk_vbdev_inject_error(uint32_t io_type_mask, uint32_t error_num) +{ + pthread_mutex_lock(&g_vbdev_error_mutex); + g_io_type_mask = io_type_mask; + g_error_num = error_num; + pthread_mutex_unlock(&g_vbdev_error_mutex); +} + +static void +vbdev_error_task_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status, + void *cb_arg) +{ + struct spdk_bdev_io *bdevio = (struct spdk_bdev_io *)cb_arg; + struct spdk_bdev_io *parent = bdevio->parent; + + spdk_bdev_io_complete(parent, SPDK_BDEV_IO_STATUS_FAILED); +} + +static void +vbdev_error_reset(struct vbdev_error_disk *error_disk, struct spdk_bdev_io *bdev_io) +{ + /* + * pass the I/O through unmodified. + * + * However, we do need to increment the generation count for the error bdev, + * since the spdk_bdev_io_complete() path that normally updates it will not execute + * after we resubmit the I/O to the base_bdev. + */ + if (bdev_io->u.reset.type == SPDK_BDEV_RESET_HARD) { + error_disk->disk.gencnt++; + } +} + +static void +vbdev_error_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) +{ + struct vbdev_error_disk *error_disk = bdev_io->bdev->ctxt; + uint32_t io_type_mask; + struct spdk_bdev_io *child; + + switch (bdev_io->type) { + case SPDK_BDEV_IO_TYPE_READ: + case SPDK_BDEV_IO_TYPE_WRITE: + case SPDK_BDEV_IO_TYPE_UNMAP: + case SPDK_BDEV_IO_TYPE_FLUSH: + break; + case SPDK_BDEV_IO_TYPE_RESET: + vbdev_error_reset(error_disk, bdev_io); + break; + default: + SPDK_ERRLOG("Error Injection: unknown I/O type %d\n", bdev_io->type); + spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); + return; + } + + io_type_mask = 1U << bdev_io->type; + + if (g_error_num == 0 || !(g_io_type_mask & io_type_mask)) { + spdk_bdev_io_resubmit(bdev_io, error_disk->base_bdev); + return; + } + + pthread_mutex_lock(&g_vbdev_error_mutex); + /* check again to make sure g_error_num has not been decremented since we checked it above */ + if (g_error_num == 0) { + spdk_bdev_io_resubmit(bdev_io, error_disk->base_bdev); + } else { + g_error_num--; + child = spdk_bdev_get_child_io(bdev_io, &error_disk->disk, vbdev_error_task_complete, NULL); + child->ch = bdev_io->ch; + spdk_bdev_io_resubmit(child, error_disk->base_bdev); + } + pthread_mutex_unlock(&g_vbdev_error_mutex); +} + +static void +vbdev_error_free(struct vbdev_error_disk *error_disk) +{ + if (!error_disk) { + return; + } + + TAILQ_REMOVE(&g_vbdev_error_disks, error_disk, tailq); + + spdk_bdev_unclaim(error_disk->base_bdev); + free(error_disk); +} + +static int +vbdev_error_destruct(void *ctx) +{ + struct vbdev_error_disk *error_disk = ctx; + + vbdev_error_free(error_disk); + return 0; +} + +static bool +vbdev_error_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type) +{ + struct vbdev_error_disk *error_disk = ctx; + + return error_disk->base_bdev->fn_table->io_type_supported(error_disk->base_bdev, + io_type); +} + +static struct spdk_io_channel * +vbdev_error_get_io_channel(void *ctx, uint32_t priority) +{ + struct vbdev_error_disk *error_disk = ctx; + + return error_disk->base_bdev->fn_table->get_io_channel(error_disk->base_bdev, + priority); +} + +static int +vbdev_error_dump_config_json(void *ctx, struct spdk_json_write_ctx *w) +{ + struct vbdev_error_disk *error_disk = ctx; + + spdk_json_write_name(w, "error_disk"); + spdk_json_write_object_begin(w); + + spdk_json_write_name(w, "base_bdev"); + spdk_json_write_string(w, error_disk->base_bdev->name); + + spdk_json_write_object_end(w); + + return 0; +} + +static struct spdk_bdev_fn_table vbdev_error_fn_table = { + .destruct = vbdev_error_destruct, + .io_type_supported = vbdev_error_io_type_supported, + .submit_request = vbdev_error_submit_request, + .get_io_channel = vbdev_error_get_io_channel, + .dump_config_json = vbdev_error_dump_config_json, +}; + +int +spdk_vbdev_error_create(struct spdk_bdev *base_bdev) +{ + struct vbdev_error_disk *disk; + int rc; + + if (!spdk_bdev_claim(base_bdev, NULL, NULL)) { + SPDK_ERRLOG("Error bdev %s is already claimed\n", base_bdev->name); + return -1; + } + + disk = calloc(1, sizeof(*disk)); + if (!disk) { + SPDK_ERRLOG("Memory allocation failure\n"); + rc = -1; + goto cleanup; + } + + disk->base_bdev = base_bdev; + memcpy(&disk->disk, base_bdev, sizeof(*base_bdev)); + snprintf(disk->disk.name, sizeof(disk->disk.name), "EE_%s", base_bdev->name); + snprintf(disk->disk.product_name, sizeof(disk->disk.product_name), "Error Injection Disk"); + disk->disk.ctxt = disk; + disk->disk.fn_table = &vbdev_error_fn_table; + + spdk_bdev_register(&disk->disk); + + TAILQ_INSERT_TAIL(&g_vbdev_error_disks, disk, tailq); + + rc = 0; + return rc; +cleanup: + free(disk); + return rc; +} + +static int +vbdev_error_init(void) +{ + struct spdk_conf_section *sp; + const char *base_bdev_name; + int i; + struct spdk_bdev *base_bdev; + + sp = spdk_conf_find_section(NULL, "BdevError"); + if (sp == NULL) { + return 0; + } + + for (i = 0; ; i++) { + if (!spdk_conf_section_get_nval(sp, "BdevError", i)) { + break; + } + + base_bdev_name = spdk_conf_section_get_nmval(sp, "BdevError", i, 0); + if (!base_bdev_name) { + SPDK_ERRLOG("ErrorInjection configuration missing blockdev name\n"); + return -1; + } + + base_bdev = spdk_bdev_get_by_name(base_bdev_name); + if (!base_bdev) { + SPDK_ERRLOG("Could not find ErrorInjection bdev %s\n", base_bdev_name); + return -1; + } + + if (spdk_vbdev_error_create(base_bdev)) { + return -1; + } + } + return 0; +} + +static void +vbdev_error_fini(void) +{ + struct vbdev_error_disk *error_disk, *tmp; + + TAILQ_FOREACH_SAFE(error_disk, &g_vbdev_error_disks, tailq, tmp) { + vbdev_error_free(error_disk); + } +} + +SPDK_VBDEV_MODULE_REGISTER(vbdev_error_init, vbdev_error_fini, NULL, NULL) diff --git a/lib/bdev/error/vbdev_error.h b/lib/bdev/error/vbdev_error.h new file mode 100644 index 000000000..869dde378 --- /dev/null +++ b/lib/bdev/error/vbdev_error.h @@ -0,0 +1,43 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SPDK_BLOCKDEV_ERROR_H +#define SPDK_BLOCKDEV_ERROR_H + +#include "spdk/stdinc.h" +#include "spdk/bdev.h" + +int spdk_vbdev_error_create(struct spdk_bdev *base_bdev); +void spdk_vbdev_inject_error(uint32_t io_type_mask, uint32_t error_num); + +#endif // SPDK_BLOCKDEV_ERROR_H diff --git a/lib/bdev/error/vbdev_error_rpc.c b/lib/bdev/error/vbdev_error_rpc.c new file mode 100644 index 000000000..ddf669162 --- /dev/null +++ b/lib/bdev/error/vbdev_error_rpc.c @@ -0,0 +1,178 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" +#include "spdk/string.h" +#include "spdk/rpc.h" +#include "spdk/util.h" + +#include "spdk_internal/log.h" +#include "vbdev_error.h" + +#define ERROR_BDEV_IO_TYPE_INVALID (1U << (SPDK_BDEV_IO_TYPE_RESET + 1)) + +static uint32_t +spdk_rpc_error_bdev_io_type_parse(char *name) +{ + if (strcmp(name, "read") == 0) { + return 1U << SPDK_BDEV_IO_TYPE_READ; + } else if (strcmp(name, "write") == 0) { + return 1U << SPDK_BDEV_IO_TYPE_WRITE; + } else if (strcmp(name, "flush") == 0) { + return 1U << SPDK_BDEV_IO_TYPE_FLUSH; + } else if (strcmp(name, "unmap") == 0) { + return 1U << SPDK_BDEV_IO_TYPE_UNMAP; + } else if (strcmp(name, "reset") == 0) { + return 1U << SPDK_BDEV_IO_TYPE_RESET; + } else if (strcmp(name, "all") == 0) { + return 0xffffffff; + } else if (strcmp(name, "clear") == 0) { + return 0; + } + return ERROR_BDEV_IO_TYPE_INVALID; +} + +struct rpc_construct_error_bdev { + char *base_name; +}; + +static void +free_rpc_construct_error_bdev(struct rpc_construct_error_bdev *req) +{ + free(req->base_name); +} + +static const struct spdk_json_object_decoder rpc_construct_error_bdev_decoders[] = { + {"base_name", offsetof(struct rpc_construct_error_bdev, base_name), spdk_json_decode_string}, +}; + +static void +spdk_rpc_construct_error_bdev(struct spdk_jsonrpc_server_conn *conn, + const struct spdk_json_val *params, + const struct spdk_json_val *id) +{ + struct rpc_construct_error_bdev req = {}; + struct spdk_json_write_ctx *w; + struct spdk_bdev *base_bdev; + + if (spdk_json_decode_object(params, rpc_construct_error_bdev_decoders, + SPDK_COUNTOF(rpc_construct_error_bdev_decoders), + &req)) { + SPDK_ERRLOG("spdk_json_decode_object failed\n"); + goto invalid; + } + + base_bdev = spdk_bdev_get_by_name(req.base_name); + if (!base_bdev) { + SPDK_ERRLOG("Could not find ErrorInjection bdev %s\n", req.base_name); + goto invalid; + } + + if (spdk_vbdev_error_create(base_bdev)) { + SPDK_ERRLOG("Could not create ErrorInjection bdev %s\n", req.base_name); + goto invalid; + } + + if (id == NULL) { + free_rpc_construct_error_bdev(&req); + return; + } + + w = spdk_jsonrpc_begin_result(conn, id); + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(conn, w); + + free_rpc_construct_error_bdev(&req); + + return; + +invalid: + spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); + free_rpc_construct_error_bdev(&req); +} +SPDK_RPC_REGISTER("construct_error_bdev", spdk_rpc_construct_error_bdev) + +struct rpc_error_information { + char *type; + uint32_t num; +}; + +static const struct spdk_json_object_decoder rpc_error_information_decoders[] = { + {"type", offsetof(struct rpc_error_information, type), spdk_json_decode_string}, + {"num", offsetof(struct rpc_error_information, num), spdk_json_decode_uint32, true}, +}; + +static void +free_rpc_error_information(struct rpc_error_information *p) +{ + free(p->type); +} + +static void +spdk_rpc_bdev_inject_error(struct spdk_jsonrpc_server_conn *conn, + const struct spdk_json_val *params, + const struct spdk_json_val *id) +{ + struct rpc_error_information req = {}; + struct spdk_json_write_ctx *w; + uint32_t ret; + + if (spdk_json_decode_object(params, rpc_error_information_decoders, + SPDK_COUNTOF(rpc_error_information_decoders), + &req)) { + SPDK_ERRLOG("spdk_json_decode_object failed\n"); + goto invalid; + } + + ret = spdk_rpc_error_bdev_io_type_parse(req.type); + if (ret == ERROR_BDEV_IO_TYPE_INVALID) { + goto invalid; + } + + spdk_vbdev_inject_error(ret, req.num); + free_rpc_error_information(&req); + + if (id == NULL) { + return; + } + + w = spdk_jsonrpc_begin_result(conn, id); + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(conn, w); + return; + +invalid: + spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); + free_rpc_error_information(&req); +} +SPDK_RPC_REGISTER("bdev_inject_error", spdk_rpc_bdev_inject_error) diff --git a/mk/spdk.modules.mk b/mk/spdk.modules.mk index 59128521f..4e7114b26 100644 --- a/mk/spdk.modules.mk +++ b/mk/spdk.modules.mk @@ -31,7 +31,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -BLOCKDEV_MODULES_LIST = bdev_malloc bdev_null bdev_nvme nvme vbdev_split +BLOCKDEV_MODULES_LIST = bdev_malloc bdev_null bdev_nvme nvme vbdev_error vbdev_split ifeq ($(CONFIG_RDMA),y) BLOCKDEV_MODULES_DEPS += -libverbs -lrdmacm diff --git a/scripts/rpc.py b/scripts/rpc.py index 7673dc263..f8d0df951 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -236,6 +236,13 @@ p.add_argument('rbd_name', help='rbd image name') p.add_argument('block_size', help='rbd block size', type=int) p.set_defaults(func=construct_rbd_bdev) +def construct_error_bdev(args): + params = {'base_name': args.base_name} + jsonrpc_call('construct_error_bdev', params) +p = subparsers.add_parser('construct_error_bdev', help='Add bdev with error injection backend') +p.add_argument('base_name', help='base bdev name') +p.set_defaults(func=construct_error_bdev) + def set_trace_flag(args): params = {'flag': args.flag} jsonrpc_call('set_trace_flag', params) @@ -446,6 +453,19 @@ p = subparsers.add_parser('delete_nvmf_subsystem', help='Delete a nvmf subsystem p.add_argument('subsystem_nqn', help='subsystem nqn to be deleted. Example: nqn.2016-06.io.spdk:cnode1.') p.set_defaults(func=delete_nvmf_subsystem) +def bdev_inject_error(args): + params = { + 'type': args.type, + 'num': args.num, + } + + jsonrpc_call('bdev_inject_error', params) + +p = subparsers.add_parser('bdev_inject_error', help='bdev inject error') +p.add_argument('type', help="""type: 'clear' 'read' 'write' 'unmap' 'flush' 'reset' 'all'""") +p.add_argument('-n', '--num', help='the number of commands you want to fail', type=int, default=1) +p.set_defaults(func=bdev_inject_error) + def kill_instance(args): params = {'sig_name': args.sig_name} jsonrpc_call('kill_instance', params) diff --git a/test/iscsi_tgt/ext4test/ext4test.sh b/test/iscsi_tgt/ext4test/ext4test.sh index 34ad77847..8e22e69aa 100755 --- a/test/iscsi_tgt/ext4test/ext4test.sh +++ b/test/iscsi_tgt/ext4test/ext4test.sh @@ -47,14 +47,14 @@ echo "iscsi_tgt is listening. Running tests..." $rpc_py add_portal_group 1 $TARGET_IP:$PORT $rpc_py add_initiator_group $INITIATOR_TAG $INITIATOR_NAME $NETMASK +$rpc_py construct_error_bdev 'Malloc0' # "1:2" ==> map PortalGroup1 to InitiatorGroup2 # "64" ==> iSCSI queue depth 64 # "1 0 0 0" ==> disable CHAP authentication if [ -z "$NO_NVME" ]; then $rpc_py construct_target_node Target0 Target0_alias Nvme0n1:0 1:2 64 1 0 0 0 fi -$rpc_py construct_target_node Target1 Target1_alias Malloc0:0 1:2 64 1 0 0 0 - +$rpc_py construct_target_node Target1 Target1_alias EE_Malloc0:0 1:2 64 1 0 0 0 sleep 1 iscsiadm -m discovery -t sendtargets -p $TARGET_IP:$PORT @@ -65,9 +65,31 @@ trap 'for new_dir in `dir -d /mnt/*dir`; do umount $new_dir; rm -rf $new_dir; do sleep 1 +$rpc_py bdev_inject_error 'all' -n 1000 devs=$(iscsiadm -m session -P 3 | grep "Attached scsi disk" | awk '{print $4}') +declare -i failcount=0 +set +e +for dev in $devs; do +mkfs.ext4 -F /dev/$dev +if [ $? -eq 0 ]; then + echo "mkfs successful" +else + echo "mkfs failed" + failcount+=1 +fi +done +set -e + +if [ $failcount -eq 1 ]; then + echo "error injection success" +else + exit 1 +fi + +$rpc_py bdev_inject_error 'clear' + for dev in $devs; do mkfs.ext4 -F /dev/$dev mkdir -p /mnt/${dev}dir