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