File Index
Files and directories
Sign in
FILE

fault_inject.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/ublk/fault_inject.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3/*
  4 * Fault injection ublk target. Hack this up however you like for
  5 * testing specific behaviors of ublk_drv. Currently is a null target
  6 * with a configurable delay before completing each I/O. This delay can
  7 * be used to test ublk_drv's handling of I/O outstanding to the ublk
  8 * server when it dies.
  9 */
 10
 11#include "kublk.h"
 12
 13static int ublk_fault_inject_tgt_init(const struct dev_ctx *ctx,
 14				      struct ublk_dev *dev)
 15{
 16	const struct ublksrv_ctrl_dev_info *info = &dev->dev_info;
 17	unsigned long dev_size = 250UL << 30;
 18
 19	if (ctx->auto_zc_fallback) {
 20		ublk_err("%s: not support auto_zc_fallback\n", __func__);
 21		return -EINVAL;
 22	}
 23
 24	dev->tgt.dev_size = dev_size;
 25	dev->tgt.params = (struct ublk_params) {
 26		.types = UBLK_PARAM_TYPE_BASIC,
 27		.basic = {
 28			.logical_bs_shift	= 9,
 29			.physical_bs_shift	= 12,
 30			.io_opt_shift		= 12,
 31			.io_min_shift		= 9,
 32			.max_sectors		= info->max_io_buf_bytes >> 9,
 33			.dev_sectors		= dev_size >> 9,
 34		},
 35	};
 36
 37	dev->private_data = (void *)(unsigned long)(ctx->fault_inject.delay_us * 1000);
 38	return 0;
 39}
 40
 41static int ublk_fault_inject_queue_io(struct ublk_thread *t,
 42				      struct ublk_queue *q, int tag)
 43{
 44	const struct ublksrv_io_desc *iod = ublk_get_iod(q, tag);
 45	struct io_uring_sqe *sqe;
 46	struct __kernel_timespec ts = {
 47		.tv_nsec = (long long)q->dev->private_data,
 48	};
 49
 50	ublk_io_alloc_sqes(t, &sqe, 1);
 51	io_uring_prep_timeout(sqe, &ts, 1, 0);
 52	sqe->user_data = build_user_data(tag, ublksrv_get_op(iod), 0, q->q_id, 1);
 53
 54	ublk_queued_tgt_io(t, q, tag, 1);
 55
 56	return 0;
 57}
 58
 59static void ublk_fault_inject_tgt_io_done(struct ublk_thread *t,
 60					  struct ublk_queue *q,
 61					  const struct io_uring_cqe *cqe)
 62{
 63	unsigned tag = user_data_to_tag(cqe->user_data);
 64	const struct ublksrv_io_desc *iod = ublk_get_iod(q, tag);
 65
 66	if (cqe->res != -ETIME)
 67		ublk_err("%s: unexpected cqe res %d\n", __func__, cqe->res);
 68
 69	if (ublk_completed_tgt_io(t, q, tag))
 70		ublk_complete_io(t, q, tag, iod->nr_sectors << 9);
 71	else
 72		ublk_err("%s: io not complete after 1 cqe\n", __func__);
 73}
 74
 75static void ublk_fault_inject_cmd_line(struct dev_ctx *ctx, int argc, char *argv[])
 76{
 77	static const struct option longopts[] = {
 78		{ "delay_us", 	1,	NULL,  0  },
 79		{ 0, 0, 0, 0 }
 80	};
 81	int option_idx, opt;
 82
 83	ctx->fault_inject.delay_us = 0;
 84	while ((opt = getopt_long(argc, argv, "",
 85				  longopts, &option_idx)) != -1) {
 86		switch (opt) {
 87		case 0:
 88			if (!strcmp(longopts[option_idx].name, "delay_us"))
 89				ctx->fault_inject.delay_us = strtoll(optarg, NULL, 10);
 90		}
 91	}
 92}
 93
 94static void ublk_fault_inject_usage(const struct ublk_tgt_ops *ops)
 95{
 96	printf("\tfault_inject: [--delay_us us (default 0)]\n");
 97}
 98
 99const struct ublk_tgt_ops fault_inject_tgt_ops = {
100	.name = "fault_inject",
101	.init_tgt = ublk_fault_inject_tgt_init,
102	.queue_io = ublk_fault_inject_queue_io,
103	.tgt_io_done = ublk_fault_inject_tgt_io_done,
104	.parse_cmd_line = ublk_fault_inject_cmd_line,
105	.usage = ublk_fault_inject_usage,
106};
~/ Read-only file preview.