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