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