4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "spdk/stdinc.h"
37 #include "spdk/nvme.h"
44 struct spdk_nvme_ctrlr
*ctrlr
;
45 struct spdk_nvme_ns
*ns
;
46 struct spdk_nvme_qpair
*qpair
;
48 char name
[SPDK_NVMF_TRADDR_MAX_LEN
+ 1];
51 static struct dev devs
[MAX_DEVS
];
52 static int num_devs
= 0;
54 #define foreach_dev(iter) \
55 for (iter = devs; iter - devs < num_devs; iter++)
57 static int outstanding_commands
= 0;
58 static int failed
= 0;
61 probe_cb(void *cb_ctx
, const struct spdk_nvme_transport_id
*trid
,
62 struct spdk_nvme_ctrlr_opts
*opts
)
64 printf("Attaching to %s\n", trid
->traddr
);
70 attach_cb(void *cb_ctx
, const struct spdk_nvme_transport_id
*trid
,
71 struct spdk_nvme_ctrlr
*ctrlr
, const struct spdk_nvme_ctrlr_opts
*opts
)
77 dev
= &devs
[num_devs
++];
78 if (num_devs
>= MAX_DEVS
) {
83 nsid
= spdk_nvme_ctrlr_get_first_active_ns(ctrlr
);
84 dev
->ns
= spdk_nvme_ctrlr_get_ns(ctrlr
, nsid
);
85 if (dev
->ns
== NULL
) {
89 dev
->qpair
= spdk_nvme_ctrlr_alloc_io_qpair(ctrlr
, NULL
, 0);
90 if (dev
->qpair
== NULL
) {
95 snprintf(dev
->name
, sizeof(dev
->name
), "%s",
98 printf("Attached to %s\n", dev
->name
);
102 get_feature_test_cb(void *cb_arg
, const struct spdk_nvme_cpl
*cpl
)
104 struct dev
*dev
= cb_arg
;
106 outstanding_commands
--;
108 if (spdk_nvme_cpl_is_error(cpl
) && dev
->error_expected
) {
109 if (cpl
->status
.sct
!= SPDK_NVME_SCT_GENERIC
||
110 cpl
->status
.sc
!= SPDK_NVME_SC_INVALID_FIELD
) {
113 printf("%s: get features failed as expected\n", dev
->name
);
117 if (!spdk_nvme_cpl_is_error(cpl
) && !dev
->error_expected
) {
118 printf("%s: get features successfully as expected\n", dev
->name
);
126 get_feature_test(bool error_expected
)
129 struct spdk_nvme_cmd cmd
;
131 memset(&cmd
, 0, sizeof(cmd
));
132 cmd
.opc
= SPDK_NVME_OPC_GET_FEATURES
;
133 cmd
.cdw10
= SPDK_NVME_FEAT_NUMBER_OF_QUEUES
;
136 dev
->error_expected
= error_expected
;
137 if (spdk_nvme_ctrlr_cmd_admin_raw(dev
->ctrlr
, &cmd
, NULL
, 0,
138 get_feature_test_cb
, dev
) != 0) {
139 printf("Error: failed to send Get Features command for dev=%p\n", dev
);
143 outstanding_commands
++;
148 while (outstanding_commands
) {
150 spdk_nvme_ctrlr_process_admin_completions(dev
->ctrlr
);
156 read_test_cb(void *cb_arg
, const struct spdk_nvme_cpl
*cpl
)
158 struct dev
*dev
= cb_arg
;
160 outstanding_commands
--;
161 spdk_dma_free(dev
->data
);
163 if (spdk_nvme_cpl_is_error(cpl
) && dev
->error_expected
) {
164 if (cpl
->status
.sct
!= SPDK_NVME_SCT_MEDIA_ERROR
||
165 cpl
->status
.sc
!= SPDK_NVME_SC_UNRECOVERED_READ_ERROR
) {
168 printf("%s: read failed as expected\n", dev
->name
);
172 if (!spdk_nvme_cpl_is_error(cpl
) && !dev
->error_expected
) {
173 printf("%s: read successfully as expected\n", dev
->name
);
181 read_test(bool error_expected
)
186 dev
->error_expected
= error_expected
;
187 dev
->data
= spdk_dma_zmalloc(0x1000, 0x1000, NULL
);
193 if (spdk_nvme_ns_cmd_read(dev
->ns
, dev
->qpair
, dev
->data
,
194 0, 1, read_test_cb
, dev
, 0) != 0) {
195 printf("Error: failed to send Read command for dev=%p\n", dev
);
200 outstanding_commands
++;
205 while (outstanding_commands
) {
207 spdk_nvme_qpair_process_completions(dev
->qpair
, 0);
212 int main(int argc
, char **argv
)
216 struct spdk_env_opts opts
;
219 spdk_env_opts_init(&opts
);
220 opts
.name
= "err_injection";
221 opts
.core_mask
= "0x1";
223 if (spdk_env_init(&opts
) < 0) {
224 fprintf(stderr
, "Unable to initialize SPDK env\n");
228 printf("NVMe Error Injection test\n");
230 if (spdk_nvme_probe(NULL
, NULL
, probe_cb
, attach_cb
, NULL
) != 0) {
231 fprintf(stderr
, "spdk_nvme_probe() failed\n");
240 printf("No NVMe controller found, %s exiting\n", argv
[0]);
245 /* Admin error injection at submission path */
246 rc
= spdk_nvme_qpair_add_cmd_error_injection(dev
->ctrlr
, NULL
,
247 SPDK_NVME_OPC_GET_FEATURES
, true, 5000, 1,
248 SPDK_NVME_SCT_GENERIC
, SPDK_NVME_SC_INVALID_FIELD
);
250 /* IO error injection at completion path */
251 rc
= spdk_nvme_qpair_add_cmd_error_injection(dev
->ctrlr
, dev
->qpair
,
252 SPDK_NVME_OPC_READ
, false, 0, 1,
253 SPDK_NVME_SCT_MEDIA_ERROR
, SPDK_NVME_SC_UNRECOVERED_READ_ERROR
);
261 /* Admin Get Feature, expect error return */
262 get_feature_test(true);
263 /* Admin Get Feature, expect successful return */
264 get_feature_test(false);
265 /* Read, expect error return */
267 /* Read, expect successful return */
271 printf("Cleaning up...\n");
272 for (i
= 0; i
< num_devs
; i
++) {
273 struct dev
*dev
= &devs
[i
];
274 spdk_nvme_detach(dev
->ctrlr
);