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