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