1010
1111#include "kublk.h"
1212
13+ struct fi_opts {
14+ long long delay_ns ;
15+ bool die_during_fetch ;
16+ };
17+
1318static int ublk_fault_inject_tgt_init (const struct dev_ctx * ctx ,
1419 struct ublk_dev * dev )
1520{
1621 const struct ublksrv_ctrl_dev_info * info = & dev -> dev_info ;
1722 unsigned long dev_size = 250UL << 30 ;
23+ struct fi_opts * opts = NULL ;
1824
1925 if (ctx -> auto_zc_fallback ) {
2026 ublk_err ("%s: not support auto_zc_fallback\n" , __func__ );
@@ -35,17 +41,52 @@ static int ublk_fault_inject_tgt_init(const struct dev_ctx *ctx,
3541 };
3642 ublk_set_integrity_params (ctx , & dev -> tgt .params );
3743
38- dev -> private_data = (void * )(unsigned long )(ctx -> fault_inject .delay_us * 1000 );
44+ opts = calloc (1 , sizeof (* opts ));
45+ if (!opts ) {
46+ ublk_err ("%s: couldn't allocate memory for opts\n" , __func__ );
47+ return - ENOMEM ;
48+ }
49+
50+ opts -> delay_ns = ctx -> fault_inject .delay_us * 1000 ;
51+ opts -> die_during_fetch = ctx -> fault_inject .die_during_fetch ;
52+ dev -> private_data = opts ;
53+
3954 return 0 ;
4055}
4156
57+ static void ublk_fault_inject_pre_fetch_io (struct ublk_thread * t ,
58+ struct ublk_queue * q , int tag ,
59+ bool batch )
60+ {
61+ struct fi_opts * opts = q -> dev -> private_data ;
62+
63+ if (!opts -> die_during_fetch )
64+ return ;
65+
66+ /*
67+ * Each queue fetches its IOs in increasing order of tags, so
68+ * dying just before we're about to fetch tag 1 (regardless of
69+ * what queue we're on) guarantees that we've fetched a nonempty
70+ * proper subset of the tags on that queue.
71+ */
72+ if (tag == 1 ) {
73+ /*
74+ * Ensure our commands are actually live in the kernel
75+ * before we die.
76+ */
77+ io_uring_submit (& t -> ring );
78+ raise (SIGKILL );
79+ }
80+ }
81+
4282static int ublk_fault_inject_queue_io (struct ublk_thread * t ,
4383 struct ublk_queue * q , int tag )
4484{
4585 const struct ublksrv_io_desc * iod = ublk_get_iod (q , tag );
4686 struct io_uring_sqe * sqe ;
87+ struct fi_opts * opts = q -> dev -> private_data ;
4788 struct __kernel_timespec ts = {
48- .tv_nsec = ( long long ) q -> dev -> private_data ,
89+ .tv_nsec = opts -> delay_ns ,
4990 };
5091
5192 ublk_io_alloc_sqes (t , & sqe , 1 );
@@ -77,29 +118,34 @@ static void ublk_fault_inject_cmd_line(struct dev_ctx *ctx, int argc, char *argv
77118{
78119 static const struct option longopts [] = {
79120 { "delay_us" , 1 , NULL , 0 },
121+ { "die_during_fetch" , 1 , NULL , 0 },
80122 { 0 , 0 , 0 , 0 }
81123 };
82124 int option_idx , opt ;
83125
84126 ctx -> fault_inject .delay_us = 0 ;
127+ ctx -> fault_inject .die_during_fetch = false;
85128 while ((opt = getopt_long (argc , argv , "" ,
86129 longopts , & option_idx )) != -1 ) {
87130 switch (opt ) {
88131 case 0 :
89132 if (!strcmp (longopts [option_idx ].name , "delay_us" ))
90133 ctx -> fault_inject .delay_us = strtoll (optarg , NULL , 10 );
134+ if (!strcmp (longopts [option_idx ].name , "die_during_fetch" ))
135+ ctx -> fault_inject .die_during_fetch = strtoll (optarg , NULL , 10 );
91136 }
92137 }
93138}
94139
95140static void ublk_fault_inject_usage (const struct ublk_tgt_ops * ops )
96141{
97- printf ("\tfault_inject: [--delay_us us (default 0)]\n" );
142+ printf ("\tfault_inject: [--delay_us us (default 0)] [--die_during_fetch 1] \n" );
98143}
99144
100145const struct ublk_tgt_ops fault_inject_tgt_ops = {
101146 .name = "fault_inject" ,
102147 .init_tgt = ublk_fault_inject_tgt_init ,
148+ .pre_fetch_io = ublk_fault_inject_pre_fetch_io ,
103149 .queue_io = ublk_fault_inject_queue_io ,
104150 .tgt_io_done = ublk_fault_inject_tgt_io_done ,
105151 .parse_cmd_line = ublk_fault_inject_cmd_line ,
0 commit comments