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