Commit d13e9dde authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

bdevperf: Abort the timeout I/O



Change the I/O timeout callback to abort the timeout I/O if g_abort
is set to true. Increase the task pool twice to submit abort task
in parallel.

Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I1722f3c0ec8fc58a400b937895ad365cba7defbe
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2626


Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 3ffdff7c
Loading
Loading
Loading
Loading
+60 −1
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ struct bdevperf_task {
	void				*buf;
	void				*md_buf;
	uint64_t			offset_blocks;
	struct bdevperf_task		*task_to_abort;
	enum spdk_bdev_io_type		io_type;
	TAILQ_ENTRY(bdevperf_task)	link;
	struct spdk_bdev_io_wait_entry	bdev_io_wait;
@@ -68,6 +69,7 @@ static bool g_continue_on_failure = false;
static bool g_unmap = false;
static bool g_write_zeroes = false;
static bool g_flush = false;
static bool g_abort = false;
static int g_queue_depth = 0;
static uint64_t g_time_in_usec;
static int g_show_performance_real_time = 0;
@@ -391,6 +393,38 @@ bdevperf_job_drain(void *ctx)
	return -1;
}

static void
bdevperf_abort_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{
	struct bdevperf_task	*task = cb_arg;
	struct bdevperf_job	*job = task->job;

	job->current_queue_depth--;

	if (success) {
		job->io_completed++;
	} else {
		job->io_failed++;
		if (!g_continue_on_failure) {
			bdevperf_job_drain(job);
			g_run_rc = -1;
		}
	}

	spdk_bdev_free_io(bdev_io);

	/* Return task to free list because abort is submitted on demand. */
	TAILQ_INSERT_TAIL(&job->task_list, task, link);

	if (job->is_draining) {
		if (job->current_queue_depth == 0) {
			spdk_put_io_channel(job->ch);
			spdk_bdev_close(job->bdev_desc);
			spdk_thread_send_msg(g_master_thread, bdevperf_job_end, NULL);
		}
	}
}

static void
bdevperf_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{
@@ -623,6 +657,9 @@ bdevperf_submit_task(void *arg)
			}
		}
		break;
	case SPDK_BDEV_IO_TYPE_ABORT:
		rc = spdk_bdev_abort(desc, ch, task->task_to_abort, bdevperf_abort_complete, task);
		break;
	default:
		assert(false);
		rc = -EINVAL;
@@ -841,8 +878,24 @@ static void
bdevperf_timeout_cb(void *cb_arg, struct spdk_bdev_io *bdev_io)
{
	struct bdevperf_job *job = cb_arg;
	struct bdevperf_task *task;

	job->io_timeout++;

	if (job->is_draining || !g_abort ||
	    !spdk_bdev_io_type_supported(job->bdev, SPDK_BDEV_IO_TYPE_ABORT)) {
		return;
	}

	task = bdevperf_job_get_task(job);
	if (task == NULL) {
		return;
	}

	task->task_to_abort = spdk_bdev_io_get_cb_arg(bdev_io);
	task->io_type = SPDK_BDEV_IO_TYPE_ABORT;

	bdevperf_submit_task(task);
}

static void
@@ -1103,6 +1156,9 @@ bdevperf_construct_job(struct spdk_bdev *bdev, struct spdk_cpuset *cpumask,
	if (g_reset) {
		task_num += 1;
	}
	if (g_abort) {
		task_num += g_queue_depth;
	}

	TAILQ_INSERT_TAIL(&g_bdevperf.jobs, job, link);

@@ -1404,6 +1460,8 @@ bdevperf_parse_arg(int ch, char *arg)
		g_wait_for_tests = true;
	} else if (ch == 'x') {
		g_zcopy = false;
	} else if (ch == 'A') {
		g_abort = true;
	} else if (ch == 'C') {
		g_multithread_mode = true;
	} else if (ch == 'f') {
@@ -1467,6 +1525,7 @@ bdevperf_usage(void)
	printf(" -f                        continue processing I/O even after failures\n");
	printf(" -x                        disable using zcopy bdev API for read or write I/O\n");
	printf(" -z                        start bdevperf, but wait for RPC to start tests\n");
	printf(" -A                        abort the timeout I/O\n");
	printf(" -C                        enable every core to send I/Os to each bdev\n");
}

@@ -1626,7 +1685,7 @@ main(int argc, char **argv)
	opts.reactor_mask = NULL;
	opts.shutdown_cb = spdk_bdevperf_shutdown_cb;

	if ((rc = spdk_app_parse_args(argc, argv, &opts, "xzfq:o:t:w:k:CM:P:S:T:", NULL,
	if ((rc = spdk_app_parse_args(argc, argv, &opts, "xzfq:o:t:w:k:ACM:P:S:T:", NULL,
				      bdevperf_parse_arg, bdevperf_usage)) !=
	    SPDK_APP_PARSE_ARGS_SUCCESS) {
		return rc;