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"
36 #include "spdk_cunit.h"
38 #include "common/lib/test_env.c"
40 pid_t g_spdk_nvme_pid
;
42 bool trace_flag
= false;
43 #define SPDK_LOG_NVME trace_flag
45 #include "nvme/nvme_qpair.c"
47 struct nvme_driver _g_nvme_driver
= {
48 .lock
= PTHREAD_MUTEX_INITIALIZER
,
52 nvme_request_remove_child(struct nvme_request
*parent
,
53 struct nvme_request
*child
)
55 parent
->num_children
--;
56 TAILQ_REMOVE(&parent
->children
, child
, child_tailq
);
60 nvme_transport_qpair_abort_reqs(struct spdk_nvme_qpair
*qpair
, uint32_t dnr
)
65 nvme_transport_qpair_submit_request(struct spdk_nvme_qpair
*qpair
, struct nvme_request
*req
)
72 nvme_transport_qpair_process_completions(struct spdk_nvme_qpair
*qpair
, uint32_t max_completions
)
79 spdk_nvme_ctrlr_free_io_qpair(struct spdk_nvme_qpair
*qpair
)
85 prepare_submit_request_test(struct spdk_nvme_qpair
*qpair
,
86 struct spdk_nvme_ctrlr
*ctrlr
)
88 memset(ctrlr
, 0, sizeof(*ctrlr
));
89 ctrlr
->free_io_qids
= NULL
;
90 TAILQ_INIT(&ctrlr
->active_io_qpairs
);
91 TAILQ_INIT(&ctrlr
->active_procs
);
92 nvme_qpair_init(qpair
, 1, ctrlr
, 0, 32);
96 cleanup_submit_request_test(struct spdk_nvme_qpair
*qpair
)
102 expected_success_callback(void *arg
, const struct spdk_nvme_cpl
*cpl
)
104 CU_ASSERT(!spdk_nvme_cpl_is_error(cpl
));
108 expected_failure_callback(void *arg
, const struct spdk_nvme_cpl
*cpl
)
110 CU_ASSERT(spdk_nvme_cpl_is_error(cpl
));
116 struct spdk_nvme_qpair qpair
= {};
117 struct nvme_request
*req
;
118 struct spdk_nvme_ctrlr ctrlr
= {};
120 prepare_submit_request_test(&qpair
, &ctrlr
);
122 req
= nvme_allocate_request_null(&qpair
, expected_success_callback
, NULL
);
123 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
125 CU_ASSERT(nvme_qpair_submit_request(&qpair
, req
) == 0);
127 nvme_free_request(req
);
129 cleanup_submit_request_test(&qpair
);
133 test_ctrlr_failed(void)
135 struct spdk_nvme_qpair qpair
= {};
136 struct nvme_request
*req
;
137 struct spdk_nvme_ctrlr ctrlr
= {};
140 prepare_submit_request_test(&qpair
, &ctrlr
);
142 req
= nvme_allocate_request_contig(&qpair
, payload
, sizeof(payload
), expected_failure_callback
,
144 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
146 /* Set the controller to failed.
147 * Set the controller to resetting so that the qpair won't get re-enabled.
149 ctrlr
.is_failed
= true;
150 ctrlr
.is_resetting
= true;
152 CU_ASSERT(nvme_qpair_submit_request(&qpair
, req
) != 0);
154 cleanup_submit_request_test(&qpair
);
157 static void struct_packing(void)
159 /* ctrlr is the first field in nvme_qpair after the fields
160 * that are used in the I/O path. Make sure the I/O path fields
161 * all fit into two cache lines.
163 CU_ASSERT(offsetof(struct spdk_nvme_qpair
, ctrlr
) <= 128);
166 static void test_nvme_qpair_process_completions(void)
168 struct spdk_nvme_qpair qpair
= {};
169 struct spdk_nvme_ctrlr ctrlr
= {};
171 prepare_submit_request_test(&qpair
, &ctrlr
);
172 qpair
.ctrlr
->is_resetting
= true;
174 spdk_nvme_qpair_process_completions(&qpair
, 0);
175 cleanup_submit_request_test(&qpair
);
178 static void test_nvme_completion_is_retry(void)
180 struct spdk_nvme_cpl cpl
= {};
182 cpl
.status
.sct
= SPDK_NVME_SCT_GENERIC
;
183 cpl
.status
.sc
= SPDK_NVME_SC_NAMESPACE_NOT_READY
;
185 CU_ASSERT_TRUE(nvme_completion_is_retry(&cpl
));
187 cpl
.status
.sc
= SPDK_NVME_SC_FORMAT_IN_PROGRESS
;
189 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
191 CU_ASSERT_TRUE(nvme_completion_is_retry(&cpl
));
193 cpl
.status
.sc
= SPDK_NVME_SC_INVALID_OPCODE
;
194 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
196 cpl
.status
.sc
= SPDK_NVME_SC_INVALID_FIELD
;
197 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
199 cpl
.status
.sc
= SPDK_NVME_SC_COMMAND_ID_CONFLICT
;
200 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
202 cpl
.status
.sc
= SPDK_NVME_SC_DATA_TRANSFER_ERROR
;
203 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
205 cpl
.status
.sc
= SPDK_NVME_SC_ABORTED_POWER_LOSS
;
206 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
208 cpl
.status
.sc
= SPDK_NVME_SC_INTERNAL_DEVICE_ERROR
;
209 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
211 cpl
.status
.sc
= SPDK_NVME_SC_ABORTED_BY_REQUEST
;
212 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
214 cpl
.status
.sc
= SPDK_NVME_SC_ABORTED_FAILED_FUSED
;
215 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
217 cpl
.status
.sc
= SPDK_NVME_SC_ABORTED_MISSING_FUSED
;
218 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
220 cpl
.status
.sc
= SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT
;
221 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
223 cpl
.status
.sc
= SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR
;
224 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
226 cpl
.status
.sc
= SPDK_NVME_SC_INVALID_SGL_SEG_DESCRIPTOR
;
227 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
229 cpl
.status
.sc
= SPDK_NVME_SC_INVALID_NUM_SGL_DESCIRPTORS
;
230 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
232 cpl
.status
.sc
= SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID
;
233 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
235 cpl
.status
.sc
= SPDK_NVME_SC_METADATA_SGL_LENGTH_INVALID
;
236 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
238 cpl
.status
.sc
= SPDK_NVME_SC_SGL_DESCRIPTOR_TYPE_INVALID
;
239 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
241 cpl
.status
.sc
= SPDK_NVME_SC_INVALID_CONTROLLER_MEM_BUF
;
242 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
244 cpl
.status
.sc
= SPDK_NVME_SC_INVALID_PRP_OFFSET
;
245 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
247 cpl
.status
.sc
= SPDK_NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED
;
248 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
250 cpl
.status
.sc
= SPDK_NVME_SC_LBA_OUT_OF_RANGE
;
251 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
253 cpl
.status
.sc
= SPDK_NVME_SC_CAPACITY_EXCEEDED
;
254 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
256 cpl
.status
.sc
= SPDK_NVME_SC_RESERVATION_CONFLICT
;
257 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
259 cpl
.status
.sc
= 0x70;
260 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
262 cpl
.status
.sct
= SPDK_NVME_SCT_COMMAND_SPECIFIC
;
263 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
265 cpl
.status
.sct
= SPDK_NVME_SCT_MEDIA_ERROR
;
266 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
268 cpl
.status
.sct
= SPDK_NVME_SCT_PATH
;
269 cpl
.status
.sc
= SPDK_NVME_SC_INTERNAL_PATH_ERROR
;
271 CU_ASSERT_TRUE(nvme_completion_is_retry(&cpl
));
273 cpl
.status
.sct
= SPDK_NVME_SCT_PATH
;
274 cpl
.status
.sc
= SPDK_NVME_SC_INTERNAL_PATH_ERROR
;
276 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
278 cpl
.status
.sct
= SPDK_NVME_SCT_VENDOR_SPECIFIC
;
279 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
281 cpl
.status
.sct
= 0x4;
282 CU_ASSERT_FALSE(nvme_completion_is_retry(&cpl
));
287 test_get_status_string(void)
289 const char *status_string
;
290 struct spdk_nvme_status status
;
292 status
.sct
= SPDK_NVME_SCT_GENERIC
;
293 status
.sc
= SPDK_NVME_SC_SUCCESS
;
294 status_string
= spdk_nvme_cpl_get_status_string(&status
);
295 CU_ASSERT(strcmp(status_string
, "SUCCESS") == 0);
297 status
.sct
= SPDK_NVME_SCT_COMMAND_SPECIFIC
;
298 status
.sc
= SPDK_NVME_SC_COMPLETION_QUEUE_INVALID
;
299 status_string
= spdk_nvme_cpl_get_status_string(&status
);
300 CU_ASSERT(strcmp(status_string
, "INVALID COMPLETION QUEUE") == 0);
302 status
.sct
= SPDK_NVME_SCT_MEDIA_ERROR
;
303 status
.sc
= SPDK_NVME_SC_UNRECOVERED_READ_ERROR
;
304 status_string
= spdk_nvme_cpl_get_status_string(&status
);
305 CU_ASSERT(strcmp(status_string
, "UNRECOVERED READ ERROR") == 0);
307 status
.sct
= SPDK_NVME_SCT_VENDOR_SPECIFIC
;
309 status_string
= spdk_nvme_cpl_get_status_string(&status
);
310 CU_ASSERT(strcmp(status_string
, "VENDOR SPECIFIC") == 0);
314 status_string
= spdk_nvme_cpl_get_status_string(&status
);
315 CU_ASSERT(strcmp(status_string
, "RESERVED") == 0);
320 test_nvme_qpair_add_cmd_error_injection(void)
322 struct spdk_nvme_qpair qpair
= {};
323 struct spdk_nvme_ctrlr ctrlr
= {};
326 prepare_submit_request_test(&qpair
, &ctrlr
);
327 ctrlr
.adminq
= &qpair
;
329 /* Admin error injection at submission path */
330 rc
= spdk_nvme_qpair_add_cmd_error_injection(&ctrlr
, NULL
,
331 SPDK_NVME_OPC_GET_FEATURES
, true, 5000, 1,
332 SPDK_NVME_SCT_GENERIC
, SPDK_NVME_SC_INVALID_FIELD
);
335 CU_ASSERT(!TAILQ_EMPTY(&qpair
.err_cmd_head
));
337 /* Remove cmd error injection */
338 spdk_nvme_qpair_remove_cmd_error_injection(&ctrlr
, NULL
, SPDK_NVME_OPC_GET_FEATURES
);
340 CU_ASSERT(TAILQ_EMPTY(&qpair
.err_cmd_head
));
342 /* IO error injection at completion path */
343 rc
= spdk_nvme_qpair_add_cmd_error_injection(&ctrlr
, &qpair
,
344 SPDK_NVME_OPC_READ
, false, 0, 1,
345 SPDK_NVME_SCT_MEDIA_ERROR
, SPDK_NVME_SC_UNRECOVERED_READ_ERROR
);
348 CU_ASSERT(!TAILQ_EMPTY(&qpair
.err_cmd_head
));
350 /* Provide the same opc, and check whether allocate a new entry */
351 rc
= spdk_nvme_qpair_add_cmd_error_injection(&ctrlr
, &qpair
,
352 SPDK_NVME_OPC_READ
, false, 0, 1,
353 SPDK_NVME_SCT_MEDIA_ERROR
, SPDK_NVME_SC_UNRECOVERED_READ_ERROR
);
356 SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&qpair
.err_cmd_head
));
357 CU_ASSERT(TAILQ_NEXT(TAILQ_FIRST(&qpair
.err_cmd_head
), link
) == NULL
);
359 /* Remove cmd error injection */
360 spdk_nvme_qpair_remove_cmd_error_injection(&ctrlr
, &qpair
, SPDK_NVME_OPC_READ
);
362 CU_ASSERT(TAILQ_EMPTY(&qpair
.err_cmd_head
));
364 rc
= spdk_nvme_qpair_add_cmd_error_injection(&ctrlr
, &qpair
,
365 SPDK_NVME_OPC_COMPARE
, true, 0, 5,
366 SPDK_NVME_SCT_GENERIC
, SPDK_NVME_SC_COMPARE_FAILURE
);
369 CU_ASSERT(!TAILQ_EMPTY(&qpair
.err_cmd_head
));
371 /* Remove cmd error injection */
372 spdk_nvme_qpair_remove_cmd_error_injection(&ctrlr
, &qpair
, SPDK_NVME_OPC_COMPARE
);
374 CU_ASSERT(TAILQ_EMPTY(&qpair
.err_cmd_head
));
376 cleanup_submit_request_test(&qpair
);
379 int main(int argc
, char **argv
)
381 CU_pSuite suite
= NULL
;
382 unsigned int num_failures
;
384 if (CU_initialize_registry() != CUE_SUCCESS
) {
385 return CU_get_error();
388 suite
= CU_add_suite("nvme_qpair", NULL
, NULL
);
390 CU_cleanup_registry();
391 return CU_get_error();
394 if (CU_add_test(suite
, "test3", test3
) == NULL
395 || CU_add_test(suite
, "ctrlr_failed", test_ctrlr_failed
) == NULL
396 || CU_add_test(suite
, "struct_packing", struct_packing
) == NULL
397 || CU_add_test(suite
, "spdk_nvme_qpair_process_completions",
398 test_nvme_qpair_process_completions
) == NULL
399 || CU_add_test(suite
, "nvme_completion_is_retry", test_nvme_completion_is_retry
) == NULL
401 || CU_add_test(suite
, "get_status_string", test_get_status_string
) == NULL
403 || CU_add_test(suite
, "spdk_nvme_qpair_add_cmd_error_injection",
404 test_nvme_qpair_add_cmd_error_injection
) == NULL
406 CU_cleanup_registry();
407 return CU_get_error();
410 CU_basic_set_mode(CU_BRM_VERBOSE
);
411 CU_basic_run_tests();
412 num_failures
= CU_get_number_of_failures();
413 CU_cleanup_registry();