Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2021 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2021, 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : : #include "spdk_internal/cunit.h"
9 : : #include "spdk/thread.h"
10 : : #include "spdk/bdev_module.h"
11 : : #include "spdk/bdev_module.h"
12 : :
13 : : #include "common/lib/ut_multithread.c"
14 : :
15 : : #include "bdev/nvme/bdev_nvme.c"
16 : :
17 : : #include "unit/lib/json_mock.c"
18 : :
19 : : #include "bdev/nvme/bdev_mdns_client.c"
20 : :
21 : : static void *g_accel_p = (void *)0xdeadbeaf;
22 : :
23 : 0 : DEFINE_STUB(spdk_nvme_probe_async, struct spdk_nvme_probe_ctx *,
24 : : (const struct spdk_nvme_transport_id *trid, void *cb_ctx,
25 : : spdk_nvme_probe_cb probe_cb, spdk_nvme_attach_cb attach_cb,
26 : : spdk_nvme_remove_cb remove_cb), NULL);
27 : :
28 : 0 : DEFINE_STUB_V(spdk_nvme_trid_populate_transport, (struct spdk_nvme_transport_id *trid,
29 : : enum spdk_nvme_transport_type trtype));
30 : :
31 : 0 : DEFINE_STUB(spdk_nvme_transport_id_trtype_str, const char *, (enum spdk_nvme_transport_type trtype),
32 : : NULL);
33 : :
34 : 0 : DEFINE_STUB(spdk_nvme_transport_id_adrfam_str, const char *, (enum spdk_nvmf_adrfam adrfam), NULL);
35 : :
36 : 24 : DEFINE_STUB(spdk_nvme_ctrlr_set_trid, int, (struct spdk_nvme_ctrlr *ctrlr,
37 : : struct spdk_nvme_transport_id *trid), 0);
38 : :
39 : 180 : DEFINE_STUB_V(spdk_nvme_ctrlr_set_remove_cb, (struct spdk_nvme_ctrlr *ctrlr,
40 : : spdk_nvme_remove_cb remove_cb, void *remove_ctx));
41 : :
42 : 291 : DEFINE_STUB(spdk_nvme_ctrlr_get_flags, uint64_t, (struct spdk_nvme_ctrlr *ctrlr), 0);
43 : :
44 : 0 : DEFINE_STUB(accel_channel_create, int, (void *io_device, void *ctx_buf), 0);
45 : 0 : DEFINE_STUB_V(accel_channel_destroy, (void *io_device, void *ctx_buf));
46 : :
47 : 0 : DEFINE_STUB(spdk_nvme_ctrlr_get_discovery_log_page, int,
48 : : (struct spdk_nvme_ctrlr *ctrlr, spdk_nvme_discovery_cb cb_fn, void *cb_arg), 0);
49 : :
50 : : DEFINE_RETURN_MOCK(spdk_nvme_ctrlr_get_memory_domains, int);
51 : :
52 : 0 : DEFINE_STUB_V(spdk_jsonrpc_send_error_response, (struct spdk_jsonrpc_request *request,
53 : : int error_code, const char *msg));
54 : 0 : DEFINE_STUB(spdk_jsonrpc_begin_result, struct spdk_json_write_ctx *,
55 : : (struct spdk_jsonrpc_request *request), NULL);
56 : 0 : DEFINE_STUB_V(spdk_jsonrpc_end_result,
57 : : (struct spdk_jsonrpc_request *request, struct spdk_json_write_ctx *w));
58 : :
59 : 0 : DEFINE_STUB_V(spdk_nvme_transport_get_opts, (struct spdk_nvme_transport_opts *opts,
60 : : size_t opts_size));
61 : :
62 : 0 : DEFINE_STUB(spdk_nvme_transport_set_opts, int, (const struct spdk_nvme_transport_opts *opts,
63 : : size_t opts_size), 0);
64 : :
65 : 174 : DEFINE_STUB(spdk_bdev_io_get_submit_tsc, uint64_t, (struct spdk_bdev_io *bdev_io), 0);
66 : :
67 : 0 : DEFINE_STUB_V(spdk_bdev_reset_io_stat, (struct spdk_bdev_io_stat *stat,
68 : : enum spdk_bdev_reset_stat_mode mode));
69 : 0 : DEFINE_STUB_V(spdk_bdev_add_io_stat, (struct spdk_bdev_io_stat *total,
70 : : struct spdk_bdev_io_stat *add));
71 : :
72 : 117 : DEFINE_STUB_V(spdk_nvme_qpair_set_abort_dnr, (struct spdk_nvme_qpair *qpair, bool dnr));
73 : :
74 : : int
75 : 42 : spdk_nvme_ctrlr_get_memory_domains(const struct spdk_nvme_ctrlr *ctrlr,
76 : : struct spdk_memory_domain **domains, int array_size)
77 : : {
78 : : int i, min_array_size;
79 : :
80 [ + + + + : 42 : if (ut_spdk_nvme_ctrlr_get_memory_domains > 0 && domains && array_size > 0) {
+ + ]
81 : 24 : min_array_size = spdk_min(ut_spdk_nvme_ctrlr_get_memory_domains, array_size);
82 [ + + ]: 57 : for (i = 0; i < min_array_size; i++) {
83 : 33 : domains[i] = (struct spdk_memory_domain *)0xf1f2f3f4f5;
84 : : }
85 : : }
86 [ + + + - ]: 42 : HANDLE_RETURN_MOCK(spdk_nvme_ctrlr_get_memory_domains);
87 : :
88 : 0 : return 0;
89 : : }
90 : :
91 : : struct spdk_io_channel *
92 : 0 : spdk_accel_get_io_channel(void)
93 : : {
94 : 0 : return spdk_get_io_channel(g_accel_p);
95 : : }
96 : :
97 : : void
98 : 300 : spdk_nvme_ctrlr_get_default_io_qpair_opts(struct spdk_nvme_ctrlr *ctrlr,
99 : : struct spdk_nvme_io_qpair_opts *opts, size_t opts_size)
100 : : {
101 : : /* Avoid warning that opts is used uninitialised */
102 [ - + ]: 300 : memset(opts, 0, opts_size);
103 : 300 : }
104 : :
105 : 111 : DEFINE_STUB(spdk_nvme_ctrlr_get_opts, const struct spdk_nvme_ctrlr_opts *,
106 : : (struct spdk_nvme_ctrlr *ctrlr), NULL);
107 : :
108 : 123 : DEFINE_STUB(spdk_nvme_ctrlr_get_max_xfer_size, uint32_t,
109 : : (const struct spdk_nvme_ctrlr *ctrlr), 0);
110 : :
111 : 0 : DEFINE_STUB(spdk_nvme_ctrlr_get_transport_id, const struct spdk_nvme_transport_id *,
112 : : (struct spdk_nvme_ctrlr *ctrlr), NULL);
113 : :
114 : 180 : DEFINE_STUB_V(spdk_nvme_ctrlr_register_aer_callback, (struct spdk_nvme_ctrlr *ctrlr,
115 : : spdk_nvme_aer_cb aer_cb_fn, void *aer_cb_arg));
116 : :
117 : 0 : DEFINE_STUB_V(spdk_nvme_ctrlr_register_timeout_callback, (struct spdk_nvme_ctrlr *ctrlr,
118 : : uint64_t timeout_io_us, uint64_t timeout_admin_us, spdk_nvme_timeout_cb cb_fn, void *cb_arg));
119 : :
120 [ - + ]: 222 : DEFINE_STUB(spdk_nvme_ctrlr_is_fabrics, bool, (struct spdk_nvme_ctrlr *ctrlr), true);
121 : :
122 [ - + ]: 180 : DEFINE_STUB(spdk_nvme_ctrlr_is_ocssd_supported, bool, (struct spdk_nvme_ctrlr *ctrlr), false);
123 : :
124 : 0 : DEFINE_STUB(spdk_nvme_ctrlr_cmd_abort, int, (struct spdk_nvme_ctrlr *ctrlr,
125 : : struct spdk_nvme_qpair *qpair, uint16_t cid, spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
126 : :
127 : 0 : DEFINE_STUB(spdk_nvme_ctrlr_cmd_io_raw, int, (struct spdk_nvme_ctrlr *ctrlr,
128 : : struct spdk_nvme_qpair *qpair, struct spdk_nvme_cmd *cmd, void *buf,
129 : : uint32_t len, spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
130 : :
131 : 0 : DEFINE_STUB(spdk_nvme_ctrlr_cmd_io_raw_with_md, int, (struct spdk_nvme_ctrlr *ctrlr,
132 : : struct spdk_nvme_qpair *qpair, struct spdk_nvme_cmd *cmd, void *buf,
133 : : uint32_t len, void *md_buf, spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
134 : :
135 : 0 : DEFINE_STUB(spdk_nvme_ctrlr_cmd_iov_raw_with_md, int, (
136 : : struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair,
137 : : struct spdk_nvme_cmd *cmd, uint32_t len, void *md_buf,
138 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
139 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
140 : : spdk_nvme_req_next_sge_cb next_sge_fn), 0);
141 : :
142 : 0 : DEFINE_STUB(spdk_nvme_cuse_get_ctrlr_name, int, (struct spdk_nvme_ctrlr *ctrlr, char *name,
143 : : size_t *size), 0);
144 : :
145 : 0 : DEFINE_STUB(spdk_nvme_ns_get_max_io_xfer_size, uint32_t, (struct spdk_nvme_ns *ns), 0);
146 : :
147 : 111 : DEFINE_STUB(spdk_nvme_ns_get_extended_sector_size, uint32_t, (struct spdk_nvme_ns *ns), 0);
148 : :
149 : 111 : DEFINE_STUB(spdk_nvme_ns_get_sector_size, uint32_t, (struct spdk_nvme_ns *ns), 0);
150 : :
151 : 0 : DEFINE_STUB(spdk_nvme_ns_get_pi_type, enum spdk_nvme_pi_type, (struct spdk_nvme_ns *ns), 0);
152 : :
153 [ # # ]: 0 : DEFINE_STUB(spdk_nvme_ns_supports_compare, bool, (struct spdk_nvme_ns *ns), false);
154 : :
155 : 111 : DEFINE_STUB(spdk_nvme_ns_get_md_size, uint32_t, (struct spdk_nvme_ns *ns), 0);
156 : :
157 : 0 : DEFINE_STUB(spdk_nvme_ns_get_dealloc_logical_block_read_value,
158 : : enum spdk_nvme_dealloc_logical_block_read_value, (struct spdk_nvme_ns *ns), 0);
159 : :
160 : 111 : DEFINE_STUB(spdk_nvme_ns_get_optimal_io_boundary, uint32_t, (struct spdk_nvme_ns *ns), 0);
161 : :
162 : 0 : DEFINE_STUB(spdk_nvme_cuse_get_ns_name, int, (struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid,
163 : : char *name, size_t *size), 0);
164 : :
165 : 0 : DEFINE_STUB(spdk_nvme_zns_ns_get_zone_size_sectors, uint64_t,
166 : : (struct spdk_nvme_ns *ns), 0);
167 : :
168 : 0 : DEFINE_STUB(spdk_nvme_zns_ctrlr_get_max_zone_append_size, uint32_t,
169 : : (const struct spdk_nvme_ctrlr *ctrlr), 0);
170 : :
171 : 0 : DEFINE_STUB(spdk_nvme_zns_ns_get_max_open_zones, uint32_t,
172 : : (struct spdk_nvme_ns *ns), 0);
173 : :
174 : 0 : DEFINE_STUB(spdk_nvme_zns_ns_get_max_active_zones, uint32_t,
175 : : (struct spdk_nvme_ns *ns), 0);
176 : :
177 : 0 : DEFINE_STUB(spdk_nvme_zns_ns_get_num_zones, uint64_t,
178 : : (struct spdk_nvme_ns *ns), 0);
179 : :
180 : 0 : DEFINE_STUB(spdk_nvme_zns_zone_append_with_md, int,
181 : : (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer, void *metadata,
182 : : uint64_t zslba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
183 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag), 0);
184 : :
185 : 0 : DEFINE_STUB(spdk_nvme_zns_zone_appendv_with_md, int,
186 : : (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t zslba,
187 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
188 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn, spdk_nvme_req_next_sge_cb next_sge_fn,
189 : : void *metadata, uint16_t apptag_mask, uint16_t apptag), 0);
190 : :
191 : 0 : DEFINE_STUB(spdk_nvme_zns_report_zones, int,
192 : : (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
193 : : void *payload, uint32_t payload_size, uint64_t slba,
194 : : enum spdk_nvme_zns_zra_report_opts report_opts, bool partial_report,
195 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
196 : :
197 : 0 : DEFINE_STUB(spdk_nvme_zns_close_zone, int,
198 : : (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
199 : : bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
200 : :
201 : 0 : DEFINE_STUB(spdk_nvme_zns_finish_zone, int,
202 : : (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
203 : : bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
204 : :
205 : 0 : DEFINE_STUB(spdk_nvme_zns_open_zone, int,
206 : : (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
207 : : bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
208 : :
209 : 0 : DEFINE_STUB(spdk_nvme_zns_reset_zone, int,
210 : : (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
211 : : bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
212 : :
213 : 111 : DEFINE_STUB(spdk_nvme_ns_get_nguid, const uint8_t *, (const struct spdk_nvme_ns *ns), NULL);
214 : :
215 : 0 : DEFINE_STUB(spdk_nvme_zns_offline_zone, int,
216 : : (struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t slba,
217 : : bool select_all, spdk_nvme_cmd_cb cb_fn, void *cb_arg), 0);
218 : :
219 : 0 : DEFINE_STUB(spdk_nvme_cpl_get_status_type_string, const char *,
220 : : (const struct spdk_nvme_status *status), NULL);
221 : :
222 : 0 : DEFINE_STUB(spdk_nvme_cpl_get_status_string, const char *,
223 : : (const struct spdk_nvme_status *status), NULL);
224 : :
225 : 3 : DEFINE_STUB_V(spdk_bdev_module_fini_done, (void));
226 : :
227 : 3 : DEFINE_STUB_V(spdk_bdev_module_list_add, (struct spdk_bdev_module *bdev_module));
228 : :
229 : 18 : DEFINE_STUB_V(spdk_bdev_close, (struct spdk_bdev_desc *desc));
230 : :
231 : 0 : DEFINE_STUB(spdk_opal_dev_construct, struct spdk_opal_dev *, (struct spdk_nvme_ctrlr *ctrlr), NULL);
232 : :
233 : 0 : DEFINE_STUB_V(spdk_opal_dev_destruct, (struct spdk_opal_dev *dev));
234 : :
235 : 0 : DEFINE_STUB(spdk_accel_submit_crc32cv, int, (struct spdk_io_channel *ch, uint32_t *dst,
236 : : struct iovec *iov,
237 : : uint32_t iov_cnt, uint32_t seed, spdk_accel_completion_cb cb_fn, void *cb_arg), 0);
238 : 0 : DEFINE_STUB(spdk_accel_append_crc32c, int,
239 : : (struct spdk_accel_sequence **seq, struct spdk_io_channel *ch, uint32_t *dst,
240 : : struct iovec *iovs, uint32_t iovcnt, struct spdk_memory_domain *domain, void *domain_ctx,
241 : : uint32_t seed, spdk_accel_step_cb cb_fn, void *cb_arg), 0);
242 : 0 : DEFINE_STUB_V(spdk_accel_sequence_finish,
243 : : (struct spdk_accel_sequence *seq, spdk_accel_completion_cb cb_fn, void *cb_arg));
244 : 6 : DEFINE_STUB_V(spdk_accel_sequence_abort, (struct spdk_accel_sequence *seq));
245 : 0 : DEFINE_STUB_V(spdk_accel_sequence_reverse, (struct spdk_accel_sequence *seq));
246 : :
247 : : struct ut_nvme_req {
248 : : uint16_t opc;
249 : : spdk_nvme_cmd_cb cb_fn;
250 : : void *cb_arg;
251 : : struct spdk_nvme_cpl cpl;
252 : : TAILQ_ENTRY(ut_nvme_req) tailq;
253 : : };
254 : :
255 : : struct spdk_nvme_ns {
256 : : struct spdk_nvme_ctrlr *ctrlr;
257 : : uint32_t id;
258 : : bool is_active;
259 : : struct spdk_uuid *uuid;
260 : : enum spdk_nvme_ana_state ana_state;
261 : : enum spdk_nvme_csi csi;
262 : : };
263 : :
264 : : struct spdk_nvme_qpair {
265 : : struct spdk_nvme_ctrlr *ctrlr;
266 : : uint8_t failure_reason;
267 : : bool is_connected;
268 : : bool in_completion_context;
269 : : bool delete_after_completion_context;
270 : : TAILQ_HEAD(, ut_nvme_req) outstanding_reqs;
271 : : uint32_t num_outstanding_reqs;
272 : : TAILQ_ENTRY(spdk_nvme_qpair) poll_group_tailq;
273 : : struct spdk_nvme_poll_group *poll_group;
274 : : void *poll_group_tailq_head;
275 : : TAILQ_ENTRY(spdk_nvme_qpair) tailq;
276 : : };
277 : :
278 : : struct spdk_nvme_ctrlr {
279 : : uint32_t num_ns;
280 : : struct spdk_nvme_ns *ns;
281 : : struct spdk_nvme_ns_data *nsdata;
282 : : struct spdk_nvme_qpair adminq;
283 : : struct spdk_nvme_ctrlr_data cdata;
284 : : bool attached;
285 : : bool is_failed;
286 : : bool fail_reset;
287 : : bool is_removed;
288 : : struct spdk_nvme_transport_id trid;
289 : : TAILQ_HEAD(, spdk_nvme_qpair) active_io_qpairs;
290 : : TAILQ_ENTRY(spdk_nvme_ctrlr) tailq;
291 : : struct spdk_nvme_ctrlr_opts opts;
292 : : };
293 : :
294 : : struct spdk_nvme_poll_group {
295 : : void *ctx;
296 : : struct spdk_nvme_accel_fn_table accel_fn_table;
297 : : TAILQ_HEAD(, spdk_nvme_qpair) connected_qpairs;
298 : : TAILQ_HEAD(, spdk_nvme_qpair) disconnected_qpairs;
299 : : };
300 : :
301 : : struct spdk_nvme_probe_ctx {
302 : : struct spdk_nvme_transport_id trid;
303 : : void *cb_ctx;
304 : : spdk_nvme_attach_cb attach_cb;
305 : : struct spdk_nvme_ctrlr *init_ctrlr;
306 : : };
307 : :
308 : : uint32_t
309 : 291 : spdk_nvme_ctrlr_get_first_active_ns(struct spdk_nvme_ctrlr *ctrlr)
310 : : {
311 : : uint32_t nsid;
312 : :
313 [ + + ]: 297 : for (nsid = 1; nsid <= ctrlr->num_ns; nsid++) {
314 [ + + + + ]: 222 : if (ctrlr->ns[nsid - 1].is_active) {
315 : 216 : return nsid;
316 : : }
317 : : }
318 : :
319 : 75 : return 0;
320 : : }
321 : :
322 : : uint32_t
323 : 291 : spdk_nvme_ctrlr_get_next_active_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
324 : : {
325 [ + + ]: 321 : for (nsid = nsid + 1; nsid <= ctrlr->num_ns; nsid++) {
326 [ + + + + ]: 105 : if (ctrlr->ns[nsid - 1].is_active) {
327 : 75 : return nsid;
328 : : }
329 : : }
330 : :
331 : 216 : return 0;
332 : : }
333 : :
334 : : uint32_t
335 : 36 : spdk_nvme_qpair_get_num_outstanding_reqs(struct spdk_nvme_qpair *qpair)
336 : : {
337 : 36 : return qpair->num_outstanding_reqs;
338 : : }
339 : :
340 : : static TAILQ_HEAD(, spdk_nvme_ctrlr) g_ut_init_ctrlrs = TAILQ_HEAD_INITIALIZER(g_ut_init_ctrlrs);
341 : : static TAILQ_HEAD(, spdk_nvme_ctrlr) g_ut_attached_ctrlrs = TAILQ_HEAD_INITIALIZER(
342 : : g_ut_attached_ctrlrs);
343 : : static int g_ut_attach_ctrlr_status;
344 : : static size_t g_ut_attach_bdev_count;
345 : : static int g_ut_register_bdev_status;
346 : : static struct spdk_bdev *g_ut_registered_bdev;
347 : : static uint16_t g_ut_cntlid;
348 : : static struct nvme_path_id g_any_path = {};
349 : :
350 : : static void
351 : 117 : ut_init_trid(struct spdk_nvme_transport_id *trid)
352 : : {
353 : 117 : trid->trtype = SPDK_NVME_TRANSPORT_TCP;
354 [ - + ]: 117 : snprintf(trid->subnqn, SPDK_NVMF_NQN_MAX_LEN, "%s", "nqn.2016-06.io.spdk:cnode1");
355 [ - + ]: 117 : snprintf(trid->traddr, SPDK_NVMF_TRADDR_MAX_LEN, "%s", "192.168.100.8");
356 [ - + ]: 117 : snprintf(trid->trsvcid, SPDK_NVMF_TRSVCID_MAX_LEN, "%s", "4420");
357 : 117 : }
358 : :
359 : : static void
360 : 48 : ut_init_trid2(struct spdk_nvme_transport_id *trid)
361 : : {
362 : 48 : trid->trtype = SPDK_NVME_TRANSPORT_TCP;
363 [ - + ]: 48 : snprintf(trid->subnqn, SPDK_NVMF_NQN_MAX_LEN, "%s", "nqn.2016-06.io.spdk:cnode1");
364 [ - + ]: 48 : snprintf(trid->traddr, SPDK_NVMF_TRADDR_MAX_LEN, "%s", "192.168.100.9");
365 [ - + ]: 48 : snprintf(trid->trsvcid, SPDK_NVMF_TRSVCID_MAX_LEN, "%s", "4420");
366 : 48 : }
367 : :
368 : : static void
369 : 15 : ut_init_trid3(struct spdk_nvme_transport_id *trid)
370 : : {
371 : 15 : trid->trtype = SPDK_NVME_TRANSPORT_TCP;
372 [ - + ]: 15 : snprintf(trid->subnqn, SPDK_NVMF_NQN_MAX_LEN, "%s", "nqn.2016-06.io.spdk:cnode1");
373 [ - + ]: 15 : snprintf(trid->traddr, SPDK_NVMF_TRADDR_MAX_LEN, "%s", "192.168.100.10");
374 [ - + ]: 15 : snprintf(trid->trsvcid, SPDK_NVMF_TRSVCID_MAX_LEN, "%s", "4420");
375 : 15 : }
376 : :
377 : : static int
378 : 843 : cmp_int(int a, int b)
379 : : {
380 : 843 : return a - b;
381 : : }
382 : :
383 : : int
384 : 522 : spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
385 : : const struct spdk_nvme_transport_id *trid2)
386 : : {
387 : : int cmp;
388 : :
389 : : /* We assume trtype is TCP for now. */
390 : 522 : CU_ASSERT(trid1->trtype == SPDK_NVME_TRANSPORT_TCP);
391 : :
392 : 522 : cmp = cmp_int(trid1->trtype, trid2->trtype);
393 [ - + ]: 522 : if (cmp) {
394 : 0 : return cmp;
395 : : }
396 : :
397 [ - + - + ]: 522 : cmp = strcasecmp(trid1->traddr, trid2->traddr);
398 [ + + ]: 522 : if (cmp) {
399 : 201 : return cmp;
400 : : }
401 : :
402 : 321 : cmp = cmp_int(trid1->adrfam, trid2->adrfam);
403 [ - + ]: 321 : if (cmp) {
404 : 0 : return cmp;
405 : : }
406 : :
407 [ - + - + ]: 321 : cmp = strcasecmp(trid1->trsvcid, trid2->trsvcid);
408 [ - + ]: 321 : if (cmp) {
409 : 0 : return cmp;
410 : : }
411 : :
412 [ - + - + ]: 321 : cmp = strcmp(trid1->subnqn, trid2->subnqn);
413 [ - + ]: 321 : if (cmp) {
414 : 0 : return cmp;
415 : : }
416 : :
417 : 321 : return 0;
418 : : }
419 : :
420 : : static struct spdk_nvme_ctrlr *
421 : 153 : ut_attach_ctrlr(const struct spdk_nvme_transport_id *trid, uint32_t num_ns,
422 : : bool ana_reporting, bool multipath)
423 : : {
424 : : struct spdk_nvme_ctrlr *ctrlr;
425 : : uint32_t i;
426 : :
427 [ + + ]: 156 : TAILQ_FOREACH(ctrlr, &g_ut_init_ctrlrs, tailq) {
428 [ - + ]: 3 : if (spdk_nvme_transport_id_compare(&ctrlr->trid, trid) == 0) {
429 : : /* There is a ctrlr whose trid matches. */
430 : 0 : return NULL;
431 : : }
432 : : }
433 : :
434 : 153 : ctrlr = calloc(1, sizeof(*ctrlr));
435 [ - + ]: 153 : if (ctrlr == NULL) {
436 : 0 : return NULL;
437 : : }
438 : :
439 : 153 : ctrlr->attached = true;
440 : 153 : ctrlr->adminq.ctrlr = ctrlr;
441 : 153 : TAILQ_INIT(&ctrlr->adminq.outstanding_reqs);
442 : 153 : ctrlr->adminq.is_connected = true;
443 : :
444 [ + + ]: 153 : if (num_ns != 0) {
445 : 114 : ctrlr->num_ns = num_ns;
446 : 114 : ctrlr->ns = calloc(num_ns, sizeof(struct spdk_nvme_ns));
447 [ - + ]: 114 : if (ctrlr->ns == NULL) {
448 : 0 : free(ctrlr);
449 : 0 : return NULL;
450 : : }
451 : :
452 : 114 : ctrlr->nsdata = calloc(num_ns, sizeof(struct spdk_nvme_ns_data));
453 [ - + ]: 114 : if (ctrlr->nsdata == NULL) {
454 : 0 : free(ctrlr->ns);
455 : 0 : free(ctrlr);
456 : 0 : return NULL;
457 : : }
458 : :
459 [ + + ]: 276 : for (i = 0; i < num_ns; i++) {
460 : 162 : ctrlr->ns[i].id = i + 1;
461 : 162 : ctrlr->ns[i].ctrlr = ctrlr;
462 : 162 : ctrlr->ns[i].is_active = true;
463 : 162 : ctrlr->ns[i].ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
464 : 162 : ctrlr->nsdata[i].nsze = 1024;
465 : 162 : ctrlr->nsdata[i].nmic.can_share = multipath;
466 : : }
467 : :
468 : 114 : ctrlr->cdata.nn = num_ns;
469 : 114 : ctrlr->cdata.mnan = num_ns;
470 : 114 : ctrlr->cdata.nanagrpid = num_ns;
471 : : }
472 : :
473 : 153 : ctrlr->cdata.cntlid = ++g_ut_cntlid;
474 : 153 : ctrlr->cdata.cmic.multi_ctrlr = multipath;
475 : 153 : ctrlr->cdata.cmic.ana_reporting = ana_reporting;
476 : 153 : ctrlr->trid = *trid;
477 : 153 : TAILQ_INIT(&ctrlr->active_io_qpairs);
478 : :
479 : 153 : TAILQ_INSERT_TAIL(&g_ut_init_ctrlrs, ctrlr, tailq);
480 : :
481 : 153 : return ctrlr;
482 : : }
483 : :
484 : : static void
485 : 150 : ut_detach_ctrlr(struct spdk_nvme_ctrlr *ctrlr)
486 : : {
487 : 150 : CU_ASSERT(TAILQ_EMPTY(&ctrlr->active_io_qpairs));
488 : :
489 [ + + ]: 150 : TAILQ_REMOVE(&g_ut_attached_ctrlrs, ctrlr, tailq);
490 : 150 : free(ctrlr->nsdata);
491 : 150 : free(ctrlr->ns);
492 : 150 : free(ctrlr);
493 : 150 : }
494 : :
495 : : static int
496 : 213 : ut_submit_nvme_request(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
497 : : uint16_t opc, spdk_nvme_cmd_cb cb_fn, void *cb_arg)
498 : : {
499 : : struct ut_nvme_req *req;
500 : :
501 : 213 : req = calloc(1, sizeof(*req));
502 [ - + ]: 213 : if (req == NULL) {
503 : 0 : return -ENOMEM;
504 : : }
505 : :
506 : 213 : req->opc = opc;
507 : 213 : req->cb_fn = cb_fn;
508 : 213 : req->cb_arg = cb_arg;
509 : :
510 : 213 : req->cpl.status.sc = SPDK_NVME_SC_SUCCESS;
511 : 213 : req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
512 : :
513 : 213 : TAILQ_INSERT_TAIL(&qpair->outstanding_reqs, req, tailq);
514 : 213 : qpair->num_outstanding_reqs++;
515 : :
516 : 213 : return 0;
517 : : }
518 : :
519 : : static struct ut_nvme_req *
520 : 30 : ut_get_outstanding_nvme_request(struct spdk_nvme_qpair *qpair, void *cb_arg)
521 : : {
522 : : struct ut_nvme_req *req;
523 : :
524 [ + - ]: 30 : TAILQ_FOREACH(req, &qpair->outstanding_reqs, tailq) {
525 [ + - ]: 30 : if (req->cb_arg == cb_arg) {
526 : 30 : break;
527 : : }
528 : : }
529 : :
530 : 30 : return req;
531 : : }
532 : :
533 : : static struct spdk_bdev_io *
534 : 54 : ut_alloc_bdev_io(enum spdk_bdev_io_type type, struct nvme_bdev *nbdev,
535 : : struct spdk_io_channel *ch)
536 : : {
537 : : struct spdk_bdev_io *bdev_io;
538 : :
539 : 54 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct nvme_bdev_io));
540 [ - + ]: 54 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
541 : 54 : bdev_io->type = type;
542 : 54 : bdev_io->bdev = &nbdev->disk;
543 : 54 : bdev_io->internal.ch = (struct spdk_bdev_channel *)ch;
544 : :
545 : 54 : return bdev_io;
546 : : }
547 : :
548 : : static void
549 : 36 : ut_bdev_io_set_buf(struct spdk_bdev_io *bdev_io)
550 : : {
551 : 36 : bdev_io->u.bdev.iovs = &bdev_io->iov;
552 : 36 : bdev_io->u.bdev.iovcnt = 1;
553 : :
554 : 36 : bdev_io->iov.iov_base = (void *)0xFEEDBEEF;
555 : 36 : bdev_io->iov.iov_len = 4096;
556 : 36 : }
557 : :
558 : : static void
559 : 153 : nvme_ctrlr_poll_internal(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_probe_ctx *probe_ctx)
560 : : {
561 [ + + + + ]: 153 : if (ctrlr->is_failed) {
562 : 3 : free(ctrlr);
563 : 3 : return;
564 : : }
565 : :
566 : 150 : spdk_nvme_ctrlr_get_default_ctrlr_opts(&ctrlr->opts, sizeof(ctrlr->opts));
567 [ + - ]: 150 : if (probe_ctx->cb_ctx) {
568 : 150 : ctrlr->opts = *(struct spdk_nvme_ctrlr_opts *)probe_ctx->cb_ctx;
569 : : }
570 : :
571 : 150 : TAILQ_INSERT_TAIL(&g_ut_attached_ctrlrs, ctrlr, tailq);
572 : :
573 [ + - ]: 150 : if (probe_ctx->attach_cb) {
574 : 150 : probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
575 : : }
576 : : }
577 : :
578 : : int
579 : 153 : spdk_nvme_probe_poll_async(struct spdk_nvme_probe_ctx *probe_ctx)
580 : : {
581 : : struct spdk_nvme_ctrlr *ctrlr, *tmp;
582 : :
583 [ + + ]: 309 : TAILQ_FOREACH_SAFE(ctrlr, &g_ut_init_ctrlrs, tailq, tmp) {
584 [ + + ]: 156 : if (spdk_nvme_transport_id_compare(&ctrlr->trid, &probe_ctx->trid) != 0) {
585 : 3 : continue;
586 : : }
587 [ + + ]: 153 : TAILQ_REMOVE(&g_ut_init_ctrlrs, ctrlr, tailq);
588 : 153 : nvme_ctrlr_poll_internal(ctrlr, probe_ctx);
589 : : }
590 : :
591 : 153 : free(probe_ctx);
592 : :
593 : 153 : return 0;
594 : : }
595 : :
596 : : struct spdk_nvme_probe_ctx *
597 : 153 : spdk_nvme_connect_async(const struct spdk_nvme_transport_id *trid,
598 : : const struct spdk_nvme_ctrlr_opts *opts,
599 : : spdk_nvme_attach_cb attach_cb)
600 : : {
601 : : struct spdk_nvme_probe_ctx *probe_ctx;
602 : :
603 [ - + ]: 153 : if (trid == NULL) {
604 : 0 : return NULL;
605 : : }
606 : :
607 : 153 : probe_ctx = calloc(1, sizeof(*probe_ctx));
608 [ - + ]: 153 : if (probe_ctx == NULL) {
609 : 0 : return NULL;
610 : : }
611 : :
612 : 153 : probe_ctx->trid = *trid;
613 : 153 : probe_ctx->cb_ctx = (void *)opts;
614 : 153 : probe_ctx->attach_cb = attach_cb;
615 : :
616 : 153 : return probe_ctx;
617 : : }
618 : :
619 : : int
620 : 207 : spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
621 : : {
622 [ + + + + ]: 207 : if (ctrlr->attached) {
623 : 150 : ut_detach_ctrlr(ctrlr);
624 : : }
625 : :
626 : 207 : return 0;
627 : : }
628 : :
629 : : int
630 : 180 : spdk_nvme_detach_async(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_detach_ctx **ctx)
631 : : {
632 [ - + ]: 180 : SPDK_CU_ASSERT_FATAL(ctx != NULL);
633 : 180 : *(struct spdk_nvme_ctrlr **)ctx = ctrlr;
634 : :
635 : 180 : return 0;
636 : : }
637 : :
638 : : int
639 : 180 : spdk_nvme_detach_poll_async(struct spdk_nvme_detach_ctx *ctx)
640 : : {
641 : 180 : return spdk_nvme_detach((struct spdk_nvme_ctrlr *)ctx);
642 : : }
643 : :
644 : : void
645 : 303 : spdk_nvme_ctrlr_get_default_ctrlr_opts(struct spdk_nvme_ctrlr_opts *opts, size_t opts_size)
646 : : {
647 [ - + ]: 303 : memset(opts, 0, opts_size);
648 : :
649 [ - + ]: 303 : snprintf(opts->hostnqn, sizeof(opts->hostnqn),
650 : : "nqn.2014-08.org.nvmexpress:uuid:7391e776-0716-11ec-9a03-0242ac130003");
651 : 303 : }
652 : :
653 : : const struct spdk_nvme_ctrlr_data *
654 : 642 : spdk_nvme_ctrlr_get_data(struct spdk_nvme_ctrlr *ctrlr)
655 : : {
656 : 642 : return &ctrlr->cdata;
657 : : }
658 : :
659 : : uint32_t
660 : 0 : spdk_nvme_ctrlr_get_num_ns(struct spdk_nvme_ctrlr *ctrlr)
661 : : {
662 : 0 : return ctrlr->num_ns;
663 : : }
664 : :
665 : : struct spdk_nvme_ns *
666 : 159 : spdk_nvme_ctrlr_get_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
667 : : {
668 [ + - - + ]: 159 : if (nsid < 1 || nsid > ctrlr->num_ns) {
669 : 0 : return NULL;
670 : : }
671 : :
672 : 159 : return &ctrlr->ns[nsid - 1];
673 : : }
674 : :
675 : : bool
676 : 48 : spdk_nvme_ctrlr_is_active_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
677 : : {
678 [ + - - + ]: 48 : if (nsid < 1 || nsid > ctrlr->num_ns) {
679 : 0 : return false;
680 : : }
681 : :
682 [ - + ]: 48 : return ctrlr->ns[nsid - 1].is_active;
683 : : }
684 : :
685 : : union spdk_nvme_csts_register
686 : 0 : spdk_nvme_ctrlr_get_regs_csts(struct spdk_nvme_ctrlr *ctrlr)
687 : : {
688 : : union spdk_nvme_csts_register csts;
689 : :
690 : 0 : csts.raw = 0;
691 : :
692 : 0 : return csts;
693 : : }
694 : :
695 : : union spdk_nvme_vs_register
696 : 0 : spdk_nvme_ctrlr_get_regs_vs(struct spdk_nvme_ctrlr *ctrlr)
697 : : {
698 : : union spdk_nvme_vs_register vs;
699 : :
700 : 0 : vs.raw = 0;
701 : :
702 : 0 : return vs;
703 : : }
704 : :
705 : : struct spdk_nvme_qpair *
706 : 300 : spdk_nvme_ctrlr_alloc_io_qpair(struct spdk_nvme_ctrlr *ctrlr,
707 : : const struct spdk_nvme_io_qpair_opts *user_opts,
708 : : size_t opts_size)
709 : : {
710 : : struct spdk_nvme_qpair *qpair;
711 : :
712 : 300 : qpair = calloc(1, sizeof(*qpair));
713 [ - + ]: 300 : if (qpair == NULL) {
714 : 0 : return NULL;
715 : : }
716 : :
717 : 300 : qpair->ctrlr = ctrlr;
718 : 300 : TAILQ_INIT(&qpair->outstanding_reqs);
719 : 300 : TAILQ_INSERT_TAIL(&ctrlr->active_io_qpairs, qpair, tailq);
720 : :
721 : 300 : return qpair;
722 : : }
723 : :
724 : : static void
725 : 300 : nvme_poll_group_connect_qpair(struct spdk_nvme_qpair *qpair)
726 : : {
727 : 300 : struct spdk_nvme_poll_group *group = qpair->poll_group;
728 : :
729 : 300 : CU_ASSERT(qpair->poll_group_tailq_head == &group->disconnected_qpairs);
730 : :
731 : 300 : qpair->poll_group_tailq_head = &group->connected_qpairs;
732 [ - + ]: 300 : TAILQ_REMOVE(&group->disconnected_qpairs, qpair, poll_group_tailq);
733 : 300 : TAILQ_INSERT_TAIL(&group->connected_qpairs, qpair, poll_group_tailq);
734 : 300 : }
735 : :
736 : : static void
737 : 300 : nvme_poll_group_disconnect_qpair(struct spdk_nvme_qpair *qpair)
738 : : {
739 : 300 : struct spdk_nvme_poll_group *group = qpair->poll_group;
740 : :
741 : 300 : CU_ASSERT(qpair->poll_group_tailq_head == &group->connected_qpairs);
742 : :
743 : 300 : qpair->poll_group_tailq_head = &group->disconnected_qpairs;
744 [ + + ]: 300 : TAILQ_REMOVE(&group->connected_qpairs, qpair, poll_group_tailq);
745 : 300 : TAILQ_INSERT_TAIL(&group->disconnected_qpairs, qpair, poll_group_tailq);
746 : 300 : }
747 : :
748 : : int
749 : 300 : spdk_nvme_ctrlr_connect_io_qpair(struct spdk_nvme_ctrlr *ctrlr,
750 : : struct spdk_nvme_qpair *qpair)
751 : : {
752 [ - + - + ]: 300 : if (qpair->is_connected) {
753 : 0 : return -EISCONN;
754 : : }
755 : :
756 : 300 : qpair->is_connected = true;
757 : 300 : qpair->failure_reason = SPDK_NVME_QPAIR_FAILURE_NONE;
758 : :
759 [ + - ]: 300 : if (qpair->poll_group) {
760 : 300 : nvme_poll_group_connect_qpair(qpair);
761 : : }
762 : :
763 : 300 : return 0;
764 : : }
765 : :
766 : : void
767 : 597 : spdk_nvme_ctrlr_disconnect_io_qpair(struct spdk_nvme_qpair *qpair)
768 : : {
769 [ + + + + ]: 597 : if (!qpair->is_connected) {
770 : 297 : return;
771 : : }
772 : :
773 : 300 : qpair->is_connected = false;
774 : :
775 [ + - ]: 300 : if (qpair->poll_group != NULL) {
776 : 300 : nvme_poll_group_disconnect_qpair(qpair);
777 : : }
778 : : }
779 : :
780 : : int
781 : 300 : spdk_nvme_ctrlr_free_io_qpair(struct spdk_nvme_qpair *qpair)
782 : : {
783 [ - + ]: 300 : SPDK_CU_ASSERT_FATAL(qpair->ctrlr != NULL);
784 : :
785 [ - + - + ]: 300 : if (qpair->in_completion_context) {
786 : 0 : qpair->delete_after_completion_context = true;
787 : 0 : return 0;
788 : : }
789 : :
790 : 300 : spdk_nvme_ctrlr_disconnect_io_qpair(qpair);
791 : :
792 [ + - ]: 300 : if (qpair->poll_group != NULL) {
793 : 300 : spdk_nvme_poll_group_remove(qpair->poll_group, qpair);
794 : : }
795 : :
796 [ + + ]: 300 : TAILQ_REMOVE(&qpair->ctrlr->active_io_qpairs, qpair, tailq);
797 : :
798 : 300 : CU_ASSERT(qpair->num_outstanding_reqs == 0);
799 : :
800 : 300 : free(qpair);
801 : :
802 : 300 : return 0;
803 : : }
804 : :
805 : : int
806 : 147 : spdk_nvme_ctrlr_reconnect_poll_async(struct spdk_nvme_ctrlr *ctrlr)
807 : : {
808 [ + + + + ]: 147 : if (ctrlr->fail_reset) {
809 : 66 : ctrlr->is_failed = true;
810 : 66 : return -EIO;
811 : : }
812 : :
813 : 81 : ctrlr->adminq.is_connected = true;
814 : 81 : return 0;
815 : : }
816 : :
817 : : void
818 : 147 : spdk_nvme_ctrlr_reconnect_async(struct spdk_nvme_ctrlr *ctrlr)
819 : : {
820 : 147 : }
821 : :
822 : : int
823 : 153 : spdk_nvme_ctrlr_disconnect(struct spdk_nvme_ctrlr *ctrlr)
824 : : {
825 [ + + + + ]: 153 : if (ctrlr->is_removed) {
826 : 3 : return -ENXIO;
827 : : }
828 : :
829 : 150 : ctrlr->adminq.is_connected = false;
830 : 150 : ctrlr->is_failed = false;
831 : :
832 : 150 : return 0;
833 : : }
834 : :
835 : : void
836 : 30 : spdk_nvme_ctrlr_fail(struct spdk_nvme_ctrlr *ctrlr)
837 : : {
838 : 30 : ctrlr->is_failed = true;
839 : 30 : }
840 : :
841 : : bool
842 : 60 : spdk_nvme_ctrlr_is_failed(struct spdk_nvme_ctrlr *ctrlr)
843 : : {
844 [ - + ]: 60 : return ctrlr->is_failed;
845 : : }
846 : :
847 : : spdk_nvme_qp_failure_reason
848 : 279 : spdk_nvme_ctrlr_get_admin_qp_failure_reason(struct spdk_nvme_ctrlr *ctrlr)
849 : : {
850 : 279 : return spdk_nvme_qpair_get_failure_reason(&ctrlr->adminq);
851 : : }
852 : :
853 : : #define UT_ANA_DESC_SIZE (sizeof(struct spdk_nvme_ana_group_descriptor) + \
854 : : sizeof(uint32_t))
855 : : static void
856 : 99 : ut_create_ana_log_page(struct spdk_nvme_ctrlr *ctrlr, char *buf, uint32_t length)
857 : : {
858 : 99 : struct spdk_nvme_ana_page ana_hdr;
859 : 99 : char _ana_desc[UT_ANA_DESC_SIZE];
860 : : struct spdk_nvme_ana_group_descriptor *ana_desc;
861 : : struct spdk_nvme_ns *ns;
862 : : uint32_t i;
863 : :
864 : 99 : memset(&ana_hdr, 0, sizeof(ana_hdr));
865 : 99 : ana_hdr.num_ana_group_desc = ctrlr->num_ns;
866 : :
867 [ - + ]: 99 : SPDK_CU_ASSERT_FATAL(sizeof(ana_hdr) <= length);
868 : 99 : memcpy(buf, (char *)&ana_hdr, sizeof(ana_hdr));
869 : :
870 : 99 : buf += sizeof(ana_hdr);
871 : 99 : length -= sizeof(ana_hdr);
872 : :
873 : 99 : ana_desc = (struct spdk_nvme_ana_group_descriptor *)_ana_desc;
874 : :
875 [ + + ]: 240 : for (i = 0; i < ctrlr->num_ns; i++) {
876 : 141 : ns = &ctrlr->ns[i];
877 : :
878 [ + + + + ]: 141 : if (!ns->is_active) {
879 : 18 : continue;
880 : : }
881 : :
882 [ - + ]: 123 : memset(ana_desc, 0, UT_ANA_DESC_SIZE);
883 : :
884 : 123 : ana_desc->ana_group_id = ns->id;
885 : 123 : ana_desc->num_of_nsid = 1;
886 : 123 : ana_desc->ana_state = ns->ana_state;
887 : 123 : ana_desc->nsid[0] = ns->id;
888 : :
889 [ - + ]: 123 : SPDK_CU_ASSERT_FATAL(UT_ANA_DESC_SIZE <= length);
890 [ - + - + ]: 123 : memcpy(buf, (char *)ana_desc, UT_ANA_DESC_SIZE);
891 : :
892 : 123 : buf += UT_ANA_DESC_SIZE;
893 : 123 : length -= UT_ANA_DESC_SIZE;
894 : : }
895 : 99 : }
896 : :
897 : : int
898 : 99 : spdk_nvme_ctrlr_cmd_get_log_page(struct spdk_nvme_ctrlr *ctrlr,
899 : : uint8_t log_page, uint32_t nsid,
900 : : void *payload, uint32_t payload_size,
901 : : uint64_t offset,
902 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
903 : : {
904 [ + - ]: 99 : if (log_page == SPDK_NVME_LOG_ASYMMETRIC_NAMESPACE_ACCESS) {
905 [ - + ]: 99 : SPDK_CU_ASSERT_FATAL(offset == 0);
906 : 99 : ut_create_ana_log_page(ctrlr, payload, payload_size);
907 : : }
908 : :
909 : 99 : return ut_submit_nvme_request(NULL, &ctrlr->adminq, SPDK_NVME_OPC_GET_LOG_PAGE,
910 : : cb_fn, cb_arg);
911 : : }
912 : :
913 : : int
914 : 12 : spdk_nvme_ctrlr_cmd_admin_raw(struct spdk_nvme_ctrlr *ctrlr,
915 : : struct spdk_nvme_cmd *cmd, void *buf, uint32_t len,
916 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
917 : : {
918 : 12 : return ut_submit_nvme_request(NULL, &ctrlr->adminq, cmd->opc, cb_fn, cb_arg);
919 : : }
920 : :
921 : : int
922 : 15 : spdk_nvme_ctrlr_cmd_abort_ext(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_qpair *qpair,
923 : : void *cmd_cb_arg,
924 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
925 : : {
926 : 15 : struct ut_nvme_req *req = NULL, *abort_req;
927 : :
928 [ + + ]: 15 : if (qpair == NULL) {
929 : 6 : qpair = &ctrlr->adminq;
930 : : }
931 : :
932 : 15 : abort_req = calloc(1, sizeof(*abort_req));
933 [ - + ]: 15 : if (abort_req == NULL) {
934 : 0 : return -ENOMEM;
935 : : }
936 : :
937 [ + + ]: 15 : TAILQ_FOREACH(req, &qpair->outstanding_reqs, tailq) {
938 [ + - ]: 9 : if (req->cb_arg == cmd_cb_arg) {
939 : 9 : break;
940 : : }
941 : : }
942 : :
943 [ + + ]: 15 : if (req == NULL) {
944 : 6 : free(abort_req);
945 : 6 : return -ENOENT;
946 : : }
947 : :
948 : 9 : req->cpl.status.sc = SPDK_NVME_SC_ABORTED_BY_REQUEST;
949 : 9 : req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
950 : :
951 : 9 : abort_req->opc = SPDK_NVME_OPC_ABORT;
952 : 9 : abort_req->cb_fn = cb_fn;
953 : 9 : abort_req->cb_arg = cb_arg;
954 : :
955 : 9 : abort_req->cpl.status.sc = SPDK_NVME_SC_SUCCESS;
956 : 9 : abort_req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
957 : 9 : abort_req->cpl.cdw0 = 0;
958 : :
959 : 9 : TAILQ_INSERT_TAIL(&ctrlr->adminq.outstanding_reqs, abort_req, tailq);
960 : 9 : ctrlr->adminq.num_outstanding_reqs++;
961 : :
962 : 9 : return 0;
963 : : }
964 : :
965 : : int32_t
966 : 438 : spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr)
967 : : {
968 : 438 : return spdk_nvme_qpair_process_completions(&ctrlr->adminq, 0);
969 : : }
970 : :
971 : : uint32_t
972 : 285 : spdk_nvme_ns_get_id(struct spdk_nvme_ns *ns)
973 : : {
974 : 285 : return ns->id;
975 : : }
976 : :
977 : : struct spdk_nvme_ctrlr *
978 : 0 : spdk_nvme_ns_get_ctrlr(struct spdk_nvme_ns *ns)
979 : : {
980 : 0 : return ns->ctrlr;
981 : : }
982 : :
983 : : static inline struct spdk_nvme_ns_data *
984 : 408 : _nvme_ns_get_data(struct spdk_nvme_ns *ns)
985 : : {
986 : 408 : return &ns->ctrlr->nsdata[ns->id - 1];
987 : : }
988 : :
989 : : const struct spdk_nvme_ns_data *
990 : 288 : spdk_nvme_ns_get_data(struct spdk_nvme_ns *ns)
991 : : {
992 : 288 : return _nvme_ns_get_data(ns);
993 : : }
994 : :
995 : : uint64_t
996 : 120 : spdk_nvme_ns_get_num_sectors(struct spdk_nvme_ns *ns)
997 : : {
998 : 120 : return _nvme_ns_get_data(ns)->nsze;
999 : : }
1000 : :
1001 : : const struct spdk_uuid *
1002 : 249 : spdk_nvme_ns_get_uuid(const struct spdk_nvme_ns *ns)
1003 : : {
1004 : 249 : return ns->uuid;
1005 : : }
1006 : :
1007 : : enum spdk_nvme_csi
1008 : 219 : spdk_nvme_ns_get_csi(const struct spdk_nvme_ns *ns) {
1009 : 219 : return ns->csi;
1010 : : }
1011 : :
1012 : : int
1013 : 6 : spdk_nvme_ns_cmd_read_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
1014 : : void *metadata, uint64_t lba, uint32_t lba_count,
1015 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1016 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
1017 : : {
1018 : 6 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_READ, cb_fn, cb_arg);
1019 : : }
1020 : :
1021 : : int
1022 : 75 : spdk_nvme_ns_cmd_write_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1023 : : void *buffer, void *metadata, uint64_t lba,
1024 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1025 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
1026 : : {
1027 : 75 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_WRITE, cb_fn, cb_arg);
1028 : : }
1029 : :
1030 : : int
1031 : 0 : spdk_nvme_ns_cmd_readv_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1032 : : uint64_t lba, uint32_t lba_count,
1033 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
1034 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
1035 : : spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
1036 : : uint16_t apptag_mask, uint16_t apptag)
1037 : : {
1038 : 0 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_READ, cb_fn, cb_arg);
1039 : : }
1040 : :
1041 : : int
1042 : 6 : spdk_nvme_ns_cmd_writev_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1043 : : uint64_t lba, uint32_t lba_count,
1044 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
1045 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
1046 : : spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
1047 : : uint16_t apptag_mask, uint16_t apptag)
1048 : : {
1049 : 6 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_WRITE, cb_fn, cb_arg);
1050 : : }
1051 : :
1052 : : static bool g_ut_readv_ext_called;
1053 : : int
1054 : 3 : spdk_nvme_ns_cmd_readv_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1055 : : uint64_t lba, uint32_t lba_count,
1056 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1057 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
1058 : : spdk_nvme_req_next_sge_cb next_sge_fn,
1059 : : struct spdk_nvme_ns_cmd_ext_io_opts *opts)
1060 : : {
1061 : 3 : g_ut_readv_ext_called = true;
1062 : 3 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_READ, cb_fn, cb_arg);
1063 : : }
1064 : :
1065 : : static bool g_ut_writev_ext_called;
1066 : : int
1067 : 0 : spdk_nvme_ns_cmd_writev_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1068 : : uint64_t lba, uint32_t lba_count,
1069 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1070 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
1071 : : spdk_nvme_req_next_sge_cb next_sge_fn,
1072 : : struct spdk_nvme_ns_cmd_ext_io_opts *opts)
1073 : : {
1074 : 0 : g_ut_writev_ext_called = true;
1075 : 0 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_WRITE, cb_fn, cb_arg);
1076 : : }
1077 : :
1078 : : int
1079 : 9 : spdk_nvme_ns_cmd_comparev_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1080 : : uint64_t lba, uint32_t lba_count,
1081 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
1082 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
1083 : : spdk_nvme_req_next_sge_cb next_sge_fn,
1084 : : void *metadata, uint16_t apptag_mask, uint16_t apptag)
1085 : : {
1086 : 9 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_COMPARE, cb_fn, cb_arg);
1087 : : }
1088 : :
1089 : : int
1090 : 3 : spdk_nvme_ns_cmd_dataset_management(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1091 : : uint32_t type, const struct spdk_nvme_dsm_range *ranges, uint16_t num_ranges,
1092 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1093 : : {
1094 : 3 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_DATASET_MANAGEMENT, cb_fn, cb_arg);
1095 : : }
1096 : :
1097 : : int
1098 : 0 : spdk_nvme_ns_cmd_write_zeroes(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1099 : : uint64_t lba, uint32_t lba_count,
1100 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1101 : : uint32_t io_flags)
1102 : : {
1103 : 0 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_WRITE_ZEROES, cb_fn, cb_arg);
1104 : : }
1105 : :
1106 : : int
1107 : 0 : spdk_nvme_ns_cmd_copy(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1108 : : const struct spdk_nvme_scc_source_range *ranges,
1109 : : uint16_t num_ranges, uint64_t dest_lba,
1110 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1111 : : {
1112 : 0 : return ut_submit_nvme_request(ns, qpair, SPDK_NVME_OPC_COPY, cb_fn, cb_arg);
1113 : : }
1114 : :
1115 : : struct spdk_nvme_poll_group *
1116 : 126 : spdk_nvme_poll_group_create(void *ctx, struct spdk_nvme_accel_fn_table *table)
1117 : : {
1118 : : struct spdk_nvme_poll_group *group;
1119 : :
1120 : 126 : group = calloc(1, sizeof(*group));
1121 [ - + ]: 126 : if (group == NULL) {
1122 : 0 : return NULL;
1123 : : }
1124 : :
1125 : 126 : group->ctx = ctx;
1126 [ + - ]: 126 : if (table != NULL) {
1127 : 126 : group->accel_fn_table = *table;
1128 : : }
1129 : 126 : TAILQ_INIT(&group->connected_qpairs);
1130 : 126 : TAILQ_INIT(&group->disconnected_qpairs);
1131 : :
1132 : 126 : return group;
1133 : : }
1134 : :
1135 : : int
1136 : 126 : spdk_nvme_poll_group_destroy(struct spdk_nvme_poll_group *group)
1137 : : {
1138 [ + - ]: 126 : if (!TAILQ_EMPTY(&group->connected_qpairs) ||
1139 [ - + ]: 126 : !TAILQ_EMPTY(&group->disconnected_qpairs)) {
1140 : 0 : return -EBUSY;
1141 : : }
1142 : :
1143 : 126 : free(group);
1144 : :
1145 : 126 : return 0;
1146 : : }
1147 : :
1148 : : spdk_nvme_qp_failure_reason
1149 : 525 : spdk_nvme_qpair_get_failure_reason(struct spdk_nvme_qpair *qpair)
1150 : : {
1151 : 525 : return qpair->failure_reason;
1152 : : }
1153 : :
1154 : : bool
1155 : 129 : spdk_nvme_qpair_is_connected(struct spdk_nvme_qpair *qpair)
1156 : : {
1157 [ - + ]: 129 : return qpair->is_connected;
1158 : : }
1159 : :
1160 : : int32_t
1161 : 2700 : spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair,
1162 : : uint32_t max_completions)
1163 : : {
1164 : : struct ut_nvme_req *req, *tmp;
1165 : 2700 : uint32_t num_completions = 0;
1166 : :
1167 [ + + + + ]: 2700 : if (!qpair->is_connected) {
1168 : 159 : return -ENXIO;
1169 : : }
1170 : :
1171 : 2541 : qpair->in_completion_context = true;
1172 : :
1173 [ + + ]: 2763 : TAILQ_FOREACH_SAFE(req, &qpair->outstanding_reqs, tailq, tmp) {
1174 [ + + ]: 222 : TAILQ_REMOVE(&qpair->outstanding_reqs, req, tailq);
1175 : 222 : qpair->num_outstanding_reqs--;
1176 : :
1177 : 222 : req->cb_fn(req->cb_arg, &req->cpl);
1178 : :
1179 : 222 : free(req);
1180 : 222 : num_completions++;
1181 : : }
1182 : :
1183 : 2541 : qpair->in_completion_context = false;
1184 [ - + - + ]: 2541 : if (qpair->delete_after_completion_context) {
1185 : 0 : spdk_nvme_ctrlr_free_io_qpair(qpair);
1186 : : }
1187 : :
1188 : 2541 : return num_completions;
1189 : : }
1190 : :
1191 : : int64_t
1192 : 3054 : spdk_nvme_poll_group_process_completions(struct spdk_nvme_poll_group *group,
1193 : : uint32_t completions_per_qpair,
1194 : : spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb)
1195 : : {
1196 : : struct spdk_nvme_qpair *qpair, *tmp_qpair;
1197 : 3054 : int64_t local_completions = 0, error_reason = 0, num_completions = 0;
1198 : :
1199 [ - + ]: 3054 : SPDK_CU_ASSERT_FATAL(completions_per_qpair == 0);
1200 : :
1201 [ - + ]: 3054 : if (disconnected_qpair_cb == NULL) {
1202 : 0 : return -EINVAL;
1203 : : }
1204 : :
1205 [ + + ]: 3351 : TAILQ_FOREACH_SAFE(qpair, &group->disconnected_qpairs, poll_group_tailq, tmp_qpair) {
1206 : 297 : disconnected_qpair_cb(qpair, group->ctx);
1207 : : }
1208 : :
1209 [ + + ]: 5328 : TAILQ_FOREACH_SAFE(qpair, &group->connected_qpairs, poll_group_tailq, tmp_qpair) {
1210 [ + + ]: 2274 : if (qpair->failure_reason != SPDK_NVME_QPAIR_FAILURE_NONE) {
1211 : 12 : spdk_nvme_ctrlr_disconnect_io_qpair(qpair);
1212 : : /* Bump the number of completions so this counts as "busy" */
1213 : 12 : num_completions++;
1214 : 12 : continue;
1215 : : }
1216 : :
1217 : 2262 : local_completions = spdk_nvme_qpair_process_completions(qpair,
1218 : : completions_per_qpair);
1219 [ - + - - ]: 2262 : if (local_completions < 0 && error_reason == 0) {
1220 : 0 : error_reason = local_completions;
1221 : : } else {
1222 : 2262 : num_completions += local_completions;
1223 [ - + ]: 2262 : assert(num_completions >= 0);
1224 : : }
1225 : : }
1226 : :
1227 [ - + ]: 3054 : return error_reason ? error_reason : num_completions;
1228 : : }
1229 : :
1230 : : int
1231 : 300 : spdk_nvme_poll_group_add(struct spdk_nvme_poll_group *group,
1232 : : struct spdk_nvme_qpair *qpair)
1233 : : {
1234 [ - + ]: 300 : CU_ASSERT(!qpair->is_connected);
1235 : :
1236 : 300 : qpair->poll_group = group;
1237 : 300 : qpair->poll_group_tailq_head = &group->disconnected_qpairs;
1238 : 300 : TAILQ_INSERT_TAIL(&group->disconnected_qpairs, qpair, poll_group_tailq);
1239 : :
1240 : 300 : return 0;
1241 : : }
1242 : :
1243 : : int
1244 : 300 : spdk_nvme_poll_group_remove(struct spdk_nvme_poll_group *group,
1245 : : struct spdk_nvme_qpair *qpair)
1246 : : {
1247 [ - + ]: 300 : CU_ASSERT(!qpair->is_connected);
1248 : :
1249 [ - + ]: 300 : if (qpair->poll_group == NULL) {
1250 : 0 : return -ENOENT;
1251 : : }
1252 : :
1253 : 300 : CU_ASSERT(qpair->poll_group_tailq_head == &group->disconnected_qpairs);
1254 : :
1255 [ + + ]: 300 : TAILQ_REMOVE(&group->disconnected_qpairs, qpair, poll_group_tailq);
1256 : :
1257 : 300 : qpair->poll_group = NULL;
1258 : 300 : qpair->poll_group_tailq_head = NULL;
1259 : :
1260 : 300 : return 0;
1261 : : }
1262 : :
1263 : : int
1264 : 111 : spdk_bdev_register(struct spdk_bdev *bdev)
1265 : : {
1266 : 111 : g_ut_registered_bdev = bdev;
1267 : :
1268 : 111 : return g_ut_register_bdev_status;
1269 : : }
1270 : :
1271 : : void
1272 : 99 : spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg)
1273 : : {
1274 : : int rc;
1275 : :
1276 : 99 : rc = bdev->fn_table->destruct(bdev->ctxt);
1277 : :
1278 [ + + ]: 99 : if (bdev == g_ut_registered_bdev) {
1279 : 69 : g_ut_registered_bdev = NULL;
1280 : : }
1281 : :
1282 [ + - - + ]: 99 : if (rc <= 0 && cb_fn != NULL) {
1283 : 0 : cb_fn(cb_arg, rc);
1284 : : }
1285 : 99 : }
1286 : :
1287 : : int
1288 : 18 : spdk_bdev_open_ext(const char *bdev_name, bool write,
1289 : : spdk_bdev_event_cb_t event_cb, void *event_ctx,
1290 : : struct spdk_bdev_desc **desc)
1291 : : {
1292 [ + - ]: 18 : if (g_ut_registered_bdev == NULL ||
1293 [ - + - + : 18 : strcmp(g_ut_registered_bdev->name, bdev_name) != 0) {
- + ]
1294 : 0 : return -ENODEV;
1295 : : }
1296 : :
1297 : 18 : *desc = (struct spdk_bdev_desc *)g_ut_registered_bdev;
1298 : :
1299 : 18 : return 0;
1300 : : }
1301 : :
1302 : : struct spdk_bdev *
1303 : 18 : spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
1304 : : {
1305 : 18 : return (struct spdk_bdev *)desc;
1306 : : }
1307 : :
1308 : : int
1309 : 3 : spdk_bdev_notify_blockcnt_change(struct spdk_bdev *bdev, uint64_t size)
1310 : : {
1311 : 3 : bdev->blockcnt = size;
1312 : :
1313 : 3 : return 0;
1314 : : }
1315 : :
1316 : : struct spdk_io_channel *
1317 : 93 : spdk_bdev_io_get_io_channel(struct spdk_bdev_io *bdev_io)
1318 : : {
1319 : 93 : return (struct spdk_io_channel *)bdev_io->internal.ch;
1320 : : }
1321 : :
1322 : : struct spdk_thread *
1323 : 39 : spdk_bdev_io_get_thread(struct spdk_bdev_io *bdev_io)
1324 : : {
1325 : 39 : return spdk_io_channel_get_thread(spdk_bdev_io_get_io_channel(bdev_io));
1326 : : }
1327 : :
1328 : : void
1329 : 141 : spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status)
1330 : : {
1331 : 141 : bdev_io->internal.status = status;
1332 : 141 : bdev_io->internal.in_submit_request = false;
1333 : 141 : }
1334 : :
1335 : : void
1336 : 87 : spdk_bdev_io_complete_nvme_status(struct spdk_bdev_io *bdev_io, uint32_t cdw0, int sct, int sc)
1337 : : {
1338 [ + + + + ]: 87 : if (sct == SPDK_NVME_SCT_GENERIC && sc == SPDK_NVME_SC_SUCCESS) {
1339 : 69 : bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
1340 [ + + + + ]: 18 : } else if (sct == SPDK_NVME_SCT_GENERIC && sc == SPDK_NVME_SC_ABORTED_BY_REQUEST) {
1341 : 12 : bdev_io->internal.status = SPDK_BDEV_IO_STATUS_ABORTED;
1342 : : } else {
1343 : 6 : bdev_io->internal.status = SPDK_BDEV_IO_STATUS_NVME_ERROR;
1344 : : }
1345 : :
1346 : 87 : bdev_io->internal.error.nvme.cdw0 = cdw0;
1347 : 87 : bdev_io->internal.error.nvme.sct = sct;
1348 : 87 : bdev_io->internal.error.nvme.sc = sc;
1349 : :
1350 : 87 : spdk_bdev_io_complete(bdev_io, bdev_io->internal.status);
1351 : 87 : }
1352 : :
1353 : : void
1354 : 3 : spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, uint64_t len)
1355 : : {
1356 : 3 : struct spdk_io_channel *ch = spdk_bdev_io_get_io_channel(bdev_io);
1357 : :
1358 : 3 : ut_bdev_io_set_buf(bdev_io);
1359 : :
1360 : 3 : cb(ch, bdev_io, true);
1361 : 3 : }
1362 : :
1363 : : static void
1364 : 3 : test_create_ctrlr(void)
1365 : : {
1366 : 3 : struct spdk_nvme_transport_id trid = {};
1367 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
1368 : : int rc;
1369 : :
1370 : 3 : ut_init_trid(&trid);
1371 : :
1372 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid, NULL);
1373 : 3 : CU_ASSERT(rc == 0);
1374 : :
1375 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") != NULL);
1376 : :
1377 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
1378 : 3 : CU_ASSERT(rc == 0);
1379 : :
1380 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") != NULL);
1381 : :
1382 : 3 : poll_threads();
1383 : 3 : spdk_delay_us(1000);
1384 : 3 : poll_threads();
1385 : :
1386 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
1387 : 3 : }
1388 : :
1389 : : static void
1390 : 3 : ut_check_hotplug_on_reset(void *cb_arg, int rc)
1391 : : {
1392 : 3 : bool *detect_remove = cb_arg;
1393 : :
1394 : 3 : CU_ASSERT(rc != 0);
1395 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(detect_remove != NULL);
1396 : :
1397 : 3 : *detect_remove = true;
1398 : 3 : }
1399 : :
1400 : : static void
1401 : 3 : test_reset_ctrlr(void)
1402 : : {
1403 : 3 : struct spdk_nvme_transport_id trid = {};
1404 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
1405 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
1406 : : struct nvme_path_id *curr_trid;
1407 : : struct spdk_io_channel *ch1, *ch2;
1408 : : struct nvme_ctrlr_channel *ctrlr_ch1, *ctrlr_ch2;
1409 : 3 : bool detect_remove;
1410 : : int rc;
1411 : :
1412 : 3 : ut_init_trid(&trid);
1413 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
1414 : :
1415 : 3 : set_thread(0);
1416 : :
1417 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid, NULL);
1418 : 3 : CU_ASSERT(rc == 0);
1419 : :
1420 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
1421 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
1422 : :
1423 : 3 : curr_trid = TAILQ_FIRST(&nvme_ctrlr->trids);
1424 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_trid != NULL);
1425 : :
1426 : 3 : ch1 = spdk_get_io_channel(nvme_ctrlr);
1427 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
1428 : :
1429 : 3 : ctrlr_ch1 = spdk_io_channel_get_ctx(ch1);
1430 : 3 : CU_ASSERT(ctrlr_ch1->qpair != NULL);
1431 : :
1432 : 3 : set_thread(1);
1433 : :
1434 : 3 : ch2 = spdk_get_io_channel(nvme_ctrlr);
1435 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
1436 : :
1437 : 3 : ctrlr_ch2 = spdk_io_channel_get_ctx(ch2);
1438 : 3 : CU_ASSERT(ctrlr_ch2->qpair != NULL);
1439 : :
1440 : : /* Reset starts from thread 1. */
1441 : 3 : set_thread(1);
1442 : :
1443 : : /* Case 1: ctrlr is already being destructed. */
1444 : 3 : nvme_ctrlr->destruct = true;
1445 : :
1446 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
1447 : 3 : CU_ASSERT(rc == -ENXIO);
1448 : :
1449 : : /* Case 2: reset is in progress. */
1450 : 3 : nvme_ctrlr->destruct = false;
1451 : 3 : nvme_ctrlr->resetting = true;
1452 : :
1453 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
1454 : 3 : CU_ASSERT(rc == -EBUSY);
1455 : :
1456 : : /* Case 3: reset completes successfully. */
1457 : 3 : nvme_ctrlr->resetting = false;
1458 : 3 : curr_trid->last_failed_tsc = spdk_get_ticks();
1459 : 3 : ctrlr.is_failed = true;
1460 : :
1461 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
1462 : 3 : CU_ASSERT(rc == 0);
1463 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1464 : 3 : CU_ASSERT(ctrlr_ch1->qpair != NULL);
1465 : 3 : CU_ASSERT(ctrlr_ch2->qpair != NULL);
1466 : :
1467 : 3 : poll_thread_times(0, 3);
1468 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
1469 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair != NULL);
1470 : :
1471 : 3 : poll_thread_times(0, 1);
1472 : 3 : poll_thread_times(1, 1);
1473 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
1474 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
1475 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == true);
1476 : :
1477 : 3 : poll_thread_times(1, 1);
1478 : 3 : poll_thread_times(0, 1);
1479 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == false);
1480 [ - + ]: 3 : CU_ASSERT(ctrlr.adminq.is_connected == false);
1481 : :
1482 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
1483 : 3 : poll_thread_times(0, 2);
1484 [ - + ]: 3 : CU_ASSERT(ctrlr.adminq.is_connected == true);
1485 : :
1486 : 3 : poll_thread_times(0, 1);
1487 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair != NULL);
1488 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
1489 : :
1490 : 3 : poll_thread_times(1, 1);
1491 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair != NULL);
1492 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair != NULL);
1493 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1494 : 3 : CU_ASSERT(curr_trid->last_failed_tsc != 0);
1495 : :
1496 : 3 : poll_thread_times(0, 2);
1497 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1498 : 3 : CU_ASSERT(curr_trid->last_failed_tsc == 0);
1499 : 3 : poll_thread_times(1, 1);
1500 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1501 : 3 : poll_thread_times(0, 1);
1502 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
1503 : :
1504 : : /* Case 4: ctrlr is already removed. */
1505 : 3 : ctrlr.is_removed = true;
1506 : :
1507 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
1508 : 3 : CU_ASSERT(rc == 0);
1509 : :
1510 : 3 : detect_remove = false;
1511 : 3 : nvme_ctrlr->ctrlr_op_cb_fn = ut_check_hotplug_on_reset;
1512 : 3 : nvme_ctrlr->ctrlr_op_cb_arg = &detect_remove;
1513 : :
1514 : 3 : poll_threads();
1515 : :
1516 : 3 : CU_ASSERT(nvme_ctrlr->ctrlr_op_cb_fn == NULL);
1517 : 3 : CU_ASSERT(nvme_ctrlr->ctrlr_op_cb_arg == NULL);
1518 [ - + ]: 3 : CU_ASSERT(detect_remove == true);
1519 : :
1520 : 3 : ctrlr.is_removed = false;
1521 : :
1522 : 3 : spdk_put_io_channel(ch2);
1523 : :
1524 : 3 : set_thread(0);
1525 : :
1526 : 3 : spdk_put_io_channel(ch1);
1527 : :
1528 : 3 : poll_threads();
1529 : :
1530 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
1531 : 3 : CU_ASSERT(rc == 0);
1532 : :
1533 : 3 : poll_threads();
1534 : 3 : spdk_delay_us(1000);
1535 : 3 : poll_threads();
1536 : :
1537 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
1538 : 3 : }
1539 : :
1540 : : static void
1541 : 3 : test_race_between_reset_and_destruct_ctrlr(void)
1542 : : {
1543 : 3 : struct spdk_nvme_transport_id trid = {};
1544 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
1545 : : struct nvme_ctrlr *nvme_ctrlr;
1546 : : struct spdk_io_channel *ch1, *ch2;
1547 : : int rc;
1548 : :
1549 : 3 : ut_init_trid(&trid);
1550 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
1551 : :
1552 : 3 : set_thread(0);
1553 : :
1554 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid, NULL);
1555 : 3 : CU_ASSERT(rc == 0);
1556 : :
1557 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
1558 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
1559 : :
1560 : 3 : ch1 = spdk_get_io_channel(nvme_ctrlr);
1561 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
1562 : :
1563 : 3 : set_thread(1);
1564 : :
1565 : 3 : ch2 = spdk_get_io_channel(nvme_ctrlr);
1566 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
1567 : :
1568 : : /* Reset starts from thread 1. */
1569 : 3 : set_thread(1);
1570 : :
1571 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
1572 : 3 : CU_ASSERT(rc == 0);
1573 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1574 : :
1575 : : /* Try destructing ctrlr while ctrlr is being reset, but it will be deferred. */
1576 : 3 : set_thread(0);
1577 : :
1578 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
1579 : 3 : CU_ASSERT(rc == 0);
1580 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == nvme_ctrlr);
1581 : 3 : CU_ASSERT(nvme_ctrlr->destruct == true);
1582 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1583 : :
1584 : 3 : poll_threads();
1585 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
1586 : 3 : poll_threads();
1587 : :
1588 : : /* Reset completed but ctrlr is not still destructed yet. */
1589 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == nvme_ctrlr);
1590 : 3 : CU_ASSERT(nvme_ctrlr->destruct == true);
1591 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
1592 : :
1593 : : /* New reset request is rejected. */
1594 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
1595 : 3 : CU_ASSERT(rc == -ENXIO);
1596 : :
1597 : : /* Additional polling called spdk_io_device_unregister() to ctrlr,
1598 : : * However there are two channels and destruct is not completed yet.
1599 : : */
1600 : 3 : poll_threads();
1601 : :
1602 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == nvme_ctrlr);
1603 : :
1604 : 3 : set_thread(0);
1605 : :
1606 : 3 : spdk_put_io_channel(ch1);
1607 : :
1608 : 3 : set_thread(1);
1609 : :
1610 : 3 : spdk_put_io_channel(ch2);
1611 : :
1612 : 3 : poll_threads();
1613 : 3 : spdk_delay_us(1000);
1614 : 3 : poll_threads();
1615 : :
1616 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
1617 : 3 : }
1618 : :
1619 : : static void
1620 : 3 : test_failover_ctrlr(void)
1621 : : {
1622 : 3 : struct spdk_nvme_transport_id trid1 = {}, trid2 = {};
1623 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
1624 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
1625 : : struct nvme_path_id *curr_trid, *next_trid;
1626 : : struct spdk_io_channel *ch1, *ch2;
1627 : : int rc;
1628 : :
1629 : 3 : ut_init_trid(&trid1);
1630 : 3 : ut_init_trid2(&trid2);
1631 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
1632 : :
1633 : 3 : set_thread(0);
1634 : :
1635 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid1, NULL);
1636 : 3 : CU_ASSERT(rc == 0);
1637 : :
1638 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
1639 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
1640 : :
1641 : 3 : ch1 = spdk_get_io_channel(nvme_ctrlr);
1642 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
1643 : :
1644 : 3 : set_thread(1);
1645 : :
1646 : 3 : ch2 = spdk_get_io_channel(nvme_ctrlr);
1647 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
1648 : :
1649 : : /* First, test one trid case. */
1650 : 3 : curr_trid = TAILQ_FIRST(&nvme_ctrlr->trids);
1651 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_trid != NULL);
1652 : :
1653 : : /* Failover starts from thread 1. */
1654 : 3 : set_thread(1);
1655 : :
1656 : : /* Case 1: ctrlr is already being destructed. */
1657 : 3 : nvme_ctrlr->destruct = true;
1658 : :
1659 : 3 : rc = bdev_nvme_failover_ctrlr(nvme_ctrlr);
1660 : 3 : CU_ASSERT(rc == -ENXIO);
1661 : 3 : CU_ASSERT(curr_trid->last_failed_tsc == 0);
1662 : :
1663 : : /* Case 2: reset is in progress. */
1664 : 3 : nvme_ctrlr->destruct = false;
1665 : 3 : nvme_ctrlr->resetting = true;
1666 : :
1667 : 3 : rc = bdev_nvme_failover_ctrlr(nvme_ctrlr);
1668 : 3 : CU_ASSERT(rc == -EINPROGRESS);
1669 : :
1670 : : /* Case 3: reset completes successfully. */
1671 : 3 : nvme_ctrlr->resetting = false;
1672 : :
1673 : 3 : rc = bdev_nvme_failover_ctrlr(nvme_ctrlr);
1674 : 3 : CU_ASSERT(rc == 0);
1675 : :
1676 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1677 : 3 : CU_ASSERT(curr_trid->last_failed_tsc != 0);
1678 : :
1679 : 3 : poll_threads();
1680 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
1681 : 3 : poll_threads();
1682 : :
1683 : 3 : curr_trid = TAILQ_FIRST(&nvme_ctrlr->trids);
1684 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_trid != NULL);
1685 : :
1686 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
1687 : 3 : CU_ASSERT(curr_trid->last_failed_tsc == 0);
1688 : :
1689 : 3 : set_thread(0);
1690 : :
1691 : : /* Second, test two trids case. */
1692 : 3 : rc = bdev_nvme_add_secondary_trid(nvme_ctrlr, &ctrlr, &trid2);
1693 : 3 : CU_ASSERT(rc == 0);
1694 : :
1695 : 3 : curr_trid = TAILQ_FIRST(&nvme_ctrlr->trids);
1696 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_trid != NULL);
1697 : 3 : CU_ASSERT(curr_trid == nvme_ctrlr->active_path_id);
1698 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&curr_trid->trid, &trid1) == 0);
1699 : :
1700 : : /* Failover starts from thread 1. */
1701 : 3 : set_thread(1);
1702 : :
1703 : : /* Case 4: reset is in progress. */
1704 : 3 : nvme_ctrlr->resetting = true;
1705 : :
1706 : 3 : rc = bdev_nvme_failover_ctrlr(nvme_ctrlr);
1707 : 3 : CU_ASSERT(rc == -EINPROGRESS);
1708 : :
1709 : : /* Case 5: failover completes successfully. */
1710 : 3 : nvme_ctrlr->resetting = false;
1711 : :
1712 : 3 : rc = bdev_nvme_failover_ctrlr(nvme_ctrlr);
1713 : 3 : CU_ASSERT(rc == 0);
1714 : :
1715 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1716 : :
1717 : 3 : next_trid = TAILQ_FIRST(&nvme_ctrlr->trids);
1718 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(next_trid != NULL);
1719 : 3 : CU_ASSERT(next_trid != curr_trid);
1720 : 3 : CU_ASSERT(next_trid == nvme_ctrlr->active_path_id);
1721 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&next_trid->trid, &trid2) == 0);
1722 : :
1723 : 3 : poll_threads();
1724 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
1725 : 3 : poll_threads();
1726 : :
1727 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
1728 : :
1729 : 3 : spdk_put_io_channel(ch2);
1730 : :
1731 : 3 : set_thread(0);
1732 : :
1733 : 3 : spdk_put_io_channel(ch1);
1734 : :
1735 : 3 : poll_threads();
1736 : :
1737 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
1738 : 3 : CU_ASSERT(rc == 0);
1739 : :
1740 : 3 : poll_threads();
1741 : 3 : spdk_delay_us(1000);
1742 : 3 : poll_threads();
1743 : :
1744 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
1745 : 3 : }
1746 : :
1747 : : /* We had a bug when running test/nvmf/host/multipath.sh. The bug was the following.
1748 : : *
1749 : : * A nvme_ctrlr had trid1 and trid2 first. trid1 was active. A connection to trid1 was
1750 : : * disconnected and reset ctrlr failed repeatedly before starting failover from trid1
1751 : : * to trid2. While processing the failed reset, trid3 was added. trid1 should
1752 : : * have been active, i.e., the head of the list until the failover completed.
1753 : : * However trid3 was inserted to the head of the list by mistake.
1754 : : *
1755 : : * I/O qpairs have smaller polling period than admin qpair. When a connection is
1756 : : * detected, I/O qpair may detect the error earlier than admin qpair. I/O qpair error
1757 : : * invokes reset ctrlr and admin qpair error invokes failover ctrlr. Hence reset ctrlr
1758 : : * may be executed repeatedly before failover is executed. Hence this bug is real.
1759 : : *
1760 : : * The following test verifies the fix.
1761 : : */
1762 : : static void
1763 : 3 : test_race_between_failover_and_add_secondary_trid(void)
1764 : : {
1765 : 3 : struct spdk_nvme_transport_id trid1 = {}, trid2 = {}, trid3 = {};
1766 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
1767 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
1768 : : struct nvme_path_id *path_id1, *path_id2, *path_id3;
1769 : : struct spdk_io_channel *ch1, *ch2;
1770 : : int rc;
1771 : :
1772 : 3 : ut_init_trid(&trid1);
1773 : 3 : ut_init_trid2(&trid2);
1774 : 3 : ut_init_trid3(&trid3);
1775 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
1776 : :
1777 : 3 : set_thread(0);
1778 : :
1779 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid1, NULL);
1780 : 3 : CU_ASSERT(rc == 0);
1781 : :
1782 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
1783 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
1784 : :
1785 : 3 : ch1 = spdk_get_io_channel(nvme_ctrlr);
1786 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
1787 : :
1788 : 3 : set_thread(1);
1789 : :
1790 : 3 : ch2 = spdk_get_io_channel(nvme_ctrlr);
1791 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
1792 : :
1793 : 3 : set_thread(0);
1794 : :
1795 : 3 : rc = bdev_nvme_add_secondary_trid(nvme_ctrlr, &ctrlr, &trid2);
1796 : 3 : CU_ASSERT(rc == 0);
1797 : :
1798 : 3 : path_id1 = TAILQ_FIRST(&nvme_ctrlr->trids);
1799 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(path_id1 != NULL);
1800 : 3 : CU_ASSERT(path_id1 == nvme_ctrlr->active_path_id);
1801 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&path_id1->trid, &trid1) == 0);
1802 : 3 : path_id2 = TAILQ_NEXT(path_id1, link);
1803 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(path_id2 != NULL);
1804 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&path_id2->trid, &trid2) == 0);
1805 : :
1806 : 3 : ctrlr.fail_reset = true;
1807 : :
1808 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
1809 : 3 : CU_ASSERT(rc == 0);
1810 : :
1811 : 3 : poll_threads();
1812 : :
1813 : 3 : CU_ASSERT(path_id1->last_failed_tsc != 0);
1814 : 3 : CU_ASSERT(path_id1 == nvme_ctrlr->active_path_id);
1815 : :
1816 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
1817 : 3 : CU_ASSERT(rc == 0);
1818 : :
1819 : 3 : rc = bdev_nvme_add_secondary_trid(nvme_ctrlr, &ctrlr, &trid3);
1820 : 3 : CU_ASSERT(rc == 0);
1821 : :
1822 : 3 : CU_ASSERT(path_id1 == TAILQ_FIRST(&nvme_ctrlr->trids));
1823 : 3 : CU_ASSERT(path_id1 == nvme_ctrlr->active_path_id);
1824 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&path_id1->trid, &trid1) == 0);
1825 : 3 : CU_ASSERT(path_id2 == TAILQ_NEXT(path_id1, link));
1826 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&path_id2->trid, &trid2) == 0);
1827 : 3 : path_id3 = TAILQ_NEXT(path_id2, link);
1828 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(path_id3 != NULL);
1829 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&path_id3->trid, &trid3) == 0);
1830 : :
1831 : 3 : poll_threads();
1832 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
1833 : 3 : poll_threads();
1834 : :
1835 : 3 : spdk_put_io_channel(ch1);
1836 : :
1837 : 3 : set_thread(1);
1838 : :
1839 : 3 : spdk_put_io_channel(ch2);
1840 : :
1841 : 3 : poll_threads();
1842 : :
1843 : 3 : set_thread(0);
1844 : :
1845 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
1846 : 3 : CU_ASSERT(rc == 0);
1847 : :
1848 : 3 : poll_threads();
1849 : 3 : spdk_delay_us(1000);
1850 : 3 : poll_threads();
1851 : :
1852 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
1853 : 3 : }
1854 : :
1855 : : static void
1856 : 153 : attach_ctrlr_done(void *cb_ctx, size_t bdev_count, int rc)
1857 : : {
1858 : 153 : CU_ASSERT(rc == g_ut_attach_ctrlr_status);
1859 : 153 : CU_ASSERT(bdev_count == g_ut_attach_bdev_count);
1860 : 153 : }
1861 : :
1862 : : static void
1863 : 3 : test_pending_reset(void)
1864 : 3 : {
1865 : 3 : struct spdk_nvme_transport_id trid = {};
1866 : : struct spdk_nvme_ctrlr *ctrlr;
1867 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
1868 : 3 : const int STRING_SIZE = 32;
1869 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
1870 : : struct nvme_bdev *bdev;
1871 : : struct spdk_bdev_io *first_bdev_io, *second_bdev_io;
1872 : : struct spdk_io_channel *ch1, *ch2;
1873 : : struct nvme_bdev_channel *nbdev_ch1, *nbdev_ch2;
1874 : : struct nvme_io_path *io_path1, *io_path2;
1875 : : struct nvme_ctrlr_channel *ctrlr_ch1, *ctrlr_ch2;
1876 : : int rc;
1877 : :
1878 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
1879 : 3 : ut_init_trid(&trid);
1880 : :
1881 : 3 : set_thread(0);
1882 : :
1883 : 3 : ctrlr = ut_attach_ctrlr(&trid, 1, false, false);
1884 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
1885 : :
1886 : 3 : g_ut_attach_ctrlr_status = 0;
1887 : 3 : g_ut_attach_bdev_count = 1;
1888 : :
1889 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
1890 : : attach_ctrlr_done, NULL, NULL, NULL, false);
1891 : 3 : CU_ASSERT(rc == 0);
1892 : :
1893 : 3 : spdk_delay_us(1000);
1894 : 3 : poll_threads();
1895 : :
1896 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
1897 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
1898 : :
1899 : 3 : bdev = nvme_ctrlr_get_ns(nvme_ctrlr, 1)->bdev;
1900 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
1901 : :
1902 : 3 : ch1 = spdk_get_io_channel(bdev);
1903 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
1904 : :
1905 : 3 : nbdev_ch1 = spdk_io_channel_get_ctx(ch1);
1906 : 3 : io_path1 = STAILQ_FIRST(&nbdev_ch1->io_path_list);
1907 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path1 != NULL);
1908 : 3 : ctrlr_ch1 = io_path1->qpair->ctrlr_ch;
1909 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr_ch1 != NULL);
1910 : :
1911 : 3 : set_thread(1);
1912 : :
1913 : 3 : ch2 = spdk_get_io_channel(bdev);
1914 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
1915 : :
1916 : 3 : nbdev_ch2 = spdk_io_channel_get_ctx(ch2);
1917 : 3 : io_path2 = STAILQ_FIRST(&nbdev_ch2->io_path_list);
1918 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path2 != NULL);
1919 : 3 : ctrlr_ch2 = io_path2->qpair->ctrlr_ch;
1920 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr_ch2 != NULL);
1921 : :
1922 : 3 : first_bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_RESET, bdev, ch2);
1923 : 3 : first_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_FAILED;
1924 : :
1925 : 3 : second_bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_RESET, bdev, ch1);
1926 : 3 : second_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_FAILED;
1927 : :
1928 : : /* The first reset request is submitted on thread 1, and the second reset request
1929 : : * is submitted on thread 0 while processing the first request.
1930 : : */
1931 : 3 : bdev_nvme_submit_request(ch2, first_bdev_io);
1932 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1933 : 3 : CU_ASSERT(TAILQ_EMPTY(&ctrlr_ch2->pending_resets));
1934 : :
1935 : 3 : set_thread(0);
1936 : :
1937 : 3 : bdev_nvme_submit_request(ch1, second_bdev_io);
1938 : 3 : CU_ASSERT(TAILQ_FIRST(&ctrlr_ch1->pending_resets) == second_bdev_io);
1939 : :
1940 : 3 : poll_threads();
1941 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
1942 : 3 : poll_threads();
1943 : :
1944 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
1945 : 3 : CU_ASSERT(first_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
1946 : 3 : CU_ASSERT(second_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
1947 : :
1948 : : /* The first reset request is submitted on thread 1, and the second reset request
1949 : : * is submitted on thread 0 while processing the first request.
1950 : : *
1951 : : * The difference from the above scenario is that the controller is removed while
1952 : : * processing the first request. Hence both reset requests should fail.
1953 : : */
1954 : 3 : set_thread(1);
1955 : :
1956 : 3 : bdev_nvme_submit_request(ch2, first_bdev_io);
1957 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
1958 : 3 : CU_ASSERT(TAILQ_EMPTY(&ctrlr_ch2->pending_resets));
1959 : :
1960 : 3 : set_thread(0);
1961 : :
1962 : 3 : bdev_nvme_submit_request(ch1, second_bdev_io);
1963 : 3 : CU_ASSERT(TAILQ_FIRST(&ctrlr_ch1->pending_resets) == second_bdev_io);
1964 : :
1965 : 3 : ctrlr->fail_reset = true;
1966 : :
1967 : 3 : poll_threads();
1968 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
1969 : 3 : poll_threads();
1970 : :
1971 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
1972 : 3 : CU_ASSERT(first_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
1973 : 3 : CU_ASSERT(second_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
1974 : :
1975 : 3 : spdk_put_io_channel(ch1);
1976 : :
1977 : 3 : set_thread(1);
1978 : :
1979 : 3 : spdk_put_io_channel(ch2);
1980 : :
1981 : 3 : poll_threads();
1982 : :
1983 : 3 : set_thread(0);
1984 : :
1985 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
1986 : 3 : CU_ASSERT(rc == 0);
1987 : :
1988 : 3 : poll_threads();
1989 : 3 : spdk_delay_us(1000);
1990 : 3 : poll_threads();
1991 : :
1992 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
1993 : :
1994 : 3 : free(first_bdev_io);
1995 : 3 : free(second_bdev_io);
1996 : 3 : }
1997 : :
1998 : : static void
1999 : 3 : test_attach_ctrlr(void)
2000 : 3 : {
2001 : 3 : struct spdk_nvme_transport_id trid = {};
2002 : : struct spdk_nvme_ctrlr *ctrlr;
2003 : : struct nvme_ctrlr *nvme_ctrlr;
2004 : 3 : const int STRING_SIZE = 32;
2005 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
2006 : : struct nvme_bdev *nbdev;
2007 : : int rc;
2008 : :
2009 : 3 : set_thread(0);
2010 : :
2011 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
2012 : 3 : ut_init_trid(&trid);
2013 : :
2014 : : /* If ctrlr fails, no nvme_ctrlr is created. Failed ctrlr is removed
2015 : : * by probe polling.
2016 : : */
2017 : 3 : ctrlr = ut_attach_ctrlr(&trid, 0, false, false);
2018 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
2019 : :
2020 : 3 : ctrlr->is_failed = true;
2021 : 3 : g_ut_attach_ctrlr_status = -EIO;
2022 : 3 : g_ut_attach_bdev_count = 0;
2023 : :
2024 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
2025 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2026 : 3 : CU_ASSERT(rc == 0);
2027 : :
2028 : 3 : spdk_delay_us(1000);
2029 : 3 : poll_threads();
2030 : :
2031 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2032 : :
2033 : : /* If ctrlr has no namespace, one nvme_ctrlr with no namespace is created */
2034 : 3 : ctrlr = ut_attach_ctrlr(&trid, 0, false, false);
2035 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
2036 : :
2037 : 3 : g_ut_attach_ctrlr_status = 0;
2038 : :
2039 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
2040 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2041 : 3 : CU_ASSERT(rc == 0);
2042 : :
2043 : 3 : spdk_delay_us(1000);
2044 : 3 : poll_threads();
2045 : :
2046 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2047 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2048 : 3 : CU_ASSERT(nvme_ctrlr->ctrlr == ctrlr);
2049 : :
2050 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
2051 : 3 : CU_ASSERT(rc == 0);
2052 : :
2053 : 3 : poll_threads();
2054 : 3 : spdk_delay_us(1000);
2055 : 3 : poll_threads();
2056 : :
2057 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2058 : :
2059 : : /* If ctrlr has one namespace, one nvme_ctrlr with one namespace and
2060 : : * one nvme_bdev is created.
2061 : : */
2062 : 3 : ctrlr = ut_attach_ctrlr(&trid, 1, false, false);
2063 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
2064 : :
2065 : 3 : g_ut_attach_bdev_count = 1;
2066 : :
2067 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
2068 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2069 : 3 : CU_ASSERT(rc == 0);
2070 : :
2071 : 3 : spdk_delay_us(1000);
2072 : 3 : poll_threads();
2073 : :
2074 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2075 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2076 : 3 : CU_ASSERT(nvme_ctrlr->ctrlr == ctrlr);
2077 : :
2078 [ + - + + : 3 : CU_ASSERT(attached_names[0] != NULL && strcmp(attached_names[0], "nvme0n1") == 0);
+ - ]
2079 : 3 : attached_names[0] = NULL;
2080 : :
2081 : 3 : nbdev = nvme_ctrlr_get_ns(nvme_ctrlr, 1)->bdev;
2082 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev != NULL);
2083 : 3 : CU_ASSERT(bdev_nvme_get_ctrlr(&nbdev->disk) == ctrlr);
2084 : :
2085 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
2086 : 3 : CU_ASSERT(rc == 0);
2087 : :
2088 : 3 : poll_threads();
2089 : 3 : spdk_delay_us(1000);
2090 : 3 : poll_threads();
2091 : :
2092 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2093 : :
2094 : : /* Ctrlr has one namespace but one nvme_ctrlr with no namespace is
2095 : : * created because creating one nvme_bdev failed.
2096 : : */
2097 : 3 : ctrlr = ut_attach_ctrlr(&trid, 1, false, false);
2098 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
2099 : :
2100 : 3 : g_ut_register_bdev_status = -EINVAL;
2101 : 3 : g_ut_attach_bdev_count = 0;
2102 : :
2103 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
2104 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2105 : 3 : CU_ASSERT(rc == 0);
2106 : :
2107 : 3 : spdk_delay_us(1000);
2108 : 3 : poll_threads();
2109 : :
2110 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2111 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2112 : 3 : CU_ASSERT(nvme_ctrlr->ctrlr == ctrlr);
2113 : :
2114 : 3 : CU_ASSERT(attached_names[0] == NULL);
2115 : :
2116 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
2117 : 3 : CU_ASSERT(rc == 0);
2118 : :
2119 : 3 : poll_threads();
2120 : 3 : spdk_delay_us(1000);
2121 : 3 : poll_threads();
2122 : :
2123 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2124 : :
2125 : 3 : g_ut_register_bdev_status = 0;
2126 : 3 : }
2127 : :
2128 : : static void
2129 : 3 : test_aer_cb(void)
2130 : 3 : {
2131 : 3 : struct spdk_nvme_transport_id trid = {};
2132 : : struct spdk_nvme_ctrlr *ctrlr;
2133 : : struct nvme_ctrlr *nvme_ctrlr;
2134 : : struct nvme_bdev *bdev;
2135 : 3 : const int STRING_SIZE = 32;
2136 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
2137 : 3 : union spdk_nvme_async_event_completion event = {};
2138 : 3 : struct spdk_nvme_cpl cpl = {};
2139 : : int rc;
2140 : :
2141 : 3 : set_thread(0);
2142 : :
2143 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
2144 : 3 : ut_init_trid(&trid);
2145 : :
2146 : : /* Attach a ctrlr, whose max number of namespaces is 4, and 2nd, 3rd, and 4th
2147 : : * namespaces are populated.
2148 : : */
2149 : 3 : ctrlr = ut_attach_ctrlr(&trid, 4, true, false);
2150 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
2151 : :
2152 : 3 : ctrlr->ns[0].is_active = false;
2153 : :
2154 : 3 : g_ut_attach_ctrlr_status = 0;
2155 : 3 : g_ut_attach_bdev_count = 3;
2156 : :
2157 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
2158 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2159 : 3 : CU_ASSERT(rc == 0);
2160 : :
2161 : 3 : spdk_delay_us(1000);
2162 : 3 : poll_threads();
2163 : :
2164 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
2165 : 3 : poll_threads();
2166 : :
2167 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2168 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2169 : :
2170 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 1) == NULL);
2171 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 2) != NULL);
2172 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 3) != NULL);
2173 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 4) != NULL);
2174 : :
2175 : 3 : bdev = nvme_ctrlr_get_ns(nvme_ctrlr, 4)->bdev;
2176 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
2177 : 3 : CU_ASSERT(bdev->disk.blockcnt == 1024);
2178 : :
2179 : : /* Dynamically populate 1st namespace and depopulate 3rd namespace, and
2180 : : * change the size of the 4th namespace.
2181 : : */
2182 : 3 : ctrlr->ns[0].is_active = true;
2183 : 3 : ctrlr->ns[2].is_active = false;
2184 : 3 : ctrlr->nsdata[3].nsze = 2048;
2185 : :
2186 : 3 : event.bits.async_event_type = SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE;
2187 : 3 : event.bits.async_event_info = SPDK_NVME_ASYNC_EVENT_NS_ATTR_CHANGED;
2188 : 3 : cpl.cdw0 = event.raw;
2189 : :
2190 : 3 : aer_cb(nvme_ctrlr, &cpl);
2191 : :
2192 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 1) != NULL);
2193 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 2) != NULL);
2194 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 3) == NULL);
2195 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 4) != NULL);
2196 : 3 : CU_ASSERT(bdev->disk.blockcnt == 2048);
2197 : :
2198 : : /* Change ANA state of active namespaces. */
2199 : 3 : ctrlr->ns[0].ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
2200 : 3 : ctrlr->ns[1].ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
2201 : 3 : ctrlr->ns[3].ana_state = SPDK_NVME_ANA_CHANGE_STATE;
2202 : :
2203 : 3 : event.bits.async_event_type = SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE;
2204 : 3 : event.bits.async_event_info = SPDK_NVME_ASYNC_EVENT_ANA_CHANGE;
2205 : 3 : cpl.cdw0 = event.raw;
2206 : :
2207 : 3 : aer_cb(nvme_ctrlr, &cpl);
2208 : :
2209 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
2210 : 3 : poll_threads();
2211 : :
2212 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 1)->ana_state == SPDK_NVME_ANA_NON_OPTIMIZED_STATE);
2213 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 2)->ana_state == SPDK_NVME_ANA_INACCESSIBLE_STATE);
2214 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 4)->ana_state == SPDK_NVME_ANA_CHANGE_STATE);
2215 : :
2216 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
2217 : 3 : CU_ASSERT(rc == 0);
2218 : :
2219 : 3 : poll_threads();
2220 : 3 : spdk_delay_us(1000);
2221 : 3 : poll_threads();
2222 : :
2223 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2224 : 3 : }
2225 : :
2226 : : static void
2227 : 18 : ut_test_submit_nvme_cmd(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
2228 : : enum spdk_bdev_io_type io_type)
2229 : : {
2230 : 18 : struct nvme_bdev_channel *nbdev_ch = spdk_io_channel_get_ctx(ch);
2231 : : struct nvme_io_path *io_path;
2232 : : struct spdk_nvme_qpair *qpair;
2233 : :
2234 : 18 : io_path = bdev_nvme_find_io_path(nbdev_ch);
2235 [ - + ]: 18 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
2236 : 18 : qpair = io_path->qpair->qpair;
2237 [ - + ]: 18 : SPDK_CU_ASSERT_FATAL(qpair != NULL);
2238 : :
2239 : 18 : bdev_io->type = io_type;
2240 : 18 : bdev_io->internal.in_submit_request = true;
2241 : :
2242 : 18 : bdev_nvme_submit_request(ch, bdev_io);
2243 : :
2244 [ - + ]: 18 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
2245 : 18 : CU_ASSERT(qpair->num_outstanding_reqs == 1);
2246 : :
2247 : 18 : poll_threads();
2248 : :
2249 [ - + ]: 18 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
2250 : 18 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
2251 : 18 : CU_ASSERT(qpair->num_outstanding_reqs == 0);
2252 : 18 : }
2253 : :
2254 : : static void
2255 : 3 : ut_test_submit_nop(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
2256 : : enum spdk_bdev_io_type io_type)
2257 : : {
2258 : 3 : struct nvme_bdev_channel *nbdev_ch = spdk_io_channel_get_ctx(ch);
2259 : : struct nvme_io_path *io_path;
2260 : : struct spdk_nvme_qpair *qpair;
2261 : :
2262 : 3 : io_path = bdev_nvme_find_io_path(nbdev_ch);
2263 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
2264 : 3 : qpair = io_path->qpair->qpair;
2265 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(qpair != NULL);
2266 : :
2267 : 3 : bdev_io->type = io_type;
2268 : 3 : bdev_io->internal.in_submit_request = true;
2269 : :
2270 : 3 : bdev_nvme_submit_request(ch, bdev_io);
2271 : :
2272 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
2273 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
2274 : 3 : CU_ASSERT(qpair->num_outstanding_reqs == 0);
2275 : 3 : }
2276 : :
2277 : : static void
2278 : 3 : ut_test_submit_fused_nvme_cmd(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
2279 : : {
2280 : 3 : struct nvme_bdev_channel *nbdev_ch = spdk_io_channel_get_ctx(ch);
2281 : 3 : struct nvme_bdev_io *bio = (struct nvme_bdev_io *)bdev_io->driver_ctx;
2282 : : struct ut_nvme_req *req;
2283 : : struct nvme_io_path *io_path;
2284 : : struct spdk_nvme_qpair *qpair;
2285 : :
2286 : 3 : io_path = bdev_nvme_find_io_path(nbdev_ch);
2287 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
2288 : 3 : qpair = io_path->qpair->qpair;
2289 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(qpair != NULL);
2290 : :
2291 : : /* Only compare and write now. */
2292 : 3 : bdev_io->type = SPDK_BDEV_IO_TYPE_COMPARE_AND_WRITE;
2293 : 3 : bdev_io->internal.in_submit_request = true;
2294 : :
2295 : 3 : bdev_nvme_submit_request(ch, bdev_io);
2296 : :
2297 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
2298 : 3 : CU_ASSERT(qpair->num_outstanding_reqs == 2);
2299 [ - + ]: 3 : CU_ASSERT(bio->first_fused_submitted == true);
2300 : :
2301 : : /* First outstanding request is compare operation. */
2302 : 3 : req = TAILQ_FIRST(&qpair->outstanding_reqs);
2303 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
2304 : 3 : CU_ASSERT(req->opc == SPDK_NVME_OPC_COMPARE);
2305 : 3 : req->cpl.cdw0 = SPDK_NVME_OPC_COMPARE;
2306 : :
2307 : 3 : poll_threads();
2308 : :
2309 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
2310 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
2311 : 3 : CU_ASSERT(qpair->num_outstanding_reqs == 0);
2312 : 3 : }
2313 : :
2314 : : static void
2315 : 3 : ut_test_submit_admin_cmd(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
2316 : : struct spdk_nvme_ctrlr *ctrlr)
2317 : : {
2318 : 3 : bdev_io->type = SPDK_BDEV_IO_TYPE_NVME_ADMIN;
2319 : 3 : bdev_io->internal.in_submit_request = true;
2320 : 3 : bdev_io->u.nvme_passthru.cmd.opc = SPDK_NVME_OPC_GET_FEATURES;
2321 : :
2322 : 3 : bdev_nvme_submit_request(ch, bdev_io);
2323 : :
2324 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
2325 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 1);
2326 : :
2327 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
2328 : 3 : poll_thread_times(1, 1);
2329 : :
2330 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
2331 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 0);
2332 : :
2333 : 3 : poll_thread_times(0, 1);
2334 : :
2335 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
2336 : 3 : }
2337 : :
2338 : : static void
2339 : 3 : test_submit_nvme_cmd(void)
2340 : 3 : {
2341 : 3 : struct spdk_nvme_transport_id trid = {};
2342 : : struct spdk_nvme_ctrlr *ctrlr;
2343 : : struct nvme_ctrlr *nvme_ctrlr;
2344 : 3 : const int STRING_SIZE = 32;
2345 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
2346 : : struct nvme_bdev *bdev;
2347 : : struct spdk_bdev_io *bdev_io;
2348 : : struct spdk_io_channel *ch;
2349 : : int rc;
2350 : :
2351 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
2352 : 3 : ut_init_trid(&trid);
2353 : :
2354 : 3 : set_thread(1);
2355 : :
2356 : 3 : ctrlr = ut_attach_ctrlr(&trid, 1, false, false);
2357 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
2358 : :
2359 : 3 : g_ut_attach_ctrlr_status = 0;
2360 : 3 : g_ut_attach_bdev_count = 1;
2361 : :
2362 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
2363 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2364 : 3 : CU_ASSERT(rc == 0);
2365 : :
2366 : 3 : spdk_delay_us(1000);
2367 : 3 : poll_threads();
2368 : :
2369 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2370 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2371 : :
2372 : 3 : bdev = nvme_ctrlr_get_ns(nvme_ctrlr, 1)->bdev;
2373 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
2374 : :
2375 : 3 : set_thread(0);
2376 : :
2377 : 3 : ch = spdk_get_io_channel(bdev);
2378 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
2379 : :
2380 : 3 : bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_INVALID, bdev, ch);
2381 : :
2382 : 3 : bdev_io->u.bdev.iovs = NULL;
2383 : :
2384 : 3 : ut_test_submit_nvme_cmd(ch, bdev_io, SPDK_BDEV_IO_TYPE_READ);
2385 : :
2386 : 3 : ut_bdev_io_set_buf(bdev_io);
2387 : :
2388 : 3 : ut_test_submit_nvme_cmd(ch, bdev_io, SPDK_BDEV_IO_TYPE_READ);
2389 : 3 : ut_test_submit_nvme_cmd(ch, bdev_io, SPDK_BDEV_IO_TYPE_WRITE);
2390 : 3 : ut_test_submit_nvme_cmd(ch, bdev_io, SPDK_BDEV_IO_TYPE_COMPARE);
2391 : 3 : ut_test_submit_nvme_cmd(ch, bdev_io, SPDK_BDEV_IO_TYPE_UNMAP);
2392 : :
2393 : 3 : ut_test_submit_nop(ch, bdev_io, SPDK_BDEV_IO_TYPE_FLUSH);
2394 : :
2395 : 3 : ut_test_submit_fused_nvme_cmd(ch, bdev_io);
2396 : :
2397 : : /* Verify that ext NVME API is called when data is described by memory domain */
2398 : 3 : g_ut_readv_ext_called = false;
2399 : 3 : bdev_io->u.bdev.memory_domain = (void *)0xdeadbeef;
2400 : 3 : ut_test_submit_nvme_cmd(ch, bdev_io, SPDK_BDEV_IO_TYPE_READ);
2401 [ - + ]: 3 : CU_ASSERT(g_ut_readv_ext_called == true);
2402 : 3 : g_ut_readv_ext_called = false;
2403 : 3 : bdev_io->u.bdev.memory_domain = NULL;
2404 : :
2405 : 3 : ut_test_submit_admin_cmd(ch, bdev_io, ctrlr);
2406 : :
2407 : 3 : free(bdev_io);
2408 : :
2409 : 3 : spdk_put_io_channel(ch);
2410 : :
2411 : 3 : poll_threads();
2412 : :
2413 : 3 : set_thread(1);
2414 : :
2415 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
2416 : 3 : CU_ASSERT(rc == 0);
2417 : :
2418 : 3 : poll_threads();
2419 : 3 : spdk_delay_us(1000);
2420 : 3 : poll_threads();
2421 : :
2422 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2423 : 3 : }
2424 : :
2425 : : static void
2426 : 3 : test_add_remove_trid(void)
2427 : 3 : {
2428 : 3 : struct nvme_path_id path1 = {}, path2 = {}, path3 = {};
2429 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2, *ctrlr3;
2430 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
2431 : 3 : const int STRING_SIZE = 32;
2432 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
2433 : : struct nvme_path_id *ctrid;
2434 : : int rc;
2435 : :
2436 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
2437 : 3 : ut_init_trid(&path1.trid);
2438 : 3 : ut_init_trid2(&path2.trid);
2439 : 3 : ut_init_trid3(&path3.trid);
2440 : :
2441 : 3 : set_thread(0);
2442 : :
2443 : 3 : g_ut_attach_ctrlr_status = 0;
2444 : 3 : g_ut_attach_bdev_count = 0;
2445 : :
2446 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 0, false, false);
2447 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
2448 : :
2449 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
2450 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2451 : 3 : CU_ASSERT(rc == 0);
2452 : :
2453 : 3 : spdk_delay_us(1000);
2454 : 3 : poll_threads();
2455 : :
2456 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2457 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2458 : :
2459 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&nvme_ctrlr->active_path_id->trid, &path1.trid) == 0);
2460 : :
2461 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 0, false, false);
2462 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
2463 : :
2464 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
2465 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2466 : 3 : CU_ASSERT(rc == 0);
2467 : :
2468 : 3 : spdk_delay_us(1000);
2469 : 3 : poll_threads();
2470 : :
2471 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&nvme_ctrlr->active_path_id->trid, &path1.trid) == 0);
2472 [ + - ]: 6 : TAILQ_FOREACH(ctrid, &nvme_ctrlr->trids, link) {
2473 [ + + ]: 6 : if (spdk_nvme_transport_id_compare(&ctrid->trid, &path2.trid) == 0) {
2474 : 3 : break;
2475 : : }
2476 : : }
2477 : 3 : CU_ASSERT(ctrid != NULL);
2478 : :
2479 : : /* trid3 is not in the registered list. */
2480 : 3 : rc = bdev_nvme_delete("nvme0", &path3, NULL, NULL);
2481 : 3 : CU_ASSERT(rc == -ENXIO);
2482 : :
2483 : : /* trid2 is not used, and simply removed. */
2484 : 3 : rc = bdev_nvme_delete("nvme0", &path2, NULL, NULL);
2485 : 3 : CU_ASSERT(rc == 0);
2486 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == nvme_ctrlr);
2487 [ + + ]: 6 : TAILQ_FOREACH(ctrid, &nvme_ctrlr->trids, link) {
2488 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&ctrid->trid, &path2.trid) != 0);
2489 : : }
2490 : :
2491 : 3 : ctrlr3 = ut_attach_ctrlr(&path3.trid, 0, false, false);
2492 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr3 != NULL);
2493 : :
2494 : 3 : rc = bdev_nvme_create(&path3.trid, "nvme0", attached_names, STRING_SIZE,
2495 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2496 : 3 : CU_ASSERT(rc == 0);
2497 : :
2498 : 3 : spdk_delay_us(1000);
2499 : 3 : poll_threads();
2500 : :
2501 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&nvme_ctrlr->active_path_id->trid, &path1.trid) == 0);
2502 [ + - ]: 6 : TAILQ_FOREACH(ctrid, &nvme_ctrlr->trids, link) {
2503 [ + + ]: 6 : if (spdk_nvme_transport_id_compare(&ctrid->trid, &path3.trid) == 0) {
2504 : 3 : break;
2505 : : }
2506 : : }
2507 : 3 : CU_ASSERT(ctrid != NULL);
2508 : :
2509 : : /* Mark path3 as failed by setting its last_failed_tsc to non-zero forcefully.
2510 : : * If we add path2 again, path2 should be inserted between path1 and path3.
2511 : : * Then, we remove path2. It is not used, and simply removed.
2512 : : */
2513 : 3 : ctrid->last_failed_tsc = spdk_get_ticks() + 1;
2514 : :
2515 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 0, false, false);
2516 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
2517 : :
2518 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
2519 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2520 : 3 : CU_ASSERT(rc == 0);
2521 : :
2522 : 3 : spdk_delay_us(1000);
2523 : 3 : poll_threads();
2524 : :
2525 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&nvme_ctrlr->active_path_id->trid, &path1.trid) == 0);
2526 : :
2527 : 3 : ctrid = TAILQ_NEXT(nvme_ctrlr->active_path_id, link);
2528 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrid != NULL);
2529 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&ctrid->trid, &path2.trid) == 0);
2530 : :
2531 : 3 : ctrid = TAILQ_NEXT(ctrid, link);
2532 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrid != NULL);
2533 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&ctrid->trid, &path3.trid) == 0);
2534 : :
2535 : 3 : rc = bdev_nvme_delete("nvme0", &path2, NULL, NULL);
2536 : 3 : CU_ASSERT(rc == 0);
2537 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == nvme_ctrlr);
2538 [ + + ]: 9 : TAILQ_FOREACH(ctrid, &nvme_ctrlr->trids, link) {
2539 : 6 : CU_ASSERT(spdk_nvme_transport_id_compare(&ctrid->trid, &path2.trid) != 0);
2540 : : }
2541 : :
2542 : : /* path1 is currently used and path3 is an alternative path.
2543 : : * If we remove path1, path is changed to path3.
2544 : : */
2545 : 3 : rc = bdev_nvme_delete("nvme0", &path1, NULL, NULL);
2546 : 3 : CU_ASSERT(rc == 0);
2547 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == nvme_ctrlr);
2548 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
2549 [ + + ]: 6 : TAILQ_FOREACH(ctrid, &nvme_ctrlr->trids, link) {
2550 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&ctrid->trid, &path1.trid) != 0);
2551 : : }
2552 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&nvme_ctrlr->active_path_id->trid, &path3.trid) == 0);
2553 : :
2554 : 3 : poll_threads();
2555 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
2556 : 3 : poll_threads();
2557 : :
2558 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
2559 : :
2560 : : /* path3 is the current and only path. If we remove path3, the corresponding
2561 : : * nvme_ctrlr is removed.
2562 : : */
2563 : 3 : rc = bdev_nvme_delete("nvme0", &path3, NULL, NULL);
2564 : 3 : CU_ASSERT(rc == 0);
2565 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == nvme_ctrlr);
2566 : :
2567 : 3 : poll_threads();
2568 : 3 : spdk_delay_us(1000);
2569 : 3 : poll_threads();
2570 : :
2571 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2572 : :
2573 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 0, false, false);
2574 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
2575 : :
2576 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
2577 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2578 : 3 : CU_ASSERT(rc == 0);
2579 : :
2580 : 3 : spdk_delay_us(1000);
2581 : 3 : poll_threads();
2582 : :
2583 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2584 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2585 : :
2586 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&nvme_ctrlr->active_path_id->trid, &path1.trid) == 0);
2587 : :
2588 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 0, false, false);
2589 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
2590 : :
2591 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
2592 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2593 : 3 : CU_ASSERT(rc == 0);
2594 : :
2595 : 3 : spdk_delay_us(1000);
2596 : 3 : poll_threads();
2597 : :
2598 : 3 : CU_ASSERT(spdk_nvme_transport_id_compare(&nvme_ctrlr->active_path_id->trid, &path1.trid) == 0);
2599 [ + - ]: 6 : TAILQ_FOREACH(ctrid, &nvme_ctrlr->trids, link) {
2600 [ + + ]: 6 : if (spdk_nvme_transport_id_compare(&ctrid->trid, &path2.trid) == 0) {
2601 : 3 : break;
2602 : : }
2603 : : }
2604 : 3 : CU_ASSERT(ctrid != NULL);
2605 : :
2606 : : /* If trid is not specified, nvme_ctrlr itself is removed. */
2607 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
2608 : 3 : CU_ASSERT(rc == 0);
2609 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == nvme_ctrlr);
2610 : :
2611 : 3 : poll_threads();
2612 : 3 : spdk_delay_us(1000);
2613 : 3 : poll_threads();
2614 : :
2615 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2616 : 3 : }
2617 : :
2618 : : static void
2619 : 3 : test_abort(void)
2620 : 3 : {
2621 : 3 : struct spdk_nvme_transport_id trid = {};
2622 : 3 : struct nvme_ctrlr_opts opts = {};
2623 : : struct spdk_nvme_ctrlr *ctrlr;
2624 : : struct nvme_ctrlr *nvme_ctrlr;
2625 : 3 : const int STRING_SIZE = 32;
2626 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
2627 : : struct nvme_bdev *bdev;
2628 : : struct spdk_bdev_io *write_io, *fuse_io, *admin_io, *abort_io;
2629 : : struct spdk_io_channel *ch1, *ch2;
2630 : : struct nvme_bdev_channel *nbdev_ch1;
2631 : : struct nvme_io_path *io_path1;
2632 : : struct nvme_qpair *nvme_qpair1;
2633 : : int rc;
2634 : :
2635 : : /* Create ctrlr on thread 1 and submit I/O and admin requests to be aborted on
2636 : : * thread 0. Aborting I/O requests are submitted on thread 0. Aborting admin requests
2637 : : * are submitted on thread 1. Both should succeed.
2638 : : */
2639 : :
2640 : 3 : ut_init_trid(&trid);
2641 : :
2642 : 3 : ctrlr = ut_attach_ctrlr(&trid, 1, false, false);
2643 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
2644 : :
2645 : 3 : g_ut_attach_ctrlr_status = 0;
2646 : 3 : g_ut_attach_bdev_count = 1;
2647 : :
2648 : 3 : set_thread(1);
2649 : :
2650 : 3 : opts.ctrlr_loss_timeout_sec = -1;
2651 : 3 : opts.reconnect_delay_sec = 1;
2652 : :
2653 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
2654 : : attach_ctrlr_done, NULL, NULL, &opts, false);
2655 : 3 : CU_ASSERT(rc == 0);
2656 : :
2657 : 3 : spdk_delay_us(1000);
2658 : 3 : poll_threads();
2659 : :
2660 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2661 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2662 : :
2663 : 3 : bdev = nvme_ctrlr_get_ns(nvme_ctrlr, 1)->bdev;
2664 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
2665 : :
2666 : 3 : write_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_WRITE, bdev, NULL);
2667 : 3 : ut_bdev_io_set_buf(write_io);
2668 : :
2669 : 3 : fuse_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_COMPARE_AND_WRITE, bdev, NULL);
2670 : 3 : ut_bdev_io_set_buf(fuse_io);
2671 : :
2672 : 3 : admin_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_NVME_ADMIN, bdev, NULL);
2673 : 3 : admin_io->u.nvme_passthru.cmd.opc = SPDK_NVME_OPC_GET_FEATURES;
2674 : :
2675 : 3 : abort_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_ABORT, bdev, NULL);
2676 : :
2677 : 3 : set_thread(0);
2678 : :
2679 : 3 : ch1 = spdk_get_io_channel(bdev);
2680 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
2681 : 3 : nbdev_ch1 = spdk_io_channel_get_ctx(ch1);
2682 : 3 : io_path1 = STAILQ_FIRST(&nbdev_ch1->io_path_list);
2683 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path1 != NULL);
2684 : 3 : nvme_qpair1 = io_path1->qpair;
2685 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair1 != NULL);
2686 : :
2687 : 3 : set_thread(1);
2688 : :
2689 : 3 : ch2 = spdk_get_io_channel(bdev);
2690 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
2691 : :
2692 : 3 : write_io->internal.ch = (struct spdk_bdev_channel *)ch1;
2693 : 3 : fuse_io->internal.ch = (struct spdk_bdev_channel *)ch1;
2694 : 3 : abort_io->internal.ch = (struct spdk_bdev_channel *)ch1;
2695 : :
2696 : : /* Aborting the already completed request should fail. */
2697 : 3 : write_io->internal.in_submit_request = true;
2698 : 3 : bdev_nvme_submit_request(ch1, write_io);
2699 : 3 : poll_threads();
2700 : :
2701 [ - + ]: 3 : CU_ASSERT(write_io->internal.in_submit_request == false);
2702 : :
2703 : 3 : abort_io->u.abort.bio_to_abort = write_io;
2704 : 3 : abort_io->internal.in_submit_request = true;
2705 : :
2706 : 3 : bdev_nvme_submit_request(ch1, abort_io);
2707 : :
2708 : 3 : poll_threads();
2709 : :
2710 [ - + ]: 3 : CU_ASSERT(abort_io->internal.in_submit_request == false);
2711 : 3 : CU_ASSERT(abort_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
2712 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 0);
2713 : :
2714 : 3 : admin_io->internal.ch = (struct spdk_bdev_channel *)ch1;
2715 : 3 : abort_io->internal.ch = (struct spdk_bdev_channel *)ch2;
2716 : :
2717 : 3 : admin_io->internal.in_submit_request = true;
2718 : 3 : bdev_nvme_submit_request(ch1, admin_io);
2719 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
2720 : 3 : poll_threads();
2721 : :
2722 [ - + ]: 3 : CU_ASSERT(admin_io->internal.in_submit_request == false);
2723 : :
2724 : 3 : abort_io->u.abort.bio_to_abort = admin_io;
2725 : 3 : abort_io->internal.in_submit_request = true;
2726 : :
2727 : 3 : bdev_nvme_submit_request(ch2, abort_io);
2728 : :
2729 : 3 : poll_threads();
2730 : :
2731 [ - + ]: 3 : CU_ASSERT(abort_io->internal.in_submit_request == false);
2732 : 3 : CU_ASSERT(abort_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
2733 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 0);
2734 : :
2735 : : /* Aborting the write request should succeed. */
2736 : 3 : write_io->internal.in_submit_request = true;
2737 : 3 : bdev_nvme_submit_request(ch1, write_io);
2738 : :
2739 [ - + ]: 3 : CU_ASSERT(write_io->internal.in_submit_request == true);
2740 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 1);
2741 : :
2742 : 3 : abort_io->internal.ch = (struct spdk_bdev_channel *)ch1;
2743 : 3 : abort_io->u.abort.bio_to_abort = write_io;
2744 : 3 : abort_io->internal.in_submit_request = true;
2745 : :
2746 : 3 : bdev_nvme_submit_request(ch1, abort_io);
2747 : :
2748 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
2749 : 3 : poll_threads();
2750 : :
2751 [ - + ]: 3 : CU_ASSERT(abort_io->internal.in_submit_request == false);
2752 : 3 : CU_ASSERT(abort_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
2753 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 0);
2754 [ - + ]: 3 : CU_ASSERT(write_io->internal.in_submit_request == false);
2755 : 3 : CU_ASSERT(write_io->internal.status == SPDK_BDEV_IO_STATUS_ABORTED);
2756 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 0);
2757 : :
2758 : : /* Aborting the fuse request should succeed. */
2759 : 3 : fuse_io->internal.in_submit_request = true;
2760 : 3 : bdev_nvme_submit_request(ch1, fuse_io);
2761 : :
2762 [ - + ]: 3 : CU_ASSERT(fuse_io->internal.in_submit_request == true);
2763 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 2);
2764 : :
2765 : 3 : abort_io->u.abort.bio_to_abort = fuse_io;
2766 : 3 : abort_io->internal.in_submit_request = true;
2767 : :
2768 : 3 : bdev_nvme_submit_request(ch1, abort_io);
2769 : :
2770 : 3 : spdk_delay_us(10000);
2771 : 3 : poll_threads();
2772 : :
2773 [ - + ]: 3 : CU_ASSERT(abort_io->internal.in_submit_request == false);
2774 : 3 : CU_ASSERT(abort_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
2775 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 0);
2776 [ - + ]: 3 : CU_ASSERT(fuse_io->internal.in_submit_request == false);
2777 : 3 : CU_ASSERT(fuse_io->internal.status == SPDK_BDEV_IO_STATUS_ABORTED);
2778 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 0);
2779 : :
2780 : : /* Aborting the admin request should succeed. */
2781 : 3 : admin_io->internal.in_submit_request = true;
2782 : 3 : bdev_nvme_submit_request(ch1, admin_io);
2783 : :
2784 [ - + ]: 3 : CU_ASSERT(admin_io->internal.in_submit_request == true);
2785 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 1);
2786 : :
2787 : 3 : abort_io->internal.ch = (struct spdk_bdev_channel *)ch2;
2788 : 3 : abort_io->u.abort.bio_to_abort = admin_io;
2789 : 3 : abort_io->internal.in_submit_request = true;
2790 : :
2791 : 3 : bdev_nvme_submit_request(ch2, abort_io);
2792 : :
2793 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
2794 : 3 : poll_threads();
2795 : :
2796 [ - + ]: 3 : CU_ASSERT(abort_io->internal.in_submit_request == false);
2797 : 3 : CU_ASSERT(abort_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
2798 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 0);
2799 [ - + ]: 3 : CU_ASSERT(admin_io->internal.in_submit_request == false);
2800 : 3 : CU_ASSERT(admin_io->internal.status == SPDK_BDEV_IO_STATUS_ABORTED);
2801 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 0);
2802 : :
2803 : 3 : set_thread(0);
2804 : :
2805 : : /* If qpair is disconnected, it is freed and then reconnected via resetting
2806 : : * the corresponding nvme_ctrlr. I/O should be queued if it is submitted
2807 : : * while resetting the nvme_ctrlr.
2808 : : */
2809 : 3 : nvme_qpair1->qpair->failure_reason = SPDK_NVME_QPAIR_FAILURE_UNKNOWN;
2810 : :
2811 : 3 : poll_thread_times(0, 3);
2812 : :
2813 : 3 : CU_ASSERT(nvme_qpair1->qpair == NULL);
2814 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
2815 : :
2816 : 3 : write_io->internal.in_submit_request = true;
2817 : :
2818 : 3 : bdev_nvme_submit_request(ch1, write_io);
2819 : :
2820 [ - + ]: 3 : CU_ASSERT(write_io->internal.in_submit_request == true);
2821 : 3 : CU_ASSERT(write_io == TAILQ_FIRST(&nbdev_ch1->retry_io_list));
2822 : :
2823 : : /* Aborting the queued write request should succeed immediately. */
2824 : 3 : abort_io->internal.ch = (struct spdk_bdev_channel *)ch1;
2825 : 3 : abort_io->u.abort.bio_to_abort = write_io;
2826 : 3 : abort_io->internal.in_submit_request = true;
2827 : :
2828 : 3 : bdev_nvme_submit_request(ch1, abort_io);
2829 : :
2830 [ - + ]: 3 : CU_ASSERT(abort_io->internal.in_submit_request == false);
2831 : 3 : CU_ASSERT(abort_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
2832 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 0);
2833 [ - + ]: 3 : CU_ASSERT(write_io->internal.in_submit_request == false);
2834 : 3 : CU_ASSERT(write_io->internal.status == SPDK_BDEV_IO_STATUS_ABORTED);
2835 : :
2836 : 3 : poll_threads();
2837 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
2838 : 3 : poll_threads();
2839 : :
2840 : 3 : spdk_put_io_channel(ch1);
2841 : :
2842 : 3 : set_thread(1);
2843 : :
2844 : 3 : spdk_put_io_channel(ch2);
2845 : :
2846 : 3 : poll_threads();
2847 : :
2848 : 3 : free(write_io);
2849 : 3 : free(fuse_io);
2850 : 3 : free(admin_io);
2851 : 3 : free(abort_io);
2852 : :
2853 : 3 : set_thread(1);
2854 : :
2855 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
2856 : 3 : CU_ASSERT(rc == 0);
2857 : :
2858 : 3 : poll_threads();
2859 : 3 : spdk_delay_us(1000);
2860 : 3 : poll_threads();
2861 : :
2862 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2863 : 3 : }
2864 : :
2865 : : static void
2866 : 3 : test_get_io_qpair(void)
2867 : : {
2868 : 3 : struct spdk_nvme_transport_id trid = {};
2869 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
2870 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
2871 : : struct spdk_io_channel *ch;
2872 : : struct nvme_ctrlr_channel *ctrlr_ch;
2873 : : struct spdk_nvme_qpair *qpair;
2874 : : int rc;
2875 : :
2876 : 3 : ut_init_trid(&trid);
2877 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
2878 : :
2879 : 3 : set_thread(0);
2880 : :
2881 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid, NULL);
2882 : 3 : CU_ASSERT(rc == 0);
2883 : :
2884 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2885 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2886 : :
2887 : 3 : ch = spdk_get_io_channel(nvme_ctrlr);
2888 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
2889 : 3 : ctrlr_ch = spdk_io_channel_get_ctx(ch);
2890 : 3 : CU_ASSERT(ctrlr_ch->qpair->qpair != NULL);
2891 : :
2892 : 3 : qpair = bdev_nvme_get_io_qpair(ch);
2893 : 3 : CU_ASSERT(qpair == ctrlr_ch->qpair->qpair);
2894 : :
2895 : 3 : spdk_put_io_channel(ch);
2896 : :
2897 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
2898 : 3 : CU_ASSERT(rc == 0);
2899 : :
2900 : 3 : poll_threads();
2901 : 3 : spdk_delay_us(1000);
2902 : 3 : poll_threads();
2903 : :
2904 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2905 : 3 : }
2906 : :
2907 : : /* Test a scenario that the bdev subsystem starts shutdown when there still exists
2908 : : * any NVMe bdev. In this scenario, spdk_bdev_unregister() is called first. Add a
2909 : : * test case to avoid regression for this scenario. spdk_bdev_unregister() calls
2910 : : * bdev_nvme_destruct() in the end, and so call bdev_nvme_destruct() directly.
2911 : : */
2912 : : static void
2913 : 3 : test_bdev_unregister(void)
2914 : 3 : {
2915 : 3 : struct spdk_nvme_transport_id trid = {};
2916 : : struct spdk_nvme_ctrlr *ctrlr;
2917 : : struct nvme_ctrlr *nvme_ctrlr;
2918 : : struct nvme_ns *nvme_ns1, *nvme_ns2;
2919 : 3 : const int STRING_SIZE = 32;
2920 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
2921 : : struct nvme_bdev *bdev1, *bdev2;
2922 : : int rc;
2923 : :
2924 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
2925 : 3 : ut_init_trid(&trid);
2926 : :
2927 : 3 : ctrlr = ut_attach_ctrlr(&trid, 2, false, false);
2928 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
2929 : :
2930 : 3 : g_ut_attach_ctrlr_status = 0;
2931 : 3 : g_ut_attach_bdev_count = 2;
2932 : :
2933 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
2934 : : attach_ctrlr_done, NULL, NULL, NULL, false);
2935 : 3 : CU_ASSERT(rc == 0);
2936 : :
2937 : 3 : spdk_delay_us(1000);
2938 : 3 : poll_threads();
2939 : :
2940 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
2941 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
2942 : :
2943 : 3 : nvme_ns1 = nvme_ctrlr_get_ns(nvme_ctrlr, 1);
2944 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ns1 != NULL);
2945 : :
2946 : 3 : bdev1 = nvme_ns1->bdev;
2947 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev1 != NULL);
2948 : :
2949 : 3 : nvme_ns2 = nvme_ctrlr_get_ns(nvme_ctrlr, 2);
2950 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ns2 != NULL);
2951 : :
2952 : 3 : bdev2 = nvme_ns2->bdev;
2953 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev2 != NULL);
2954 : :
2955 : 3 : bdev_nvme_destruct(&bdev1->disk);
2956 : 3 : bdev_nvme_destruct(&bdev2->disk);
2957 : :
2958 : 3 : poll_threads();
2959 : :
2960 : 3 : CU_ASSERT(nvme_ns1->bdev == NULL);
2961 : 3 : CU_ASSERT(nvme_ns2->bdev == NULL);
2962 : :
2963 : 3 : nvme_ctrlr->destruct = true;
2964 : 3 : _nvme_ctrlr_destruct(nvme_ctrlr);
2965 : :
2966 : 3 : poll_threads();
2967 : 3 : spdk_delay_us(1000);
2968 : 3 : poll_threads();
2969 : :
2970 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
2971 : 3 : }
2972 : :
2973 : : static void
2974 : 3 : test_compare_ns(void)
2975 : : {
2976 : 3 : struct spdk_nvme_ns_data nsdata1 = {}, nsdata2 = {};
2977 : 3 : struct spdk_nvme_ctrlr ctrlr1 = { .nsdata = &nsdata1, }, ctrlr2 = { .nsdata = &nsdata2, };
2978 : 3 : struct spdk_nvme_ns ns1 = { .id = 1, .ctrlr = &ctrlr1, }, ns2 = { .id = 1, .ctrlr = &ctrlr2, };
2979 : 3 : struct spdk_uuid uuid1 = { .u.raw = { 0xAA } };
2980 : 3 : struct spdk_uuid uuid2 = { .u.raw = { 0xAB } };
2981 : :
2982 : : /* No IDs are defined. */
2983 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == true);
2984 : :
2985 : : /* Only EUI64 are defined and not matched. */
2986 : 3 : nsdata1.eui64 = 0xABCDEF0123456789;
2987 : 3 : nsdata2.eui64 = 0xBBCDEF0123456789;
2988 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == false);
2989 : :
2990 : : /* Only EUI64 are defined and matched. */
2991 : 3 : nsdata2.eui64 = 0xABCDEF0123456789;
2992 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == true);
2993 : :
2994 : : /* Only NGUID are defined and not matched. */
2995 : 3 : nsdata1.eui64 = 0x0;
2996 : 3 : nsdata2.eui64 = 0x0;
2997 : 3 : nsdata1.nguid[0] = 0x12;
2998 : 3 : nsdata2.nguid[0] = 0x10;
2999 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == false);
3000 : :
3001 : : /* Only NGUID are defined and matched. */
3002 : 3 : nsdata2.nguid[0] = 0x12;
3003 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == true);
3004 : :
3005 : : /* Only UUID are defined and not matched. */
3006 : 3 : nsdata1.nguid[0] = 0x0;
3007 : 3 : nsdata2.nguid[0] = 0x0;
3008 : 3 : ns1.uuid = &uuid1;
3009 : 3 : ns2.uuid = &uuid2;
3010 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == false);
3011 : :
3012 : : /* Only one UUID is defined. */
3013 : 3 : ns1.uuid = NULL;
3014 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == false);
3015 : :
3016 : : /* Only UUID are defined and matched. */
3017 : 3 : ns1.uuid = &uuid2;
3018 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == true);
3019 : :
3020 : : /* All EUI64, NGUID, and UUID are defined and matched. */
3021 : 3 : nsdata1.eui64 = 0x123456789ABCDEF;
3022 : 3 : nsdata2.eui64 = 0x123456789ABCDEF;
3023 : 3 : nsdata1.nguid[15] = 0x34;
3024 : 3 : nsdata2.nguid[15] = 0x34;
3025 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == true);
3026 : :
3027 : : /* CSI are not matched. */
3028 : 3 : ns1.csi = SPDK_NVME_CSI_ZNS;
3029 : 3 : CU_ASSERT(bdev_nvme_compare_ns(&ns1, &ns2) == false);
3030 : 3 : }
3031 : :
3032 : : static void
3033 : 3 : test_init_ana_log_page(void)
3034 : 3 : {
3035 : 3 : struct spdk_nvme_transport_id trid = {};
3036 : : struct spdk_nvme_ctrlr *ctrlr;
3037 : : struct nvme_ctrlr *nvme_ctrlr;
3038 : 3 : const int STRING_SIZE = 32;
3039 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
3040 : : int rc;
3041 : :
3042 : 3 : set_thread(0);
3043 : :
3044 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
3045 : 3 : ut_init_trid(&trid);
3046 : :
3047 : 3 : ctrlr = ut_attach_ctrlr(&trid, 5, true, false);
3048 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
3049 : :
3050 : 3 : ctrlr->ns[0].ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
3051 : 3 : ctrlr->ns[1].ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
3052 : 3 : ctrlr->ns[2].ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
3053 : 3 : ctrlr->ns[3].ana_state = SPDK_NVME_ANA_PERSISTENT_LOSS_STATE;
3054 : 3 : ctrlr->ns[4].ana_state = SPDK_NVME_ANA_CHANGE_STATE;
3055 : :
3056 : 3 : g_ut_attach_ctrlr_status = 0;
3057 : 3 : g_ut_attach_bdev_count = 5;
3058 : :
3059 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
3060 : : attach_ctrlr_done, NULL, NULL, NULL, false);
3061 : 3 : CU_ASSERT(rc == 0);
3062 : :
3063 : 3 : spdk_delay_us(1000);
3064 : 3 : poll_threads();
3065 : :
3066 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3067 : 3 : poll_threads();
3068 : :
3069 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
3070 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
3071 : :
3072 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 1) != NULL);
3073 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 2) != NULL);
3074 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 3) != NULL);
3075 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 4) != NULL);
3076 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 5) != NULL);
3077 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 1)->ana_state == SPDK_NVME_ANA_OPTIMIZED_STATE);
3078 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 2)->ana_state == SPDK_NVME_ANA_NON_OPTIMIZED_STATE);
3079 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 3)->ana_state == SPDK_NVME_ANA_INACCESSIBLE_STATE);
3080 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 4)->ana_state == SPDK_NVME_ANA_PERSISTENT_LOSS_STATE);
3081 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 5)->ana_state == SPDK_NVME_ANA_CHANGE_STATE);
3082 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 1)->bdev != NULL);
3083 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 2)->bdev != NULL);
3084 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 3)->bdev != NULL);
3085 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 4)->bdev != NULL);
3086 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr, 5)->bdev != NULL);
3087 : :
3088 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
3089 : 3 : CU_ASSERT(rc == 0);
3090 : :
3091 : 3 : poll_threads();
3092 : 3 : spdk_delay_us(1000);
3093 : 3 : poll_threads();
3094 : :
3095 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
3096 : 3 : }
3097 : :
3098 : : static void
3099 : 3 : init_accel(void)
3100 : : {
3101 : 3 : spdk_io_device_register(g_accel_p, accel_channel_create, accel_channel_destroy,
3102 : : sizeof(int), "accel_p");
3103 : 3 : }
3104 : :
3105 : : static void
3106 : 3 : fini_accel(void)
3107 : : {
3108 : 3 : spdk_io_device_unregister(g_accel_p, NULL);
3109 : 3 : }
3110 : :
3111 : : static void
3112 : 3 : test_get_memory_domains(void)
3113 : : {
3114 : 3 : struct nvme_ctrlr ctrlr_1 = { .ctrlr = (struct spdk_nvme_ctrlr *) 0xbaadbeef };
3115 : 3 : struct nvme_ctrlr ctrlr_2 = { .ctrlr = (struct spdk_nvme_ctrlr *) 0xbaaadbeeef };
3116 : 3 : struct nvme_ns ns_1 = { .ctrlr = &ctrlr_1 };
3117 : 3 : struct nvme_ns ns_2 = { .ctrlr = &ctrlr_2 };
3118 : 3 : struct nvme_bdev nbdev = { .nvme_ns_list = TAILQ_HEAD_INITIALIZER(nbdev.nvme_ns_list) };
3119 : 3 : struct spdk_memory_domain *domains[4] = {};
3120 : 3 : int rc = 0;
3121 : :
3122 : 3 : TAILQ_INSERT_TAIL(&nbdev.nvme_ns_list, &ns_1, tailq);
3123 : :
3124 : : /* nvme controller doesn't have memory domains */
3125 : 3 : MOCK_SET(spdk_nvme_ctrlr_get_memory_domains, 0);
3126 : 3 : rc = bdev_nvme_get_memory_domains(&nbdev, domains, 2);
3127 : 3 : CU_ASSERT(rc == 0);
3128 : 3 : CU_ASSERT(domains[0] == NULL);
3129 : 3 : CU_ASSERT(domains[1] == NULL);
3130 : :
3131 : : /* nvme controller has a memory domain */
3132 : 3 : MOCK_SET(spdk_nvme_ctrlr_get_memory_domains, 1);
3133 : 3 : rc = bdev_nvme_get_memory_domains(&nbdev, domains, 2);
3134 : 3 : CU_ASSERT(rc == 1);
3135 : 3 : CU_ASSERT(domains[0] != NULL);
3136 [ - + ]: 3 : memset(domains, 0, sizeof(domains));
3137 : :
3138 : : /* multipath, 2 controllers report 1 memory domain each */
3139 : 3 : TAILQ_INSERT_TAIL(&nbdev.nvme_ns_list, &ns_2, tailq);
3140 : :
3141 : 3 : rc = bdev_nvme_get_memory_domains(&nbdev, domains, 2);
3142 : 3 : CU_ASSERT(rc == 2);
3143 : 3 : CU_ASSERT(domains[0] != NULL);
3144 : 3 : CU_ASSERT(domains[1] != NULL);
3145 [ - + ]: 3 : memset(domains, 0, sizeof(domains));
3146 : :
3147 : : /* multipath, 2 controllers report 1 memory domain each, NULL domains ptr */
3148 : 3 : rc = bdev_nvme_get_memory_domains(&nbdev, NULL, 2);
3149 : 3 : CU_ASSERT(rc == 2);
3150 : :
3151 : : /* multipath, 2 controllers report 1 memory domain each, array_size = 0 */
3152 : 3 : rc = bdev_nvme_get_memory_domains(&nbdev, domains, 0);
3153 : 3 : CU_ASSERT(rc == 2);
3154 : 3 : CU_ASSERT(domains[0] == NULL);
3155 : 3 : CU_ASSERT(domains[1] == NULL);
3156 : :
3157 : : /* multipath, 2 controllers report 1 memory domain each, array_size = 1 */
3158 : 3 : rc = bdev_nvme_get_memory_domains(&nbdev, domains, 1);
3159 : 3 : CU_ASSERT(rc == 2);
3160 : 3 : CU_ASSERT(domains[0] != NULL);
3161 : 3 : CU_ASSERT(domains[1] == NULL);
3162 [ - + ]: 3 : memset(domains, 0, sizeof(domains));
3163 : :
3164 : : /* multipath, 2 controllers report 2 memory domain each (not possible, just for test) */
3165 : 3 : MOCK_SET(spdk_nvme_ctrlr_get_memory_domains, 2);
3166 : 3 : rc = bdev_nvme_get_memory_domains(&nbdev, domains, 4);
3167 : 3 : CU_ASSERT(rc == 4);
3168 : 3 : CU_ASSERT(domains[0] != NULL);
3169 : 3 : CU_ASSERT(domains[1] != NULL);
3170 : 3 : CU_ASSERT(domains[2] != NULL);
3171 : 3 : CU_ASSERT(domains[3] != NULL);
3172 [ - + ]: 3 : memset(domains, 0, sizeof(domains));
3173 : :
3174 : : /* multipath, 2 controllers report 2 memory domain each (not possible, just for test)
3175 : : * Array size is less than the number of memory domains */
3176 : 3 : MOCK_SET(spdk_nvme_ctrlr_get_memory_domains, 2);
3177 : 3 : rc = bdev_nvme_get_memory_domains(&nbdev, domains, 3);
3178 : 3 : CU_ASSERT(rc == 4);
3179 : 3 : CU_ASSERT(domains[0] != NULL);
3180 : 3 : CU_ASSERT(domains[1] != NULL);
3181 : 3 : CU_ASSERT(domains[2] != NULL);
3182 : 3 : CU_ASSERT(domains[3] == NULL);
3183 [ - + ]: 3 : memset(domains, 0, sizeof(domains));
3184 : :
3185 : 3 : MOCK_CLEAR(spdk_nvme_ctrlr_get_memory_domains);
3186 : 3 : }
3187 : :
3188 : : static void
3189 : 3 : test_reconnect_qpair(void)
3190 : 3 : {
3191 : 3 : struct spdk_nvme_transport_id trid = {};
3192 : : struct spdk_nvme_ctrlr *ctrlr;
3193 : : struct nvme_ctrlr *nvme_ctrlr;
3194 : 3 : const int STRING_SIZE = 32;
3195 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
3196 : : struct nvme_bdev *bdev;
3197 : : struct spdk_io_channel *ch1, *ch2;
3198 : : struct nvme_bdev_channel *nbdev_ch1, *nbdev_ch2;
3199 : : struct nvme_io_path *io_path1, *io_path2;
3200 : : struct nvme_qpair *nvme_qpair1, *nvme_qpair2;
3201 : : int rc;
3202 : :
3203 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
3204 : 3 : ut_init_trid(&trid);
3205 : :
3206 : 3 : set_thread(0);
3207 : :
3208 : 3 : ctrlr = ut_attach_ctrlr(&trid, 1, false, false);
3209 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
3210 : :
3211 : 3 : g_ut_attach_ctrlr_status = 0;
3212 : 3 : g_ut_attach_bdev_count = 1;
3213 : :
3214 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
3215 : : attach_ctrlr_done, NULL, NULL, NULL, false);
3216 : 3 : CU_ASSERT(rc == 0);
3217 : :
3218 : 3 : spdk_delay_us(1000);
3219 : 3 : poll_threads();
3220 : :
3221 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
3222 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
3223 : :
3224 : 3 : bdev = nvme_ctrlr_get_ns(nvme_ctrlr, 1)->bdev;
3225 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
3226 : :
3227 : 3 : ch1 = spdk_get_io_channel(bdev);
3228 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
3229 : :
3230 : 3 : nbdev_ch1 = spdk_io_channel_get_ctx(ch1);
3231 : 3 : io_path1 = STAILQ_FIRST(&nbdev_ch1->io_path_list);
3232 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path1 != NULL);
3233 : 3 : nvme_qpair1 = io_path1->qpair;
3234 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair1 != NULL);
3235 : :
3236 : 3 : set_thread(1);
3237 : :
3238 : 3 : ch2 = spdk_get_io_channel(bdev);
3239 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
3240 : :
3241 : 3 : nbdev_ch2 = spdk_io_channel_get_ctx(ch2);
3242 : 3 : io_path2 = STAILQ_FIRST(&nbdev_ch2->io_path_list);
3243 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path2 != NULL);
3244 : 3 : nvme_qpair2 = io_path2->qpair;
3245 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair2 != NULL);
3246 : :
3247 : : /* If a qpair is disconnected, it is freed and then reconnected via
3248 : : * resetting the corresponding nvme_ctrlr.
3249 : : */
3250 : 3 : nvme_qpair2->qpair->failure_reason = SPDK_NVME_QPAIR_FAILURE_UNKNOWN;
3251 : 3 : ctrlr->is_failed = true;
3252 : :
3253 : 3 : poll_thread_times(1, 3);
3254 : 3 : CU_ASSERT(nvme_qpair1->qpair != NULL);
3255 : 3 : CU_ASSERT(nvme_qpair2->qpair == NULL);
3256 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
3257 : :
3258 : 3 : poll_thread_times(0, 3);
3259 : 3 : CU_ASSERT(nvme_qpair1->qpair == NULL);
3260 : 3 : CU_ASSERT(nvme_qpair2->qpair == NULL);
3261 [ - + ]: 3 : CU_ASSERT(ctrlr->is_failed == true);
3262 : :
3263 : 3 : poll_thread_times(1, 2);
3264 : 3 : poll_thread_times(0, 1);
3265 [ - + ]: 3 : CU_ASSERT(ctrlr->is_failed == false);
3266 [ - + ]: 3 : CU_ASSERT(ctrlr->adminq.is_connected == false);
3267 : :
3268 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3269 : 3 : poll_thread_times(0, 2);
3270 [ - + ]: 3 : CU_ASSERT(ctrlr->adminq.is_connected == true);
3271 : :
3272 : 3 : poll_thread_times(0, 1);
3273 : 3 : poll_thread_times(1, 1);
3274 : 3 : CU_ASSERT(nvme_qpair1->qpair != NULL);
3275 : 3 : CU_ASSERT(nvme_qpair2->qpair != NULL);
3276 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
3277 : :
3278 : 3 : poll_thread_times(0, 2);
3279 : 3 : poll_thread_times(1, 1);
3280 : 3 : poll_thread_times(0, 1);
3281 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
3282 : :
3283 : 3 : poll_threads();
3284 : :
3285 : : /* If a qpair is disconnected and resetting the corresponding nvme_ctrlr
3286 : : * fails, the qpair is just freed.
3287 : : */
3288 : 3 : nvme_qpair2->qpair->failure_reason = SPDK_NVME_QPAIR_FAILURE_UNKNOWN;
3289 : 3 : ctrlr->is_failed = true;
3290 : 3 : ctrlr->fail_reset = true;
3291 : :
3292 : 3 : poll_thread_times(1, 3);
3293 : 3 : CU_ASSERT(nvme_qpair1->qpair != NULL);
3294 : 3 : CU_ASSERT(nvme_qpair2->qpair == NULL);
3295 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
3296 : :
3297 : 3 : poll_thread_times(0, 3);
3298 : 3 : poll_thread_times(1, 1);
3299 : 3 : CU_ASSERT(nvme_qpair1->qpair == NULL);
3300 : 3 : CU_ASSERT(nvme_qpair2->qpair == NULL);
3301 [ - + ]: 3 : CU_ASSERT(ctrlr->is_failed == true);
3302 : :
3303 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3304 : 3 : poll_thread_times(0, 3);
3305 : 3 : poll_thread_times(1, 1);
3306 : 3 : poll_thread_times(0, 1);
3307 [ - + ]: 3 : CU_ASSERT(ctrlr->is_failed == true);
3308 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
3309 : 3 : CU_ASSERT(nvme_qpair1->qpair == NULL);
3310 : 3 : CU_ASSERT(nvme_qpair2->qpair == NULL);
3311 : :
3312 : 3 : poll_threads();
3313 : :
3314 : 3 : spdk_put_io_channel(ch2);
3315 : :
3316 : 3 : set_thread(0);
3317 : :
3318 : 3 : spdk_put_io_channel(ch1);
3319 : :
3320 : 3 : poll_threads();
3321 : :
3322 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
3323 : 3 : CU_ASSERT(rc == 0);
3324 : :
3325 : 3 : poll_threads();
3326 : 3 : spdk_delay_us(1000);
3327 : 3 : poll_threads();
3328 : :
3329 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
3330 : 3 : }
3331 : :
3332 : : static void
3333 : 3 : test_create_bdev_ctrlr(void)
3334 : 3 : {
3335 : 3 : struct nvme_path_id path1 = {}, path2 = {};
3336 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2;
3337 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
3338 : 3 : const int STRING_SIZE = 32;
3339 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
3340 : : int rc;
3341 : :
3342 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
3343 : 3 : ut_init_trid(&path1.trid);
3344 : 3 : ut_init_trid2(&path2.trid);
3345 : :
3346 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 0, true, true);
3347 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
3348 : :
3349 : 3 : g_ut_attach_ctrlr_status = 0;
3350 : 3 : g_ut_attach_bdev_count = 0;
3351 : :
3352 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
3353 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3354 : 3 : CU_ASSERT(rc == 0);
3355 : :
3356 : 3 : spdk_delay_us(1000);
3357 : 3 : poll_threads();
3358 : :
3359 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3360 : 3 : poll_threads();
3361 : :
3362 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
3363 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
3364 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid) != NULL);
3365 : :
3366 : : /* cntlid is duplicated, and adding the second ctrlr should fail. */
3367 : 3 : g_ut_attach_ctrlr_status = -EINVAL;
3368 : :
3369 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 0, true, true);
3370 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
3371 : :
3372 : 3 : ctrlr2->cdata.cntlid = ctrlr1->cdata.cntlid;
3373 : :
3374 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
3375 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3376 : 3 : CU_ASSERT(rc == 0);
3377 : :
3378 : 3 : spdk_delay_us(1000);
3379 : 3 : poll_threads();
3380 : :
3381 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3382 : 3 : poll_threads();
3383 : :
3384 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid) == NULL);
3385 : :
3386 : : /* cntlid is not duplicated, and adding the third ctrlr should succeed. */
3387 : 3 : g_ut_attach_ctrlr_status = 0;
3388 : :
3389 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 0, true, true);
3390 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
3391 : :
3392 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
3393 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3394 : 3 : CU_ASSERT(rc == 0);
3395 : :
3396 : 3 : spdk_delay_us(1000);
3397 : 3 : poll_threads();
3398 : :
3399 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3400 : 3 : poll_threads();
3401 : :
3402 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid) != NULL);
3403 : :
3404 : : /* Delete two ctrlrs at once. */
3405 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
3406 : 3 : CU_ASSERT(rc == 0);
3407 : :
3408 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == nbdev_ctrlr);
3409 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid) != NULL);
3410 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid) != NULL);
3411 : :
3412 : 3 : poll_threads();
3413 : 3 : spdk_delay_us(1000);
3414 : 3 : poll_threads();
3415 : :
3416 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
3417 : :
3418 : : /* Add two ctrlrs and delete one by one. */
3419 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 0, true, true);
3420 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
3421 : :
3422 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 0, true, true);
3423 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
3424 : :
3425 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
3426 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3427 : 3 : CU_ASSERT(rc == 0);
3428 : :
3429 : 3 : spdk_delay_us(1000);
3430 : 3 : poll_threads();
3431 : :
3432 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3433 : 3 : poll_threads();
3434 : :
3435 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
3436 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3437 : 3 : CU_ASSERT(rc == 0);
3438 : :
3439 : 3 : spdk_delay_us(1000);
3440 : 3 : poll_threads();
3441 : :
3442 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3443 : 3 : poll_threads();
3444 : :
3445 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
3446 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
3447 : :
3448 : 3 : rc = bdev_nvme_delete("nvme0", &path1, NULL, NULL);
3449 : 3 : CU_ASSERT(rc == 0);
3450 : :
3451 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == nbdev_ctrlr);
3452 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid) != NULL);
3453 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid) != NULL);
3454 : :
3455 : 3 : poll_threads();
3456 : 3 : spdk_delay_us(1000);
3457 : 3 : poll_threads();
3458 : :
3459 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == nbdev_ctrlr);
3460 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid) == NULL);
3461 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid) != NULL);
3462 : :
3463 : 3 : rc = bdev_nvme_delete("nvme0", &path2, NULL, NULL);
3464 : 3 : CU_ASSERT(rc == 0);
3465 : :
3466 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == nbdev_ctrlr);
3467 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid) == NULL);
3468 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid) != NULL);
3469 : :
3470 : 3 : poll_threads();
3471 : 3 : spdk_delay_us(1000);
3472 : 3 : poll_threads();
3473 : :
3474 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
3475 : 3 : }
3476 : :
3477 : : static struct nvme_ns *
3478 : 21 : _nvme_bdev_get_ns(struct nvme_bdev *bdev, struct nvme_ctrlr *nvme_ctrlr)
3479 : : {
3480 : : struct nvme_ns *nvme_ns;
3481 : :
3482 [ + - ]: 36 : TAILQ_FOREACH(nvme_ns, &bdev->nvme_ns_list, tailq) {
3483 [ + + ]: 36 : if (nvme_ns->ctrlr == nvme_ctrlr) {
3484 : 21 : return nvme_ns;
3485 : : }
3486 : : }
3487 : :
3488 : 0 : return NULL;
3489 : : }
3490 : :
3491 : : static void
3492 : 3 : test_add_multi_ns_to_bdev(void)
3493 : 3 : {
3494 : 3 : struct nvme_path_id path1 = {}, path2 = {};
3495 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2;
3496 : : struct nvme_ctrlr *nvme_ctrlr1, *nvme_ctrlr2;
3497 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
3498 : : struct nvme_ns *nvme_ns1, *nvme_ns2;
3499 : : struct nvme_bdev *bdev1, *bdev2, *bdev3, *bdev4;
3500 : 3 : const int STRING_SIZE = 32;
3501 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
3502 : 3 : struct spdk_uuid uuid1 = { .u.raw = { 0x1 } };
3503 : 3 : struct spdk_uuid uuid2 = { .u.raw = { 0x2 } };
3504 : 3 : struct spdk_uuid uuid3 = { .u.raw = { 0x3 } };
3505 : 3 : struct spdk_uuid uuid4 = { .u.raw = { 0x4 } };
3506 : 3 : struct spdk_uuid uuid44 = { .u.raw = { 0x44 } };
3507 : : int rc;
3508 : :
3509 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
3510 : 3 : ut_init_trid(&path1.trid);
3511 : 3 : ut_init_trid2(&path2.trid);
3512 : :
3513 : : /* Create nvme_bdevs, some of which have shared namespaces between two ctrlrs. */
3514 : :
3515 : : /* Attach 1st ctrlr, whose max number of namespaces is 5, and 1st, 3rd, and 4th
3516 : : * namespaces are populated.
3517 : : */
3518 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 5, true, true);
3519 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
3520 : :
3521 : 3 : ctrlr1->ns[1].is_active = false;
3522 : 3 : ctrlr1->ns[4].is_active = false;
3523 : 3 : ctrlr1->ns[0].uuid = &uuid1;
3524 : 3 : ctrlr1->ns[2].uuid = &uuid3;
3525 : 3 : ctrlr1->ns[3].uuid = &uuid4;
3526 : :
3527 : 3 : g_ut_attach_ctrlr_status = 0;
3528 : 3 : g_ut_attach_bdev_count = 3;
3529 : :
3530 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, 32,
3531 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3532 : 3 : CU_ASSERT(rc == 0);
3533 : :
3534 : 3 : spdk_delay_us(1000);
3535 : 3 : poll_threads();
3536 : :
3537 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3538 : 3 : poll_threads();
3539 : :
3540 : : /* Attach 2nd ctrlr, whose max number of namespaces is 5, and 1st, 2nd, and 4th
3541 : : * namespaces are populated. The uuid of 4th namespace is different, and hence
3542 : : * adding 4th namespace to a bdev should fail.
3543 : : */
3544 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 5, true, true);
3545 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
3546 : :
3547 : 3 : ctrlr2->ns[2].is_active = false;
3548 : 3 : ctrlr2->ns[4].is_active = false;
3549 : 3 : ctrlr2->ns[0].uuid = &uuid1;
3550 : 3 : ctrlr2->ns[1].uuid = &uuid2;
3551 : 3 : ctrlr2->ns[3].uuid = &uuid44;
3552 : :
3553 : 3 : g_ut_attach_ctrlr_status = 0;
3554 : 3 : g_ut_attach_bdev_count = 2;
3555 : :
3556 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, 32,
3557 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3558 : 3 : CU_ASSERT(rc == 0);
3559 : :
3560 : 3 : spdk_delay_us(1000);
3561 : 3 : poll_threads();
3562 : :
3563 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3564 : 3 : poll_threads();
3565 : :
3566 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
3567 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
3568 : :
3569 : 3 : nvme_ctrlr1 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid);
3570 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr1 != NULL);
3571 : :
3572 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr1, 1) != NULL);
3573 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr1, 2) == NULL);
3574 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr1, 3) != NULL);
3575 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr1, 4) != NULL);
3576 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr1, 5) == NULL);
3577 : :
3578 : 3 : nvme_ctrlr2 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid);
3579 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr2 != NULL);
3580 : :
3581 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr2, 1) != NULL);
3582 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr2, 2) != NULL);
3583 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr2, 3) == NULL);
3584 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr2, 4) == NULL);
3585 : 3 : CU_ASSERT(nvme_ctrlr_get_ns(nvme_ctrlr2, 5) == NULL);
3586 : :
3587 : 3 : bdev1 = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
3588 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev1 != NULL);
3589 : 3 : bdev2 = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 2);
3590 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev2 != NULL);
3591 : 3 : bdev3 = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 3);
3592 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev3 != NULL);
3593 : 3 : bdev4 = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 4);
3594 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev4 != NULL);
3595 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 5) == NULL);
3596 : :
3597 : 3 : CU_ASSERT(bdev1->ref == 2);
3598 : 3 : CU_ASSERT(bdev2->ref == 1);
3599 : 3 : CU_ASSERT(bdev3->ref == 1);
3600 : 3 : CU_ASSERT(bdev4->ref == 1);
3601 : :
3602 : : /* Test if nvme_bdevs can be deleted by deleting ctrlr one by one. */
3603 : 3 : rc = bdev_nvme_delete("nvme0", &path1, NULL, NULL);
3604 : 3 : CU_ASSERT(rc == 0);
3605 : :
3606 : 3 : poll_threads();
3607 : 3 : spdk_delay_us(1000);
3608 : 3 : poll_threads();
3609 : :
3610 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == nbdev_ctrlr);
3611 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid) == NULL);
3612 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid) == nvme_ctrlr2);
3613 : :
3614 : 3 : rc = bdev_nvme_delete("nvme0", &path2, NULL, NULL);
3615 : 3 : CU_ASSERT(rc == 0);
3616 : :
3617 : 3 : poll_threads();
3618 : 3 : spdk_delay_us(1000);
3619 : 3 : poll_threads();
3620 : :
3621 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
3622 : :
3623 : : /* Test if a nvme_bdev which has a shared namespace between two ctrlrs
3624 : : * can be deleted when the bdev subsystem shutdown.
3625 : : */
3626 : 3 : g_ut_attach_bdev_count = 1;
3627 : :
3628 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 1, true, true);
3629 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
3630 : :
3631 : 3 : ctrlr1->ns[0].uuid = &uuid1;
3632 : :
3633 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, 32,
3634 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3635 : 3 : CU_ASSERT(rc == 0);
3636 : :
3637 : 3 : spdk_delay_us(1000);
3638 : 3 : poll_threads();
3639 : :
3640 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3641 : 3 : poll_threads();
3642 : :
3643 : 3 : ut_init_trid2(&path2.trid);
3644 : :
3645 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 1, true, true);
3646 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
3647 : :
3648 : 3 : ctrlr2->ns[0].uuid = &uuid1;
3649 : :
3650 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, 32,
3651 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3652 : 3 : CU_ASSERT(rc == 0);
3653 : :
3654 : 3 : spdk_delay_us(1000);
3655 : 3 : poll_threads();
3656 : :
3657 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3658 : 3 : poll_threads();
3659 : :
3660 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
3661 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
3662 : :
3663 : 3 : bdev1 = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
3664 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev1 != NULL);
3665 : :
3666 : 3 : nvme_ctrlr1 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid);
3667 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr1 != NULL);
3668 : :
3669 : 3 : nvme_ctrlr2 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid);
3670 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr2 != NULL);
3671 : :
3672 : : /* Check if a nvme_bdev has two nvme_ns. */
3673 : 3 : nvme_ns1 = _nvme_bdev_get_ns(bdev1, nvme_ctrlr1);
3674 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ns1 != NULL);
3675 : 3 : CU_ASSERT(nvme_ns1->bdev == bdev1);
3676 : :
3677 : 3 : nvme_ns2 = _nvme_bdev_get_ns(bdev1, nvme_ctrlr2);
3678 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ns2 != NULL);
3679 : 3 : CU_ASSERT(nvme_ns2->bdev == bdev1);
3680 : :
3681 : : /* Delete nvme_bdev first when the bdev subsystem shutdown. */
3682 : 3 : bdev_nvme_destruct(&bdev1->disk);
3683 : :
3684 : 3 : poll_threads();
3685 : :
3686 : 3 : CU_ASSERT(nvme_ns1->bdev == NULL);
3687 : 3 : CU_ASSERT(nvme_ns2->bdev == NULL);
3688 : :
3689 : 3 : nvme_ctrlr1->destruct = true;
3690 : 3 : _nvme_ctrlr_destruct(nvme_ctrlr1);
3691 : :
3692 : 3 : poll_threads();
3693 : 3 : spdk_delay_us(1000);
3694 : 3 : poll_threads();
3695 : :
3696 : 3 : nvme_ctrlr2->destruct = true;
3697 : 3 : _nvme_ctrlr_destruct(nvme_ctrlr2);
3698 : :
3699 : 3 : poll_threads();
3700 : 3 : spdk_delay_us(1000);
3701 : 3 : poll_threads();
3702 : :
3703 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
3704 : 3 : }
3705 : :
3706 : : static void
3707 : 3 : test_add_multi_io_paths_to_nbdev_ch(void)
3708 : 3 : {
3709 : 3 : struct nvme_path_id path1 = {}, path2 = {}, path3 = {};
3710 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2, *ctrlr3;
3711 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
3712 : : struct nvme_ctrlr *nvme_ctrlr1, *nvme_ctrlr2, *nvme_ctrlr3;
3713 : : struct nvme_ns *nvme_ns1, *nvme_ns2, *nvme_ns3;
3714 : 3 : const int STRING_SIZE = 32;
3715 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
3716 : : struct nvme_bdev *bdev;
3717 : : struct spdk_io_channel *ch;
3718 : : struct nvme_bdev_channel *nbdev_ch;
3719 : : struct nvme_io_path *io_path1, *io_path2, *io_path3;
3720 : 3 : struct spdk_uuid uuid1 = { .u.raw = { 0x1 } };
3721 : : int rc;
3722 : :
3723 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
3724 : 3 : ut_init_trid(&path1.trid);
3725 : 3 : ut_init_trid2(&path2.trid);
3726 : 3 : ut_init_trid3(&path3.trid);
3727 : 3 : g_ut_attach_ctrlr_status = 0;
3728 : 3 : g_ut_attach_bdev_count = 1;
3729 : :
3730 : 3 : set_thread(1);
3731 : :
3732 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 1, true, true);
3733 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
3734 : :
3735 : 3 : ctrlr1->ns[0].uuid = &uuid1;
3736 : :
3737 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
3738 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3739 : 3 : CU_ASSERT(rc == 0);
3740 : :
3741 : 3 : spdk_delay_us(1000);
3742 : 3 : poll_threads();
3743 : :
3744 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3745 : 3 : poll_threads();
3746 : :
3747 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 1, true, true);
3748 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
3749 : :
3750 : 3 : ctrlr2->ns[0].uuid = &uuid1;
3751 : :
3752 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
3753 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3754 : 3 : CU_ASSERT(rc == 0);
3755 : :
3756 : 3 : spdk_delay_us(1000);
3757 : 3 : poll_threads();
3758 : :
3759 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3760 : 3 : poll_threads();
3761 : :
3762 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
3763 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
3764 : :
3765 : 3 : nvme_ctrlr1 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid);
3766 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr1 != NULL);
3767 : :
3768 : 3 : nvme_ctrlr2 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid);
3769 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr2 != NULL);
3770 : :
3771 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
3772 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
3773 : :
3774 : 3 : nvme_ns1 = _nvme_bdev_get_ns(bdev, nvme_ctrlr1);
3775 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ns1 != NULL);
3776 : :
3777 : 3 : nvme_ns2 = _nvme_bdev_get_ns(bdev, nvme_ctrlr2);
3778 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ns2 != NULL);
3779 : :
3780 : 3 : set_thread(0);
3781 : :
3782 : 3 : ch = spdk_get_io_channel(bdev);
3783 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
3784 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
3785 : :
3786 : 3 : io_path1 = _bdev_nvme_get_io_path(nbdev_ch, nvme_ns1);
3787 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path1 != NULL);
3788 : :
3789 : 3 : io_path2 = _bdev_nvme_get_io_path(nbdev_ch, nvme_ns2);
3790 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path2 != NULL);
3791 : :
3792 : 3 : set_thread(1);
3793 : :
3794 : : /* Check if I/O path is dynamically added to nvme_bdev_channel. */
3795 : 3 : ctrlr3 = ut_attach_ctrlr(&path3.trid, 1, true, true);
3796 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr3 != NULL);
3797 : :
3798 : 3 : ctrlr3->ns[0].uuid = &uuid1;
3799 : :
3800 : 3 : rc = bdev_nvme_create(&path3.trid, "nvme0", attached_names, STRING_SIZE,
3801 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3802 : 3 : CU_ASSERT(rc == 0);
3803 : :
3804 : 3 : spdk_delay_us(1000);
3805 : 3 : poll_threads();
3806 : :
3807 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3808 : 3 : poll_threads();
3809 : :
3810 : 3 : nvme_ctrlr3 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path3.trid);
3811 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr3 != NULL);
3812 : :
3813 : 3 : nvme_ns3 = _nvme_bdev_get_ns(bdev, nvme_ctrlr3);
3814 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ns3 != NULL);
3815 : :
3816 : 3 : io_path3 = _bdev_nvme_get_io_path(nbdev_ch, nvme_ns3);
3817 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path3 != NULL);
3818 : :
3819 : : /* Check if I/O path is dynamically deleted from nvme_bdev_channel. */
3820 : 3 : rc = bdev_nvme_delete("nvme0", &path2, NULL, NULL);
3821 : 3 : CU_ASSERT(rc == 0);
3822 : :
3823 : 3 : poll_threads();
3824 : 3 : spdk_delay_us(1000);
3825 : 3 : poll_threads();
3826 : :
3827 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid) == nvme_ctrlr1);
3828 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid) == NULL);
3829 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path3.trid) == nvme_ctrlr3);
3830 : :
3831 : 3 : CU_ASSERT(_bdev_nvme_get_io_path(nbdev_ch, nvme_ns1) == io_path1);
3832 : 3 : CU_ASSERT(_bdev_nvme_get_io_path(nbdev_ch, nvme_ns2) == NULL);
3833 : 3 : CU_ASSERT(_bdev_nvme_get_io_path(nbdev_ch, nvme_ns3) == io_path3);
3834 : :
3835 : 3 : set_thread(0);
3836 : :
3837 : 3 : spdk_put_io_channel(ch);
3838 : :
3839 : 3 : poll_threads();
3840 : :
3841 : 3 : set_thread(1);
3842 : :
3843 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
3844 : 3 : CU_ASSERT(rc == 0);
3845 : :
3846 : 3 : poll_threads();
3847 : 3 : spdk_delay_us(1000);
3848 : 3 : poll_threads();
3849 : :
3850 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
3851 : 3 : }
3852 : :
3853 : : static void
3854 : 3 : test_admin_path(void)
3855 : 3 : {
3856 : 3 : struct nvme_path_id path1 = {}, path2 = {};
3857 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2;
3858 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
3859 : 3 : const int STRING_SIZE = 32;
3860 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
3861 : : struct nvme_bdev *bdev;
3862 : : struct spdk_io_channel *ch;
3863 : : struct spdk_bdev_io *bdev_io;
3864 : 3 : struct spdk_uuid uuid1 = { .u.raw = { 0x1 } };
3865 : : int rc;
3866 : :
3867 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
3868 : 3 : ut_init_trid(&path1.trid);
3869 : 3 : ut_init_trid2(&path2.trid);
3870 : 3 : g_ut_attach_ctrlr_status = 0;
3871 : 3 : g_ut_attach_bdev_count = 1;
3872 : :
3873 : 3 : set_thread(0);
3874 : :
3875 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 1, true, true);
3876 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
3877 : :
3878 : 3 : ctrlr1->ns[0].uuid = &uuid1;
3879 : :
3880 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
3881 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3882 : 3 : CU_ASSERT(rc == 0);
3883 : :
3884 : 3 : spdk_delay_us(1000);
3885 : 3 : poll_threads();
3886 : :
3887 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3888 : 3 : poll_threads();
3889 : :
3890 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 1, true, true);
3891 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
3892 : :
3893 : 3 : ctrlr2->ns[0].uuid = &uuid1;
3894 : :
3895 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
3896 : : attach_ctrlr_done, NULL, NULL, NULL, true);
3897 : 3 : CU_ASSERT(rc == 0);
3898 : :
3899 : 3 : spdk_delay_us(1000);
3900 : 3 : poll_threads();
3901 : :
3902 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3903 : 3 : poll_threads();
3904 : :
3905 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
3906 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
3907 : :
3908 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
3909 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
3910 : :
3911 : 3 : ch = spdk_get_io_channel(bdev);
3912 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
3913 : :
3914 : 3 : bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_NVME_ADMIN, bdev, ch);
3915 : 3 : bdev_io->u.nvme_passthru.cmd.opc = SPDK_NVME_OPC_GET_FEATURES;
3916 : :
3917 : : /* ctrlr1 is failed but ctrlr2 is not failed. admin command is
3918 : : * submitted to ctrlr2.
3919 : : */
3920 : 3 : ctrlr1->is_failed = true;
3921 : 3 : bdev_io->internal.in_submit_request = true;
3922 : :
3923 : 3 : bdev_nvme_submit_request(ch, bdev_io);
3924 : :
3925 : 3 : CU_ASSERT(ctrlr1->adminq.num_outstanding_reqs == 0);
3926 : 3 : CU_ASSERT(ctrlr2->adminq.num_outstanding_reqs == 1);
3927 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
3928 : :
3929 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
3930 : 3 : poll_threads();
3931 : :
3932 : 3 : CU_ASSERT(ctrlr2->adminq.num_outstanding_reqs == 0);
3933 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
3934 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
3935 : :
3936 : : /* both ctrlr1 and ctrlr2 are failed. admin command is failed to submit. */
3937 : 3 : ctrlr2->is_failed = true;
3938 : 3 : bdev_io->internal.in_submit_request = true;
3939 : :
3940 : 3 : bdev_nvme_submit_request(ch, bdev_io);
3941 : :
3942 : 3 : CU_ASSERT(ctrlr1->adminq.num_outstanding_reqs == 0);
3943 : 3 : CU_ASSERT(ctrlr2->adminq.num_outstanding_reqs == 0);
3944 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
3945 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
3946 : :
3947 : 3 : free(bdev_io);
3948 : :
3949 : 3 : spdk_put_io_channel(ch);
3950 : :
3951 : 3 : poll_threads();
3952 : :
3953 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
3954 : 3 : CU_ASSERT(rc == 0);
3955 : :
3956 : 3 : poll_threads();
3957 : 3 : spdk_delay_us(1000);
3958 : 3 : poll_threads();
3959 : :
3960 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
3961 : 3 : }
3962 : :
3963 : : static struct nvme_io_path *
3964 : 39 : ut_get_io_path_by_ctrlr(struct nvme_bdev_channel *nbdev_ch,
3965 : : struct nvme_ctrlr *nvme_ctrlr)
3966 : : {
3967 : : struct nvme_io_path *io_path;
3968 : :
3969 [ + - ]: 51 : STAILQ_FOREACH(io_path, &nbdev_ch->io_path_list, stailq) {
3970 [ + + ]: 51 : if (io_path->qpair->ctrlr == nvme_ctrlr) {
3971 : 39 : return io_path;
3972 : : }
3973 : : }
3974 : :
3975 : 0 : return NULL;
3976 : : }
3977 : :
3978 : : static void
3979 : 3 : test_reset_bdev_ctrlr(void)
3980 : 3 : {
3981 : 3 : struct nvme_path_id path1 = {}, path2 = {};
3982 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2;
3983 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
3984 : : struct nvme_ctrlr *nvme_ctrlr1, *nvme_ctrlr2;
3985 : : struct nvme_path_id *curr_path1, *curr_path2;
3986 : 3 : const int STRING_SIZE = 32;
3987 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
3988 : : struct nvme_bdev *bdev;
3989 : : struct spdk_bdev_io *first_bdev_io, *second_bdev_io;
3990 : : struct nvme_bdev_io *first_bio;
3991 : : struct spdk_io_channel *ch1, *ch2;
3992 : : struct nvme_bdev_channel *nbdev_ch1, *nbdev_ch2;
3993 : : struct nvme_io_path *io_path11, *io_path12, *io_path21, *io_path22;
3994 : : int rc;
3995 : :
3996 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
3997 : 3 : ut_init_trid(&path1.trid);
3998 : 3 : ut_init_trid2(&path2.trid);
3999 : 3 : g_ut_attach_ctrlr_status = 0;
4000 : 3 : g_ut_attach_bdev_count = 1;
4001 : :
4002 : 3 : set_thread(0);
4003 : :
4004 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 1, true, true);
4005 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
4006 : :
4007 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
4008 : : attach_ctrlr_done, NULL, NULL, NULL, true);
4009 : 3 : CU_ASSERT(rc == 0);
4010 : :
4011 : 3 : spdk_delay_us(1000);
4012 : 3 : poll_threads();
4013 : :
4014 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4015 : 3 : poll_threads();
4016 : :
4017 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 1, true, true);
4018 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
4019 : :
4020 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
4021 : : attach_ctrlr_done, NULL, NULL, NULL, true);
4022 : 3 : CU_ASSERT(rc == 0);
4023 : :
4024 : 3 : spdk_delay_us(1000);
4025 : 3 : poll_threads();
4026 : :
4027 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4028 : 3 : poll_threads();
4029 : :
4030 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
4031 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
4032 : :
4033 : 3 : nvme_ctrlr1 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid);
4034 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr1 != NULL);
4035 : :
4036 : 3 : curr_path1 = TAILQ_FIRST(&nvme_ctrlr1->trids);
4037 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_path1 != NULL);
4038 : :
4039 : 3 : nvme_ctrlr2 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid);
4040 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr2 != NULL);
4041 : :
4042 : 3 : curr_path2 = TAILQ_FIRST(&nvme_ctrlr2->trids);
4043 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_path2 != NULL);
4044 : :
4045 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
4046 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
4047 : :
4048 : 3 : set_thread(0);
4049 : :
4050 : 3 : ch1 = spdk_get_io_channel(bdev);
4051 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
4052 : :
4053 : 3 : nbdev_ch1 = spdk_io_channel_get_ctx(ch1);
4054 : 3 : io_path11 = ut_get_io_path_by_ctrlr(nbdev_ch1, nvme_ctrlr1);
4055 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path11 != NULL);
4056 : 3 : io_path12 = ut_get_io_path_by_ctrlr(nbdev_ch1, nvme_ctrlr2);
4057 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path12 != NULL);
4058 : :
4059 : 3 : first_bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_RESET, bdev, ch1);
4060 : 3 : first_bio = (struct nvme_bdev_io *)first_bdev_io->driver_ctx;
4061 : :
4062 : 3 : set_thread(1);
4063 : :
4064 : 3 : ch2 = spdk_get_io_channel(bdev);
4065 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
4066 : :
4067 : 3 : nbdev_ch2 = spdk_io_channel_get_ctx(ch2);
4068 : 3 : io_path21 = ut_get_io_path_by_ctrlr(nbdev_ch2, nvme_ctrlr1);
4069 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path21 != NULL);
4070 : 3 : io_path22 = ut_get_io_path_by_ctrlr(nbdev_ch2, nvme_ctrlr2);
4071 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path22 != NULL);
4072 : :
4073 : 3 : second_bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_RESET, bdev, ch2);
4074 : :
4075 : : /* The first reset request from bdev_io is submitted on thread 0.
4076 : : * Check if ctrlr1 is reset and then ctrlr2 is reset.
4077 : : *
4078 : : * A few extra polls are necessary after resetting ctrlr1 to check
4079 : : * pending reset requests for ctrlr1.
4080 : : */
4081 : 3 : ctrlr1->is_failed = true;
4082 : 3 : curr_path1->last_failed_tsc = spdk_get_ticks();
4083 : 3 : ctrlr2->is_failed = true;
4084 : 3 : curr_path2->last_failed_tsc = spdk_get_ticks();
4085 : :
4086 : 3 : set_thread(0);
4087 : :
4088 : 3 : bdev_nvme_submit_request(ch1, first_bdev_io);
4089 : 3 : CU_ASSERT(first_bio->io_path == io_path11);
4090 : 3 : CU_ASSERT(nvme_ctrlr1->resetting == true);
4091 : 3 : CU_ASSERT(nvme_ctrlr1->ctrlr_op_cb_arg == first_bio);
4092 : :
4093 : 3 : poll_thread_times(0, 3);
4094 : 3 : CU_ASSERT(io_path11->qpair->qpair == NULL);
4095 : 3 : CU_ASSERT(io_path21->qpair->qpair != NULL);
4096 : :
4097 : 3 : poll_thread_times(1, 2);
4098 : 3 : CU_ASSERT(io_path11->qpair->qpair == NULL);
4099 : 3 : CU_ASSERT(io_path21->qpair->qpair == NULL);
4100 [ - + ]: 3 : CU_ASSERT(ctrlr1->is_failed == true);
4101 : :
4102 : 3 : poll_thread_times(0, 1);
4103 : 3 : CU_ASSERT(nvme_ctrlr1->resetting == true);
4104 [ - + ]: 3 : CU_ASSERT(ctrlr1->is_failed == false);
4105 [ - + ]: 3 : CU_ASSERT(ctrlr1->adminq.is_connected == false);
4106 : 3 : CU_ASSERT(curr_path1->last_failed_tsc != 0);
4107 : :
4108 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4109 : 3 : poll_thread_times(0, 2);
4110 [ - + ]: 3 : CU_ASSERT(ctrlr1->adminq.is_connected == true);
4111 : :
4112 : 3 : poll_thread_times(0, 1);
4113 : 3 : CU_ASSERT(io_path11->qpair->qpair != NULL);
4114 : 3 : CU_ASSERT(io_path21->qpair->qpair == NULL);
4115 : :
4116 : 3 : poll_thread_times(1, 1);
4117 : 3 : CU_ASSERT(io_path11->qpair->qpair != NULL);
4118 : 3 : CU_ASSERT(io_path21->qpair->qpair != NULL);
4119 : :
4120 : 3 : poll_thread_times(0, 2);
4121 : 3 : CU_ASSERT(nvme_ctrlr1->resetting == true);
4122 : 3 : poll_thread_times(1, 1);
4123 : 3 : CU_ASSERT(nvme_ctrlr1->resetting == true);
4124 : 3 : poll_thread_times(0, 2);
4125 : 3 : CU_ASSERT(nvme_ctrlr1->resetting == false);
4126 : 3 : CU_ASSERT(curr_path1->last_failed_tsc == 0);
4127 : 3 : CU_ASSERT(first_bio->io_path == io_path12);
4128 : 3 : CU_ASSERT(nvme_ctrlr2->resetting == true);
4129 : :
4130 : 3 : poll_thread_times(0, 3);
4131 : 3 : CU_ASSERT(io_path12->qpair->qpair == NULL);
4132 : 3 : CU_ASSERT(io_path22->qpair->qpair != NULL);
4133 : :
4134 : 3 : poll_thread_times(1, 2);
4135 : 3 : CU_ASSERT(io_path12->qpair->qpair == NULL);
4136 : 3 : CU_ASSERT(io_path22->qpair->qpair == NULL);
4137 [ - + ]: 3 : CU_ASSERT(ctrlr2->is_failed == true);
4138 : :
4139 : 3 : poll_thread_times(0, 1);
4140 : 3 : CU_ASSERT(nvme_ctrlr2->resetting == true);
4141 [ - + ]: 3 : CU_ASSERT(ctrlr2->is_failed == false);
4142 [ - + ]: 3 : CU_ASSERT(ctrlr2->adminq.is_connected == false);
4143 : 3 : CU_ASSERT(curr_path2->last_failed_tsc != 0);
4144 : :
4145 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4146 : 3 : poll_thread_times(0, 2);
4147 [ - + ]: 3 : CU_ASSERT(ctrlr2->adminq.is_connected == true);
4148 : :
4149 : 3 : poll_thread_times(0, 1);
4150 : 3 : CU_ASSERT(io_path12->qpair->qpair != NULL);
4151 : 3 : CU_ASSERT(io_path22->qpair->qpair == NULL);
4152 : :
4153 : 3 : poll_thread_times(1, 2);
4154 : 3 : CU_ASSERT(io_path12->qpair->qpair != NULL);
4155 : 3 : CU_ASSERT(io_path22->qpair->qpair != NULL);
4156 : :
4157 : 3 : poll_thread_times(0, 2);
4158 : 3 : CU_ASSERT(nvme_ctrlr2->resetting == true);
4159 : 3 : poll_thread_times(1, 1);
4160 : 3 : CU_ASSERT(nvme_ctrlr2->resetting == true);
4161 : 3 : poll_thread_times(0, 2);
4162 : 3 : CU_ASSERT(first_bio->io_path == NULL);
4163 : 3 : CU_ASSERT(nvme_ctrlr2->resetting == false);
4164 : 3 : CU_ASSERT(curr_path2->last_failed_tsc == 0);
4165 : :
4166 : 3 : poll_threads();
4167 : :
4168 : : /* There is a race between two reset requests from bdev_io.
4169 : : *
4170 : : * The first reset request is submitted on thread 0, and the second reset
4171 : : * request is submitted on thread 1 while the first is resetting ctrlr1.
4172 : : * The second is pending on ctrlr1. After the first completes resetting ctrlr1,
4173 : : * both reset requests go to ctrlr2. The first comes earlier than the second.
4174 : : * The second is pending on ctrlr2 again. After the first completes resetting
4175 : : * ctrl2, both complete successfully.
4176 : : */
4177 : 3 : ctrlr1->is_failed = true;
4178 : 3 : curr_path1->last_failed_tsc = spdk_get_ticks();
4179 : 3 : ctrlr2->is_failed = true;
4180 : 3 : curr_path2->last_failed_tsc = spdk_get_ticks();
4181 : 3 : first_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_FAILED;
4182 : 3 : second_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_FAILED;
4183 : :
4184 : 3 : set_thread(0);
4185 : :
4186 : 3 : bdev_nvme_submit_request(ch1, first_bdev_io);
4187 : :
4188 : 3 : set_thread(1);
4189 : :
4190 : 3 : bdev_nvme_submit_request(ch2, second_bdev_io);
4191 : :
4192 : 3 : CU_ASSERT(nvme_ctrlr1->resetting == true);
4193 : 3 : CU_ASSERT(nvme_ctrlr1->ctrlr_op_cb_arg == first_bio);
4194 : 3 : CU_ASSERT(TAILQ_FIRST(&io_path21->qpair->ctrlr_ch->pending_resets) == second_bdev_io);
4195 : :
4196 : 3 : poll_threads();
4197 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4198 : 3 : poll_threads();
4199 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4200 : 3 : poll_threads();
4201 : :
4202 [ - + ]: 3 : CU_ASSERT(ctrlr1->is_failed == false);
4203 : 3 : CU_ASSERT(curr_path1->last_failed_tsc == 0);
4204 [ - + ]: 3 : CU_ASSERT(ctrlr2->is_failed == false);
4205 : 3 : CU_ASSERT(curr_path2->last_failed_tsc == 0);
4206 : 3 : CU_ASSERT(first_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
4207 : 3 : CU_ASSERT(second_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
4208 : :
4209 : 3 : set_thread(0);
4210 : :
4211 : 3 : spdk_put_io_channel(ch1);
4212 : :
4213 : 3 : set_thread(1);
4214 : :
4215 : 3 : spdk_put_io_channel(ch2);
4216 : :
4217 : 3 : poll_threads();
4218 : :
4219 : 3 : set_thread(0);
4220 : :
4221 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
4222 : 3 : CU_ASSERT(rc == 0);
4223 : :
4224 : 3 : poll_threads();
4225 : 3 : spdk_delay_us(1000);
4226 : 3 : poll_threads();
4227 : :
4228 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
4229 : :
4230 : 3 : free(first_bdev_io);
4231 : 3 : free(second_bdev_io);
4232 : 3 : }
4233 : :
4234 : : static void
4235 : 3 : test_find_io_path(void)
4236 : : {
4237 : 3 : struct nvme_bdev_channel nbdev_ch = {
4238 : : .io_path_list = STAILQ_HEAD_INITIALIZER(nbdev_ch.io_path_list),
4239 : : };
4240 : 3 : struct spdk_nvme_qpair qpair1 = {}, qpair2 = {};
4241 : 3 : struct spdk_nvme_ctrlr ctrlr1 = {}, ctrlr2 = {};
4242 : 3 : struct spdk_nvme_ns ns1 = {}, ns2 = {};
4243 : 3 : struct nvme_ctrlr nvme_ctrlr1 = { .ctrlr = &ctrlr1, }, nvme_ctrlr2 = { .ctrlr = &ctrlr2, };
4244 : 3 : struct nvme_ctrlr_channel ctrlr_ch1 = {}, ctrlr_ch2 = {};
4245 : 3 : struct nvme_qpair nvme_qpair1 = { .ctrlr_ch = &ctrlr_ch1, .ctrlr = &nvme_ctrlr1, };
4246 : 3 : struct nvme_qpair nvme_qpair2 = { .ctrlr_ch = &ctrlr_ch2, .ctrlr = &nvme_ctrlr2, };
4247 : 3 : struct nvme_ns nvme_ns1 = { .ns = &ns1, }, nvme_ns2 = { .ns = &ns2, };
4248 : 3 : struct nvme_io_path io_path1 = { .qpair = &nvme_qpair1, .nvme_ns = &nvme_ns1, };
4249 : 3 : struct nvme_io_path io_path2 = { .qpair = &nvme_qpair2, .nvme_ns = &nvme_ns2, };
4250 : :
4251 : 3 : STAILQ_INSERT_TAIL(&nbdev_ch.io_path_list, &io_path1, stailq);
4252 : :
4253 : : /* Test if io_path whose ANA state is not accessible is excluded. */
4254 : :
4255 : 3 : nvme_qpair1.qpair = &qpair1;
4256 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
4257 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == NULL);
4258 : :
4259 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_PERSISTENT_LOSS_STATE;
4260 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == NULL);
4261 : :
4262 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_CHANGE_STATE;
4263 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == NULL);
4264 : :
4265 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
4266 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path1);
4267 : :
4268 : 3 : nbdev_ch.current_io_path = NULL;
4269 : :
4270 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
4271 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path1);
4272 : :
4273 : 3 : nbdev_ch.current_io_path = NULL;
4274 : :
4275 : : /* Test if io_path whose qpair is resetting is excluded. */
4276 : :
4277 : 3 : nvme_qpair1.qpair = NULL;
4278 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == NULL);
4279 : :
4280 : 3 : STAILQ_INSERT_TAIL(&nbdev_ch.io_path_list, &io_path2, stailq);
4281 : :
4282 : : /* Test if ANA optimized state or the first found ANA non-optimized state
4283 : : * is prioritized.
4284 : : */
4285 : :
4286 : 3 : nvme_qpair1.qpair = &qpair1;
4287 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
4288 : 3 : nvme_qpair2.qpair = &qpair2;
4289 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
4290 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path2);
4291 : :
4292 : 3 : nbdev_ch.current_io_path = NULL;
4293 : :
4294 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
4295 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path1);
4296 : :
4297 : 3 : nbdev_ch.current_io_path = NULL;
4298 : 3 : }
4299 : :
4300 : : static void
4301 : 3 : test_retry_io_if_ana_state_is_updating(void)
4302 : 3 : {
4303 : 3 : struct nvme_path_id path = {};
4304 : 3 : struct nvme_ctrlr_opts opts = {};
4305 : : struct spdk_nvme_ctrlr *ctrlr;
4306 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
4307 : : struct nvme_ctrlr *nvme_ctrlr;
4308 : 3 : const int STRING_SIZE = 32;
4309 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
4310 : : struct nvme_bdev *bdev;
4311 : : struct nvme_ns *nvme_ns;
4312 : : struct spdk_bdev_io *bdev_io1;
4313 : : struct spdk_io_channel *ch;
4314 : : struct nvme_bdev_channel *nbdev_ch;
4315 : : struct nvme_io_path *io_path;
4316 : : struct nvme_qpair *nvme_qpair;
4317 : : int rc;
4318 : :
4319 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
4320 : 3 : ut_init_trid(&path.trid);
4321 : :
4322 : 3 : set_thread(0);
4323 : :
4324 : 3 : ctrlr = ut_attach_ctrlr(&path.trid, 1, false, false);
4325 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
4326 : :
4327 : 3 : g_ut_attach_ctrlr_status = 0;
4328 : 3 : g_ut_attach_bdev_count = 1;
4329 : :
4330 : 3 : opts.ctrlr_loss_timeout_sec = -1;
4331 : 3 : opts.reconnect_delay_sec = 1;
4332 : :
4333 : 3 : rc = bdev_nvme_create(&path.trid, "nvme0", attached_names, STRING_SIZE,
4334 : : attach_ctrlr_done, NULL, NULL, &opts, false);
4335 : 3 : CU_ASSERT(rc == 0);
4336 : :
4337 : 3 : spdk_delay_us(1000);
4338 : 3 : poll_threads();
4339 : :
4340 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
4341 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
4342 : :
4343 : 3 : nvme_ctrlr = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path.trid);
4344 : 3 : CU_ASSERT(nvme_ctrlr != NULL);
4345 : :
4346 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
4347 : 3 : CU_ASSERT(bdev != NULL);
4348 : :
4349 : 3 : nvme_ns = nvme_ctrlr_get_first_active_ns(nvme_ctrlr);
4350 : 3 : CU_ASSERT(nvme_ns != NULL);
4351 : :
4352 : 3 : bdev_io1 = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_WRITE, bdev, NULL);
4353 : 3 : ut_bdev_io_set_buf(bdev_io1);
4354 : :
4355 : 3 : ch = spdk_get_io_channel(bdev);
4356 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
4357 : :
4358 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
4359 : :
4360 : 3 : io_path = ut_get_io_path_by_ctrlr(nbdev_ch, nvme_ctrlr);
4361 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
4362 : :
4363 : 3 : nvme_qpair = io_path->qpair;
4364 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair != NULL);
4365 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair->qpair != NULL);
4366 : :
4367 : 3 : bdev_io1->internal.ch = (struct spdk_bdev_channel *)ch;
4368 : :
4369 : : /* If qpair is connected, I/O should succeed. */
4370 : 3 : bdev_io1->internal.in_submit_request = true;
4371 : :
4372 : 3 : bdev_nvme_submit_request(ch, bdev_io1);
4373 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == true);
4374 : :
4375 : 3 : poll_threads();
4376 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == false);
4377 : 3 : CU_ASSERT(bdev_io1->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS);
4378 : :
4379 : : /* If ANA state of namespace is inaccessible, I/O should be queued. */
4380 : 3 : nvme_ns->ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
4381 : 3 : nbdev_ch->current_io_path = NULL;
4382 : :
4383 : 3 : bdev_io1->internal.in_submit_request = true;
4384 : :
4385 : 3 : bdev_nvme_submit_request(ch, bdev_io1);
4386 : :
4387 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
4388 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == true);
4389 : 3 : CU_ASSERT(bdev_io1 == TAILQ_FIRST(&nbdev_ch->retry_io_list));
4390 : :
4391 : : /* ANA state became accessible while I/O was queued. */
4392 : 3 : nvme_ns->ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
4393 : :
4394 : 3 : spdk_delay_us(1000000);
4395 : :
4396 : 3 : poll_thread_times(0, 1);
4397 : :
4398 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 1);
4399 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == true);
4400 : 3 : CU_ASSERT(TAILQ_EMPTY(&nbdev_ch->retry_io_list));
4401 : :
4402 : 3 : poll_threads();
4403 : :
4404 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
4405 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == false);
4406 : 3 : CU_ASSERT(bdev_io1->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
4407 : :
4408 : 3 : free(bdev_io1);
4409 : :
4410 : 3 : spdk_put_io_channel(ch);
4411 : :
4412 : 3 : poll_threads();
4413 : :
4414 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
4415 : 3 : CU_ASSERT(rc == 0);
4416 : :
4417 : 3 : poll_threads();
4418 : 3 : spdk_delay_us(1000);
4419 : 3 : poll_threads();
4420 : :
4421 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
4422 : 3 : }
4423 : :
4424 : : static void
4425 : 3 : test_retry_io_for_io_path_error(void)
4426 : 3 : {
4427 : 3 : struct nvme_path_id path1 = {}, path2 = {};
4428 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2;
4429 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
4430 : : struct nvme_ctrlr *nvme_ctrlr1, *nvme_ctrlr2;
4431 : 3 : const int STRING_SIZE = 32;
4432 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
4433 : : struct nvme_bdev *bdev;
4434 : : struct nvme_ns *nvme_ns1, *nvme_ns2;
4435 : : struct spdk_bdev_io *bdev_io;
4436 : : struct nvme_bdev_io *bio;
4437 : : struct spdk_io_channel *ch;
4438 : : struct nvme_bdev_channel *nbdev_ch;
4439 : : struct nvme_io_path *io_path1, *io_path2;
4440 : : struct nvme_qpair *nvme_qpair1, *nvme_qpair2;
4441 : : struct ut_nvme_req *req;
4442 : 3 : struct spdk_uuid uuid1 = { .u.raw = { 0x1 } };
4443 : : int rc;
4444 : :
4445 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
4446 : 3 : ut_init_trid(&path1.trid);
4447 : 3 : ut_init_trid2(&path2.trid);
4448 : :
4449 : 3 : g_opts.bdev_retry_count = 1;
4450 : :
4451 : 3 : set_thread(0);
4452 : :
4453 : 3 : g_ut_attach_ctrlr_status = 0;
4454 : 3 : g_ut_attach_bdev_count = 1;
4455 : :
4456 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 1, true, true);
4457 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
4458 : :
4459 : 3 : ctrlr1->ns[0].uuid = &uuid1;
4460 : :
4461 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
4462 : : attach_ctrlr_done, NULL, NULL, NULL, true);
4463 : 3 : CU_ASSERT(rc == 0);
4464 : :
4465 : 3 : spdk_delay_us(1000);
4466 : 3 : poll_threads();
4467 : :
4468 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4469 : 3 : poll_threads();
4470 : :
4471 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
4472 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
4473 : :
4474 : 3 : nvme_ctrlr1 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid);
4475 : 3 : CU_ASSERT(nvme_ctrlr1 != NULL);
4476 : :
4477 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
4478 : 3 : CU_ASSERT(bdev != NULL);
4479 : :
4480 : 3 : nvme_ns1 = nvme_ctrlr_get_first_active_ns(nvme_ctrlr1);
4481 : 3 : CU_ASSERT(nvme_ns1 != NULL);
4482 : 3 : CU_ASSERT(nvme_ns1 == _nvme_bdev_get_ns(bdev, nvme_ctrlr1));
4483 : :
4484 : 3 : bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_WRITE, bdev, NULL);
4485 : 3 : ut_bdev_io_set_buf(bdev_io);
4486 : :
4487 : 3 : bio = (struct nvme_bdev_io *)bdev_io->driver_ctx;
4488 : :
4489 : 3 : ch = spdk_get_io_channel(bdev);
4490 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
4491 : :
4492 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
4493 : :
4494 : 3 : io_path1 = ut_get_io_path_by_ctrlr(nbdev_ch, nvme_ctrlr1);
4495 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path1 != NULL);
4496 : :
4497 : 3 : nvme_qpair1 = io_path1->qpair;
4498 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair1 != NULL);
4499 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair1->qpair != NULL);
4500 : :
4501 : 3 : bdev_io->internal.ch = (struct spdk_bdev_channel *)ch;
4502 : :
4503 : : /* I/O got a temporary I/O path error, but it should not retry if DNR is set. */
4504 : 3 : bdev_io->internal.in_submit_request = true;
4505 : :
4506 : 3 : bdev_nvme_submit_request(ch, bdev_io);
4507 : :
4508 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 1);
4509 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4510 : :
4511 : 3 : req = ut_get_outstanding_nvme_request(nvme_qpair1->qpair, bio);
4512 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
4513 : :
4514 : 3 : req->cpl.status.sc = SPDK_NVME_SC_INTERNAL_PATH_ERROR;
4515 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_PATH;
4516 : 3 : req->cpl.status.dnr = 1;
4517 : :
4518 : 3 : poll_thread_times(0, 1);
4519 : :
4520 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 0);
4521 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
4522 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_NVME_ERROR);
4523 : :
4524 : : /* I/O got a temporary I/O path error, but it should succeed after retry. */
4525 : 3 : bdev_io->internal.in_submit_request = true;
4526 : :
4527 : 3 : bdev_nvme_submit_request(ch, bdev_io);
4528 : :
4529 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 1);
4530 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4531 : :
4532 : 3 : req = ut_get_outstanding_nvme_request(nvme_qpair1->qpair, bio);
4533 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
4534 : :
4535 : 3 : req->cpl.status.sc = SPDK_NVME_SC_INTERNAL_PATH_ERROR;
4536 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_PATH;
4537 : :
4538 : 3 : poll_thread_times(0, 1);
4539 : :
4540 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 0);
4541 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4542 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
4543 : :
4544 : 3 : poll_threads();
4545 : :
4546 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 0);
4547 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
4548 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
4549 : :
4550 : : /* Add io_path2 dynamically, and create a multipath configuration. */
4551 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 1, true, true);
4552 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
4553 : :
4554 : 3 : ctrlr2->ns[0].uuid = &uuid1;
4555 : :
4556 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
4557 : : attach_ctrlr_done, NULL, NULL, NULL, true);
4558 : 3 : CU_ASSERT(rc == 0);
4559 : :
4560 : 3 : spdk_delay_us(1000);
4561 : 3 : poll_threads();
4562 : :
4563 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4564 : 3 : poll_threads();
4565 : :
4566 : 3 : nvme_ctrlr2 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid);
4567 : 3 : CU_ASSERT(nvme_ctrlr2 != NULL);
4568 : :
4569 : 3 : nvme_ns2 = nvme_ctrlr_get_first_active_ns(nvme_ctrlr2);
4570 : 3 : CU_ASSERT(nvme_ns2 != NULL);
4571 : 3 : CU_ASSERT(nvme_ns2 == _nvme_bdev_get_ns(bdev, nvme_ctrlr2));
4572 : :
4573 : 3 : io_path2 = ut_get_io_path_by_ctrlr(nbdev_ch, nvme_ctrlr2);
4574 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path2 != NULL);
4575 : :
4576 : 3 : nvme_qpair2 = io_path2->qpair;
4577 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair2 != NULL);
4578 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair2->qpair != NULL);
4579 : :
4580 : : /* I/O is submitted to io_path1, but qpair of io_path1 was disconnected
4581 : : * and deleted. Hence the I/O was aborted. But io_path2 is available.
4582 : : * So after a retry, I/O is submitted to io_path2 and should succeed.
4583 : : */
4584 : 3 : bdev_io->internal.in_submit_request = true;
4585 : :
4586 : 3 : bdev_nvme_submit_request(ch, bdev_io);
4587 : :
4588 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 1);
4589 : 3 : CU_ASSERT(nvme_qpair2->qpair->num_outstanding_reqs == 0);
4590 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4591 : :
4592 : 3 : req = ut_get_outstanding_nvme_request(nvme_qpair1->qpair, bio);
4593 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
4594 : :
4595 : 3 : req->cpl.status.sc = SPDK_NVME_SC_ABORTED_SQ_DELETION;
4596 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
4597 : :
4598 : 3 : poll_thread_times(0, 1);
4599 : :
4600 : 3 : CU_ASSERT(nvme_qpair1->qpair->num_outstanding_reqs == 0);
4601 : 3 : CU_ASSERT(nvme_qpair2->qpair->num_outstanding_reqs == 0);
4602 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4603 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
4604 : :
4605 : 3 : spdk_nvme_ctrlr_free_io_qpair(nvme_qpair1->qpair);
4606 : 3 : nvme_qpair1->qpair = NULL;
4607 : :
4608 : 3 : poll_threads();
4609 : :
4610 : 3 : CU_ASSERT(nvme_qpair2->qpair->num_outstanding_reqs == 0);
4611 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
4612 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
4613 : :
4614 : 3 : free(bdev_io);
4615 : :
4616 : 3 : spdk_put_io_channel(ch);
4617 : :
4618 : 3 : poll_threads();
4619 : :
4620 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
4621 : 3 : CU_ASSERT(rc == 0);
4622 : :
4623 : 3 : poll_threads();
4624 : 3 : spdk_delay_us(1000);
4625 : 3 : poll_threads();
4626 : :
4627 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
4628 : :
4629 : 3 : g_opts.bdev_retry_count = 0;
4630 : 3 : }
4631 : :
4632 : : static void
4633 : 3 : test_retry_io_count(void)
4634 : 3 : {
4635 : 3 : struct nvme_path_id path = {};
4636 : : struct spdk_nvme_ctrlr *ctrlr;
4637 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
4638 : : struct nvme_ctrlr *nvme_ctrlr;
4639 : 3 : const int STRING_SIZE = 32;
4640 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
4641 : : struct nvme_bdev *bdev;
4642 : : struct nvme_ns *nvme_ns;
4643 : : struct spdk_bdev_io *bdev_io;
4644 : : struct nvme_bdev_io *bio;
4645 : : struct spdk_io_channel *ch;
4646 : : struct nvme_bdev_channel *nbdev_ch;
4647 : : struct nvme_io_path *io_path;
4648 : : struct nvme_qpair *nvme_qpair;
4649 : : struct ut_nvme_req *req;
4650 : : int rc;
4651 : :
4652 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
4653 : 3 : ut_init_trid(&path.trid);
4654 : :
4655 : 3 : set_thread(0);
4656 : :
4657 : 3 : ctrlr = ut_attach_ctrlr(&path.trid, 1, false, false);
4658 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
4659 : :
4660 : 3 : g_ut_attach_ctrlr_status = 0;
4661 : 3 : g_ut_attach_bdev_count = 1;
4662 : :
4663 : 3 : rc = bdev_nvme_create(&path.trid, "nvme0", attached_names, STRING_SIZE,
4664 : : attach_ctrlr_done, NULL, NULL, NULL, false);
4665 : 3 : CU_ASSERT(rc == 0);
4666 : :
4667 : 3 : spdk_delay_us(1000);
4668 : 3 : poll_threads();
4669 : :
4670 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
4671 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
4672 : :
4673 : 3 : nvme_ctrlr = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path.trid);
4674 : 3 : CU_ASSERT(nvme_ctrlr != NULL);
4675 : :
4676 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
4677 : 3 : CU_ASSERT(bdev != NULL);
4678 : :
4679 : 3 : nvme_ns = nvme_ctrlr_get_first_active_ns(nvme_ctrlr);
4680 : 3 : CU_ASSERT(nvme_ns != NULL);
4681 : :
4682 : 3 : bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_WRITE, bdev, NULL);
4683 : 3 : ut_bdev_io_set_buf(bdev_io);
4684 : :
4685 : 3 : bio = (struct nvme_bdev_io *)bdev_io->driver_ctx;
4686 : :
4687 : 3 : ch = spdk_get_io_channel(bdev);
4688 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
4689 : :
4690 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
4691 : :
4692 : 3 : io_path = ut_get_io_path_by_ctrlr(nbdev_ch, nvme_ctrlr);
4693 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
4694 : :
4695 : 3 : nvme_qpair = io_path->qpair;
4696 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair != NULL);
4697 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair->qpair != NULL);
4698 : :
4699 : 3 : bdev_io->internal.ch = (struct spdk_bdev_channel *)ch;
4700 : :
4701 : : /* If I/O is aborted by request, it should not be retried. */
4702 : 3 : g_opts.bdev_retry_count = 1;
4703 : :
4704 : 3 : bdev_io->internal.in_submit_request = true;
4705 : :
4706 : 3 : bdev_nvme_submit_request(ch, bdev_io);
4707 : :
4708 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 1);
4709 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4710 : :
4711 : 3 : req = ut_get_outstanding_nvme_request(nvme_qpair->qpair, bio);
4712 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
4713 : :
4714 : 3 : req->cpl.status.sc = SPDK_NVME_SC_ABORTED_BY_REQUEST;
4715 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
4716 : :
4717 : 3 : poll_thread_times(0, 1);
4718 : :
4719 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
4720 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
4721 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_ABORTED);
4722 : :
4723 : : /* If bio->retry_count is not less than g_opts.bdev_retry_count,
4724 : : * the failed I/O should not be retried.
4725 : : */
4726 : 3 : g_opts.bdev_retry_count = 4;
4727 : :
4728 : 3 : bdev_io->internal.in_submit_request = true;
4729 : :
4730 : 3 : bdev_nvme_submit_request(ch, bdev_io);
4731 : :
4732 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 1);
4733 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4734 : :
4735 : 3 : req = ut_get_outstanding_nvme_request(nvme_qpair->qpair, bio);
4736 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
4737 : :
4738 : 3 : req->cpl.status.sc = SPDK_NVME_SC_NAMESPACE_NOT_READY;
4739 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
4740 : 3 : bio->retry_count = 4;
4741 : :
4742 : 3 : poll_thread_times(0, 1);
4743 : :
4744 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
4745 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
4746 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_NVME_ERROR);
4747 : :
4748 : : /* If g_opts.bdev_retry_count is -1, the failed I/O always should be retried. */
4749 : 3 : g_opts.bdev_retry_count = -1;
4750 : :
4751 : 3 : bdev_io->internal.in_submit_request = true;
4752 : :
4753 : 3 : bdev_nvme_submit_request(ch, bdev_io);
4754 : :
4755 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 1);
4756 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4757 : :
4758 : 3 : req = ut_get_outstanding_nvme_request(nvme_qpair->qpair, bio);
4759 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
4760 : :
4761 : 3 : req->cpl.status.sc = SPDK_NVME_SC_NAMESPACE_NOT_READY;
4762 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
4763 : 3 : bio->retry_count = 4;
4764 : :
4765 : 3 : poll_thread_times(0, 1);
4766 : :
4767 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
4768 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4769 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
4770 : :
4771 : 3 : poll_threads();
4772 : :
4773 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
4774 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
4775 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
4776 : :
4777 : : /* If bio->retry_count is less than g_opts.bdev_retry_count,
4778 : : * the failed I/O should be retried.
4779 : : */
4780 : 3 : g_opts.bdev_retry_count = 4;
4781 : :
4782 : 3 : bdev_io->internal.in_submit_request = true;
4783 : :
4784 : 3 : bdev_nvme_submit_request(ch, bdev_io);
4785 : :
4786 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 1);
4787 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4788 : :
4789 : 3 : req = ut_get_outstanding_nvme_request(nvme_qpair->qpair, bio);
4790 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
4791 : :
4792 : 3 : req->cpl.status.sc = SPDK_NVME_SC_NAMESPACE_NOT_READY;
4793 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
4794 : 3 : bio->retry_count = 3;
4795 : :
4796 : 3 : poll_thread_times(0, 1);
4797 : :
4798 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
4799 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
4800 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
4801 : :
4802 : 3 : poll_threads();
4803 : :
4804 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
4805 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
4806 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
4807 : :
4808 : 3 : free(bdev_io);
4809 : :
4810 : 3 : spdk_put_io_channel(ch);
4811 : :
4812 : 3 : poll_threads();
4813 : :
4814 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
4815 : 3 : CU_ASSERT(rc == 0);
4816 : :
4817 : 3 : poll_threads();
4818 : 3 : spdk_delay_us(1000);
4819 : 3 : poll_threads();
4820 : :
4821 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
4822 : :
4823 : 3 : g_opts.bdev_retry_count = 0;
4824 : 3 : }
4825 : :
4826 : : static void
4827 : 3 : test_concurrent_read_ana_log_page(void)
4828 : 3 : {
4829 : 3 : struct spdk_nvme_transport_id trid = {};
4830 : : struct spdk_nvme_ctrlr *ctrlr;
4831 : : struct nvme_ctrlr *nvme_ctrlr;
4832 : 3 : const int STRING_SIZE = 32;
4833 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
4834 : : int rc;
4835 : :
4836 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
4837 : 3 : ut_init_trid(&trid);
4838 : :
4839 : 3 : set_thread(0);
4840 : :
4841 : 3 : ctrlr = ut_attach_ctrlr(&trid, 1, true, false);
4842 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
4843 : :
4844 : 3 : ctrlr->ns[0].ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
4845 : :
4846 : 3 : g_ut_attach_ctrlr_status = 0;
4847 : 3 : g_ut_attach_bdev_count = 1;
4848 : :
4849 : 3 : rc = bdev_nvme_create(&trid, "nvme0", attached_names, STRING_SIZE,
4850 : : attach_ctrlr_done, NULL, NULL, NULL, false);
4851 : 3 : CU_ASSERT(rc == 0);
4852 : :
4853 : 3 : spdk_delay_us(1000);
4854 : 3 : poll_threads();
4855 : :
4856 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4857 : 3 : poll_threads();
4858 : :
4859 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
4860 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
4861 : :
4862 : 3 : nvme_ctrlr_read_ana_log_page(nvme_ctrlr);
4863 : :
4864 : 3 : CU_ASSERT(nvme_ctrlr->ana_log_page_updating == true);
4865 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 1);
4866 : :
4867 : : /* Following read request should be rejected. */
4868 : 3 : nvme_ctrlr_read_ana_log_page(nvme_ctrlr);
4869 : :
4870 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 1);
4871 : :
4872 : 3 : set_thread(1);
4873 : :
4874 : 3 : nvme_ctrlr_read_ana_log_page(nvme_ctrlr);
4875 : :
4876 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 1);
4877 : :
4878 : : /* Reset request while reading ANA log page should not be rejected. */
4879 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
4880 : 3 : CU_ASSERT(rc == 0);
4881 : :
4882 : 3 : poll_threads();
4883 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4884 : 3 : poll_threads();
4885 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4886 : 3 : poll_threads();
4887 : :
4888 : 3 : CU_ASSERT(nvme_ctrlr->ana_log_page_updating == false);
4889 : 3 : CU_ASSERT(ctrlr->adminq.num_outstanding_reqs == 0);
4890 : :
4891 : : /* Read ANA log page while resetting ctrlr should be rejected. */
4892 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
4893 : 3 : CU_ASSERT(rc == 0);
4894 : :
4895 : 3 : nvme_ctrlr_read_ana_log_page(nvme_ctrlr);
4896 : :
4897 : 3 : CU_ASSERT(nvme_ctrlr->ana_log_page_updating == false);
4898 : :
4899 : 3 : poll_threads();
4900 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4901 : 3 : poll_threads();
4902 : :
4903 : 3 : set_thread(0);
4904 : :
4905 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
4906 : 3 : CU_ASSERT(rc == 0);
4907 : :
4908 : 3 : poll_threads();
4909 : 3 : spdk_delay_us(1000);
4910 : 3 : poll_threads();
4911 : :
4912 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
4913 : 3 : }
4914 : :
4915 : : static void
4916 : 3 : test_retry_io_for_ana_error(void)
4917 : 3 : {
4918 : 3 : struct nvme_path_id path = {};
4919 : : struct spdk_nvme_ctrlr *ctrlr;
4920 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
4921 : : struct nvme_ctrlr *nvme_ctrlr;
4922 : 3 : const int STRING_SIZE = 32;
4923 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
4924 : : struct nvme_bdev *bdev;
4925 : : struct nvme_ns *nvme_ns;
4926 : : struct spdk_bdev_io *bdev_io;
4927 : : struct nvme_bdev_io *bio;
4928 : : struct spdk_io_channel *ch;
4929 : : struct nvme_bdev_channel *nbdev_ch;
4930 : : struct nvme_io_path *io_path;
4931 : : struct nvme_qpair *nvme_qpair;
4932 : : struct ut_nvme_req *req;
4933 : : uint64_t now;
4934 : : int rc;
4935 : :
4936 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
4937 : 3 : ut_init_trid(&path.trid);
4938 : :
4939 : 3 : g_opts.bdev_retry_count = 1;
4940 : :
4941 : 3 : set_thread(0);
4942 : :
4943 : 3 : ctrlr = ut_attach_ctrlr(&path.trid, 1, true, false);
4944 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
4945 : :
4946 : 3 : g_ut_attach_ctrlr_status = 0;
4947 : 3 : g_ut_attach_bdev_count = 1;
4948 : :
4949 : 3 : rc = bdev_nvme_create(&path.trid, "nvme0", attached_names, STRING_SIZE,
4950 : : attach_ctrlr_done, NULL, NULL, NULL, false);
4951 : 3 : CU_ASSERT(rc == 0);
4952 : :
4953 : 3 : spdk_delay_us(1000);
4954 : 3 : poll_threads();
4955 : :
4956 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
4957 : 3 : poll_threads();
4958 : :
4959 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
4960 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
4961 : :
4962 : 3 : nvme_ctrlr = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path.trid);
4963 : 3 : CU_ASSERT(nvme_ctrlr != NULL);
4964 : :
4965 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
4966 : 3 : CU_ASSERT(bdev != NULL);
4967 : :
4968 : 3 : nvme_ns = nvme_ctrlr_get_first_active_ns(nvme_ctrlr);
4969 : 3 : CU_ASSERT(nvme_ns != NULL);
4970 : :
4971 : 3 : bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_WRITE, bdev, NULL);
4972 : 3 : ut_bdev_io_set_buf(bdev_io);
4973 : :
4974 : 3 : bio = (struct nvme_bdev_io *)bdev_io->driver_ctx;
4975 : :
4976 : 3 : ch = spdk_get_io_channel(bdev);
4977 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
4978 : :
4979 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
4980 : :
4981 : 3 : io_path = ut_get_io_path_by_ctrlr(nbdev_ch, nvme_ctrlr);
4982 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
4983 : :
4984 : 3 : nvme_qpair = io_path->qpair;
4985 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair != NULL);
4986 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair->qpair != NULL);
4987 : :
4988 : 3 : now = spdk_get_ticks();
4989 : :
4990 : 3 : bdev_io->internal.ch = (struct spdk_bdev_channel *)ch;
4991 : :
4992 : : /* If I/O got ANA error, it should be queued, the corresponding namespace
4993 : : * should be freezed and its ANA state should be updated.
4994 : : */
4995 : 3 : bdev_io->internal.in_submit_request = true;
4996 : :
4997 : 3 : bdev_nvme_submit_request(ch, bdev_io);
4998 : :
4999 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 1);
5000 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
5001 : :
5002 : 3 : req = ut_get_outstanding_nvme_request(nvme_qpair->qpair, bio);
5003 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
5004 : :
5005 : 3 : nvme_ns->ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
5006 : 3 : req->cpl.status.sc = SPDK_NVME_SC_ASYMMETRIC_ACCESS_INACCESSIBLE;
5007 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_PATH;
5008 : :
5009 : 3 : poll_thread_times(0, 1);
5010 : :
5011 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
5012 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
5013 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
5014 : : /* I/O should be retried immediately. */
5015 : 3 : CU_ASSERT(bio->retry_ticks == now);
5016 [ - + ]: 3 : CU_ASSERT(nvme_ns->ana_state_updating == true);
5017 : 3 : CU_ASSERT(nvme_ctrlr->ana_log_page_updating == true);
5018 : :
5019 : 3 : poll_threads();
5020 : :
5021 : : /* Namespace is inaccessible, and hence I/O should be queued again. */
5022 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
5023 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
5024 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
5025 : : /* I/O should be retried after a second if no I/O path was found but
5026 : : * any I/O path may become available.
5027 : : */
5028 : 3 : CU_ASSERT(bio->retry_ticks == now + spdk_get_ticks_hz());
5029 : :
5030 : : /* Namespace should be unfreezed after completing to update its ANA state. */
5031 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5032 : 3 : poll_threads();
5033 : :
5034 [ - + ]: 3 : CU_ASSERT(nvme_ns->ana_state_updating == false);
5035 : 3 : CU_ASSERT(nvme_ns->ana_state == SPDK_NVME_ANA_OPTIMIZED_STATE);
5036 : 3 : CU_ASSERT(nvme_ctrlr->ana_log_page_updating == false);
5037 : :
5038 : : /* Retry the queued I/O should succeed. */
5039 : 3 : spdk_delay_us(spdk_get_ticks_hz() - g_opts.nvme_adminq_poll_period_us);
5040 : 3 : poll_threads();
5041 : :
5042 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
5043 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
5044 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
5045 : :
5046 : 3 : free(bdev_io);
5047 : :
5048 : 3 : spdk_put_io_channel(ch);
5049 : :
5050 : 3 : poll_threads();
5051 : :
5052 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
5053 : 3 : CU_ASSERT(rc == 0);
5054 : :
5055 : 3 : poll_threads();
5056 : 3 : spdk_delay_us(1000);
5057 : 3 : poll_threads();
5058 : :
5059 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
5060 : :
5061 : 3 : g_opts.bdev_retry_count = 0;
5062 : 3 : }
5063 : :
5064 : : static void
5065 : 3 : test_check_io_error_resiliency_params(void)
5066 : : {
5067 : : /* 1st parameter is ctrlr_loss_timeout_sec, 2nd parameter is reconnect_delay_sec, and
5068 : : * 3rd parameter is fast_io_fail_timeout_sec.
5069 : : */
5070 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(-2, 1, 0) == false);
5071 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(-1, 0, 0) == false);
5072 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(1, 0, 0) == false);
5073 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(1, 2, 0) == false);
5074 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(0, 1, 0) == false);
5075 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(-1, 1, 0) == true);
5076 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(2, 2, 0) == true);
5077 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(2, 1, 0) == true);
5078 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(INT32_MAX, INT32_MAX, 0) == true);
5079 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(-1, UINT32_MAX, 0) == true);
5080 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(0, 0, 1) == false);
5081 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(-1, 2, 1) == false);
5082 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(3, 2, 4) == false);
5083 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(3, 2, 1) == false);
5084 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(-1, 1, 1) == true);
5085 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(2, 1, 2) == true);
5086 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(2, 1, 1) == true);
5087 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(INT32_MAX, INT32_MAX, INT32_MAX) == true);
5088 : 3 : CU_ASSERT(bdev_nvme_check_io_error_resiliency_params(-1, UINT32_MAX, UINT32_MAX) == true);
5089 : 3 : }
5090 : :
5091 : : static void
5092 : 3 : test_retry_io_if_ctrlr_is_resetting(void)
5093 : 3 : {
5094 : 3 : struct nvme_path_id path = {};
5095 : 3 : struct nvme_ctrlr_opts opts = {};
5096 : : struct spdk_nvme_ctrlr *ctrlr;
5097 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
5098 : : struct nvme_ctrlr *nvme_ctrlr;
5099 : 3 : const int STRING_SIZE = 32;
5100 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
5101 : : struct nvme_bdev *bdev;
5102 : : struct nvme_ns *nvme_ns;
5103 : : struct spdk_bdev_io *bdev_io1, *bdev_io2;
5104 : : struct spdk_io_channel *ch;
5105 : : struct nvme_bdev_channel *nbdev_ch;
5106 : : struct nvme_io_path *io_path;
5107 : : struct nvme_qpair *nvme_qpair;
5108 : : int rc;
5109 : :
5110 : 3 : g_opts.bdev_retry_count = 1;
5111 : :
5112 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
5113 : 3 : ut_init_trid(&path.trid);
5114 : :
5115 : 3 : set_thread(0);
5116 : :
5117 : 3 : ctrlr = ut_attach_ctrlr(&path.trid, 1, false, false);
5118 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
5119 : :
5120 : 3 : g_ut_attach_ctrlr_status = 0;
5121 : 3 : g_ut_attach_bdev_count = 1;
5122 : :
5123 : 3 : opts.ctrlr_loss_timeout_sec = -1;
5124 : 3 : opts.reconnect_delay_sec = 1;
5125 : :
5126 : 3 : rc = bdev_nvme_create(&path.trid, "nvme0", attached_names, STRING_SIZE,
5127 : : attach_ctrlr_done, NULL, NULL, &opts, false);
5128 : 3 : CU_ASSERT(rc == 0);
5129 : :
5130 : 3 : spdk_delay_us(1000);
5131 : 3 : poll_threads();
5132 : :
5133 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
5134 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
5135 : :
5136 : 3 : nvme_ctrlr = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path.trid);
5137 : 3 : CU_ASSERT(nvme_ctrlr != NULL);
5138 : :
5139 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
5140 : 3 : CU_ASSERT(bdev != NULL);
5141 : :
5142 : 3 : nvme_ns = nvme_ctrlr_get_first_active_ns(nvme_ctrlr);
5143 : 3 : CU_ASSERT(nvme_ns != NULL);
5144 : :
5145 : 3 : bdev_io1 = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_WRITE, bdev, NULL);
5146 : 3 : ut_bdev_io_set_buf(bdev_io1);
5147 : :
5148 : 3 : bdev_io2 = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_WRITE, bdev, NULL);
5149 : 3 : ut_bdev_io_set_buf(bdev_io2);
5150 : :
5151 : 3 : ch = spdk_get_io_channel(bdev);
5152 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
5153 : :
5154 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
5155 : :
5156 : 3 : io_path = ut_get_io_path_by_ctrlr(nbdev_ch, nvme_ctrlr);
5157 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
5158 : :
5159 : 3 : nvme_qpair = io_path->qpair;
5160 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair != NULL);
5161 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_qpair->qpair != NULL);
5162 : :
5163 : 3 : bdev_io1->internal.ch = (struct spdk_bdev_channel *)ch;
5164 : 3 : bdev_io2->internal.ch = (struct spdk_bdev_channel *)ch;
5165 : :
5166 : : /* If qpair is connected, I/O should succeed. */
5167 : 3 : bdev_io1->internal.in_submit_request = true;
5168 : :
5169 : 3 : bdev_nvme_submit_request(ch, bdev_io1);
5170 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == true);
5171 : :
5172 : 3 : poll_threads();
5173 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == false);
5174 : 3 : CU_ASSERT(bdev_io1->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS);
5175 : :
5176 : : /* If qpair is disconnected, it is freed and then reconnected via resetting
5177 : : * the corresponding nvme_ctrlr. I/O should be queued if it is submitted
5178 : : * while resetting the nvme_ctrlr.
5179 : : */
5180 : 3 : nvme_qpair->qpair->failure_reason = SPDK_NVME_QPAIR_FAILURE_UNKNOWN;
5181 : 3 : ctrlr->is_failed = true;
5182 : :
5183 : 3 : poll_thread_times(0, 5);
5184 : :
5185 : 3 : CU_ASSERT(nvme_qpair->qpair == NULL);
5186 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
5187 [ - + ]: 3 : CU_ASSERT(ctrlr->is_failed == false);
5188 : :
5189 : 3 : bdev_io1->internal.in_submit_request = true;
5190 : :
5191 : 3 : bdev_nvme_submit_request(ch, bdev_io1);
5192 : :
5193 : 3 : spdk_delay_us(1);
5194 : :
5195 : 3 : bdev_io2->internal.in_submit_request = true;
5196 : :
5197 : 3 : bdev_nvme_submit_request(ch, bdev_io2);
5198 : :
5199 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == true);
5200 [ - + ]: 3 : CU_ASSERT(bdev_io2->internal.in_submit_request == true);
5201 : 3 : CU_ASSERT(bdev_io1 == TAILQ_FIRST(&nbdev_ch->retry_io_list));
5202 : 3 : CU_ASSERT(bdev_io2 == TAILQ_NEXT(bdev_io1, module_link));
5203 : :
5204 : 3 : poll_threads();
5205 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5206 : 3 : poll_threads();
5207 : :
5208 : 3 : CU_ASSERT(nvme_qpair->qpair != NULL);
5209 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5210 : :
5211 : 3 : spdk_delay_us(999999 - g_opts.nvme_adminq_poll_period_us);
5212 : :
5213 : 3 : poll_thread_times(0, 1);
5214 : :
5215 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 1);
5216 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == true);
5217 [ - + ]: 3 : CU_ASSERT(bdev_io2->internal.in_submit_request == true);
5218 : 3 : CU_ASSERT(bdev_io2 == TAILQ_FIRST(&nbdev_ch->retry_io_list));
5219 : :
5220 : 3 : poll_threads();
5221 : :
5222 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
5223 [ - + ]: 3 : CU_ASSERT(bdev_io1->internal.in_submit_request == false);
5224 : 3 : CU_ASSERT(bdev_io1->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
5225 [ - + ]: 3 : CU_ASSERT(bdev_io2->internal.in_submit_request == true);
5226 : 3 : CU_ASSERT(bdev_io2 == TAILQ_FIRST(&nbdev_ch->retry_io_list));
5227 : :
5228 : 3 : spdk_delay_us(1);
5229 : :
5230 : 3 : poll_thread_times(0, 1);
5231 : :
5232 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 1);
5233 [ - + ]: 3 : CU_ASSERT(bdev_io2->internal.in_submit_request == true);
5234 : 3 : CU_ASSERT(TAILQ_EMPTY(&nbdev_ch->retry_io_list));
5235 : :
5236 : 3 : poll_threads();
5237 : :
5238 : 3 : CU_ASSERT(nvme_qpair->qpair->num_outstanding_reqs == 0);
5239 [ - + ]: 3 : CU_ASSERT(bdev_io2->internal.in_submit_request == false);
5240 : 3 : CU_ASSERT(bdev_io2->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
5241 : :
5242 : 3 : free(bdev_io1);
5243 : 3 : free(bdev_io2);
5244 : :
5245 : 3 : spdk_put_io_channel(ch);
5246 : :
5247 : 3 : poll_threads();
5248 : :
5249 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
5250 : 3 : CU_ASSERT(rc == 0);
5251 : :
5252 : 3 : poll_threads();
5253 : 3 : spdk_delay_us(1000);
5254 : 3 : poll_threads();
5255 : :
5256 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
5257 : :
5258 : 3 : g_opts.bdev_retry_count = 0;
5259 : 3 : }
5260 : :
5261 : : static void
5262 : 3 : test_reconnect_ctrlr(void)
5263 : : {
5264 : 3 : struct spdk_nvme_transport_id trid = {};
5265 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
5266 : : struct nvme_ctrlr *nvme_ctrlr;
5267 : : struct spdk_io_channel *ch1, *ch2;
5268 : : struct nvme_ctrlr_channel *ctrlr_ch1, *ctrlr_ch2;
5269 : : int rc;
5270 : :
5271 : 3 : ut_init_trid(&trid);
5272 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
5273 : :
5274 : 3 : set_thread(0);
5275 : :
5276 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid, NULL);
5277 : 3 : CU_ASSERT(rc == 0);
5278 : :
5279 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
5280 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
5281 : :
5282 : 3 : nvme_ctrlr->opts.ctrlr_loss_timeout_sec = 2;
5283 : 3 : nvme_ctrlr->opts.reconnect_delay_sec = 1;
5284 : :
5285 : 3 : ch1 = spdk_get_io_channel(nvme_ctrlr);
5286 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
5287 : :
5288 : 3 : ctrlr_ch1 = spdk_io_channel_get_ctx(ch1);
5289 : 3 : CU_ASSERT(ctrlr_ch1->qpair != NULL);
5290 : :
5291 : 3 : set_thread(1);
5292 : :
5293 : 3 : ch2 = spdk_get_io_channel(nvme_ctrlr);
5294 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
5295 : :
5296 : 3 : ctrlr_ch2 = spdk_io_channel_get_ctx(ch2);
5297 : :
5298 : : /* Reset starts from thread 1. */
5299 : 3 : set_thread(1);
5300 : :
5301 : : /* The reset should fail and a reconnect timer should be registered. */
5302 : 3 : ctrlr.fail_reset = true;
5303 : 3 : ctrlr.is_failed = true;
5304 : :
5305 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
5306 : 3 : CU_ASSERT(rc == 0);
5307 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
5308 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == true);
5309 : :
5310 : 3 : poll_threads();
5311 : :
5312 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5313 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == false);
5314 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
5315 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
5316 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL);
5317 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == true);
5318 : :
5319 : : /* A new reset starts from thread 0. */
5320 : 3 : set_thread(1);
5321 : :
5322 : : /* The reset should cancel the reconnect timer and should start from reconnection.
5323 : : * Then, the reset should fail and a reconnect timer should be registered again.
5324 : : */
5325 : 3 : ctrlr.fail_reset = true;
5326 : 3 : ctrlr.is_failed = true;
5327 : :
5328 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
5329 : 3 : CU_ASSERT(rc == 0);
5330 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
5331 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == false);
5332 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == true);
5333 : :
5334 : 3 : poll_threads();
5335 : :
5336 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5337 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == false);
5338 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
5339 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
5340 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL);
5341 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == true);
5342 : :
5343 : : /* Then a reconnect retry should suceeed. */
5344 : 3 : ctrlr.fail_reset = false;
5345 : :
5346 : 3 : spdk_delay_us(SPDK_SEC_TO_USEC);
5347 : 3 : poll_thread_times(0, 1);
5348 : :
5349 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
5350 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer == NULL);
5351 : :
5352 : 3 : poll_threads();
5353 : :
5354 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5355 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair != NULL);
5356 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair != NULL);
5357 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == false);
5358 : :
5359 : : /* The reset should fail and a reconnect timer should be registered. */
5360 : 3 : ctrlr.fail_reset = true;
5361 : 3 : ctrlr.is_failed = true;
5362 : :
5363 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
5364 : 3 : CU_ASSERT(rc == 0);
5365 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
5366 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == true);
5367 : :
5368 : 3 : poll_threads();
5369 : :
5370 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5371 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == false);
5372 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
5373 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
5374 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL);
5375 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == true);
5376 : :
5377 : : /* Then a reconnect retry should still fail. */
5378 : 3 : spdk_delay_us(SPDK_SEC_TO_USEC);
5379 : 3 : poll_thread_times(0, 1);
5380 : :
5381 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
5382 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer == NULL);
5383 : :
5384 : 3 : poll_threads();
5385 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5386 : 3 : poll_threads();
5387 : :
5388 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5389 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == false);
5390 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
5391 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
5392 : 3 : CU_ASSERT(bdev_nvme_check_ctrlr_loss_timeout(nvme_ctrlr) == false);
5393 : :
5394 : : /* Then a reconnect retry should still fail and the ctrlr should be deleted. */
5395 : 3 : spdk_delay_us(SPDK_SEC_TO_USEC);
5396 : 3 : poll_threads();
5397 : :
5398 : 3 : CU_ASSERT(nvme_ctrlr == nvme_ctrlr_get_by_name("nvme0"));
5399 : 3 : CU_ASSERT(bdev_nvme_check_ctrlr_loss_timeout(nvme_ctrlr) == true);
5400 : 3 : CU_ASSERT(nvme_ctrlr->destruct == true);
5401 : :
5402 : 3 : spdk_put_io_channel(ch2);
5403 : :
5404 : 3 : set_thread(0);
5405 : :
5406 : 3 : spdk_put_io_channel(ch1);
5407 : :
5408 : 3 : poll_threads();
5409 : 3 : spdk_delay_us(1000);
5410 : 3 : poll_threads();
5411 : :
5412 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
5413 : 3 : }
5414 : :
5415 : : static struct nvme_path_id *
5416 : 15 : ut_get_path_id_by_trid(struct nvme_ctrlr *nvme_ctrlr,
5417 : : const struct spdk_nvme_transport_id *trid)
5418 : : {
5419 : : struct nvme_path_id *p;
5420 : :
5421 [ + + ]: 30 : TAILQ_FOREACH(p, &nvme_ctrlr->trids, link) {
5422 [ + + ]: 27 : if (spdk_nvme_transport_id_compare(&p->trid, trid) == 0) {
5423 : 12 : break;
5424 : : }
5425 : : }
5426 : :
5427 : 15 : return p;
5428 : : }
5429 : :
5430 : : static void
5431 : 3 : test_retry_failover_ctrlr(void)
5432 : : {
5433 : 3 : struct spdk_nvme_transport_id trid1 = {}, trid2 = {}, trid3 = {};
5434 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
5435 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
5436 : : struct nvme_path_id *path_id1, *path_id2, *path_id3;
5437 : : struct spdk_io_channel *ch;
5438 : : struct nvme_ctrlr_channel *ctrlr_ch;
5439 : : int rc;
5440 : :
5441 : 3 : ut_init_trid(&trid1);
5442 : 3 : ut_init_trid2(&trid2);
5443 : 3 : ut_init_trid3(&trid3);
5444 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
5445 : :
5446 : 3 : set_thread(0);
5447 : :
5448 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid1, NULL);
5449 : 3 : CU_ASSERT(rc == 0);
5450 : :
5451 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
5452 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
5453 : :
5454 : 3 : nvme_ctrlr->opts.ctrlr_loss_timeout_sec = -1;
5455 : 3 : nvme_ctrlr->opts.reconnect_delay_sec = 1;
5456 : :
5457 : 3 : rc = bdev_nvme_add_secondary_trid(nvme_ctrlr, &ctrlr, &trid2);
5458 : 3 : CU_ASSERT(rc == 0);
5459 : :
5460 : 3 : rc = bdev_nvme_add_secondary_trid(nvme_ctrlr, &ctrlr, &trid3);
5461 : 3 : CU_ASSERT(rc == 0);
5462 : :
5463 : 3 : ch = spdk_get_io_channel(nvme_ctrlr);
5464 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
5465 : :
5466 : 3 : ctrlr_ch = spdk_io_channel_get_ctx(ch);
5467 : :
5468 : 3 : path_id1 = ut_get_path_id_by_trid(nvme_ctrlr, &trid1);
5469 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(path_id1 != NULL);
5470 : 3 : CU_ASSERT(path_id1->last_failed_tsc == 0);
5471 : 3 : CU_ASSERT(path_id1 == nvme_ctrlr->active_path_id);
5472 : :
5473 : : /* If reset failed and reconnect is scheduled, path_id is switched from trid1 to trid2. */
5474 : 3 : path_id2 = ut_get_path_id_by_trid(nvme_ctrlr, &trid2);
5475 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(path_id2 != NULL);
5476 : :
5477 : 3 : path_id3 = ut_get_path_id_by_trid(nvme_ctrlr, &trid3);
5478 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(path_id3 != NULL);
5479 : :
5480 : : /* It is expected that connecting both of trid1, trid2, and trid3 fail,
5481 : : * and a reconnect timer is started. */
5482 : 3 : ctrlr.fail_reset = true;
5483 : 3 : ctrlr.is_failed = true;
5484 : :
5485 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
5486 : 3 : CU_ASSERT(rc == 0);
5487 : :
5488 : 3 : poll_threads();
5489 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5490 : 3 : poll_threads();
5491 : :
5492 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5493 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == false);
5494 : 3 : CU_ASSERT(ctrlr_ch->qpair->qpair == NULL);
5495 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL);
5496 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == true);
5497 : 3 : CU_ASSERT(path_id1->last_failed_tsc != 0);
5498 : :
5499 : 3 : CU_ASSERT(path_id2->last_failed_tsc != 0);
5500 : 3 : CU_ASSERT(path_id3->last_failed_tsc != 0);
5501 : 3 : CU_ASSERT(path_id1 == nvme_ctrlr->active_path_id);
5502 : :
5503 : : /* If we remove trid1 while reconnect is scheduled, trid1 is removed and path_id is
5504 : : * switched to trid2 but reset is not started.
5505 : : */
5506 : 3 : rc = bdev_nvme_failover_ctrlr_unsafe(nvme_ctrlr, true);
5507 : 3 : CU_ASSERT(rc == -EALREADY);
5508 : :
5509 : 3 : CU_ASSERT(ut_get_path_id_by_trid(nvme_ctrlr, &trid1) == NULL);
5510 : 3 : CU_ASSERT(path_id2 == nvme_ctrlr->active_path_id);
5511 : :
5512 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5513 : :
5514 : : /* If reconnect succeeds, trid2 should be the active path_id */
5515 : 3 : ctrlr.fail_reset = false;
5516 : :
5517 : 3 : spdk_delay_us(SPDK_SEC_TO_USEC);
5518 : 3 : poll_thread_times(0, 1);
5519 : :
5520 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
5521 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer == NULL);
5522 : :
5523 : 3 : poll_threads();
5524 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5525 : 3 : poll_threads();
5526 : :
5527 : 3 : CU_ASSERT(ut_get_path_id_by_trid(nvme_ctrlr, &trid2) != NULL);
5528 : 3 : CU_ASSERT(path_id2->last_failed_tsc == 0);
5529 : 3 : CU_ASSERT(path_id2 == nvme_ctrlr->active_path_id);
5530 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5531 : 3 : CU_ASSERT(ctrlr_ch->qpair->qpair != NULL);
5532 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == false);
5533 : :
5534 : 3 : spdk_put_io_channel(ch);
5535 : :
5536 : 3 : poll_threads();
5537 : :
5538 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
5539 : 3 : CU_ASSERT(rc == 0);
5540 : :
5541 : 3 : poll_threads();
5542 : 3 : spdk_delay_us(1000);
5543 : 3 : poll_threads();
5544 : :
5545 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
5546 : 3 : }
5547 : :
5548 : : static void
5549 : 3 : test_fail_path(void)
5550 : 3 : {
5551 : 3 : struct nvme_path_id path = {};
5552 : 3 : struct nvme_ctrlr_opts opts = {};
5553 : : struct spdk_nvme_ctrlr *ctrlr;
5554 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
5555 : : struct nvme_ctrlr *nvme_ctrlr;
5556 : 3 : const int STRING_SIZE = 32;
5557 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
5558 : : struct nvme_bdev *bdev;
5559 : : struct nvme_ns *nvme_ns;
5560 : : struct spdk_bdev_io *bdev_io;
5561 : : struct spdk_io_channel *ch;
5562 : : struct nvme_bdev_channel *nbdev_ch;
5563 : : struct nvme_io_path *io_path;
5564 : : struct nvme_ctrlr_channel *ctrlr_ch;
5565 : : int rc;
5566 : :
5567 : : /* The test scenario is the following.
5568 : : * - We set ctrlr_fail_timeout_sec to be smaller than ctrlr_loss_timeout_sec.
5569 : : * - Rresetting a ctrlr fails and reconnecting the ctrlr is repeated.
5570 : : * - While reconnecting the ctrlr, an I/O is submitted and queued.
5571 : : * - The I/O waits until the ctrlr is recovered but ctrlr_fail_timeout_sec
5572 : : * comes first. The queued I/O is failed.
5573 : : * - After ctrlr_fail_timeout_sec, any I/O is failed immediately.
5574 : : * - Then ctrlr_loss_timeout_sec comes and the ctrlr is deleted.
5575 : : */
5576 : :
5577 : 3 : g_opts.bdev_retry_count = 1;
5578 : :
5579 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
5580 : 3 : ut_init_trid(&path.trid);
5581 : :
5582 : 3 : set_thread(0);
5583 : :
5584 : 3 : ctrlr = ut_attach_ctrlr(&path.trid, 1, false, false);
5585 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
5586 : :
5587 : 3 : g_ut_attach_ctrlr_status = 0;
5588 : 3 : g_ut_attach_bdev_count = 1;
5589 : :
5590 : 3 : opts.ctrlr_loss_timeout_sec = 4;
5591 : 3 : opts.reconnect_delay_sec = 1;
5592 : 3 : opts.fast_io_fail_timeout_sec = 2;
5593 : :
5594 : 3 : rc = bdev_nvme_create(&path.trid, "nvme0", attached_names, STRING_SIZE,
5595 : : attach_ctrlr_done, NULL, NULL, &opts, false);
5596 : 3 : CU_ASSERT(rc == 0);
5597 : :
5598 : 3 : spdk_delay_us(1000);
5599 : 3 : poll_threads();
5600 : :
5601 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
5602 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
5603 : :
5604 : 3 : nvme_ctrlr = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path.trid);
5605 : 3 : CU_ASSERT(nvme_ctrlr != NULL);
5606 : :
5607 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
5608 : 3 : CU_ASSERT(bdev != NULL);
5609 : :
5610 : 3 : nvme_ns = nvme_ctrlr_get_first_active_ns(nvme_ctrlr);
5611 : 3 : CU_ASSERT(nvme_ns != NULL);
5612 : :
5613 : 3 : ch = spdk_get_io_channel(bdev);
5614 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
5615 : :
5616 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
5617 : :
5618 : 3 : io_path = ut_get_io_path_by_ctrlr(nbdev_ch, nvme_ctrlr);
5619 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
5620 : :
5621 : 3 : ctrlr_ch = io_path->qpair->ctrlr_ch;
5622 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr_ch != NULL);
5623 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr_ch->qpair->qpair != NULL);
5624 : :
5625 : 3 : bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_WRITE, bdev, ch);
5626 : 3 : ut_bdev_io_set_buf(bdev_io);
5627 : :
5628 : :
5629 : : /* Resetting a ctrlr should fail and a reconnect timer should be registered. */
5630 : 3 : ctrlr->fail_reset = true;
5631 : 3 : ctrlr->is_failed = true;
5632 : :
5633 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
5634 : 3 : CU_ASSERT(rc == 0);
5635 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
5636 [ - + ]: 3 : CU_ASSERT(ctrlr->is_failed == true);
5637 : :
5638 : 3 : poll_threads();
5639 : :
5640 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5641 [ - + ]: 3 : CU_ASSERT(ctrlr->is_failed == false);
5642 : 3 : CU_ASSERT(ctrlr_ch->qpair->qpair == NULL);
5643 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL);
5644 : 3 : CU_ASSERT(nvme_ctrlr->reset_start_tsc != 0);
5645 : 3 : CU_ASSERT(nvme_ctrlr->fast_io_fail_timedout == false);
5646 : :
5647 : : /* I/O should be queued. */
5648 : 3 : bdev_io->internal.in_submit_request = true;
5649 : :
5650 : 3 : bdev_nvme_submit_request(ch, bdev_io);
5651 : :
5652 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
5653 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
5654 : :
5655 : : /* After a second, the I/O should be still queued and the ctrlr should be
5656 : : * still recovering.
5657 : : */
5658 : 3 : spdk_delay_us(SPDK_SEC_TO_USEC);
5659 : 3 : poll_threads();
5660 : :
5661 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
5662 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
5663 : :
5664 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5665 [ - + ]: 3 : CU_ASSERT(ctrlr->is_failed == false);
5666 : 3 : CU_ASSERT(ctrlr_ch->qpair->qpair == NULL);
5667 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL);
5668 : 3 : CU_ASSERT(bdev_nvme_check_ctrlr_loss_timeout(nvme_ctrlr) == false);
5669 : 3 : CU_ASSERT(nvme_ctrlr->fast_io_fail_timedout == false);
5670 : :
5671 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL);
5672 : :
5673 : : /* After two seconds, ctrlr_fail_timeout_sec should expire. */
5674 : 3 : spdk_delay_us(SPDK_SEC_TO_USEC);
5675 : 3 : poll_threads();
5676 : :
5677 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
5678 [ - + ]: 3 : CU_ASSERT(ctrlr->is_failed == false);
5679 : 3 : CU_ASSERT(ctrlr_ch->qpair->qpair == NULL);
5680 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL);
5681 : 3 : CU_ASSERT(bdev_nvme_check_ctrlr_loss_timeout(nvme_ctrlr) == false);
5682 : 3 : CU_ASSERT(nvme_ctrlr->fast_io_fail_timedout == true);
5683 : :
5684 : : /* Then within a second, pending I/O should be failed. */
5685 : 3 : spdk_delay_us(SPDK_SEC_TO_USEC);
5686 : 3 : poll_threads();
5687 : :
5688 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5689 : 3 : poll_threads();
5690 : :
5691 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
5692 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
5693 : 3 : CU_ASSERT(TAILQ_EMPTY(&nbdev_ch->retry_io_list));
5694 : :
5695 : : /* Another I/O submission should be failed immediately. */
5696 : 3 : bdev_io->internal.in_submit_request = true;
5697 : :
5698 : 3 : bdev_nvme_submit_request(ch, bdev_io);
5699 : :
5700 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
5701 : 3 : CU_ASSERT(bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
5702 : :
5703 : : /* After four seconds, path_loss_timeout_sec should expire and ctrlr should
5704 : : * be deleted.
5705 : : */
5706 : 3 : spdk_delay_us(SPDK_SEC_TO_USEC);
5707 : 3 : poll_threads();
5708 : :
5709 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5710 : 3 : poll_threads();
5711 : :
5712 : 3 : CU_ASSERT(nvme_ctrlr == nvme_ctrlr_get_by_name("nvme0"));
5713 : 3 : CU_ASSERT(bdev_nvme_check_ctrlr_loss_timeout(nvme_ctrlr) == true);
5714 : 3 : CU_ASSERT(nvme_ctrlr->destruct == true);
5715 : :
5716 : 3 : spdk_put_io_channel(ch);
5717 : :
5718 : 3 : poll_threads();
5719 : 3 : spdk_delay_us(1000);
5720 : 3 : poll_threads();
5721 : :
5722 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
5723 : :
5724 : 3 : free(bdev_io);
5725 : :
5726 : 3 : g_opts.bdev_retry_count = 0;
5727 : 3 : }
5728 : :
5729 : : static void
5730 : 3 : test_nvme_ns_cmp(void)
5731 : : {
5732 : 3 : struct nvme_ns nvme_ns1 = {}, nvme_ns2 = {};
5733 : :
5734 : 3 : nvme_ns1.id = 0;
5735 : 3 : nvme_ns2.id = UINT32_MAX;
5736 : :
5737 : 3 : CU_ASSERT(nvme_ns_cmp(&nvme_ns1, &nvme_ns2) < 0);
5738 : 3 : CU_ASSERT(nvme_ns_cmp(&nvme_ns2, &nvme_ns1) > 0);
5739 : 3 : }
5740 : :
5741 : : static void
5742 : 3 : test_ana_transition(void)
5743 : : {
5744 : 3 : struct spdk_nvme_ctrlr ctrlr = { .cdata.anatt = 10, };
5745 : 3 : struct nvme_ctrlr nvme_ctrlr = { .ctrlr = &ctrlr, };
5746 : 3 : struct nvme_ns nvme_ns = { .ctrlr = &nvme_ctrlr, };
5747 : 3 : struct spdk_nvme_ana_group_descriptor desc = { .ana_group_id = 1, };
5748 : :
5749 : : /* case 1: ANA transition timedout is canceled. */
5750 : 3 : nvme_ns.ana_state = SPDK_NVME_ANA_CHANGE_STATE;
5751 : 3 : nvme_ns.ana_transition_timedout = true;
5752 : :
5753 : 3 : desc.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
5754 : :
5755 : 3 : _nvme_ns_set_ana_state(&nvme_ns, &desc);
5756 : :
5757 [ - + ]: 3 : CU_ASSERT(nvme_ns.ana_transition_timedout == false);
5758 : 3 : CU_ASSERT(nvme_ns.ana_state == SPDK_NVME_ANA_OPTIMIZED_STATE);
5759 : :
5760 : : /* case 2: ANATT timer is kept. */
5761 : 3 : nvme_ns.ana_state = SPDK_NVME_ANA_CHANGE_STATE;
5762 : 3 : nvme_ns.anatt_timer = SPDK_POLLER_REGISTER(nvme_ns_ana_transition_timedout,
5763 : : &nvme_ns,
5764 : : ctrlr.cdata.anatt * SPDK_SEC_TO_USEC);
5765 : :
5766 : 3 : desc.ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
5767 : :
5768 : 3 : _nvme_ns_set_ana_state(&nvme_ns, &desc);
5769 : :
5770 : 3 : CU_ASSERT(nvme_ns.anatt_timer != NULL);
5771 : 3 : CU_ASSERT(nvme_ns.ana_state == SPDK_NVME_ANA_INACCESSIBLE_STATE);
5772 : :
5773 : : /* case 3: ANATT timer is stopped. */
5774 : 3 : desc.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
5775 : :
5776 : 3 : _nvme_ns_set_ana_state(&nvme_ns, &desc);
5777 : :
5778 : 3 : CU_ASSERT(nvme_ns.anatt_timer == NULL);
5779 : 3 : CU_ASSERT(nvme_ns.ana_state == SPDK_NVME_ANA_OPTIMIZED_STATE);
5780 : :
5781 : : /* ANATT timer is started. */
5782 : 3 : desc.ana_state = SPDK_NVME_ANA_CHANGE_STATE;
5783 : :
5784 : 3 : _nvme_ns_set_ana_state(&nvme_ns, &desc);
5785 : :
5786 : 3 : CU_ASSERT(nvme_ns.anatt_timer != NULL);
5787 : 3 : CU_ASSERT(nvme_ns.ana_state == SPDK_NVME_ANA_CHANGE_STATE);
5788 : :
5789 : : /* ANATT timer is expired. */
5790 : 3 : spdk_delay_us(ctrlr.cdata.anatt * SPDK_SEC_TO_USEC);
5791 : :
5792 : 3 : poll_threads();
5793 : :
5794 : 3 : CU_ASSERT(nvme_ns.anatt_timer == NULL);
5795 [ - + ]: 3 : CU_ASSERT(nvme_ns.ana_transition_timedout == true);
5796 : 3 : }
5797 : :
5798 : : static void
5799 : 9 : _set_preferred_path_cb(void *cb_arg, int rc)
5800 : : {
5801 : 9 : bool *done = cb_arg;
5802 : :
5803 : 9 : *done = true;
5804 : 9 : }
5805 : :
5806 : : static void
5807 : 3 : test_set_preferred_path(void)
5808 : 3 : {
5809 : 3 : struct nvme_path_id path1 = {}, path2 = {}, path3 = {};
5810 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2, *ctrlr3;
5811 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
5812 : 3 : const int STRING_SIZE = 32;
5813 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
5814 : : struct nvme_bdev *bdev;
5815 : : struct spdk_io_channel *ch;
5816 : : struct nvme_bdev_channel *nbdev_ch;
5817 : : struct nvme_io_path *io_path;
5818 : 3 : struct spdk_uuid uuid1 = { .u.raw = { 0x1 } };
5819 : : const struct spdk_nvme_ctrlr_data *cdata;
5820 : 3 : bool done;
5821 : : int rc;
5822 : :
5823 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
5824 : 3 : ut_init_trid(&path1.trid);
5825 : 3 : ut_init_trid2(&path2.trid);
5826 : 3 : ut_init_trid3(&path3.trid);
5827 : 3 : g_ut_attach_ctrlr_status = 0;
5828 : 3 : g_ut_attach_bdev_count = 1;
5829 : :
5830 : 3 : set_thread(0);
5831 : :
5832 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 1, true, true);
5833 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
5834 : :
5835 : 3 : ctrlr1->ns[0].uuid = &uuid1;
5836 : :
5837 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
5838 : : attach_ctrlr_done, NULL, NULL, NULL, true);
5839 : 3 : CU_ASSERT(rc == 0);
5840 : :
5841 : 3 : spdk_delay_us(1000);
5842 : 3 : poll_threads();
5843 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5844 : 3 : poll_threads();
5845 : :
5846 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 1, true, true);
5847 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
5848 : :
5849 : 3 : ctrlr2->ns[0].uuid = &uuid1;
5850 : :
5851 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
5852 : : attach_ctrlr_done, NULL, NULL, NULL, true);
5853 : 3 : CU_ASSERT(rc == 0);
5854 : :
5855 : 3 : spdk_delay_us(1000);
5856 : 3 : poll_threads();
5857 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5858 : 3 : poll_threads();
5859 : :
5860 : 3 : ctrlr3 = ut_attach_ctrlr(&path3.trid, 1, true, true);
5861 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr3 != NULL);
5862 : :
5863 : 3 : ctrlr3->ns[0].uuid = &uuid1;
5864 : :
5865 : 3 : rc = bdev_nvme_create(&path3.trid, "nvme0", attached_names, STRING_SIZE,
5866 : : attach_ctrlr_done, NULL, NULL, NULL, true);
5867 : 3 : CU_ASSERT(rc == 0);
5868 : :
5869 : 3 : spdk_delay_us(1000);
5870 : 3 : poll_threads();
5871 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
5872 : 3 : poll_threads();
5873 : :
5874 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
5875 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
5876 : :
5877 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
5878 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
5879 : :
5880 : : /* ctrlr1 was added first. Hence io_path to ctrlr1 should be preferred. */
5881 : :
5882 : 3 : ch = spdk_get_io_channel(bdev);
5883 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
5884 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
5885 : :
5886 : 3 : io_path = bdev_nvme_find_io_path(nbdev_ch);
5887 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
5888 : :
5889 : 3 : CU_ASSERT(io_path->nvme_ns->ctrlr->ctrlr == ctrlr1);
5890 : :
5891 : : /* If io_path to ctrlr2 is set to the preferred path dynamically, find_io_path()
5892 : : * should return io_path to ctrlr2.
5893 : : */
5894 : :
5895 : 3 : cdata = spdk_nvme_ctrlr_get_data(ctrlr2);
5896 : 3 : done = false;
5897 : :
5898 : 3 : bdev_nvme_set_preferred_path(bdev->disk.name, cdata->cntlid, _set_preferred_path_cb, &done);
5899 : :
5900 : 3 : poll_threads();
5901 [ - + ]: 3 : CU_ASSERT(done == true);
5902 : :
5903 : 3 : io_path = bdev_nvme_find_io_path(nbdev_ch);
5904 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
5905 : :
5906 : 3 : CU_ASSERT(io_path->nvme_ns->ctrlr->ctrlr == ctrlr2);
5907 : :
5908 : : /* If io_path to ctrlr3 is set to the preferred path and then a new I/O channel is
5909 : : * acquired, find_io_path() should return io_path to ctrlr3.
5910 : : */
5911 : :
5912 : 3 : spdk_put_io_channel(ch);
5913 : :
5914 : 3 : poll_threads();
5915 : :
5916 : 3 : cdata = spdk_nvme_ctrlr_get_data(ctrlr3);
5917 : 3 : done = false;
5918 : :
5919 : 3 : bdev_nvme_set_preferred_path(bdev->disk.name, cdata->cntlid, _set_preferred_path_cb, &done);
5920 : :
5921 : 3 : poll_threads();
5922 [ - + ]: 3 : CU_ASSERT(done == true);
5923 : :
5924 : 3 : ch = spdk_get_io_channel(bdev);
5925 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
5926 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
5927 : :
5928 : 3 : io_path = bdev_nvme_find_io_path(nbdev_ch);
5929 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
5930 : :
5931 : 3 : CU_ASSERT(io_path->nvme_ns->ctrlr->ctrlr == ctrlr3);
5932 : :
5933 : 3 : spdk_put_io_channel(ch);
5934 : :
5935 : 3 : poll_threads();
5936 : :
5937 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
5938 : 3 : CU_ASSERT(rc == 0);
5939 : :
5940 : 3 : poll_threads();
5941 : 3 : spdk_delay_us(1000);
5942 : 3 : poll_threads();
5943 : :
5944 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
5945 : 3 : }
5946 : :
5947 : : static void
5948 : 3 : test_find_next_io_path(void)
5949 : : {
5950 : 3 : struct nvme_bdev_channel nbdev_ch = {
5951 : : .io_path_list = STAILQ_HEAD_INITIALIZER(nbdev_ch.io_path_list),
5952 : : .mp_policy = BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE,
5953 : : .mp_selector = BDEV_NVME_MP_SELECTOR_ROUND_ROBIN,
5954 : : };
5955 : 3 : struct spdk_nvme_qpair qpair1 = {}, qpair2 = {}, qpair3 = {};
5956 : 3 : struct spdk_nvme_ctrlr ctrlr1 = {}, ctrlr2 = {}, ctrlr3 = {};
5957 : 3 : struct spdk_nvme_ns ns1 = {}, ns2 = {}, ns3 = {};
5958 : 3 : struct nvme_ctrlr nvme_ctrlr1 = { .ctrlr = &ctrlr1, };
5959 : 3 : struct nvme_ctrlr nvme_ctrlr2 = { .ctrlr = &ctrlr2, };
5960 : 3 : struct nvme_ctrlr nvme_ctrlr3 = { .ctrlr = &ctrlr3, };
5961 : 3 : struct nvme_ctrlr_channel ctrlr_ch1 = {};
5962 : 3 : struct nvme_ctrlr_channel ctrlr_ch2 = {};
5963 : 3 : struct nvme_ctrlr_channel ctrlr_ch3 = {};
5964 : 3 : struct nvme_qpair nvme_qpair1 = { .ctrlr_ch = &ctrlr_ch1, .ctrlr = &nvme_ctrlr1, .qpair = &qpair1, };
5965 : 3 : struct nvme_qpair nvme_qpair2 = { .ctrlr_ch = &ctrlr_ch2, .ctrlr = &nvme_ctrlr2, .qpair = &qpair2, };
5966 : 3 : struct nvme_qpair nvme_qpair3 = { .ctrlr_ch = &ctrlr_ch3, .ctrlr = &nvme_ctrlr3, .qpair = &qpair3, };
5967 : 3 : struct nvme_ns nvme_ns1 = { .ns = &ns1, }, nvme_ns2 = { .ns = &ns2, }, nvme_ns3 = { .ns = &ns3, };
5968 : 3 : struct nvme_io_path io_path1 = { .qpair = &nvme_qpair1, .nvme_ns = &nvme_ns1, };
5969 : 3 : struct nvme_io_path io_path2 = { .qpair = &nvme_qpair2, .nvme_ns = &nvme_ns2, };
5970 : 3 : struct nvme_io_path io_path3 = { .qpair = &nvme_qpair3, .nvme_ns = &nvme_ns3, };
5971 : :
5972 : 3 : STAILQ_INSERT_TAIL(&nbdev_ch.io_path_list, &io_path1, stailq);
5973 : 3 : STAILQ_INSERT_TAIL(&nbdev_ch.io_path_list, &io_path2, stailq);
5974 : 3 : STAILQ_INSERT_TAIL(&nbdev_ch.io_path_list, &io_path3, stailq);
5975 : :
5976 : : /* test the case when nbdev_ch->current_io_path is filled, the case of current_io_path = NULL
5977 : : * is covered in test_find_io_path.
5978 : : */
5979 : :
5980 : 3 : nbdev_ch.current_io_path = &io_path2;
5981 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
5982 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
5983 : 3 : nvme_ns3.ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
5984 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path2);
5985 : :
5986 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
5987 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
5988 : 3 : nvme_ns3.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
5989 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path2);
5990 : :
5991 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
5992 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
5993 : 3 : nvme_ns3.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
5994 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path1);
5995 : :
5996 : 3 : nbdev_ch.current_io_path = &io_path3;
5997 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
5998 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
5999 : 3 : nvme_ns3.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
6000 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path2);
6001 : :
6002 : : /* Test if next io_path is selected according to rr_min_io */
6003 : :
6004 : 3 : nbdev_ch.current_io_path = NULL;
6005 : 3 : nbdev_ch.rr_min_io = 2;
6006 : 3 : nbdev_ch.rr_counter = 0;
6007 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
6008 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
6009 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path1);
6010 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path1);
6011 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path2);
6012 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path2);
6013 : :
6014 : 3 : nvme_ns3.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
6015 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path1);
6016 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path1);
6017 : 3 : }
6018 : :
6019 : : static void
6020 : 3 : test_find_io_path_min_qd(void)
6021 : : {
6022 : 3 : struct nvme_bdev_channel nbdev_ch = {
6023 : : .io_path_list = STAILQ_HEAD_INITIALIZER(nbdev_ch.io_path_list),
6024 : : .mp_policy = BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE,
6025 : : .mp_selector = BDEV_NVME_MP_SELECTOR_QUEUE_DEPTH,
6026 : : };
6027 : 3 : struct spdk_nvme_qpair qpair1 = {}, qpair2 = {}, qpair3 = {};
6028 : 3 : struct spdk_nvme_ctrlr ctrlr1 = {}, ctrlr2 = {}, ctrlr3 = {};
6029 : 3 : struct spdk_nvme_ns ns1 = {}, ns2 = {}, ns3 = {};
6030 : 3 : struct nvme_ctrlr nvme_ctrlr1 = { .ctrlr = &ctrlr1, };
6031 : 3 : struct nvme_ctrlr nvme_ctrlr2 = { .ctrlr = &ctrlr2, };
6032 : 3 : struct nvme_ctrlr nvme_ctrlr3 = { .ctrlr = &ctrlr3, };
6033 : 3 : struct nvme_ctrlr_channel ctrlr_ch1 = {};
6034 : 3 : struct nvme_ctrlr_channel ctrlr_ch2 = {};
6035 : 3 : struct nvme_ctrlr_channel ctrlr_ch3 = {};
6036 : 3 : struct nvme_qpair nvme_qpair1 = { .ctrlr_ch = &ctrlr_ch1, .ctrlr = &nvme_ctrlr1, .qpair = &qpair1, };
6037 : 3 : struct nvme_qpair nvme_qpair2 = { .ctrlr_ch = &ctrlr_ch2, .ctrlr = &nvme_ctrlr2, .qpair = &qpair2, };
6038 : 3 : struct nvme_qpair nvme_qpair3 = { .ctrlr_ch = &ctrlr_ch3, .ctrlr = &nvme_ctrlr3, .qpair = &qpair3, };
6039 : 3 : struct nvme_ns nvme_ns1 = { .ns = &ns1, }, nvme_ns2 = { .ns = &ns2, }, nvme_ns3 = { .ns = &ns3, };
6040 : 3 : struct nvme_io_path io_path1 = { .qpair = &nvme_qpair1, .nvme_ns = &nvme_ns1, };
6041 : 3 : struct nvme_io_path io_path2 = { .qpair = &nvme_qpair2, .nvme_ns = &nvme_ns2, };
6042 : 3 : struct nvme_io_path io_path3 = { .qpair = &nvme_qpair3, .nvme_ns = &nvme_ns3, };
6043 : :
6044 : 3 : STAILQ_INSERT_TAIL(&nbdev_ch.io_path_list, &io_path1, stailq);
6045 : 3 : STAILQ_INSERT_TAIL(&nbdev_ch.io_path_list, &io_path2, stailq);
6046 : 3 : STAILQ_INSERT_TAIL(&nbdev_ch.io_path_list, &io_path3, stailq);
6047 : :
6048 : : /* Test if the minumum io_outstanding or the ANA optimized state is
6049 : : * prioritized when using least queue depth selector
6050 : : */
6051 : 3 : qpair1.num_outstanding_reqs = 2;
6052 : 3 : qpair2.num_outstanding_reqs = 1;
6053 : 3 : qpair3.num_outstanding_reqs = 0;
6054 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
6055 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
6056 : 3 : nvme_ns3.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
6057 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path2);
6058 : :
6059 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
6060 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
6061 : 3 : nvme_ns3.ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
6062 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path2);
6063 : :
6064 : 3 : nvme_ns1.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
6065 : 3 : nvme_ns2.ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
6066 : 3 : nvme_ns3.ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
6067 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path2);
6068 : :
6069 : 3 : qpair2.num_outstanding_reqs = 4;
6070 : 3 : CU_ASSERT(bdev_nvme_find_io_path(&nbdev_ch) == &io_path1);
6071 : 3 : }
6072 : :
6073 : : static void
6074 : 3 : test_disable_auto_failback(void)
6075 : 3 : {
6076 : 3 : struct nvme_path_id path1 = {}, path2 = {};
6077 : 3 : struct nvme_ctrlr_opts opts = {};
6078 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2;
6079 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
6080 : : struct nvme_ctrlr *nvme_ctrlr1;
6081 : 3 : const int STRING_SIZE = 32;
6082 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
6083 : : struct nvme_bdev *bdev;
6084 : : struct spdk_io_channel *ch;
6085 : : struct nvme_bdev_channel *nbdev_ch;
6086 : : struct nvme_io_path *io_path;
6087 : 3 : struct spdk_uuid uuid1 = { .u.raw = { 0x1 } };
6088 : : const struct spdk_nvme_ctrlr_data *cdata;
6089 : 3 : bool done;
6090 : : int rc;
6091 : :
6092 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
6093 : 3 : ut_init_trid(&path1.trid);
6094 : 3 : ut_init_trid2(&path2.trid);
6095 : 3 : g_ut_attach_ctrlr_status = 0;
6096 : 3 : g_ut_attach_bdev_count = 1;
6097 : :
6098 : 3 : g_opts.disable_auto_failback = true;
6099 : :
6100 : 3 : opts.ctrlr_loss_timeout_sec = -1;
6101 : 3 : opts.reconnect_delay_sec = 1;
6102 : :
6103 : 3 : set_thread(0);
6104 : :
6105 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 1, true, true);
6106 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
6107 : :
6108 : 3 : ctrlr1->ns[0].uuid = &uuid1;
6109 : :
6110 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
6111 : : attach_ctrlr_done, NULL, NULL, &opts, true);
6112 : 3 : CU_ASSERT(rc == 0);
6113 : :
6114 : 3 : spdk_delay_us(1000);
6115 : 3 : poll_threads();
6116 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6117 : 3 : poll_threads();
6118 : :
6119 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 1, true, true);
6120 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
6121 : :
6122 : 3 : ctrlr2->ns[0].uuid = &uuid1;
6123 : :
6124 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
6125 : : attach_ctrlr_done, NULL, NULL, &opts, true);
6126 : 3 : CU_ASSERT(rc == 0);
6127 : :
6128 : 3 : spdk_delay_us(1000);
6129 : 3 : poll_threads();
6130 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6131 : 3 : poll_threads();
6132 : :
6133 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
6134 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
6135 : :
6136 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
6137 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
6138 : :
6139 : 3 : nvme_ctrlr1 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid);
6140 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr1 != NULL);
6141 : :
6142 : : /* ctrlr1 was added first. Hence io_path to ctrlr1 should be preferred. */
6143 : :
6144 : 3 : ch = spdk_get_io_channel(bdev);
6145 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
6146 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
6147 : :
6148 : 3 : io_path = bdev_nvme_find_io_path(nbdev_ch);
6149 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
6150 : :
6151 : 3 : CU_ASSERT(io_path->nvme_ns->ctrlr->ctrlr == ctrlr1);
6152 : :
6153 : : /* If resetting ctrlr1 failed, io_path to ctrlr2 should be used. */
6154 : 3 : ctrlr1->fail_reset = true;
6155 : 3 : ctrlr1->is_failed = true;
6156 : :
6157 : 3 : bdev_nvme_reset_ctrlr(nvme_ctrlr1);
6158 : :
6159 : 3 : poll_threads();
6160 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6161 : 3 : poll_threads();
6162 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6163 : 3 : poll_threads();
6164 : :
6165 [ - + ]: 3 : CU_ASSERT(ctrlr1->adminq.is_connected == false);
6166 : :
6167 : 3 : io_path = bdev_nvme_find_io_path(nbdev_ch);
6168 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
6169 : :
6170 : 3 : CU_ASSERT(io_path->nvme_ns->ctrlr->ctrlr == ctrlr2);
6171 : :
6172 : : /* After a second, ctrlr1 is recovered. However, automatic failback is disabled.
6173 : : * Hence, io_path to ctrlr2 should still be used.
6174 : : */
6175 : 3 : ctrlr1->fail_reset = false;
6176 : :
6177 : 3 : spdk_delay_us(SPDK_SEC_TO_USEC);
6178 : 3 : poll_threads();
6179 : :
6180 [ - + ]: 3 : CU_ASSERT(ctrlr1->adminq.is_connected == true);
6181 : :
6182 : 3 : io_path = bdev_nvme_find_io_path(nbdev_ch);
6183 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
6184 : :
6185 : 3 : CU_ASSERT(io_path->nvme_ns->ctrlr->ctrlr == ctrlr2);
6186 : :
6187 : : /* Set io_path to ctrlr1 to preferred explicitly. Then io_path to ctrlr1 should
6188 : : * be used again.
6189 : : */
6190 : :
6191 : 3 : cdata = spdk_nvme_ctrlr_get_data(ctrlr1);
6192 : 3 : done = false;
6193 : :
6194 : 3 : bdev_nvme_set_preferred_path(bdev->disk.name, cdata->cntlid, _set_preferred_path_cb, &done);
6195 : :
6196 : 3 : poll_threads();
6197 [ - + ]: 3 : CU_ASSERT(done == true);
6198 : :
6199 : 3 : io_path = bdev_nvme_find_io_path(nbdev_ch);
6200 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path != NULL);
6201 : :
6202 : 3 : CU_ASSERT(io_path->nvme_ns->ctrlr->ctrlr == ctrlr1);
6203 : :
6204 : 3 : spdk_put_io_channel(ch);
6205 : :
6206 : 3 : poll_threads();
6207 : :
6208 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
6209 : 3 : CU_ASSERT(rc == 0);
6210 : :
6211 : 3 : poll_threads();
6212 : 3 : spdk_delay_us(1000);
6213 : 3 : poll_threads();
6214 : :
6215 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
6216 : :
6217 : 3 : g_opts.disable_auto_failback = false;
6218 : 3 : }
6219 : :
6220 : : static void
6221 : 9 : ut_set_multipath_policy_done(void *cb_arg, int rc)
6222 : : {
6223 : 9 : int *done = cb_arg;
6224 : :
6225 [ - + ]: 9 : SPDK_CU_ASSERT_FATAL(done != NULL);
6226 : 9 : *done = rc;
6227 : 9 : }
6228 : :
6229 : : static void
6230 : 3 : test_set_multipath_policy(void)
6231 : 3 : {
6232 : 3 : struct nvme_path_id path1 = {}, path2 = {};
6233 : 3 : struct nvme_ctrlr_opts opts = {};
6234 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2;
6235 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
6236 : 3 : const int STRING_SIZE = 32;
6237 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
6238 : : struct nvme_bdev *bdev;
6239 : : struct spdk_io_channel *ch;
6240 : : struct nvme_bdev_channel *nbdev_ch;
6241 : 3 : struct spdk_uuid uuid1 = { .u.raw = { 0x1 } };
6242 : 3 : int done;
6243 : : int rc;
6244 : :
6245 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
6246 : 3 : ut_init_trid(&path1.trid);
6247 : 3 : ut_init_trid2(&path2.trid);
6248 : 3 : g_ut_attach_ctrlr_status = 0;
6249 : 3 : g_ut_attach_bdev_count = 1;
6250 : :
6251 : 3 : g_opts.disable_auto_failback = true;
6252 : :
6253 : 3 : opts.ctrlr_loss_timeout_sec = -1;
6254 : 3 : opts.reconnect_delay_sec = 1;
6255 : :
6256 : 3 : set_thread(0);
6257 : :
6258 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 1, true, true);
6259 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
6260 : :
6261 : 3 : ctrlr1->ns[0].uuid = &uuid1;
6262 : :
6263 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
6264 : : attach_ctrlr_done, NULL, NULL, &opts, true);
6265 : 3 : CU_ASSERT(rc == 0);
6266 : :
6267 : 3 : spdk_delay_us(1000);
6268 : 3 : poll_threads();
6269 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6270 : 3 : poll_threads();
6271 : :
6272 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 1, true, true);
6273 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
6274 : :
6275 : 3 : ctrlr2->ns[0].uuid = &uuid1;
6276 : :
6277 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
6278 : : attach_ctrlr_done, NULL, NULL, &opts, true);
6279 : 3 : CU_ASSERT(rc == 0);
6280 : :
6281 : 3 : spdk_delay_us(1000);
6282 : 3 : poll_threads();
6283 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6284 : 3 : poll_threads();
6285 : :
6286 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
6287 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
6288 : :
6289 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
6290 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
6291 : :
6292 : : /* If multipath policy is updated before getting any I/O channel,
6293 : : * an new I/O channel should have the update.
6294 : : */
6295 : 3 : done = -1;
6296 : 3 : bdev_nvme_set_multipath_policy(bdev->disk.name, BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE,
6297 : : BDEV_NVME_MP_SELECTOR_QUEUE_DEPTH, UINT32_MAX,
6298 : : ut_set_multipath_policy_done, &done);
6299 : 3 : poll_threads();
6300 : 3 : CU_ASSERT(done == 0);
6301 : :
6302 : 3 : CU_ASSERT(bdev->mp_policy == BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE);
6303 : 3 : CU_ASSERT(bdev->mp_selector == BDEV_NVME_MP_SELECTOR_QUEUE_DEPTH);
6304 : 3 : CU_ASSERT(bdev->rr_min_io == UINT32_MAX);
6305 : :
6306 : 3 : ch = spdk_get_io_channel(bdev);
6307 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
6308 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
6309 : :
6310 : 3 : CU_ASSERT(nbdev_ch->mp_policy == BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE);
6311 : 3 : CU_ASSERT(nbdev_ch->mp_selector == BDEV_NVME_MP_SELECTOR_QUEUE_DEPTH);
6312 : 3 : CU_ASSERT(nbdev_ch->rr_min_io == UINT32_MAX);
6313 : :
6314 : : /* If multipath policy is updated while a I/O channel is active,
6315 : : * the update should be applied to the I/O channel immediately.
6316 : : */
6317 : 3 : done = -1;
6318 : 3 : bdev_nvme_set_multipath_policy(bdev->disk.name, BDEV_NVME_MP_POLICY_ACTIVE_PASSIVE,
6319 : : BDEV_NVME_MP_SELECTOR_ROUND_ROBIN, UINT32_MAX,
6320 : : ut_set_multipath_policy_done, &done);
6321 : 3 : poll_threads();
6322 : 3 : CU_ASSERT(done == 0);
6323 : :
6324 : 3 : CU_ASSERT(bdev->mp_policy == BDEV_NVME_MP_POLICY_ACTIVE_PASSIVE);
6325 : 3 : CU_ASSERT(nbdev_ch->mp_policy == BDEV_NVME_MP_POLICY_ACTIVE_PASSIVE);
6326 : 3 : CU_ASSERT(bdev->mp_selector == BDEV_NVME_MP_SELECTOR_ROUND_ROBIN);
6327 : 3 : CU_ASSERT(nbdev_ch->mp_selector == BDEV_NVME_MP_SELECTOR_ROUND_ROBIN);
6328 : 3 : CU_ASSERT(bdev->rr_min_io == UINT32_MAX);
6329 : 3 : CU_ASSERT(nbdev_ch->rr_min_io == UINT32_MAX);
6330 : :
6331 : 3 : spdk_put_io_channel(ch);
6332 : :
6333 : 3 : poll_threads();
6334 : :
6335 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
6336 : 3 : CU_ASSERT(rc == 0);
6337 : :
6338 : 3 : poll_threads();
6339 : 3 : spdk_delay_us(1000);
6340 : 3 : poll_threads();
6341 : :
6342 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
6343 : 3 : }
6344 : :
6345 : : static void
6346 : 3 : test_uuid_generation(void)
6347 : : {
6348 : 3 : uint32_t nsid1 = 1, nsid2 = 2;
6349 : 3 : char sn1[21] = "SPDK CTRLR SERIAL 01", sn2[21] = "SPDK CTRLR SERIAL 02";
6350 : 3 : char sn3[21] = " ";
6351 : 3 : char uuid_str[SPDK_UUID_STRING_LEN] = {'\0'};
6352 : 3 : struct spdk_uuid uuid1, uuid2;
6353 : :
6354 : : /* Test case 1:
6355 : : * Serial numbers are the same, nsids are different.
6356 : : * Compare two generated UUID - they should be different. */
6357 : 3 : uuid1 = nvme_generate_uuid(sn1, nsid1);
6358 : 3 : uuid2 = nvme_generate_uuid(sn1, nsid2);
6359 : :
6360 : 3 : CU_ASSERT((spdk_uuid_compare(&uuid1, &uuid2)) != 0);
6361 : :
6362 : : /* Test case 2:
6363 : : * Serial numbers differ only by one character, nsids are the same.
6364 : : * Compare two generated UUID - they should be different. */
6365 : 3 : uuid1 = nvme_generate_uuid(sn1, nsid1);
6366 : 3 : uuid2 = nvme_generate_uuid(sn2, nsid1);
6367 : :
6368 : 3 : CU_ASSERT((spdk_uuid_compare(&uuid1, &uuid2)) != 0);
6369 : :
6370 : : /* Test case 3:
6371 : : * Serial number comprises only of space characters.
6372 : : * Validate the generated UUID. */
6373 : 3 : uuid1 = nvme_generate_uuid(sn3, nsid1);
6374 : 3 : CU_ASSERT((spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &uuid1)) == 0);
6375 : 3 : }
6376 : :
6377 : : static void
6378 : 3 : test_retry_io_to_same_path(void)
6379 : 3 : {
6380 : 3 : struct nvme_path_id path1 = {}, path2 = {};
6381 : : struct spdk_nvme_ctrlr *ctrlr1, *ctrlr2;
6382 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
6383 : : struct nvme_ctrlr *nvme_ctrlr1, *nvme_ctrlr2;
6384 : 3 : const int STRING_SIZE = 32;
6385 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
6386 : : struct nvme_bdev *bdev;
6387 : : struct spdk_bdev_io *bdev_io;
6388 : : struct nvme_bdev_io *bio;
6389 : : struct spdk_io_channel *ch;
6390 : : struct nvme_bdev_channel *nbdev_ch;
6391 : : struct nvme_io_path *io_path1, *io_path2;
6392 : : struct ut_nvme_req *req;
6393 : 3 : struct spdk_uuid uuid1 = { .u.raw = { 0x1 } };
6394 : 3 : int done;
6395 : : int rc;
6396 : :
6397 : 3 : g_opts.nvme_ioq_poll_period_us = 1;
6398 : :
6399 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
6400 : 3 : ut_init_trid(&path1.trid);
6401 : 3 : ut_init_trid2(&path2.trid);
6402 : 3 : g_ut_attach_ctrlr_status = 0;
6403 : 3 : g_ut_attach_bdev_count = 1;
6404 : :
6405 : 3 : set_thread(0);
6406 : :
6407 : 3 : ctrlr1 = ut_attach_ctrlr(&path1.trid, 1, true, true);
6408 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr1 != NULL);
6409 : :
6410 : 3 : ctrlr1->ns[0].uuid = &uuid1;
6411 : :
6412 : 3 : rc = bdev_nvme_create(&path1.trid, "nvme0", attached_names, STRING_SIZE,
6413 : : attach_ctrlr_done, NULL, NULL, NULL, true);
6414 : 3 : CU_ASSERT(rc == 0);
6415 : :
6416 : 3 : spdk_delay_us(1000);
6417 : 3 : poll_threads();
6418 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6419 : 3 : poll_threads();
6420 : :
6421 : 3 : ctrlr2 = ut_attach_ctrlr(&path2.trid, 1, true, true);
6422 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr2 != NULL);
6423 : :
6424 : 3 : ctrlr2->ns[0].uuid = &uuid1;
6425 : :
6426 : 3 : rc = bdev_nvme_create(&path2.trid, "nvme0", attached_names, STRING_SIZE,
6427 : : attach_ctrlr_done, NULL, NULL, NULL, true);
6428 : 3 : CU_ASSERT(rc == 0);
6429 : :
6430 : 3 : spdk_delay_us(1000);
6431 : 3 : poll_threads();
6432 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6433 : 3 : poll_threads();
6434 : :
6435 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
6436 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
6437 : :
6438 : 3 : nvme_ctrlr1 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path1.trid);
6439 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr1 != NULL);
6440 : :
6441 : 3 : nvme_ctrlr2 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid);
6442 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr2 != NULL);
6443 : :
6444 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
6445 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
6446 : :
6447 : 3 : done = -1;
6448 : 3 : bdev_nvme_set_multipath_policy(bdev->disk.name, BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE,
6449 : : BDEV_NVME_MP_SELECTOR_ROUND_ROBIN, 1, ut_set_multipath_policy_done, &done);
6450 : 3 : poll_threads();
6451 : 3 : CU_ASSERT(done == 0);
6452 : :
6453 : 3 : CU_ASSERT(bdev->mp_policy == BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE);
6454 : 3 : CU_ASSERT(bdev->mp_selector == BDEV_NVME_MP_SELECTOR_ROUND_ROBIN);
6455 : 3 : CU_ASSERT(bdev->rr_min_io == 1);
6456 : :
6457 : 3 : ch = spdk_get_io_channel(bdev);
6458 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
6459 : 3 : nbdev_ch = spdk_io_channel_get_ctx(ch);
6460 : :
6461 : 3 : CU_ASSERT(nbdev_ch->mp_policy == BDEV_NVME_MP_POLICY_ACTIVE_ACTIVE);
6462 : 3 : CU_ASSERT(bdev->mp_selector == BDEV_NVME_MP_SELECTOR_ROUND_ROBIN);
6463 : 3 : CU_ASSERT(nbdev_ch->rr_min_io == 1);
6464 : :
6465 : 3 : bdev_io = ut_alloc_bdev_io(SPDK_BDEV_IO_TYPE_WRITE, bdev, ch);
6466 : 3 : ut_bdev_io_set_buf(bdev_io);
6467 : :
6468 : 3 : bio = (struct nvme_bdev_io *)bdev_io->driver_ctx;
6469 : :
6470 : 3 : io_path1 = ut_get_io_path_by_ctrlr(nbdev_ch, nvme_ctrlr1);
6471 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path1 != NULL);
6472 : :
6473 : 3 : io_path2 = ut_get_io_path_by_ctrlr(nbdev_ch, nvme_ctrlr2);
6474 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_path2 != NULL);
6475 : :
6476 : : /* The 1st I/O should be submitted to io_path1. */
6477 : 3 : bdev_io->internal.in_submit_request = true;
6478 : :
6479 : 3 : bdev_nvme_submit_request(ch, bdev_io);
6480 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
6481 : 3 : CU_ASSERT(bio->io_path == io_path1);
6482 : 3 : CU_ASSERT(io_path1->qpair->qpair->num_outstanding_reqs == 1);
6483 : :
6484 : 3 : spdk_delay_us(1);
6485 : :
6486 : 3 : poll_threads();
6487 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
6488 : 3 : CU_ASSERT(bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS);
6489 : :
6490 : : /* The 2nd I/O should be submitted to io_path2 because the path selection
6491 : : * policy is round-robin.
6492 : : */
6493 : 3 : bdev_io->internal.in_submit_request = true;
6494 : :
6495 : 3 : bdev_nvme_submit_request(ch, bdev_io);
6496 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
6497 : 3 : CU_ASSERT(bio->io_path == io_path2);
6498 : 3 : CU_ASSERT(io_path2->qpair->qpair->num_outstanding_reqs == 1);
6499 : :
6500 : 3 : req = ut_get_outstanding_nvme_request(io_path2->qpair->qpair, bio);
6501 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
6502 : :
6503 : : /* Set retry count to non-zero. */
6504 : 3 : g_opts.bdev_retry_count = 2;
6505 : :
6506 : : /* Inject an I/O error. */
6507 : 3 : req->cpl.status.sc = SPDK_NVME_SC_NAMESPACE_NOT_READY;
6508 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
6509 : :
6510 : : /* The 2nd I/O should be queued to nbdev_ch. */
6511 : 3 : spdk_delay_us(1);
6512 : 3 : poll_thread_times(0, 1);
6513 : :
6514 : 3 : CU_ASSERT(io_path2->qpair->qpair->num_outstanding_reqs == 0);
6515 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
6516 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
6517 : :
6518 : : /* The 2nd I/O should keep caching io_path2. */
6519 : 3 : CU_ASSERT(bio->io_path == io_path2);
6520 : :
6521 : : /* The 2nd I/O should be submitted to io_path2 again. */
6522 : 3 : poll_thread_times(0, 1);
6523 : :
6524 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
6525 : 3 : CU_ASSERT(bio->io_path == io_path2);
6526 : 3 : CU_ASSERT(io_path2->qpair->qpair->num_outstanding_reqs == 1);
6527 : :
6528 : 3 : req = ut_get_outstanding_nvme_request(io_path2->qpair->qpair, bio);
6529 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
6530 : :
6531 : : /* Inject an I/O error again. */
6532 : 3 : req->cpl.status.sc = SPDK_NVME_SC_NAMESPACE_NOT_READY;
6533 : 3 : req->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
6534 : 3 : req->cpl.status.crd = 1;
6535 : :
6536 : 3 : ctrlr2->cdata.crdt[1] = 1;
6537 : :
6538 : : /* The 2nd I/O should be queued to nbdev_ch. */
6539 : 3 : spdk_delay_us(1);
6540 : 3 : poll_thread_times(0, 1);
6541 : :
6542 : 3 : CU_ASSERT(io_path2->qpair->qpair->num_outstanding_reqs == 0);
6543 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == true);
6544 : 3 : CU_ASSERT(bdev_io == TAILQ_FIRST(&nbdev_ch->retry_io_list));
6545 : :
6546 : : /* The 2nd I/O should keep caching io_path2. */
6547 : 3 : CU_ASSERT(bio->io_path == io_path2);
6548 : :
6549 : : /* Detach ctrlr2 dynamically. */
6550 : 3 : rc = bdev_nvme_delete("nvme0", &path2, NULL, NULL);
6551 : 3 : CU_ASSERT(rc == 0);
6552 : :
6553 : 3 : spdk_delay_us(1000);
6554 : 3 : poll_threads();
6555 : 3 : spdk_delay_us(1000);
6556 : 3 : poll_threads();
6557 : 3 : spdk_delay_us(1000);
6558 : 3 : poll_threads();
6559 : 3 : spdk_delay_us(1000);
6560 : 3 : poll_threads();
6561 : :
6562 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path2.trid) == NULL);
6563 : :
6564 : 3 : poll_threads();
6565 : 3 : spdk_delay_us(100000);
6566 : 3 : poll_threads();
6567 : 3 : spdk_delay_us(1);
6568 : 3 : poll_threads();
6569 : :
6570 : : /* The 2nd I/O should succeed by io_path1. */
6571 [ - + ]: 3 : CU_ASSERT(bdev_io->internal.in_submit_request == false);
6572 : 3 : CU_ASSERT(bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS);
6573 : 3 : CU_ASSERT(bio->io_path == io_path1);
6574 : :
6575 : 3 : free(bdev_io);
6576 : :
6577 : 3 : spdk_put_io_channel(ch);
6578 : :
6579 : 3 : poll_threads();
6580 : 3 : spdk_delay_us(1);
6581 : 3 : poll_threads();
6582 : :
6583 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
6584 : 3 : CU_ASSERT(rc == 0);
6585 : :
6586 : 3 : poll_threads();
6587 : 3 : spdk_delay_us(1000);
6588 : 3 : poll_threads();
6589 : :
6590 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
6591 : :
6592 : 3 : g_opts.nvme_ioq_poll_period_us = 0;
6593 : 3 : g_opts.bdev_retry_count = 0;
6594 : 3 : }
6595 : :
6596 : : /* This case is to verify a fix for a complex race condition that
6597 : : * failover is lost if fabric connect command gets timeout while
6598 : : * controller is being reset.
6599 : : */
6600 : : static void
6601 : 3 : test_race_between_reset_and_disconnected(void)
6602 : : {
6603 : 3 : struct spdk_nvme_transport_id trid = {};
6604 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
6605 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
6606 : : struct nvme_path_id *curr_trid;
6607 : : struct spdk_io_channel *ch1, *ch2;
6608 : : struct nvme_ctrlr_channel *ctrlr_ch1, *ctrlr_ch2;
6609 : : int rc;
6610 : :
6611 : 3 : ut_init_trid(&trid);
6612 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
6613 : :
6614 : 3 : set_thread(0);
6615 : :
6616 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid, NULL);
6617 : 3 : CU_ASSERT(rc == 0);
6618 : :
6619 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
6620 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
6621 : :
6622 : 3 : curr_trid = TAILQ_FIRST(&nvme_ctrlr->trids);
6623 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_trid != NULL);
6624 : :
6625 : 3 : ch1 = spdk_get_io_channel(nvme_ctrlr);
6626 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
6627 : :
6628 : 3 : ctrlr_ch1 = spdk_io_channel_get_ctx(ch1);
6629 : 3 : CU_ASSERT(ctrlr_ch1->qpair != NULL);
6630 : :
6631 : 3 : set_thread(1);
6632 : :
6633 : 3 : ch2 = spdk_get_io_channel(nvme_ctrlr);
6634 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
6635 : :
6636 : 3 : ctrlr_ch2 = spdk_io_channel_get_ctx(ch2);
6637 : 3 : CU_ASSERT(ctrlr_ch2->qpair != NULL);
6638 : :
6639 : : /* Reset starts from thread 1. */
6640 : 3 : set_thread(1);
6641 : :
6642 : 3 : nvme_ctrlr->resetting = false;
6643 : 3 : curr_trid->last_failed_tsc = spdk_get_ticks();
6644 : 3 : ctrlr.is_failed = true;
6645 : :
6646 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
6647 : 3 : CU_ASSERT(rc == 0);
6648 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
6649 : 3 : CU_ASSERT(ctrlr_ch1->qpair != NULL);
6650 : 3 : CU_ASSERT(ctrlr_ch2->qpair != NULL);
6651 : :
6652 : 3 : poll_thread_times(0, 3);
6653 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
6654 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair != NULL);
6655 : :
6656 : 3 : poll_thread_times(0, 1);
6657 : 3 : poll_thread_times(1, 1);
6658 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
6659 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
6660 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == true);
6661 : :
6662 : 3 : poll_thread_times(1, 1);
6663 : 3 : poll_thread_times(0, 1);
6664 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == false);
6665 [ - + ]: 3 : CU_ASSERT(ctrlr.adminq.is_connected == false);
6666 : :
6667 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6668 : 3 : poll_thread_times(0, 2);
6669 [ - + ]: 3 : CU_ASSERT(ctrlr.adminq.is_connected == true);
6670 : :
6671 : 3 : poll_thread_times(0, 1);
6672 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair != NULL);
6673 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
6674 : :
6675 : 3 : poll_thread_times(1, 1);
6676 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair != NULL);
6677 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair != NULL);
6678 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
6679 : 3 : CU_ASSERT(curr_trid->last_failed_tsc != 0);
6680 : :
6681 : 3 : poll_thread_times(0, 2);
6682 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
6683 : 3 : CU_ASSERT(curr_trid->last_failed_tsc == 0);
6684 : 3 : poll_thread_times(1, 1);
6685 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
6686 : 3 : CU_ASSERT(nvme_ctrlr->pending_failover == false);
6687 : :
6688 : : /* Here is just one poll before _bdev_nvme_reset_complete() is executed.
6689 : : *
6690 : : * spdk_nvme_ctrlr_reconnect_poll_async() returns success before fabric
6691 : : * connect command is executed. If fabric connect command gets timeout,
6692 : : * bdev_nvme_failover_ctrlr() is executed. This should be deferred until
6693 : : * _bdev_nvme_reset_complete() sets ctrlr->resetting to false.
6694 : : *
6695 : : * Simulate fabric connect command timeout by calling bdev_nvme_failover_ctrlr().
6696 : : */
6697 : 3 : rc = bdev_nvme_failover_ctrlr(nvme_ctrlr);
6698 : 3 : CU_ASSERT(rc == -EINPROGRESS);
6699 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
6700 : 3 : CU_ASSERT(nvme_ctrlr->pending_failover == true);
6701 : 3 : CU_ASSERT(curr_trid->last_failed_tsc == 0);
6702 : :
6703 : 3 : poll_thread_times(0, 1);
6704 : :
6705 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
6706 : 3 : CU_ASSERT(nvme_ctrlr->pending_failover == false);
6707 : 3 : CU_ASSERT(curr_trid->last_failed_tsc != 0);
6708 : :
6709 : 3 : poll_threads();
6710 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6711 : 3 : poll_threads();
6712 : :
6713 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
6714 : 3 : CU_ASSERT(nvme_ctrlr->pending_failover == false);
6715 : 3 : CU_ASSERT(curr_trid->last_failed_tsc == 0);
6716 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair != NULL);
6717 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair != NULL);
6718 : :
6719 : 3 : spdk_put_io_channel(ch2);
6720 : :
6721 : 3 : set_thread(0);
6722 : :
6723 : 3 : spdk_put_io_channel(ch1);
6724 : :
6725 : 3 : poll_threads();
6726 : :
6727 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
6728 : 3 : CU_ASSERT(rc == 0);
6729 : :
6730 : 3 : poll_threads();
6731 : 3 : spdk_delay_us(1000);
6732 : 3 : poll_threads();
6733 : :
6734 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
6735 : 3 : }
6736 : : static void
6737 : 15 : ut_ctrlr_op_rpc_cb(void *cb_arg, int rc)
6738 : : {
6739 : 15 : int *_rc = (int *)cb_arg;
6740 : :
6741 [ - + ]: 15 : SPDK_CU_ASSERT_FATAL(_rc != NULL);
6742 : 15 : *_rc = rc;
6743 : 15 : }
6744 : :
6745 : : static void
6746 : 3 : test_ctrlr_op_rpc(void)
6747 : : {
6748 : 3 : struct spdk_nvme_transport_id trid = {};
6749 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
6750 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
6751 : : struct nvme_path_id *curr_trid;
6752 : : struct spdk_io_channel *ch1, *ch2;
6753 : : struct nvme_ctrlr_channel *ctrlr_ch1, *ctrlr_ch2;
6754 : 3 : int ctrlr_op_rc;
6755 : : int rc;
6756 : :
6757 : 3 : ut_init_trid(&trid);
6758 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
6759 : :
6760 : 3 : set_thread(0);
6761 : :
6762 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid, NULL);
6763 : 3 : CU_ASSERT(rc == 0);
6764 : :
6765 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
6766 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
6767 : :
6768 : 3 : curr_trid = TAILQ_FIRST(&nvme_ctrlr->trids);
6769 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_trid != NULL);
6770 : :
6771 : 3 : ch1 = spdk_get_io_channel(nvme_ctrlr);
6772 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
6773 : :
6774 : 3 : ctrlr_ch1 = spdk_io_channel_get_ctx(ch1);
6775 : 3 : CU_ASSERT(ctrlr_ch1->qpair != NULL);
6776 : :
6777 : 3 : set_thread(1);
6778 : :
6779 : 3 : ch2 = spdk_get_io_channel(nvme_ctrlr);
6780 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
6781 : :
6782 : 3 : ctrlr_ch2 = spdk_io_channel_get_ctx(ch2);
6783 : 3 : CU_ASSERT(ctrlr_ch2->qpair != NULL);
6784 : :
6785 : : /* Reset starts from thread 1. */
6786 : 3 : set_thread(1);
6787 : :
6788 : : /* Case 1: ctrlr is already being destructed. */
6789 : 3 : nvme_ctrlr->destruct = true;
6790 : 3 : ctrlr_op_rc = 0;
6791 : :
6792 : 3 : nvme_ctrlr_op_rpc(nvme_ctrlr, NVME_CTRLR_OP_RESET,
6793 : : ut_ctrlr_op_rpc_cb, &ctrlr_op_rc);
6794 : :
6795 : 3 : poll_threads();
6796 : :
6797 : 3 : CU_ASSERT(ctrlr_op_rc == -ENXIO);
6798 : :
6799 : : /* Case 2: reset is in progress. */
6800 : 3 : nvme_ctrlr->destruct = false;
6801 : 3 : nvme_ctrlr->resetting = true;
6802 : 3 : ctrlr_op_rc = 0;
6803 : :
6804 : 3 : nvme_ctrlr_op_rpc(nvme_ctrlr, NVME_CTRLR_OP_RESET,
6805 : : ut_ctrlr_op_rpc_cb, &ctrlr_op_rc);
6806 : :
6807 : 3 : poll_threads();
6808 : :
6809 : 3 : CU_ASSERT(ctrlr_op_rc == -EBUSY);
6810 : :
6811 : : /* Case 3: reset completes successfully. */
6812 : 3 : nvme_ctrlr->resetting = false;
6813 : 3 : curr_trid->last_failed_tsc = spdk_get_ticks();
6814 : 3 : ctrlr.is_failed = true;
6815 : 3 : ctrlr_op_rc = -1;
6816 : :
6817 : 3 : nvme_ctrlr_op_rpc(nvme_ctrlr, NVME_CTRLR_OP_RESET,
6818 : : ut_ctrlr_op_rpc_cb, &ctrlr_op_rc);
6819 : :
6820 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
6821 : 3 : CU_ASSERT(ctrlr_op_rc == -1);
6822 : :
6823 : 3 : poll_threads();
6824 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6825 : 3 : poll_threads();
6826 : :
6827 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
6828 : 3 : CU_ASSERT(curr_trid->last_failed_tsc == 0);
6829 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == false);
6830 : 3 : CU_ASSERT(ctrlr_op_rc == 0);
6831 : :
6832 : : /* Case 4: invalid operation. */
6833 : 3 : nvme_ctrlr_op_rpc(nvme_ctrlr, -1,
6834 : : ut_ctrlr_op_rpc_cb, &ctrlr_op_rc);
6835 : :
6836 : 3 : poll_threads();
6837 : :
6838 : 3 : CU_ASSERT(ctrlr_op_rc == -EINVAL);
6839 : :
6840 : 3 : spdk_put_io_channel(ch2);
6841 : :
6842 : 3 : set_thread(0);
6843 : :
6844 : 3 : spdk_put_io_channel(ch1);
6845 : :
6846 : 3 : poll_threads();
6847 : :
6848 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
6849 : 3 : CU_ASSERT(rc == 0);
6850 : :
6851 : 3 : poll_threads();
6852 : 3 : spdk_delay_us(1000);
6853 : 3 : poll_threads();
6854 : :
6855 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
6856 : 3 : }
6857 : :
6858 : : static void
6859 : 3 : test_bdev_ctrlr_op_rpc(void)
6860 : : {
6861 : 3 : struct spdk_nvme_transport_id trid1 = {}, trid2 = {};
6862 : 3 : struct spdk_nvme_ctrlr ctrlr1 = {}, ctrlr2 = {};
6863 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
6864 : 3 : struct nvme_ctrlr *nvme_ctrlr1 = NULL, *nvme_ctrlr2 = NULL;
6865 : : struct nvme_path_id *curr_trid1, *curr_trid2;
6866 : : struct spdk_io_channel *ch11, *ch12, *ch21, *ch22;
6867 : : struct nvme_ctrlr_channel *ctrlr_ch11, *ctrlr_ch12, *ctrlr_ch21, *ctrlr_ch22;
6868 : 3 : int ctrlr_op_rc;
6869 : : int rc;
6870 : :
6871 : 3 : ut_init_trid(&trid1);
6872 : 3 : ut_init_trid2(&trid2);
6873 : 3 : TAILQ_INIT(&ctrlr1.active_io_qpairs);
6874 : 3 : TAILQ_INIT(&ctrlr2.active_io_qpairs);
6875 : 3 : ctrlr1.cdata.cmic.multi_ctrlr = 1;
6876 : 3 : ctrlr2.cdata.cmic.multi_ctrlr = 1;
6877 : 3 : ctrlr1.cdata.cntlid = 1;
6878 : 3 : ctrlr2.cdata.cntlid = 2;
6879 : 3 : ctrlr1.adminq.is_connected = true;
6880 : 3 : ctrlr2.adminq.is_connected = true;
6881 : :
6882 : 3 : set_thread(0);
6883 : :
6884 : 3 : rc = nvme_ctrlr_create(&ctrlr1, "nvme0", &trid1, NULL);
6885 : 3 : CU_ASSERT(rc == 0);
6886 : :
6887 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
6888 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
6889 : :
6890 : 3 : nvme_ctrlr1 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &trid1);
6891 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr1 != NULL);
6892 : :
6893 : 3 : curr_trid1 = TAILQ_FIRST(&nvme_ctrlr1->trids);
6894 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_trid1 != NULL);
6895 : :
6896 : 3 : ch11 = spdk_get_io_channel(nvme_ctrlr1);
6897 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch11 != NULL);
6898 : :
6899 : 3 : ctrlr_ch11 = spdk_io_channel_get_ctx(ch11);
6900 : 3 : CU_ASSERT(ctrlr_ch11->qpair != NULL);
6901 : :
6902 : 3 : set_thread(1);
6903 : :
6904 : 3 : ch12 = spdk_get_io_channel(nvme_ctrlr1);
6905 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch12 != NULL);
6906 : :
6907 : 3 : ctrlr_ch12 = spdk_io_channel_get_ctx(ch12);
6908 : 3 : CU_ASSERT(ctrlr_ch12->qpair != NULL);
6909 : :
6910 : 3 : set_thread(0);
6911 : :
6912 : 3 : rc = nvme_ctrlr_create(&ctrlr2, "nvme0", &trid2, NULL);
6913 : 3 : CU_ASSERT(rc == 0);
6914 : :
6915 : 3 : nvme_ctrlr2 = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &trid2);
6916 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr2 != NULL);
6917 : :
6918 : 3 : curr_trid2 = TAILQ_FIRST(&nvme_ctrlr2->trids);
6919 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_trid2 != NULL);
6920 : :
6921 : 3 : ch21 = spdk_get_io_channel(nvme_ctrlr2);
6922 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch21 != NULL);
6923 : :
6924 : 3 : ctrlr_ch21 = spdk_io_channel_get_ctx(ch21);
6925 : 3 : CU_ASSERT(ctrlr_ch21->qpair != NULL);
6926 : :
6927 : 3 : set_thread(1);
6928 : :
6929 : 3 : ch22 = spdk_get_io_channel(nvme_ctrlr2);
6930 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch22 != NULL);
6931 : :
6932 : 3 : ctrlr_ch22 = spdk_io_channel_get_ctx(ch22);
6933 : 3 : CU_ASSERT(ctrlr_ch22->qpair != NULL);
6934 : :
6935 : : /* Reset starts from thread 1. */
6936 : 3 : set_thread(1);
6937 : :
6938 : 3 : nvme_ctrlr1->resetting = false;
6939 : 3 : nvme_ctrlr2->resetting = false;
6940 : 3 : curr_trid1->last_failed_tsc = spdk_get_ticks();
6941 : 3 : curr_trid2->last_failed_tsc = spdk_get_ticks();
6942 : 3 : ctrlr_op_rc = -1;
6943 : :
6944 : 3 : nvme_bdev_ctrlr_op_rpc(nbdev_ctrlr, NVME_CTRLR_OP_RESET,
6945 : : ut_ctrlr_op_rpc_cb, &ctrlr_op_rc);
6946 : :
6947 : 3 : CU_ASSERT(nvme_ctrlr1->resetting == true);
6948 : 3 : CU_ASSERT(ctrlr_ch11->qpair != NULL);
6949 : 3 : CU_ASSERT(ctrlr_ch12->qpair != NULL);
6950 : 3 : CU_ASSERT(nvme_ctrlr2->resetting == false);
6951 : :
6952 : 3 : poll_thread_times(0, 3);
6953 : 3 : CU_ASSERT(ctrlr_ch11->qpair->qpair == NULL);
6954 : 3 : CU_ASSERT(ctrlr_ch12->qpair->qpair != NULL);
6955 : :
6956 : 3 : poll_thread_times(0, 1);
6957 : 3 : poll_thread_times(1, 1);
6958 : 3 : CU_ASSERT(ctrlr_ch11->qpair->qpair == NULL);
6959 : 3 : CU_ASSERT(ctrlr_ch12->qpair->qpair == NULL);
6960 : :
6961 : 3 : poll_thread_times(1, 1);
6962 : 3 : poll_thread_times(0, 1);
6963 [ - + ]: 3 : CU_ASSERT(ctrlr1.adminq.is_connected == false);
6964 : :
6965 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6966 : 3 : poll_thread_times(0, 2);
6967 [ - + ]: 3 : CU_ASSERT(ctrlr1.adminq.is_connected == true);
6968 : :
6969 : 3 : poll_thread_times(0, 1);
6970 : 3 : CU_ASSERT(ctrlr_ch11->qpair->qpair != NULL);
6971 : 3 : CU_ASSERT(ctrlr_ch12->qpair->qpair == NULL);
6972 : :
6973 : 3 : poll_thread_times(1, 1);
6974 : 3 : CU_ASSERT(ctrlr_ch11->qpair->qpair != NULL);
6975 : 3 : CU_ASSERT(ctrlr_ch12->qpair->qpair != NULL);
6976 : 3 : CU_ASSERT(nvme_ctrlr1->resetting == true);
6977 : 3 : CU_ASSERT(curr_trid1->last_failed_tsc != 0);
6978 : :
6979 : 3 : poll_thread_times(0, 2);
6980 : 3 : poll_thread_times(1, 1);
6981 : 3 : poll_thread_times(0, 1);
6982 : 3 : poll_thread_times(1, 1);
6983 : 3 : poll_thread_times(0, 1);
6984 : 3 : poll_thread_times(1, 1);
6985 : 3 : poll_thread_times(0, 1);
6986 : :
6987 : 3 : CU_ASSERT(nvme_ctrlr1->resetting == false);
6988 : 3 : CU_ASSERT(curr_trid1->last_failed_tsc == 0);
6989 : 3 : CU_ASSERT(nvme_ctrlr2->resetting == true);
6990 : :
6991 : 3 : poll_threads();
6992 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
6993 : 3 : poll_threads();
6994 : :
6995 : 3 : CU_ASSERT(nvme_ctrlr2->resetting == false);
6996 : 3 : CU_ASSERT(ctrlr_op_rc == 0);
6997 : :
6998 : 3 : set_thread(1);
6999 : :
7000 : 3 : spdk_put_io_channel(ch12);
7001 : 3 : spdk_put_io_channel(ch22);
7002 : :
7003 : 3 : set_thread(0);
7004 : :
7005 : 3 : spdk_put_io_channel(ch11);
7006 : 3 : spdk_put_io_channel(ch21);
7007 : :
7008 : 3 : poll_threads();
7009 : :
7010 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
7011 : 3 : CU_ASSERT(rc == 0);
7012 : :
7013 : 3 : poll_threads();
7014 : 3 : spdk_delay_us(1000);
7015 : 3 : poll_threads();
7016 : :
7017 : 3 : CU_ASSERT(nvme_bdev_ctrlr_get_by_name("nvme0") == NULL);
7018 : 3 : }
7019 : :
7020 : : static void
7021 : 3 : test_disable_enable_ctrlr(void)
7022 : : {
7023 : 3 : struct spdk_nvme_transport_id trid = {};
7024 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
7025 : 3 : struct nvme_ctrlr *nvme_ctrlr = NULL;
7026 : : struct nvme_path_id *curr_trid;
7027 : : struct spdk_io_channel *ch1, *ch2;
7028 : : struct nvme_ctrlr_channel *ctrlr_ch1, *ctrlr_ch2;
7029 : : int rc;
7030 : :
7031 : 3 : ut_init_trid(&trid);
7032 : 3 : TAILQ_INIT(&ctrlr.active_io_qpairs);
7033 : 3 : ctrlr.adminq.is_connected = true;
7034 : :
7035 : 3 : set_thread(0);
7036 : :
7037 : 3 : rc = nvme_ctrlr_create(&ctrlr, "nvme0", &trid, NULL);
7038 : 3 : CU_ASSERT(rc == 0);
7039 : :
7040 : 3 : nvme_ctrlr = nvme_ctrlr_get_by_name("nvme0");
7041 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nvme_ctrlr != NULL);
7042 : :
7043 : 3 : curr_trid = TAILQ_FIRST(&nvme_ctrlr->trids);
7044 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(curr_trid != NULL);
7045 : :
7046 : 3 : ch1 = spdk_get_io_channel(nvme_ctrlr);
7047 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch1 != NULL);
7048 : :
7049 : 3 : ctrlr_ch1 = spdk_io_channel_get_ctx(ch1);
7050 : 3 : CU_ASSERT(ctrlr_ch1->qpair != NULL);
7051 : :
7052 : 3 : set_thread(1);
7053 : :
7054 : 3 : ch2 = spdk_get_io_channel(nvme_ctrlr);
7055 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch2 != NULL);
7056 : :
7057 : 3 : ctrlr_ch2 = spdk_io_channel_get_ctx(ch2);
7058 : 3 : CU_ASSERT(ctrlr_ch2->qpair != NULL);
7059 : :
7060 : : /* Disable starts from thread 1. */
7061 : 3 : set_thread(1);
7062 : :
7063 : : /* Case 1: ctrlr is already disabled. */
7064 : 3 : nvme_ctrlr->disabled = true;
7065 : :
7066 : 3 : rc = bdev_nvme_disable_ctrlr(nvme_ctrlr);
7067 : 3 : CU_ASSERT(rc == -EALREADY);
7068 : :
7069 : : /* Case 2: ctrlr is already being destructed. */
7070 : 3 : nvme_ctrlr->disabled = false;
7071 : 3 : nvme_ctrlr->destruct = true;
7072 : :
7073 : 3 : rc = bdev_nvme_disable_ctrlr(nvme_ctrlr);
7074 : 3 : CU_ASSERT(rc == -ENXIO);
7075 : :
7076 : : /* Case 3: reset is in progress. */
7077 : 3 : nvme_ctrlr->destruct = false;
7078 : 3 : nvme_ctrlr->resetting = true;
7079 : :
7080 : 3 : rc = bdev_nvme_disable_ctrlr(nvme_ctrlr);
7081 : 3 : CU_ASSERT(rc == -EBUSY);
7082 : :
7083 : : /* Case 4: disable completes successfully. */
7084 : 3 : nvme_ctrlr->resetting = false;
7085 : :
7086 : 3 : rc = bdev_nvme_disable_ctrlr(nvme_ctrlr);
7087 : 3 : CU_ASSERT(rc == 0);
7088 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
7089 : 3 : CU_ASSERT(ctrlr_ch1->qpair != NULL);
7090 : 3 : CU_ASSERT(ctrlr_ch2->qpair != NULL);
7091 : :
7092 : 3 : poll_thread_times(0, 3);
7093 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
7094 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair != NULL);
7095 : :
7096 : 3 : poll_thread_times(0, 1);
7097 : 3 : poll_thread_times(1, 1);
7098 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
7099 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
7100 : :
7101 : 3 : poll_thread_times(1, 1);
7102 : 3 : poll_thread_times(0, 1);
7103 [ - + ]: 3 : CU_ASSERT(ctrlr.adminq.is_connected == false);
7104 : 3 : poll_thread_times(1, 1);
7105 : 3 : poll_thread_times(0, 1);
7106 : 3 : poll_thread_times(1, 1);
7107 : 3 : poll_thread_times(0, 1);
7108 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
7109 : 3 : CU_ASSERT(nvme_ctrlr->disabled == true);
7110 : :
7111 : : /* Case 5: enable completes successfully. */
7112 : 3 : rc = bdev_nvme_enable_ctrlr(nvme_ctrlr);
7113 : 3 : CU_ASSERT(rc == 0);
7114 : :
7115 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
7116 : 3 : CU_ASSERT(nvme_ctrlr->disabled == false);
7117 : :
7118 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
7119 : 3 : poll_thread_times(0, 2);
7120 [ - + ]: 3 : CU_ASSERT(ctrlr.adminq.is_connected == true);
7121 : :
7122 : 3 : poll_thread_times(0, 1);
7123 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair != NULL);
7124 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
7125 : :
7126 : 3 : poll_thread_times(1, 1);
7127 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair != NULL);
7128 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair != NULL);
7129 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
7130 : :
7131 : 3 : poll_thread_times(0, 2);
7132 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
7133 : 3 : poll_thread_times(1, 1);
7134 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
7135 : 3 : poll_thread_times(0, 1);
7136 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
7137 : :
7138 : : /* Case 6: ctrlr is already enabled. */
7139 : 3 : rc = bdev_nvme_enable_ctrlr(nvme_ctrlr);
7140 : 3 : CU_ASSERT(rc == -EALREADY);
7141 : :
7142 : 3 : set_thread(0);
7143 : :
7144 : : /* Case 7: disable cancels delayed reconnect. */
7145 : 3 : nvme_ctrlr->opts.reconnect_delay_sec = 10;
7146 : 3 : ctrlr.fail_reset = true;
7147 : :
7148 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
7149 : 3 : CU_ASSERT(rc == 0);
7150 : :
7151 : 3 : poll_threads();
7152 : :
7153 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
7154 [ - + ]: 3 : CU_ASSERT(ctrlr.is_failed == false);
7155 : 3 : CU_ASSERT(ctrlr_ch1->qpair->qpair == NULL);
7156 : 3 : CU_ASSERT(ctrlr_ch2->qpair->qpair == NULL);
7157 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_delay_timer != NULL);
7158 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == true);
7159 : :
7160 : 3 : rc = bdev_nvme_disable_ctrlr(nvme_ctrlr);
7161 : 3 : CU_ASSERT(rc == 0);
7162 : :
7163 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
7164 : 3 : CU_ASSERT(nvme_ctrlr->reconnect_is_delayed == false);
7165 : :
7166 : 3 : poll_threads();
7167 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
7168 : 3 : poll_threads();
7169 : :
7170 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
7171 : 3 : CU_ASSERT(nvme_ctrlr->disabled == true);
7172 : :
7173 : 3 : rc = bdev_nvme_enable_ctrlr(nvme_ctrlr);
7174 : 3 : CU_ASSERT(rc == 0);
7175 : :
7176 : 3 : CU_ASSERT(nvme_ctrlr->resetting == true);
7177 : 3 : CU_ASSERT(nvme_ctrlr->disabled == false);
7178 : :
7179 : 3 : poll_threads();
7180 : :
7181 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
7182 : :
7183 : 3 : set_thread(1);
7184 : :
7185 : 3 : spdk_put_io_channel(ch2);
7186 : :
7187 : 3 : set_thread(0);
7188 : :
7189 : 3 : spdk_put_io_channel(ch1);
7190 : :
7191 : 3 : poll_threads();
7192 : :
7193 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
7194 : 3 : CU_ASSERT(rc == 0);
7195 : :
7196 : 3 : poll_threads();
7197 : 3 : spdk_delay_us(1000);
7198 : 3 : poll_threads();
7199 : :
7200 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
7201 : 3 : }
7202 : :
7203 : : static void
7204 : 3 : ut_delete_done(void *ctx, int rc)
7205 : : {
7206 : 3 : int *delete_done_rc = ctx;
7207 : 3 : *delete_done_rc = rc;
7208 : 3 : }
7209 : :
7210 : : static void
7211 : 3 : test_delete_ctrlr_done(void)
7212 : : {
7213 : 3 : struct spdk_nvme_transport_id trid = {};
7214 : 3 : struct spdk_nvme_ctrlr ctrlr = {};
7215 : 3 : int delete_done_rc = 0xDEADBEEF;
7216 : : int rc;
7217 : :
7218 : 3 : ut_init_trid(&trid);
7219 : :
7220 : 3 : nvme_ctrlr_create(&ctrlr, "nvme0", &trid, NULL);
7221 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") != NULL);
7222 : :
7223 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, ut_delete_done, &delete_done_rc);
7224 : 3 : CU_ASSERT(rc == 0);
7225 : :
7226 [ + - ]: 9 : for (int i = 0; i < 20; i++) {
7227 : 9 : poll_threads();
7228 [ + + ]: 9 : if (delete_done_rc == 0) {
7229 : 3 : break;
7230 : : }
7231 : 6 : spdk_delay_us(1000);
7232 : : }
7233 : :
7234 : 3 : CU_ASSERT(delete_done_rc == 0);
7235 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
7236 : 3 : }
7237 : :
7238 : : static void
7239 : 3 : test_ns_remove_during_reset(void)
7240 : 3 : {
7241 : 3 : struct nvme_path_id path = {};
7242 : 3 : struct nvme_ctrlr_opts opts = {};
7243 : : struct spdk_nvme_ctrlr *ctrlr;
7244 : : struct nvme_bdev_ctrlr *nbdev_ctrlr;
7245 : : struct nvme_ctrlr *nvme_ctrlr;
7246 : 3 : const int STRING_SIZE = 32;
7247 [ - + ]: 3 : const char *attached_names[STRING_SIZE];
7248 : : struct nvme_bdev *bdev;
7249 : : struct nvme_ns *nvme_ns;
7250 : 3 : union spdk_nvme_async_event_completion event = {};
7251 : 3 : struct spdk_nvme_cpl cpl = {};
7252 : : int rc;
7253 : :
7254 [ - + ]: 3 : memset(attached_names, 0, sizeof(char *) * STRING_SIZE);
7255 : 3 : ut_init_trid(&path.trid);
7256 : :
7257 : 3 : set_thread(0);
7258 : :
7259 : 3 : ctrlr = ut_attach_ctrlr(&path.trid, 1, false, false);
7260 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlr != NULL);
7261 : :
7262 : 3 : g_ut_attach_ctrlr_status = 0;
7263 : 3 : g_ut_attach_bdev_count = 1;
7264 : :
7265 : 3 : rc = bdev_nvme_create(&path.trid, "nvme0", attached_names, STRING_SIZE,
7266 : : attach_ctrlr_done, NULL, NULL, &opts, false);
7267 : 3 : CU_ASSERT(rc == 0);
7268 : :
7269 : 3 : spdk_delay_us(1000);
7270 : 3 : poll_threads();
7271 : :
7272 : 3 : nbdev_ctrlr = nvme_bdev_ctrlr_get_by_name("nvme0");
7273 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(nbdev_ctrlr != NULL);
7274 : :
7275 : 3 : nvme_ctrlr = nvme_bdev_ctrlr_get_ctrlr(nbdev_ctrlr, &path.trid);
7276 : 3 : CU_ASSERT(nvme_ctrlr != NULL);
7277 : :
7278 : 3 : bdev = nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1);
7279 : 3 : CU_ASSERT(bdev != NULL);
7280 : :
7281 : 3 : nvme_ns = nvme_ctrlr_get_first_active_ns(nvme_ctrlr);
7282 : 3 : CU_ASSERT(nvme_ns != NULL);
7283 : :
7284 : : /* If ns is removed during ctrlr reset, nvme_ns and bdev should still exist,
7285 : : * but nvme_ns->ns should be NULL.
7286 : : */
7287 : :
7288 [ - + ]: 3 : CU_ASSERT(ctrlr->ns[0].is_active == true);
7289 : 3 : ctrlr->ns[0].is_active = false;
7290 : :
7291 : 3 : rc = bdev_nvme_reset_ctrlr(nvme_ctrlr);
7292 : 3 : CU_ASSERT(rc == 0);
7293 : :
7294 : 3 : poll_threads();
7295 : 3 : spdk_delay_us(g_opts.nvme_adminq_poll_period_us);
7296 : 3 : poll_threads();
7297 : :
7298 : 3 : CU_ASSERT(nvme_ctrlr->resetting == false);
7299 [ - + ]: 3 : CU_ASSERT(ctrlr->adminq.is_connected == true);
7300 : :
7301 : 3 : CU_ASSERT(nvme_ns == nvme_ctrlr_get_first_active_ns(nvme_ctrlr));
7302 : 3 : CU_ASSERT(bdev == nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1));
7303 : 3 : CU_ASSERT(nvme_ns->bdev == bdev);
7304 : 3 : CU_ASSERT(nvme_ns->ns == NULL);
7305 : :
7306 : : /* Then, async event should fill nvme_ns->ns again. */
7307 : :
7308 : 3 : ctrlr->ns[0].is_active = true;
7309 : :
7310 : 3 : event.bits.async_event_type = SPDK_NVME_ASYNC_EVENT_TYPE_NOTICE;
7311 : 3 : event.bits.async_event_info = SPDK_NVME_ASYNC_EVENT_NS_ATTR_CHANGED;
7312 : 3 : cpl.cdw0 = event.raw;
7313 : :
7314 : 3 : aer_cb(nvme_ctrlr, &cpl);
7315 : :
7316 : 3 : CU_ASSERT(nvme_ns == nvme_ctrlr_get_first_active_ns(nvme_ctrlr));
7317 : 3 : CU_ASSERT(bdev == nvme_bdev_ctrlr_get_bdev(nbdev_ctrlr, 1));
7318 : 3 : CU_ASSERT(nvme_ns->bdev == bdev);
7319 : 3 : CU_ASSERT(nvme_ns->ns == &ctrlr->ns[0]);
7320 : :
7321 : 3 : rc = bdev_nvme_delete("nvme0", &g_any_path, NULL, NULL);
7322 : 3 : CU_ASSERT(rc == 0);
7323 : :
7324 : 3 : poll_threads();
7325 : 3 : spdk_delay_us(1000);
7326 : 3 : poll_threads();
7327 : :
7328 : 3 : CU_ASSERT(nvme_ctrlr_get_by_name("nvme0") == NULL);
7329 : 3 : }
7330 : :
7331 : : int
7332 : 3 : main(int argc, char **argv)
7333 : : {
7334 : 3 : CU_pSuite suite = NULL;
7335 : : unsigned int num_failures;
7336 : :
7337 : 3 : CU_initialize_registry();
7338 : :
7339 : 3 : suite = CU_add_suite("nvme", NULL, NULL);
7340 : :
7341 : 3 : CU_ADD_TEST(suite, test_create_ctrlr);
7342 : 3 : CU_ADD_TEST(suite, test_reset_ctrlr);
7343 : 3 : CU_ADD_TEST(suite, test_race_between_reset_and_destruct_ctrlr);
7344 : 3 : CU_ADD_TEST(suite, test_failover_ctrlr);
7345 : 3 : CU_ADD_TEST(suite, test_race_between_failover_and_add_secondary_trid);
7346 : 3 : CU_ADD_TEST(suite, test_pending_reset);
7347 : 3 : CU_ADD_TEST(suite, test_attach_ctrlr);
7348 : 3 : CU_ADD_TEST(suite, test_aer_cb);
7349 : 3 : CU_ADD_TEST(suite, test_submit_nvme_cmd);
7350 : 3 : CU_ADD_TEST(suite, test_add_remove_trid);
7351 : 3 : CU_ADD_TEST(suite, test_abort);
7352 : 3 : CU_ADD_TEST(suite, test_get_io_qpair);
7353 : 3 : CU_ADD_TEST(suite, test_bdev_unregister);
7354 : 3 : CU_ADD_TEST(suite, test_compare_ns);
7355 : 3 : CU_ADD_TEST(suite, test_init_ana_log_page);
7356 : 3 : CU_ADD_TEST(suite, test_get_memory_domains);
7357 : 3 : CU_ADD_TEST(suite, test_reconnect_qpair);
7358 : 3 : CU_ADD_TEST(suite, test_create_bdev_ctrlr);
7359 : 3 : CU_ADD_TEST(suite, test_add_multi_ns_to_bdev);
7360 : 3 : CU_ADD_TEST(suite, test_add_multi_io_paths_to_nbdev_ch);
7361 : 3 : CU_ADD_TEST(suite, test_admin_path);
7362 : 3 : CU_ADD_TEST(suite, test_reset_bdev_ctrlr);
7363 : 3 : CU_ADD_TEST(suite, test_find_io_path);
7364 : 3 : CU_ADD_TEST(suite, test_retry_io_if_ana_state_is_updating);
7365 : 3 : CU_ADD_TEST(suite, test_retry_io_for_io_path_error);
7366 : 3 : CU_ADD_TEST(suite, test_retry_io_count);
7367 : 3 : CU_ADD_TEST(suite, test_concurrent_read_ana_log_page);
7368 : 3 : CU_ADD_TEST(suite, test_retry_io_for_ana_error);
7369 : 3 : CU_ADD_TEST(suite, test_check_io_error_resiliency_params);
7370 : 3 : CU_ADD_TEST(suite, test_retry_io_if_ctrlr_is_resetting);
7371 : 3 : CU_ADD_TEST(suite, test_reconnect_ctrlr);
7372 : 3 : CU_ADD_TEST(suite, test_retry_failover_ctrlr);
7373 : 3 : CU_ADD_TEST(suite, test_fail_path);
7374 : 3 : CU_ADD_TEST(suite, test_nvme_ns_cmp);
7375 : 3 : CU_ADD_TEST(suite, test_ana_transition);
7376 : 3 : CU_ADD_TEST(suite, test_set_preferred_path);
7377 : 3 : CU_ADD_TEST(suite, test_find_next_io_path);
7378 : 3 : CU_ADD_TEST(suite, test_find_io_path_min_qd);
7379 : 3 : CU_ADD_TEST(suite, test_disable_auto_failback);
7380 : 3 : CU_ADD_TEST(suite, test_set_multipath_policy);
7381 : 3 : CU_ADD_TEST(suite, test_uuid_generation);
7382 : 3 : CU_ADD_TEST(suite, test_retry_io_to_same_path);
7383 : 3 : CU_ADD_TEST(suite, test_race_between_reset_and_disconnected);
7384 : 3 : CU_ADD_TEST(suite, test_ctrlr_op_rpc);
7385 : 3 : CU_ADD_TEST(suite, test_bdev_ctrlr_op_rpc);
7386 : 3 : CU_ADD_TEST(suite, test_disable_enable_ctrlr);
7387 : 3 : CU_ADD_TEST(suite, test_delete_ctrlr_done);
7388 : 3 : CU_ADD_TEST(suite, test_ns_remove_during_reset);
7389 : :
7390 : 3 : allocate_threads(3);
7391 : 3 : set_thread(0);
7392 : 3 : bdev_nvme_library_init();
7393 : 3 : init_accel();
7394 : :
7395 : 3 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
7396 : :
7397 : 3 : set_thread(0);
7398 : 3 : bdev_nvme_library_fini();
7399 : 3 : fini_accel();
7400 : 3 : free_threads();
7401 : :
7402 : 3 : CU_cleanup_registry();
7403 : :
7404 : 3 : return num_failures;
7405 : : }
|