bdev/error: Add new bdev/error to inject errors in bdev layer.
Change-Id: I3c68cb5911b3662dbb35f551dc291d5ebdd84bf6 Signed-off-by: Cunyin Chang <cunyin.chang@intel.com>
This commit is contained in:
parent
679e2831bd
commit
32b4ab71a2
@ -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
|
||||
|
41
lib/bdev/error/Makefile
Normal file
41
lib/bdev/error/Makefile
Normal file
@ -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
|
285
lib/bdev/error/vbdev_error.c
Normal file
285
lib/bdev/error/vbdev_error.c
Normal file
@ -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)
|
43
lib/bdev/error/vbdev_error.h
Normal file
43
lib/bdev/error/vbdev_error.h
Normal file
@ -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
|
178
lib/bdev/error/vbdev_error_rpc.c
Normal file
178
lib/bdev/error/vbdev_error_rpc.c
Normal file
@ -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)
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user