Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES.
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include "spdk_internal/cunit.h"
8 : :
9 : : #include "common/lib/ut_multithread.c"
10 : : #include "unit/lib/json_mock.c"
11 : :
12 : : #include "spdk/config.h"
13 : : /* HACK: disable VTune integration so the unit test doesn't need VTune headers and libs to build */
14 : : #undef SPDK_CONFIG_VTUNE
15 : :
16 : : #include "bdev/bdev.c"
17 : :
18 : : #define BDEV_UT_NUM_THREADS 3
19 : :
20 : 340 : DEFINE_STUB(spdk_notify_send, uint64_t, (const char *type, const char *ctx), 0);
21 : 230 : DEFINE_STUB(spdk_notify_type_register, struct spdk_notify_type *, (const char *type), NULL);
22 : 0 : DEFINE_STUB_V(spdk_scsi_nvme_translate, (const struct spdk_bdev_io *bdev_io, int *sc, int *sk,
23 : : int *asc, int *ascq));
24 : 0 : DEFINE_STUB(spdk_memory_domain_get_dma_device_id, const char *, (struct spdk_memory_domain *domain),
25 : : "test_domain");
26 : 0 : DEFINE_STUB(spdk_memory_domain_get_dma_device_type, enum spdk_dma_device_type,
27 : : (struct spdk_memory_domain *domain), 0);
28 : 0 : DEFINE_STUB_V(spdk_accel_sequence_finish,
29 : : (struct spdk_accel_sequence *seq, spdk_accel_completion_cb cb_fn, void *cb_arg));
30 : 0 : DEFINE_STUB_V(spdk_accel_sequence_abort, (struct spdk_accel_sequence *seq));
31 : 0 : DEFINE_STUB_V(spdk_accel_sequence_reverse, (struct spdk_accel_sequence *seq));
32 : 0 : DEFINE_STUB(spdk_accel_append_copy, int,
33 : : (struct spdk_accel_sequence **seq, struct spdk_io_channel *ch, struct iovec *dst_iovs,
34 : : uint32_t dst_iovcnt, struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
35 : : struct iovec *src_iovs, uint32_t src_iovcnt, struct spdk_memory_domain *src_domain,
36 : : void *src_domain_ctx, int flags, spdk_accel_step_cb cb_fn, void *cb_arg), 0);
37 : 0 : DEFINE_STUB(spdk_accel_get_memory_domain, struct spdk_memory_domain *, (void), NULL);
38 : :
39 : : DEFINE_RETURN_MOCK(spdk_memory_domain_pull_data, int);
40 : : int
41 : 0 : spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
42 : : struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, uint32_t dst_iov_cnt,
43 : : spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
44 : : {
45 [ # # # # ]: 0 : HANDLE_RETURN_MOCK(spdk_memory_domain_pull_data);
46 : :
47 : 0 : cpl_cb(cpl_cb_arg, 0);
48 : 0 : return 0;
49 : : }
50 : :
51 : : DEFINE_RETURN_MOCK(spdk_memory_domain_push_data, int);
52 : : int
53 : 0 : spdk_memory_domain_push_data(struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
54 : : struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt,
55 : : spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
56 : : {
57 [ # # # # ]: 0 : HANDLE_RETURN_MOCK(spdk_memory_domain_push_data);
58 : :
59 : 0 : cpl_cb(cpl_cb_arg, 0);
60 : 0 : return 0;
61 : : }
62 : :
63 : : static int g_accel_io_device;
64 : :
65 : : struct spdk_io_channel *
66 : 180 : spdk_accel_get_io_channel(void)
67 : : {
68 : 180 : return spdk_get_io_channel(&g_accel_io_device);
69 : : }
70 : :
71 : : struct ut_bdev {
72 : : struct spdk_bdev bdev;
73 : : void *io_target;
74 : : };
75 : :
76 : : struct ut_bdev_channel {
77 : : TAILQ_HEAD(, spdk_bdev_io) outstanding_io;
78 : : uint32_t outstanding_cnt;
79 : : uint32_t avail_cnt;
80 : : struct spdk_thread *thread;
81 : : TAILQ_ENTRY(ut_bdev_channel) link;
82 : : };
83 : :
84 : : int g_io_device;
85 : : struct ut_bdev g_bdev;
86 : : struct spdk_bdev_desc *g_desc;
87 : : bool g_teardown_done = false;
88 : : bool g_get_io_channel = true;
89 : : bool g_create_ch = true;
90 : : bool g_init_complete_called = false;
91 : : bool g_fini_start_called = true;
92 : : int g_status = 0;
93 : : int g_count = 0;
94 : : struct spdk_histogram_data *g_histogram = NULL;
95 : : TAILQ_HEAD(, ut_bdev_channel) g_ut_channels;
96 : :
97 : : static int
98 : 170 : ut_accel_ch_create_cb(void *io_device, void *ctx)
99 : : {
100 : 170 : return 0;
101 : : }
102 : :
103 : : static void
104 : 170 : ut_accel_ch_destroy_cb(void *io_device, void *ctx)
105 : : {
106 : 170 : }
107 : :
108 : : static int
109 : 180 : stub_create_ch(void *io_device, void *ctx_buf)
110 : : {
111 : 180 : struct ut_bdev_channel *ch = ctx_buf;
112 : :
113 [ + + + + ]: 180 : if (g_create_ch == false) {
114 : 5 : return -1;
115 : : }
116 : :
117 : 175 : TAILQ_INIT(&ch->outstanding_io);
118 : 175 : ch->outstanding_cnt = 0;
119 : : /*
120 : : * When avail gets to 0, the submit_request function will return ENOMEM.
121 : : * Most tests to not want ENOMEM to occur, so by default set this to a
122 : : * big value that won't get hit. The ENOMEM tests can then override this
123 : : * value to something much smaller to induce ENOMEM conditions.
124 : : */
125 : 175 : ch->avail_cnt = 2048;
126 : 175 : ch->thread = spdk_get_thread();
127 : :
128 : 175 : TAILQ_INSERT_TAIL(&g_ut_channels, ch, link);
129 : :
130 : 175 : return 0;
131 : : }
132 : :
133 : : static void
134 : 175 : stub_destroy_ch(void *io_device, void *ctx_buf)
135 : : {
136 : 175 : struct ut_bdev_channel *ch = ctx_buf;
137 : :
138 [ + + ]: 175 : TAILQ_REMOVE(&g_ut_channels, ch, link);
139 : 175 : }
140 : :
141 : : static struct spdk_io_channel *
142 : 190 : stub_get_io_channel(void *ctx)
143 : : {
144 : 190 : struct ut_bdev *ut_bdev = ctx;
145 : :
146 [ + + + + ]: 190 : if (g_get_io_channel == true) {
147 : 185 : return spdk_get_io_channel(ut_bdev->io_target);
148 : : } else {
149 : 5 : return NULL;
150 : : }
151 : : }
152 : :
153 : : static int
154 : 170 : stub_destruct(void *ctx)
155 : : {
156 : 170 : return 0;
157 : : }
158 : :
159 : : static void
160 : 55 : stub_reset_channel(void *ctx)
161 : : {
162 : 55 : struct ut_bdev_channel *ch = ctx;
163 : : struct spdk_bdev_io *io;
164 : :
165 [ + + ]: 155 : while (!TAILQ_EMPTY(&ch->outstanding_io)) {
166 : 100 : io = TAILQ_FIRST(&ch->outstanding_io);
167 [ + + ]: 100 : TAILQ_REMOVE(&ch->outstanding_io, io, module_link);
168 : 100 : ch->outstanding_cnt--;
169 : 100 : spdk_bdev_io_complete(io, SPDK_BDEV_IO_STATUS_ABORTED);
170 : 100 : ch->avail_cnt++;
171 : : }
172 : 55 : }
173 : :
174 : : static void
175 : 710 : stub_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
176 : : {
177 : 710 : struct ut_bdev_channel *ch = spdk_io_channel_get_ctx(_ch), *tmp_ch;
178 : : struct spdk_bdev_io *io;
179 : :
180 [ + + ]: 710 : if (bdev_io->type == SPDK_BDEV_IO_TYPE_RESET) {
181 [ + + ]: 95 : TAILQ_FOREACH(tmp_ch, &g_ut_channels, link) {
182 [ + + ]: 55 : if (spdk_get_thread() == tmp_ch->thread) {
183 : 40 : stub_reset_channel(tmp_ch);
184 : : } else {
185 : 15 : spdk_thread_send_msg(tmp_ch->thread, stub_reset_channel, tmp_ch);
186 : : }
187 : : }
188 [ + + ]: 670 : } else if (bdev_io->type == SPDK_BDEV_IO_TYPE_ABORT) {
189 [ + - ]: 10 : TAILQ_FOREACH(io, &ch->outstanding_io, module_link) {
190 [ + - ]: 10 : if (io == bdev_io->u.abort.bio_to_abort) {
191 [ - + ]: 10 : TAILQ_REMOVE(&ch->outstanding_io, io, module_link);
192 : 10 : ch->outstanding_cnt--;
193 : 10 : spdk_bdev_io_complete(io, SPDK_BDEV_IO_STATUS_ABORTED);
194 : 10 : ch->avail_cnt++;
195 : :
196 : 10 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
197 : 10 : return;
198 : : }
199 : : }
200 : :
201 : 0 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
202 : 0 : return;
203 : : }
204 : :
205 [ + + ]: 700 : if (ch->avail_cnt > 0) {
206 : 675 : TAILQ_INSERT_TAIL(&ch->outstanding_io, bdev_io, module_link);
207 : 675 : ch->outstanding_cnt++;
208 : 675 : ch->avail_cnt--;
209 : : } else {
210 : 25 : spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
211 : : }
212 : : }
213 : :
214 : : static uint32_t
215 : 270 : stub_complete_io(void *io_target, uint32_t num_to_complete)
216 : : {
217 : 270 : struct spdk_io_channel *_ch = spdk_get_io_channel(io_target);
218 : 270 : struct ut_bdev_channel *ch = spdk_io_channel_get_ctx(_ch);
219 : : struct spdk_bdev_io *io;
220 : 270 : bool complete_all = (num_to_complete == 0);
221 : 270 : uint32_t num_completed = 0;
222 : :
223 [ + + + + ]: 835 : while (complete_all || num_completed < num_to_complete) {
224 [ + + ]: 725 : if (TAILQ_EMPTY(&ch->outstanding_io)) {
225 : 160 : break;
226 : : }
227 : 565 : io = TAILQ_FIRST(&ch->outstanding_io);
228 [ + + ]: 565 : TAILQ_REMOVE(&ch->outstanding_io, io, module_link);
229 : 565 : ch->outstanding_cnt--;
230 : 565 : spdk_bdev_io_complete(io, SPDK_BDEV_IO_STATUS_SUCCESS);
231 : 565 : ch->avail_cnt++;
232 : 565 : num_completed++;
233 : : }
234 : 270 : spdk_put_io_channel(_ch);
235 : 270 : return num_completed;
236 : : }
237 : :
238 : : static bool
239 : 350 : stub_io_type_supported(void *ctx, enum spdk_bdev_io_type type)
240 : : {
241 : 350 : return true;
242 : : }
243 : :
244 : : static struct spdk_bdev_fn_table fn_table = {
245 : : .get_io_channel = stub_get_io_channel,
246 : : .destruct = stub_destruct,
247 : : .submit_request = stub_submit_request,
248 : : .io_type_supported = stub_io_type_supported,
249 : : };
250 : :
251 : : struct spdk_bdev_module bdev_ut_if;
252 : :
253 : : static int
254 : 115 : module_init(void)
255 : : {
256 : 115 : spdk_bdev_module_init_done(&bdev_ut_if);
257 : 115 : return 0;
258 : : }
259 : :
260 : : static void
261 : 115 : module_fini(void)
262 : : {
263 : 115 : }
264 : :
265 : : static void
266 : 115 : init_complete(void)
267 : : {
268 : 115 : g_init_complete_called = true;
269 : 115 : }
270 : :
271 : : static void
272 : 115 : fini_start(void)
273 : : {
274 : 115 : g_fini_start_called = true;
275 : 115 : }
276 : :
277 : : struct spdk_bdev_module bdev_ut_if = {
278 : : .name = "bdev_ut",
279 : : .module_init = module_init,
280 : : .module_fini = module_fini,
281 : : .async_init = true,
282 : : .init_complete = init_complete,
283 : : .fini_start = fini_start,
284 : : };
285 : :
286 : 5 : SPDK_BDEV_MODULE_REGISTER(bdev_ut, &bdev_ut_if)
287 : :
288 : : static void
289 : 160 : register_bdev(struct ut_bdev *ut_bdev, char *name, void *io_target)
290 : : {
291 [ - + ]: 160 : memset(ut_bdev, 0, sizeof(*ut_bdev));
292 : :
293 : 160 : ut_bdev->io_target = io_target;
294 : 160 : ut_bdev->bdev.ctxt = ut_bdev;
295 : 160 : ut_bdev->bdev.name = name;
296 : 160 : ut_bdev->bdev.fn_table = &fn_table;
297 : 160 : ut_bdev->bdev.module = &bdev_ut_if;
298 : 160 : ut_bdev->bdev.blocklen = 4096;
299 : 160 : ut_bdev->bdev.blockcnt = 1024;
300 : :
301 : 160 : spdk_bdev_register(&ut_bdev->bdev);
302 : 160 : }
303 : :
304 : : static void
305 : 145 : unregister_bdev(struct ut_bdev *ut_bdev)
306 : : {
307 : : /* Handle any deferred messages. */
308 : 145 : poll_threads();
309 : 145 : spdk_bdev_unregister(&ut_bdev->bdev, NULL, NULL);
310 : : /* Handle the async bdev unregister. */
311 : 145 : poll_threads();
312 : 145 : }
313 : :
314 : : static void
315 : 110 : bdev_init_cb(void *done, int rc)
316 : : {
317 : 110 : CU_ASSERT(rc == 0);
318 : 110 : *(bool *)done = true;
319 : 110 : }
320 : :
321 : : static void
322 : 25 : _bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
323 : : void *event_ctx)
324 : : {
325 [ + + - ]: 25 : switch (type) {
326 : 20 : case SPDK_BDEV_EVENT_REMOVE:
327 [ + + ]: 20 : if (event_ctx != NULL) {
328 : 5 : *(bool *)event_ctx = true;
329 : : }
330 : 20 : break;
331 : 5 : case SPDK_BDEV_EVENT_RESIZE:
332 [ + - ]: 5 : if (event_ctx != NULL) {
333 : 5 : *(int *)event_ctx += 1;
334 : : }
335 : 5 : break;
336 : 0 : default:
337 : 0 : CU_ASSERT(false);
338 : 0 : break;
339 : : }
340 : 25 : }
341 : :
342 : : static void
343 : 110 : setup_test(void)
344 : : {
345 : 110 : bool done = false;
346 : : int rc;
347 : :
348 : 110 : TAILQ_INIT(&g_ut_channels);
349 : :
350 : 110 : allocate_cores(BDEV_UT_NUM_THREADS);
351 : 110 : allocate_threads(BDEV_UT_NUM_THREADS);
352 : 110 : set_thread(0);
353 : :
354 : 110 : rc = spdk_iobuf_initialize();
355 : 110 : CU_ASSERT(rc == 0);
356 : 110 : spdk_bdev_initialize(bdev_init_cb, &done);
357 : 110 : spdk_io_device_register(&g_io_device, stub_create_ch, stub_destroy_ch,
358 : : sizeof(struct ut_bdev_channel), NULL);
359 : 110 : spdk_io_device_register(&g_accel_io_device, ut_accel_ch_create_cb,
360 : : ut_accel_ch_destroy_cb, 0, NULL);
361 : 110 : register_bdev(&g_bdev, "ut_bdev", &g_io_device);
362 : 110 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &g_desc);
363 : 110 : }
364 : :
365 : : static void
366 : 225 : finish_cb(void *cb_arg)
367 : : {
368 : 225 : g_teardown_done = true;
369 : 225 : }
370 : :
371 : : static void
372 : 105 : teardown_test(void)
373 : : {
374 : 105 : set_thread(0);
375 : 105 : g_teardown_done = false;
376 : 105 : spdk_bdev_close(g_desc);
377 : 105 : g_desc = NULL;
378 : 105 : unregister_bdev(&g_bdev);
379 : 105 : spdk_io_device_unregister(&g_io_device, NULL);
380 : 105 : spdk_bdev_finish(finish_cb, NULL);
381 : 105 : spdk_io_device_unregister(&g_accel_io_device, NULL);
382 : 105 : spdk_iobuf_finish(finish_cb, NULL);
383 : 105 : poll_threads();
384 [ - + ]: 105 : memset(&g_bdev, 0, sizeof(g_bdev));
385 [ - + ]: 105 : CU_ASSERT(g_teardown_done == true);
386 : 105 : g_teardown_done = false;
387 : 105 : free_threads();
388 : 105 : free_cores();
389 : 105 : CU_ASSERT(TAILQ_EMPTY(&g_ut_channels))
390 : 105 : }
391 : :
392 : : static uint32_t
393 : 35 : bdev_io_tailq_cnt(bdev_io_tailq_t *tailq)
394 : : {
395 : : struct spdk_bdev_io *io;
396 : 35 : uint32_t cnt = 0;
397 : :
398 [ + + ]: 1250 : TAILQ_FOREACH(io, tailq, internal.link) {
399 : 1215 : cnt++;
400 : : }
401 : :
402 : 35 : return cnt;
403 : : }
404 : :
405 : : static void
406 : 5 : basic(void)
407 : : {
408 : 5 : g_init_complete_called = false;
409 : 5 : setup_test();
410 [ - + ]: 5 : CU_ASSERT(g_init_complete_called == true);
411 : :
412 : 5 : set_thread(0);
413 : :
414 : 5 : g_get_io_channel = false;
415 : 5 : g_ut_threads[0].ch = spdk_bdev_get_io_channel(g_desc);
416 : 5 : CU_ASSERT(g_ut_threads[0].ch == NULL);
417 : :
418 : 5 : g_get_io_channel = true;
419 : 5 : g_create_ch = false;
420 : 5 : g_ut_threads[0].ch = spdk_bdev_get_io_channel(g_desc);
421 : 5 : CU_ASSERT(g_ut_threads[0].ch == NULL);
422 : :
423 : 5 : g_get_io_channel = true;
424 : 5 : g_create_ch = true;
425 : 5 : g_ut_threads[0].ch = spdk_bdev_get_io_channel(g_desc);
426 : 5 : CU_ASSERT(g_ut_threads[0].ch != NULL);
427 : 5 : spdk_put_io_channel(g_ut_threads[0].ch);
428 : :
429 : 5 : g_fini_start_called = false;
430 : 5 : teardown_test();
431 [ - + ]: 5 : CU_ASSERT(g_fini_start_called == true);
432 : 5 : }
433 : :
434 : : static void
435 : 25 : _bdev_unregistered(void *done, int rc)
436 : : {
437 : 25 : CU_ASSERT(rc == 0);
438 : 25 : *(bool *)done = true;
439 : 25 : }
440 : :
441 : : static void
442 : 5 : unregister_and_close(void)
443 : : {
444 : 4 : bool done, remove_notify;
445 : 5 : struct spdk_bdev_desc *desc = NULL;
446 : :
447 : 5 : setup_test();
448 : 5 : set_thread(0);
449 : :
450 : : /* setup_test() automatically opens the bdev,
451 : : * but this test needs to do that in a different
452 : : * way. */
453 : 5 : spdk_bdev_close(g_desc);
454 : 5 : poll_threads();
455 : :
456 : : /* Try hotremoving a bdev with descriptors which don't provide
457 : : * any context to the notification callback */
458 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &desc);
459 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(desc != NULL);
460 : :
461 : : /* There is an open descriptor on the device. Unregister it,
462 : : * which can't proceed until the descriptor is closed. */
463 : 5 : done = false;
464 : 5 : spdk_bdev_unregister(&g_bdev.bdev, _bdev_unregistered, &done);
465 : :
466 : : /* Poll the threads to allow all events to be processed */
467 : 5 : poll_threads();
468 : :
469 : : /* Make sure the bdev was not unregistered. We still have a
470 : : * descriptor open */
471 [ - + ]: 5 : CU_ASSERT(done == false);
472 : :
473 : 5 : spdk_bdev_close(desc);
474 : 5 : poll_threads();
475 : 5 : desc = NULL;
476 : :
477 : : /* The unregister should have completed */
478 [ - + ]: 5 : CU_ASSERT(done == true);
479 : :
480 : :
481 : : /* Register the bdev again */
482 : 5 : register_bdev(&g_bdev, "ut_bdev", &g_io_device);
483 : :
484 : 5 : remove_notify = false;
485 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, &remove_notify, &desc);
486 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(desc != NULL);
487 [ - + ]: 5 : CU_ASSERT(remove_notify == false);
488 : :
489 : : /* There is an open descriptor on the device. Unregister it,
490 : : * which can't proceed until the descriptor is closed. */
491 : 5 : done = false;
492 : 5 : spdk_bdev_unregister(&g_bdev.bdev, _bdev_unregistered, &done);
493 : : /* No polling has occurred, so neither of these should execute */
494 [ - + ]: 5 : CU_ASSERT(remove_notify == false);
495 [ - + ]: 5 : CU_ASSERT(done == false);
496 : :
497 : : /* Prior to the unregister completing, close the descriptor */
498 : 5 : spdk_bdev_close(desc);
499 : :
500 : : /* Poll the threads to allow all events to be processed */
501 : 5 : poll_threads();
502 : :
503 : : /* Remove notify should not have been called because the
504 : : * descriptor is already closed. */
505 [ - + ]: 5 : CU_ASSERT(remove_notify == false);
506 : :
507 : : /* The unregister should have completed */
508 [ - + ]: 5 : CU_ASSERT(done == true);
509 : :
510 : : /* Restore the original g_bdev so that we can use teardown_test(). */
511 : 5 : register_bdev(&g_bdev, "ut_bdev", &g_io_device);
512 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &g_desc);
513 : 5 : teardown_test();
514 : 5 : }
515 : :
516 : : static void
517 : 5 : unregister_and_close_different_threads(void)
518 : : {
519 : 4 : bool done;
520 : 5 : struct spdk_bdev_desc *desc = NULL;
521 : :
522 : 5 : setup_test();
523 : 5 : set_thread(0);
524 : :
525 : : /* setup_test() automatically opens the bdev,
526 : : * but this test needs to do that in a different
527 : : * way. */
528 : 5 : spdk_bdev_close(g_desc);
529 : 5 : poll_threads();
530 : :
531 : 5 : set_thread(1);
532 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &desc);
533 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(desc != NULL);
534 : 5 : done = false;
535 : :
536 : 5 : set_thread(0);
537 : 5 : spdk_bdev_unregister(&g_bdev.bdev, _bdev_unregistered, &done);
538 : :
539 : : /* Poll the threads to allow all events to be processed */
540 : 5 : poll_threads();
541 : :
542 : : /* Make sure the bdev was not unregistered. We still have a
543 : : * descriptor open */
544 [ - + ]: 5 : CU_ASSERT(done == false);
545 : :
546 : : /* Close the descriptor on thread 1. Poll the thread and confirm the
547 : : * unregister did not complete, since it was unregistered on thread 0.
548 : : */
549 : 5 : set_thread(1);
550 : 5 : spdk_bdev_close(desc);
551 : 5 : poll_thread(1);
552 [ - + ]: 5 : CU_ASSERT(done == false);
553 : :
554 : : /* Now poll thread 0 and confirm the unregister completed. */
555 : 5 : set_thread(0);
556 : 5 : poll_thread(0);
557 [ - + ]: 5 : CU_ASSERT(done == true);
558 : :
559 : : /* Restore the original g_bdev so that we can use teardown_test(). */
560 : 5 : register_bdev(&g_bdev, "ut_bdev", &g_io_device);
561 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &g_desc);
562 : 5 : teardown_test();
563 : 5 : }
564 : :
565 : : static void
566 : 10 : reset_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
567 : : {
568 : 10 : bool *done = cb_arg;
569 : :
570 : 10 : CU_ASSERT(success == true);
571 : 10 : *done = true;
572 : 10 : spdk_bdev_free_io(bdev_io);
573 : 10 : }
574 : :
575 : : static void
576 : 5 : put_channel_during_reset(void)
577 : : {
578 : : struct spdk_io_channel *io_ch;
579 : 5 : bool done = false;
580 : :
581 : 5 : setup_test();
582 : :
583 : 5 : set_thread(0);
584 : 5 : io_ch = spdk_bdev_get_io_channel(g_desc);
585 : 5 : CU_ASSERT(io_ch != NULL);
586 : :
587 : : /*
588 : : * Start a reset, but then put the I/O channel before
589 : : * the deferred messages for the reset get a chance to
590 : : * execute.
591 : : */
592 : 5 : spdk_bdev_reset(g_desc, io_ch, reset_done, &done);
593 : 5 : spdk_put_io_channel(io_ch);
594 : 5 : poll_threads();
595 : 5 : stub_complete_io(g_bdev.io_target, 0);
596 : :
597 : 5 : teardown_test();
598 : 5 : }
599 : :
600 : : static void
601 : 20 : aborted_reset_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
602 : : {
603 : 20 : enum spdk_bdev_io_status *status = cb_arg;
604 : :
605 [ + + ]: 20 : *status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
606 : 20 : spdk_bdev_free_io(bdev_io);
607 : 20 : }
608 : :
609 : : static void io_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg);
610 : :
611 : : static void
612 : 5 : aborted_reset(void)
613 : : {
614 : : struct spdk_io_channel *io_ch[2];
615 : 5 : enum spdk_bdev_io_status status1 = SPDK_BDEV_IO_STATUS_PENDING,
616 : 5 : status2 = SPDK_BDEV_IO_STATUS_PENDING;
617 : :
618 : 5 : setup_test();
619 : :
620 : 5 : set_thread(0);
621 : 5 : io_ch[0] = spdk_bdev_get_io_channel(g_desc);
622 : 5 : CU_ASSERT(io_ch[0] != NULL);
623 : 5 : spdk_bdev_reset(g_desc, io_ch[0], aborted_reset_done, &status1);
624 : 5 : poll_threads();
625 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress != NULL);
626 : :
627 : : /*
628 : : * First reset has been submitted on ch0. Now submit a second
629 : : * reset on ch1 which will get queued since there is already a
630 : : * reset in progress.
631 : : */
632 : 5 : set_thread(1);
633 : 5 : io_ch[1] = spdk_bdev_get_io_channel(g_desc);
634 : 5 : CU_ASSERT(io_ch[1] != NULL);
635 : 5 : spdk_bdev_reset(g_desc, io_ch[1], aborted_reset_done, &status2);
636 : 5 : poll_threads();
637 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress != NULL);
638 : :
639 : : /*
640 : : * Now destroy ch1. This will abort the queued reset. Check that
641 : : * the second reset was completed with failed status. Also check
642 : : * that bdev->internal.reset_in_progress != NULL, since the
643 : : * original reset has not been completed yet. This ensures that
644 : : * the bdev code is correctly noticing that the failed reset is
645 : : * *not* the one that had been submitted to the bdev module.
646 : : */
647 : 5 : set_thread(1);
648 : 5 : spdk_put_io_channel(io_ch[1]);
649 : 5 : poll_threads();
650 : 5 : CU_ASSERT(status2 == SPDK_BDEV_IO_STATUS_FAILED);
651 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress != NULL);
652 : :
653 : : /*
654 : : * Now complete the first reset, verify that it completed with SUCCESS
655 : : * status and that bdev->internal.reset_in_progress is also set back to NULL.
656 : : */
657 : 5 : set_thread(0);
658 : 5 : spdk_put_io_channel(io_ch[0]);
659 : 5 : stub_complete_io(g_bdev.io_target, 0);
660 : 5 : poll_threads();
661 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_SUCCESS);
662 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress == NULL);
663 : :
664 : 5 : teardown_test();
665 : 5 : }
666 : :
667 : : static void
668 : 5 : aborted_reset_no_outstanding_io(void)
669 : : {
670 : : struct spdk_io_channel *io_ch[2];
671 : : struct spdk_bdev_channel *bdev_ch[2];
672 : : struct spdk_bdev *bdev[2];
673 : 5 : enum spdk_bdev_io_status status1 = SPDK_BDEV_IO_STATUS_PENDING,
674 : 5 : status2 = SPDK_BDEV_IO_STATUS_PENDING;
675 : :
676 : 5 : setup_test();
677 : :
678 : : /*
679 : : * This time we test the reset without any outstanding IO
680 : : * present on the bdev channel, so both resets should finish
681 : : * immediately.
682 : : */
683 : :
684 : 5 : set_thread(0);
685 : : /* Set reset_io_drain_timeout to allow bdev
686 : : * reset to stay pending until we call abort. */
687 : 5 : io_ch[0] = spdk_bdev_get_io_channel(g_desc);
688 : 5 : bdev_ch[0] = spdk_io_channel_get_ctx(io_ch[0]);
689 : 5 : bdev[0] = bdev_ch[0]->bdev;
690 : 5 : bdev[0]->reset_io_drain_timeout = SPDK_BDEV_RESET_IO_DRAIN_RECOMMENDED_VALUE;
691 : 5 : CU_ASSERT(io_ch[0] != NULL);
692 : 5 : spdk_bdev_reset(g_desc, io_ch[0], aborted_reset_done, &status1);
693 : 5 : poll_threads();
694 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress == NULL);
695 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_SUCCESS);
696 : 5 : spdk_put_io_channel(io_ch[0]);
697 : :
698 : 5 : set_thread(1);
699 : : /* Set reset_io_drain_timeout to allow bdev
700 : : * reset to stay pending until we call abort. */
701 : 5 : io_ch[1] = spdk_bdev_get_io_channel(g_desc);
702 : 5 : bdev_ch[1] = spdk_io_channel_get_ctx(io_ch[1]);
703 : 5 : bdev[1] = bdev_ch[1]->bdev;
704 : 5 : bdev[1]->reset_io_drain_timeout = SPDK_BDEV_RESET_IO_DRAIN_RECOMMENDED_VALUE;
705 : 5 : CU_ASSERT(io_ch[1] != NULL);
706 : 5 : spdk_bdev_reset(g_desc, io_ch[1], aborted_reset_done, &status2);
707 : 5 : poll_threads();
708 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress == NULL);
709 : 5 : CU_ASSERT(status2 == SPDK_BDEV_IO_STATUS_SUCCESS);
710 : 5 : spdk_put_io_channel(io_ch[1]);
711 : :
712 : 5 : stub_complete_io(g_bdev.io_target, 0);
713 : 5 : poll_threads();
714 : :
715 : 5 : teardown_test();
716 : 5 : }
717 : :
718 : :
719 : : static void
720 : 185 : io_during_io_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
721 : : {
722 : 185 : enum spdk_bdev_io_status *status = cb_arg;
723 : :
724 : 185 : *status = bdev_io->internal.status;
725 : 185 : spdk_bdev_free_io(bdev_io);
726 : 185 : }
727 : :
728 : : static void
729 : 5 : io_during_reset(void)
730 : : {
731 : : struct spdk_io_channel *io_ch[2];
732 : : struct spdk_bdev_channel *bdev_ch[2];
733 : 4 : enum spdk_bdev_io_status status0, status1, status_reset;
734 : : int rc;
735 : :
736 : 5 : setup_test();
737 : :
738 : : /*
739 : : * First test normal case - submit an I/O on each of two channels (with no resets)
740 : : * and verify they complete successfully.
741 : : */
742 : 5 : set_thread(0);
743 : 5 : io_ch[0] = spdk_bdev_get_io_channel(g_desc);
744 : 5 : bdev_ch[0] = spdk_io_channel_get_ctx(io_ch[0]);
745 : 5 : CU_ASSERT(bdev_ch[0]->flags == 0);
746 : 5 : status0 = SPDK_BDEV_IO_STATUS_PENDING;
747 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[0], NULL, 0, 1, io_during_io_done, &status0);
748 : 5 : CU_ASSERT(rc == 0);
749 : :
750 : 5 : set_thread(1);
751 : 5 : io_ch[1] = spdk_bdev_get_io_channel(g_desc);
752 : 5 : bdev_ch[1] = spdk_io_channel_get_ctx(io_ch[1]);
753 : 5 : CU_ASSERT(bdev_ch[1]->flags == 0);
754 : 5 : status1 = SPDK_BDEV_IO_STATUS_PENDING;
755 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[1], NULL, 0, 1, io_during_io_done, &status1);
756 : 5 : CU_ASSERT(rc == 0);
757 : :
758 : 5 : poll_threads();
759 : 5 : CU_ASSERT(status0 == SPDK_BDEV_IO_STATUS_PENDING);
760 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_PENDING);
761 : :
762 : 5 : set_thread(0);
763 : 5 : stub_complete_io(g_bdev.io_target, 0);
764 : 5 : CU_ASSERT(status0 == SPDK_BDEV_IO_STATUS_SUCCESS);
765 : :
766 : 5 : set_thread(1);
767 : 5 : stub_complete_io(g_bdev.io_target, 0);
768 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_SUCCESS);
769 : :
770 : : /*
771 : : * Now submit a reset, and leave it pending while we submit I/O on two different
772 : : * channels. These I/O should be failed by the bdev layer since the reset is in
773 : : * progress.
774 : : */
775 : 5 : set_thread(0);
776 : 5 : status_reset = SPDK_BDEV_IO_STATUS_PENDING;
777 : 5 : rc = spdk_bdev_reset(g_desc, io_ch[0], io_during_io_done, &status_reset);
778 : 5 : CU_ASSERT(rc == 0);
779 : :
780 : 5 : CU_ASSERT(bdev_ch[0]->flags == 0);
781 : 5 : CU_ASSERT(bdev_ch[1]->flags == 0);
782 : 5 : poll_threads();
783 : 5 : CU_ASSERT(bdev_ch[0]->flags == BDEV_CH_RESET_IN_PROGRESS);
784 : 5 : CU_ASSERT(bdev_ch[1]->flags == BDEV_CH_RESET_IN_PROGRESS);
785 : :
786 : 5 : set_thread(0);
787 : 5 : status0 = SPDK_BDEV_IO_STATUS_PENDING;
788 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[0], NULL, 0, 1, io_during_io_done, &status0);
789 : 5 : CU_ASSERT(rc == 0);
790 : :
791 : 5 : set_thread(1);
792 : 5 : status1 = SPDK_BDEV_IO_STATUS_PENDING;
793 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[1], NULL, 0, 1, io_during_io_done, &status1);
794 : 5 : CU_ASSERT(rc == 0);
795 : :
796 : : /*
797 : : * A reset is in progress so these read I/O should complete with aborted. Note that we
798 : : * need to poll_threads() since I/O completed inline have their completion deferred.
799 : : */
800 : 5 : poll_threads();
801 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_PENDING);
802 : 5 : CU_ASSERT(status0 == SPDK_BDEV_IO_STATUS_ABORTED);
803 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_ABORTED);
804 : :
805 : : /*
806 : : * Complete the reset
807 : : */
808 : 5 : set_thread(0);
809 : 5 : stub_complete_io(g_bdev.io_target, 0);
810 : :
811 : : /*
812 : : * Only poll thread 0. We should not get a completion.
813 : : */
814 : 5 : poll_thread(0);
815 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_PENDING);
816 : :
817 : : /*
818 : : * Poll both thread 0 and 1 so the messages can propagate and we
819 : : * get a completion.
820 : : */
821 : 5 : poll_threads();
822 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_SUCCESS);
823 : :
824 : 5 : spdk_put_io_channel(io_ch[0]);
825 : 5 : set_thread(1);
826 : 5 : spdk_put_io_channel(io_ch[1]);
827 : 5 : poll_threads();
828 : :
829 : 5 : teardown_test();
830 : 5 : }
831 : :
832 : : static uint32_t
833 : 70 : count_queued_resets(void *io_target)
834 : : {
835 : 70 : struct spdk_io_channel *_ch = spdk_get_io_channel(io_target);
836 : 70 : struct ut_bdev_channel *ch = spdk_io_channel_get_ctx(_ch);
837 : : struct spdk_bdev_io *io;
838 : 70 : uint32_t submitted_resets = 0;
839 : :
840 [ + + ]: 125 : TAILQ_FOREACH(io, &ch->outstanding_io, module_link) {
841 [ + + ]: 55 : if (io->type == SPDK_BDEV_IO_TYPE_RESET) {
842 : 10 : submitted_resets++;
843 : : }
844 : : }
845 : :
846 : 70 : spdk_put_io_channel(_ch);
847 : :
848 : 70 : return submitted_resets;
849 : : }
850 : :
851 : : static void
852 : 5 : reset_completions(void)
853 : : {
854 : : struct spdk_io_channel *io_ch;
855 : : struct spdk_bdev_channel *bdev_ch;
856 : : struct spdk_bdev *bdev;
857 : 4 : enum spdk_bdev_io_status status0, status_reset;
858 : : int rc, iter;
859 : :
860 : 5 : setup_test();
861 : :
862 : : /* This test covers four test cases:
863 : : * 1) reset_io_drain_timeout of a bdev is greater than 0
864 : : * 2) No outstandind IO are present on any bdev channel
865 : : * 3) Outstanding IO finish during bdev reset
866 : : * 4) Outstanding IO do not finish before reset is done waiting
867 : : * for them.
868 : : *
869 : : * Above conditions mainly affect the timing of bdev reset completion
870 : : * and whether a reset should be skipped via spdk_bdev_io_complete()
871 : : * or sent down to the underlying bdev module via bdev_io_submit_reset(). */
872 : :
873 : : /* Test preparation */
874 : 5 : set_thread(0);
875 : 5 : io_ch = spdk_bdev_get_io_channel(g_desc);
876 : 5 : bdev_ch = spdk_io_channel_get_ctx(io_ch);
877 : 5 : CU_ASSERT(bdev_ch->flags == 0);
878 : :
879 : :
880 : : /* Test case 1) reset_io_drain_timeout set to 0. Reset should be sent down immediately. */
881 : 5 : bdev = &g_bdev.bdev;
882 : 5 : bdev->reset_io_drain_timeout = 0;
883 : :
884 : 5 : status_reset = SPDK_BDEV_IO_STATUS_PENDING;
885 : 5 : rc = spdk_bdev_reset(g_desc, io_ch, io_during_io_done, &status_reset);
886 : 5 : CU_ASSERT(rc == 0);
887 : 5 : poll_threads();
888 : 5 : CU_ASSERT(count_queued_resets(g_bdev.io_target) == 1);
889 : :
890 : : /* Call reset completion inside bdev module. */
891 : 5 : stub_complete_io(g_bdev.io_target, 0);
892 : 5 : poll_threads();
893 : 5 : CU_ASSERT(count_queued_resets(g_bdev.io_target) == 0);
894 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_SUCCESS);
895 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress == NULL);
896 : :
897 : :
898 : : /* Test case 2) no outstanding IO are present. Reset should perform one iteration over
899 : : * channels and then be skipped. */
900 : 5 : bdev->reset_io_drain_timeout = SPDK_BDEV_RESET_IO_DRAIN_RECOMMENDED_VALUE;
901 : 5 : status_reset = SPDK_BDEV_IO_STATUS_PENDING;
902 : :
903 : 5 : rc = spdk_bdev_reset(g_desc, io_ch, io_during_io_done, &status_reset);
904 : 5 : CU_ASSERT(rc == 0);
905 : 5 : poll_threads();
906 : : /* Reset was never submitted to the bdev module. */
907 : 5 : CU_ASSERT(count_queued_resets(g_bdev.io_target) == 0);
908 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_SUCCESS);
909 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress == NULL);
910 : :
911 : :
912 : : /* Test case 3) outstanding IO finish during bdev reset procedure. Reset should initiate
913 : : * wait poller to check for IO completions every second, until reset_io_drain_timeout is
914 : : * reached, but finish earlier than this threshold. */
915 : 5 : status0 = SPDK_BDEV_IO_STATUS_PENDING;
916 : 5 : status_reset = SPDK_BDEV_IO_STATUS_PENDING;
917 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, io_during_io_done, &status0);
918 : 5 : CU_ASSERT(rc == 0);
919 : :
920 : 5 : rc = spdk_bdev_reset(g_desc, io_ch, io_during_io_done, &status_reset);
921 : 5 : CU_ASSERT(rc == 0);
922 : 5 : poll_threads();
923 : : /* The reset just started and should not have been submitted yet. */
924 : 5 : CU_ASSERT(count_queued_resets(g_bdev.io_target) == 0);
925 : :
926 : 5 : poll_threads();
927 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_PENDING);
928 : : /* Let the poller wait for about half the time then complete outstanding IO. */
929 [ + + ]: 15 : for (iter = 0; iter < 2; iter++) {
930 : : /* Reset is still processing and not submitted at this point. */
931 : 10 : CU_ASSERT(count_queued_resets(g_bdev.io_target) == 0);
932 : 10 : spdk_delay_us(1000 * 1000);
933 : 10 : poll_threads();
934 : 10 : poll_threads();
935 : : }
936 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_PENDING);
937 : 5 : stub_complete_io(g_bdev.io_target, 0);
938 : 5 : poll_threads();
939 : 5 : spdk_delay_us(BDEV_RESET_CHECK_OUTSTANDING_IO_PERIOD);
940 : 5 : poll_threads();
941 : 5 : poll_threads();
942 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_SUCCESS);
943 : : /* Sending reset to the bdev module has been skipped. */
944 : 5 : CU_ASSERT(count_queued_resets(g_bdev.io_target) == 0);
945 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress == NULL);
946 : :
947 : :
948 : : /* Test case 4) outstanding IO are still present after reset_io_drain_timeout
949 : : * seconds have passed. */
950 : 5 : status0 = SPDK_BDEV_IO_STATUS_PENDING;
951 : 5 : status_reset = SPDK_BDEV_IO_STATUS_PENDING;
952 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, io_during_io_done, &status0);
953 : 5 : CU_ASSERT(rc == 0);
954 : :
955 : 5 : rc = spdk_bdev_reset(g_desc, io_ch, io_during_io_done, &status_reset);
956 : 5 : CU_ASSERT(rc == 0);
957 : 5 : poll_threads();
958 : : /* The reset just started and should not have been submitted yet. */
959 : 5 : CU_ASSERT(count_queued_resets(g_bdev.io_target) == 0);
960 : :
961 : 5 : poll_threads();
962 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_PENDING);
963 : : /* Let the poller wait for reset_io_drain_timeout seconds. */
964 [ + + ]: 30 : for (iter = 0; iter < bdev->reset_io_drain_timeout; iter++) {
965 : 25 : CU_ASSERT(count_queued_resets(g_bdev.io_target) == 0);
966 : 25 : spdk_delay_us(BDEV_RESET_CHECK_OUTSTANDING_IO_PERIOD);
967 : 25 : poll_threads();
968 : 25 : poll_threads();
969 : : }
970 : :
971 : : /* After timing out, the reset should have been sent to the module. */
972 : 5 : CU_ASSERT(count_queued_resets(g_bdev.io_target) == 1);
973 : : /* Complete reset submitted to the module and the read IO. */
974 : 5 : stub_complete_io(g_bdev.io_target, 0);
975 : 5 : poll_threads();
976 : 5 : CU_ASSERT(status_reset == SPDK_BDEV_IO_STATUS_SUCCESS);
977 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress == NULL);
978 : :
979 : :
980 : : /* Destroy the channel and end the test. */
981 : 5 : spdk_put_io_channel(io_ch);
982 : 5 : poll_threads();
983 : :
984 : 5 : teardown_test();
985 : 5 : }
986 : :
987 : :
988 : : static void
989 : 5 : basic_qos(void)
990 : : {
991 : : struct spdk_io_channel *io_ch[2];
992 : : struct spdk_bdev_channel *bdev_ch[2];
993 : : struct spdk_bdev *bdev;
994 : 4 : enum spdk_bdev_io_status status, abort_status;
995 : : int rc;
996 : :
997 : 5 : setup_test();
998 : :
999 : : /* Enable QoS */
1000 : 5 : bdev = &g_bdev.bdev;
1001 : 5 : bdev->internal.qos = calloc(1, sizeof(*bdev->internal.qos));
1002 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(bdev->internal.qos != NULL);
1003 : : /*
1004 : : * Enable read/write IOPS, read only byte per second and
1005 : : * read/write byte per second rate limits.
1006 : : * In this case, all rate limits will take equal effect.
1007 : : */
1008 : : /* 2000 read/write I/O per second, or 2 per millisecond */
1009 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT].limit = 2000;
1010 : : /* 8K read/write byte per millisecond with 4K block size */
1011 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT].limit = 8192000;
1012 : : /* 8K read only byte per millisecond with 4K block size */
1013 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT].limit = 8192000;
1014 : :
1015 : 5 : g_get_io_channel = true;
1016 : :
1017 : 5 : set_thread(0);
1018 : 5 : io_ch[0] = spdk_bdev_get_io_channel(g_desc);
1019 : 5 : bdev_ch[0] = spdk_io_channel_get_ctx(io_ch[0]);
1020 : 5 : CU_ASSERT(bdev_ch[0]->flags == BDEV_CH_QOS_ENABLED);
1021 : :
1022 : 5 : set_thread(1);
1023 : 5 : io_ch[1] = spdk_bdev_get_io_channel(g_desc);
1024 : 5 : bdev_ch[1] = spdk_io_channel_get_ctx(io_ch[1]);
1025 : 5 : CU_ASSERT(bdev_ch[1]->flags == BDEV_CH_QOS_ENABLED);
1026 : :
1027 : : /*
1028 : : * Send an I/O on thread 0, which is where the QoS thread is running.
1029 : : */
1030 : 5 : set_thread(0);
1031 : 5 : status = SPDK_BDEV_IO_STATUS_PENDING;
1032 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[0], NULL, 0, 1, io_during_io_done, &status);
1033 : 5 : CU_ASSERT(rc == 0);
1034 : 5 : CU_ASSERT(status == SPDK_BDEV_IO_STATUS_PENDING);
1035 : 5 : poll_threads();
1036 : 5 : stub_complete_io(g_bdev.io_target, 0);
1037 : 5 : poll_threads();
1038 : 5 : CU_ASSERT(status == SPDK_BDEV_IO_STATUS_SUCCESS);
1039 : :
1040 : : /* Send an I/O on thread 1. The QoS thread is not running here. */
1041 : 5 : status = SPDK_BDEV_IO_STATUS_PENDING;
1042 : 5 : set_thread(1);
1043 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[1], NULL, 0, 1, io_during_io_done, &status);
1044 : 5 : CU_ASSERT(rc == 0);
1045 : 5 : CU_ASSERT(status == SPDK_BDEV_IO_STATUS_PENDING);
1046 : 5 : poll_threads();
1047 : : /* Complete I/O on thread 0. This should not complete the I/O we submitted. */
1048 : 5 : set_thread(0);
1049 : 5 : stub_complete_io(g_bdev.io_target, 0);
1050 : 5 : poll_threads();
1051 : 5 : CU_ASSERT(status == SPDK_BDEV_IO_STATUS_PENDING);
1052 : : /* Now complete I/O on original thread 1. */
1053 : 5 : set_thread(1);
1054 : 5 : poll_threads();
1055 : 5 : stub_complete_io(g_bdev.io_target, 0);
1056 : 5 : poll_threads();
1057 : 5 : CU_ASSERT(status == SPDK_BDEV_IO_STATUS_SUCCESS);
1058 : :
1059 : : /* Reset rate limit for the next test cases. */
1060 : 5 : spdk_delay_us(SPDK_BDEV_QOS_TIMESLICE_IN_USEC);
1061 : 5 : poll_threads();
1062 : :
1063 : : /*
1064 : : * Test abort request when QoS is enabled.
1065 : : */
1066 : :
1067 : : /* Send an I/O on thread 0, which is where the QoS thread is running. */
1068 : 5 : set_thread(0);
1069 : 5 : status = SPDK_BDEV_IO_STATUS_PENDING;
1070 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[0], NULL, 0, 1, io_during_io_done, &status);
1071 : 5 : CU_ASSERT(rc == 0);
1072 : 5 : CU_ASSERT(status == SPDK_BDEV_IO_STATUS_PENDING);
1073 : : /* Send an abort to the I/O on the same thread. */
1074 : 5 : abort_status = SPDK_BDEV_IO_STATUS_PENDING;
1075 : 5 : rc = spdk_bdev_abort(g_desc, io_ch[0], &status, io_during_io_done, &abort_status);
1076 : 5 : CU_ASSERT(rc == 0);
1077 : 5 : CU_ASSERT(abort_status == SPDK_BDEV_IO_STATUS_PENDING);
1078 : 5 : poll_threads();
1079 : 5 : CU_ASSERT(abort_status == SPDK_BDEV_IO_STATUS_SUCCESS);
1080 : 5 : CU_ASSERT(status == SPDK_BDEV_IO_STATUS_ABORTED);
1081 : :
1082 : : /* Send an I/O on thread 1. The QoS thread is not running here. */
1083 : 5 : status = SPDK_BDEV_IO_STATUS_PENDING;
1084 : 5 : set_thread(1);
1085 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[1], NULL, 0, 1, io_during_io_done, &status);
1086 : 5 : CU_ASSERT(rc == 0);
1087 : 5 : CU_ASSERT(status == SPDK_BDEV_IO_STATUS_PENDING);
1088 : 5 : poll_threads();
1089 : : /* Send an abort to the I/O on the same thread. */
1090 : 5 : abort_status = SPDK_BDEV_IO_STATUS_PENDING;
1091 : 5 : rc = spdk_bdev_abort(g_desc, io_ch[1], &status, io_during_io_done, &abort_status);
1092 : 5 : CU_ASSERT(rc == 0);
1093 : 5 : CU_ASSERT(abort_status == SPDK_BDEV_IO_STATUS_PENDING);
1094 : 5 : poll_threads();
1095 : : /* Complete the I/O with failure and the abort with success on thread 1. */
1096 : 5 : CU_ASSERT(abort_status == SPDK_BDEV_IO_STATUS_SUCCESS);
1097 : 5 : CU_ASSERT(status == SPDK_BDEV_IO_STATUS_ABORTED);
1098 : :
1099 : 5 : set_thread(0);
1100 : :
1101 : : /*
1102 : : * Close the descriptor only, which should stop the qos channel as
1103 : : * the last descriptor removed.
1104 : : */
1105 : 5 : spdk_bdev_close(g_desc);
1106 : 5 : poll_threads();
1107 : 5 : CU_ASSERT(bdev->internal.qos->ch == NULL);
1108 : :
1109 : : /*
1110 : : * Open the bdev again which shall setup the qos channel as the
1111 : : * channels are valid.
1112 : : */
1113 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &g_desc);
1114 : 5 : poll_threads();
1115 : 5 : CU_ASSERT(bdev->internal.qos->ch != NULL);
1116 : :
1117 : : /* Tear down the channels */
1118 : 5 : set_thread(0);
1119 : 5 : spdk_put_io_channel(io_ch[0]);
1120 : 5 : set_thread(1);
1121 : 5 : spdk_put_io_channel(io_ch[1]);
1122 : 5 : poll_threads();
1123 : 5 : set_thread(0);
1124 : :
1125 : : /* Close the descriptor, which should stop the qos channel */
1126 : 5 : spdk_bdev_close(g_desc);
1127 : 5 : poll_threads();
1128 : 5 : CU_ASSERT(bdev->internal.qos->ch == NULL);
1129 : :
1130 : : /* Open the bdev again, no qos channel setup without valid channels. */
1131 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &g_desc);
1132 : 5 : poll_threads();
1133 : 5 : CU_ASSERT(bdev->internal.qos->ch == NULL);
1134 : :
1135 : : /* Create the channels in reverse order. */
1136 : 5 : set_thread(1);
1137 : 5 : io_ch[1] = spdk_bdev_get_io_channel(g_desc);
1138 : 5 : bdev_ch[1] = spdk_io_channel_get_ctx(io_ch[1]);
1139 : 5 : CU_ASSERT(bdev_ch[1]->flags == BDEV_CH_QOS_ENABLED);
1140 : :
1141 : 5 : set_thread(0);
1142 : 5 : io_ch[0] = spdk_bdev_get_io_channel(g_desc);
1143 : 5 : bdev_ch[0] = spdk_io_channel_get_ctx(io_ch[0]);
1144 : 5 : CU_ASSERT(bdev_ch[0]->flags == BDEV_CH_QOS_ENABLED);
1145 : :
1146 : : /* Confirm that the qos thread is now thread 1 */
1147 : 5 : CU_ASSERT(bdev->internal.qos->ch == bdev_ch[1]);
1148 : :
1149 : : /* Tear down the channels */
1150 : 5 : set_thread(0);
1151 : 5 : spdk_put_io_channel(io_ch[0]);
1152 : 5 : set_thread(1);
1153 : 5 : spdk_put_io_channel(io_ch[1]);
1154 : 5 : poll_threads();
1155 : :
1156 : 5 : set_thread(0);
1157 : :
1158 : 5 : teardown_test();
1159 : 5 : }
1160 : :
1161 : : static void
1162 : 5 : io_during_qos_queue(void)
1163 : : {
1164 : : struct spdk_io_channel *io_ch[2];
1165 : : struct spdk_bdev_channel *bdev_ch[2];
1166 : : struct spdk_bdev *bdev;
1167 : 4 : enum spdk_bdev_io_status status0, status1, status2;
1168 : : int rc;
1169 : :
1170 : 5 : setup_test();
1171 : 5 : MOCK_SET(spdk_get_ticks, 0);
1172 : :
1173 : : /* Enable QoS */
1174 : 5 : bdev = &g_bdev.bdev;
1175 : 5 : bdev->internal.qos = calloc(1, sizeof(*bdev->internal.qos));
1176 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(bdev->internal.qos != NULL);
1177 : :
1178 : : /*
1179 : : * Enable read/write IOPS, read only byte per sec, write only
1180 : : * byte per sec and read/write byte per sec rate limits.
1181 : : * In this case, both read only and write only byte per sec
1182 : : * rate limit will take effect.
1183 : : */
1184 : : /* 4000 read/write I/O per second, or 4 per millisecond */
1185 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT].limit = 4000;
1186 : : /* 8K byte per millisecond with 4K block size */
1187 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT].limit = 8192000;
1188 : : /* 4K byte per millisecond with 4K block size */
1189 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT].limit = 4096000;
1190 : : /* 4K byte per millisecond with 4K block size */
1191 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT].limit = 4096000;
1192 : :
1193 : 5 : g_get_io_channel = true;
1194 : :
1195 : : /* Create channels */
1196 : 5 : set_thread(0);
1197 : 5 : io_ch[0] = spdk_bdev_get_io_channel(g_desc);
1198 : 5 : bdev_ch[0] = spdk_io_channel_get_ctx(io_ch[0]);
1199 : 5 : CU_ASSERT(bdev_ch[0]->flags == BDEV_CH_QOS_ENABLED);
1200 : :
1201 : 5 : set_thread(1);
1202 : 5 : io_ch[1] = spdk_bdev_get_io_channel(g_desc);
1203 : 5 : bdev_ch[1] = spdk_io_channel_get_ctx(io_ch[1]);
1204 : 5 : CU_ASSERT(bdev_ch[1]->flags == BDEV_CH_QOS_ENABLED);
1205 : :
1206 : : /* Send two read I/Os */
1207 : 5 : status1 = SPDK_BDEV_IO_STATUS_PENDING;
1208 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[1], NULL, 0, 1, io_during_io_done, &status1);
1209 : 5 : CU_ASSERT(rc == 0);
1210 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_PENDING);
1211 : 5 : set_thread(0);
1212 : 5 : status0 = SPDK_BDEV_IO_STATUS_PENDING;
1213 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[0], NULL, 0, 1, io_during_io_done, &status0);
1214 : 5 : CU_ASSERT(rc == 0);
1215 : 5 : CU_ASSERT(status0 == SPDK_BDEV_IO_STATUS_PENDING);
1216 : : /* Send one write I/O */
1217 : 5 : status2 = SPDK_BDEV_IO_STATUS_PENDING;
1218 : 5 : rc = spdk_bdev_write_blocks(g_desc, io_ch[0], NULL, 0, 1, io_during_io_done, &status2);
1219 : 5 : CU_ASSERT(rc == 0);
1220 : 5 : CU_ASSERT(status2 == SPDK_BDEV_IO_STATUS_PENDING);
1221 : :
1222 : : /* Complete any I/O that arrived at the disk */
1223 : 5 : poll_threads();
1224 : 5 : set_thread(1);
1225 : 5 : stub_complete_io(g_bdev.io_target, 0);
1226 : 5 : set_thread(0);
1227 : 5 : stub_complete_io(g_bdev.io_target, 0);
1228 : 5 : poll_threads();
1229 : :
1230 : : /* Only one of the two read I/Os should complete. (logical XOR) */
1231 [ - + ]: 5 : if (status0 == SPDK_BDEV_IO_STATUS_SUCCESS) {
1232 : 0 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_PENDING);
1233 : : } else {
1234 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_SUCCESS);
1235 : : }
1236 : : /* The write I/O should complete. */
1237 : 5 : CU_ASSERT(status2 == SPDK_BDEV_IO_STATUS_SUCCESS);
1238 : :
1239 : : /* Advance in time by a millisecond */
1240 : 5 : spdk_delay_us(1000);
1241 : :
1242 : : /* Complete more I/O */
1243 : 5 : poll_threads();
1244 : 5 : set_thread(1);
1245 : 5 : stub_complete_io(g_bdev.io_target, 0);
1246 : 5 : set_thread(0);
1247 : 5 : stub_complete_io(g_bdev.io_target, 0);
1248 : 5 : poll_threads();
1249 : :
1250 : : /* Now the second read I/O should be done */
1251 : 5 : CU_ASSERT(status0 == SPDK_BDEV_IO_STATUS_SUCCESS);
1252 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_SUCCESS);
1253 : :
1254 : : /* Tear down the channels */
1255 : 5 : set_thread(1);
1256 : 5 : spdk_put_io_channel(io_ch[1]);
1257 : 5 : set_thread(0);
1258 : 5 : spdk_put_io_channel(io_ch[0]);
1259 : 5 : poll_threads();
1260 : :
1261 : 5 : teardown_test();
1262 : 5 : }
1263 : :
1264 : : static void
1265 : 5 : io_during_qos_reset(void)
1266 : : {
1267 : : struct spdk_io_channel *io_ch[2];
1268 : : struct spdk_bdev_channel *bdev_ch[2];
1269 : : struct spdk_bdev *bdev;
1270 : 4 : enum spdk_bdev_io_status status0, status1, reset_status;
1271 : : int rc;
1272 : :
1273 : 5 : setup_test();
1274 : 5 : MOCK_SET(spdk_get_ticks, 0);
1275 : :
1276 : : /* Enable QoS */
1277 : 5 : bdev = &g_bdev.bdev;
1278 : 5 : bdev->internal.qos = calloc(1, sizeof(*bdev->internal.qos));
1279 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(bdev->internal.qos != NULL);
1280 : :
1281 : : /*
1282 : : * Enable read/write IOPS, write only byte per sec and
1283 : : * read/write byte per second rate limits.
1284 : : * In this case, read/write byte per second rate limit will
1285 : : * take effect first.
1286 : : */
1287 : : /* 2000 read/write I/O per second, or 2 per millisecond */
1288 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT].limit = 2000;
1289 : : /* 4K byte per millisecond with 4K block size */
1290 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT].limit = 4096000;
1291 : : /* 8K byte per millisecond with 4K block size */
1292 : 5 : bdev->internal.qos->rate_limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT].limit = 8192000;
1293 : :
1294 : 5 : g_get_io_channel = true;
1295 : :
1296 : : /* Create channels */
1297 : 5 : set_thread(0);
1298 : 5 : io_ch[0] = spdk_bdev_get_io_channel(g_desc);
1299 : 5 : bdev_ch[0] = spdk_io_channel_get_ctx(io_ch[0]);
1300 : 5 : CU_ASSERT(bdev_ch[0]->flags == BDEV_CH_QOS_ENABLED);
1301 : :
1302 : 5 : set_thread(1);
1303 : 5 : io_ch[1] = spdk_bdev_get_io_channel(g_desc);
1304 : 5 : bdev_ch[1] = spdk_io_channel_get_ctx(io_ch[1]);
1305 : 5 : CU_ASSERT(bdev_ch[1]->flags == BDEV_CH_QOS_ENABLED);
1306 : :
1307 : : /* Send two I/O. One of these gets queued by QoS. The other is sitting at the disk. */
1308 : 5 : status1 = SPDK_BDEV_IO_STATUS_PENDING;
1309 : 5 : rc = spdk_bdev_write_blocks(g_desc, io_ch[1], NULL, 0, 1, io_during_io_done, &status1);
1310 : 5 : CU_ASSERT(rc == 0);
1311 : 5 : set_thread(0);
1312 : 5 : status0 = SPDK_BDEV_IO_STATUS_PENDING;
1313 : 5 : rc = spdk_bdev_write_blocks(g_desc, io_ch[0], NULL, 0, 1, io_during_io_done, &status0);
1314 : 5 : CU_ASSERT(rc == 0);
1315 : :
1316 : 5 : poll_threads();
1317 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_PENDING);
1318 : 5 : CU_ASSERT(status0 == SPDK_BDEV_IO_STATUS_PENDING);
1319 : :
1320 : : /* Reset the bdev. */
1321 : 5 : reset_status = SPDK_BDEV_IO_STATUS_PENDING;
1322 : 5 : rc = spdk_bdev_reset(g_desc, io_ch[0], io_during_io_done, &reset_status);
1323 : 5 : CU_ASSERT(rc == 0);
1324 : :
1325 : : /* Complete any I/O that arrived at the disk */
1326 : 5 : poll_threads();
1327 : 5 : set_thread(1);
1328 : 5 : stub_complete_io(g_bdev.io_target, 0);
1329 : 5 : set_thread(0);
1330 : 5 : stub_complete_io(g_bdev.io_target, 0);
1331 : 5 : poll_threads();
1332 : :
1333 : 5 : CU_ASSERT(reset_status == SPDK_BDEV_IO_STATUS_SUCCESS);
1334 : 5 : CU_ASSERT(status0 == SPDK_BDEV_IO_STATUS_ABORTED);
1335 : 5 : CU_ASSERT(status1 == SPDK_BDEV_IO_STATUS_ABORTED);
1336 : :
1337 : : /* Tear down the channels */
1338 : 5 : set_thread(1);
1339 : 5 : spdk_put_io_channel(io_ch[1]);
1340 : 5 : set_thread(0);
1341 : 5 : spdk_put_io_channel(io_ch[0]);
1342 : 5 : poll_threads();
1343 : :
1344 : 5 : teardown_test();
1345 : 5 : }
1346 : :
1347 : : static void
1348 : 645 : enomem_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
1349 : : {
1350 : 645 : enum spdk_bdev_io_status *status = cb_arg;
1351 : :
1352 [ + + ]: 645 : *status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED;
1353 : 645 : spdk_bdev_free_io(bdev_io);
1354 : 645 : }
1355 : :
1356 : : static void
1357 : 5 : enomem(void)
1358 : 5 : {
1359 : : struct spdk_io_channel *io_ch;
1360 : : struct spdk_bdev_channel *bdev_ch;
1361 : : struct spdk_bdev_shared_resource *shared_resource;
1362 : : struct ut_bdev_channel *ut_ch;
1363 : 5 : const uint32_t IO_ARRAY_SIZE = 64;
1364 : 5 : const uint32_t AVAIL = 20;
1365 [ - + ]: 5 : enum spdk_bdev_io_status status[IO_ARRAY_SIZE], status_reset;
1366 : : uint32_t nomem_cnt, i;
1367 : : struct spdk_bdev_io *first_io;
1368 : : int rc;
1369 : :
1370 : 5 : setup_test();
1371 : :
1372 : 5 : set_thread(0);
1373 : 5 : io_ch = spdk_bdev_get_io_channel(g_desc);
1374 : 5 : bdev_ch = spdk_io_channel_get_ctx(io_ch);
1375 : 5 : shared_resource = bdev_ch->shared_resource;
1376 : 5 : ut_ch = spdk_io_channel_get_ctx(bdev_ch->channel);
1377 : 5 : ut_ch->avail_cnt = AVAIL;
1378 : :
1379 : : /* First submit a number of IOs equal to what the channel can support. */
1380 [ + + ]: 105 : for (i = 0; i < AVAIL; i++) {
1381 : 100 : status[i] = SPDK_BDEV_IO_STATUS_PENDING;
1382 : 100 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, enomem_done, &status[i]);
1383 : 100 : CU_ASSERT(rc == 0);
1384 : : }
1385 : 5 : CU_ASSERT(TAILQ_EMPTY(&shared_resource->nomem_io));
1386 : :
1387 : : /*
1388 : : * Next, submit one additional I/O. This one should fail with ENOMEM and then go onto
1389 : : * the enomem_io list.
1390 : : */
1391 : 5 : status[AVAIL] = SPDK_BDEV_IO_STATUS_PENDING;
1392 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, enomem_done, &status[AVAIL]);
1393 : 5 : CU_ASSERT(rc == 0);
1394 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&shared_resource->nomem_io));
1395 : 5 : first_io = TAILQ_FIRST(&shared_resource->nomem_io);
1396 : :
1397 : : /*
1398 : : * Now submit a bunch more I/O. These should all fail with ENOMEM and get queued behind
1399 : : * the first_io above.
1400 : : */
1401 [ + + ]: 220 : for (i = AVAIL + 1; i < IO_ARRAY_SIZE; i++) {
1402 : 215 : status[i] = SPDK_BDEV_IO_STATUS_PENDING;
1403 : 215 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, enomem_done, &status[i]);
1404 : 215 : CU_ASSERT(rc == 0);
1405 : : }
1406 : :
1407 : : /* Assert that first_io is still at the head of the list. */
1408 : 5 : CU_ASSERT(TAILQ_FIRST(&shared_resource->nomem_io) == first_io);
1409 : 5 : CU_ASSERT(bdev_io_tailq_cnt(&shared_resource->nomem_io) == (IO_ARRAY_SIZE - AVAIL));
1410 : 5 : nomem_cnt = bdev_io_tailq_cnt(&shared_resource->nomem_io);
1411 : 5 : CU_ASSERT(shared_resource->nomem_threshold == (AVAIL - NOMEM_THRESHOLD_COUNT));
1412 : :
1413 : : /*
1414 : : * Complete 1 I/O only. The key check here is bdev_io_tailq_cnt - this should not have
1415 : : * changed since completing just 1 I/O should not trigger retrying the queued nomem_io
1416 : : * list.
1417 : : */
1418 : 5 : stub_complete_io(g_bdev.io_target, 1);
1419 : 5 : CU_ASSERT(bdev_io_tailq_cnt(&shared_resource->nomem_io) == nomem_cnt);
1420 : :
1421 : : /*
1422 : : * Complete enough I/O to hit the nomem_threshold. This should trigger retrying nomem_io,
1423 : : * and we should see I/O get resubmitted to the test bdev module.
1424 : : */
1425 : 5 : stub_complete_io(g_bdev.io_target, NOMEM_THRESHOLD_COUNT - 1);
1426 : 5 : CU_ASSERT(bdev_io_tailq_cnt(&shared_resource->nomem_io) < nomem_cnt);
1427 : 5 : nomem_cnt = bdev_io_tailq_cnt(&shared_resource->nomem_io);
1428 : :
1429 : : /* Complete 1 I/O only. This should not trigger retrying the queued nomem_io. */
1430 : 5 : stub_complete_io(g_bdev.io_target, 1);
1431 : 5 : CU_ASSERT(bdev_io_tailq_cnt(&shared_resource->nomem_io) == nomem_cnt);
1432 : :
1433 : : /*
1434 : : * Send a reset and confirm that all I/O are completed, including the ones that
1435 : : * were queued on the nomem_io list.
1436 : : */
1437 : 5 : status_reset = SPDK_BDEV_IO_STATUS_PENDING;
1438 : 5 : rc = spdk_bdev_reset(g_desc, io_ch, enomem_done, &status_reset);
1439 : 5 : poll_threads();
1440 : 5 : CU_ASSERT(rc == 0);
1441 : : /* This will complete the reset. */
1442 : 5 : stub_complete_io(g_bdev.io_target, 0);
1443 : :
1444 : 5 : CU_ASSERT(bdev_io_tailq_cnt(&shared_resource->nomem_io) == 0);
1445 : 5 : CU_ASSERT(shared_resource->io_outstanding == 0);
1446 : :
1447 : 5 : spdk_put_io_channel(io_ch);
1448 : 5 : poll_threads();
1449 : 5 : teardown_test();
1450 : 5 : }
1451 : :
1452 : : static void
1453 : 5 : enomem_multi_bdev(void)
1454 : 5 : {
1455 : : struct spdk_io_channel *io_ch;
1456 : : struct spdk_bdev_channel *bdev_ch;
1457 : : struct spdk_bdev_shared_resource *shared_resource;
1458 : : struct ut_bdev_channel *ut_ch;
1459 : 5 : const uint32_t IO_ARRAY_SIZE = 64;
1460 : 5 : const uint32_t AVAIL = 20;
1461 [ - + ]: 5 : enum spdk_bdev_io_status status[IO_ARRAY_SIZE];
1462 : : uint32_t i;
1463 : : struct ut_bdev *second_bdev;
1464 : 5 : struct spdk_bdev_desc *second_desc = NULL;
1465 : : struct spdk_bdev_channel *second_bdev_ch;
1466 : : struct spdk_io_channel *second_ch;
1467 : : int rc;
1468 : :
1469 : 5 : setup_test();
1470 : :
1471 : : /* Register second bdev with the same io_target */
1472 : 5 : second_bdev = calloc(1, sizeof(*second_bdev));
1473 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(second_bdev != NULL);
1474 : 5 : register_bdev(second_bdev, "ut_bdev2", g_bdev.io_target);
1475 : 5 : spdk_bdev_open_ext("ut_bdev2", true, _bdev_event_cb, NULL, &second_desc);
1476 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(second_desc != NULL);
1477 : :
1478 : 5 : set_thread(0);
1479 : 5 : io_ch = spdk_bdev_get_io_channel(g_desc);
1480 : 5 : bdev_ch = spdk_io_channel_get_ctx(io_ch);
1481 : 5 : shared_resource = bdev_ch->shared_resource;
1482 : 5 : ut_ch = spdk_io_channel_get_ctx(bdev_ch->channel);
1483 : 5 : ut_ch->avail_cnt = AVAIL;
1484 : :
1485 : 5 : second_ch = spdk_bdev_get_io_channel(second_desc);
1486 : 5 : second_bdev_ch = spdk_io_channel_get_ctx(second_ch);
1487 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(shared_resource == second_bdev_ch->shared_resource);
1488 : :
1489 : : /* Saturate io_target through bdev A. */
1490 [ + + ]: 105 : for (i = 0; i < AVAIL; i++) {
1491 : 100 : status[i] = SPDK_BDEV_IO_STATUS_PENDING;
1492 : 100 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, enomem_done, &status[i]);
1493 : 100 : CU_ASSERT(rc == 0);
1494 : : }
1495 : 5 : CU_ASSERT(TAILQ_EMPTY(&shared_resource->nomem_io));
1496 : :
1497 : : /*
1498 : : * Now submit I/O through the second bdev. This should fail with ENOMEM
1499 : : * and then go onto the nomem_io list.
1500 : : */
1501 : 5 : status[AVAIL] = SPDK_BDEV_IO_STATUS_PENDING;
1502 : 5 : rc = spdk_bdev_read_blocks(second_desc, second_ch, NULL, 0, 1, enomem_done, &status[AVAIL]);
1503 : 5 : CU_ASSERT(rc == 0);
1504 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&shared_resource->nomem_io));
1505 : :
1506 : : /* Complete first bdev's I/O. This should retry sending second bdev's nomem_io */
1507 : 5 : stub_complete_io(g_bdev.io_target, AVAIL);
1508 : :
1509 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&shared_resource->nomem_io));
1510 : 5 : CU_ASSERT(shared_resource->io_outstanding == 1);
1511 : :
1512 : : /* Now complete our retried I/O */
1513 : 5 : stub_complete_io(g_bdev.io_target, 1);
1514 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(shared_resource->io_outstanding == 0);
1515 : :
1516 : 5 : spdk_put_io_channel(io_ch);
1517 : 5 : spdk_put_io_channel(second_ch);
1518 : 5 : spdk_bdev_close(second_desc);
1519 : 5 : unregister_bdev(second_bdev);
1520 : 5 : poll_threads();
1521 : 5 : free(second_bdev);
1522 : 5 : teardown_test();
1523 : 5 : }
1524 : :
1525 : : static void
1526 : 5 : enomem_multi_bdev_unregister(void)
1527 : 5 : {
1528 : : struct spdk_io_channel *io_ch;
1529 : : struct spdk_bdev_channel *bdev_ch;
1530 : : struct spdk_bdev_shared_resource *shared_resource;
1531 : : struct ut_bdev_channel *ut_ch;
1532 : 5 : const uint32_t IO_ARRAY_SIZE = 64;
1533 : 5 : const uint32_t AVAIL = 20;
1534 [ - + ]: 5 : enum spdk_bdev_io_status status[IO_ARRAY_SIZE];
1535 : : uint32_t i;
1536 : : int rc;
1537 : :
1538 : 5 : setup_test();
1539 : :
1540 : 5 : set_thread(0);
1541 : 5 : io_ch = spdk_bdev_get_io_channel(g_desc);
1542 : 5 : bdev_ch = spdk_io_channel_get_ctx(io_ch);
1543 : 5 : shared_resource = bdev_ch->shared_resource;
1544 : 5 : ut_ch = spdk_io_channel_get_ctx(bdev_ch->channel);
1545 : 5 : ut_ch->avail_cnt = AVAIL;
1546 : :
1547 : : /* Saturate io_target through the bdev. */
1548 [ + + ]: 105 : for (i = 0; i < AVAIL; i++) {
1549 : 100 : status[i] = SPDK_BDEV_IO_STATUS_PENDING;
1550 : 100 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, enomem_done, &status[i]);
1551 : 100 : CU_ASSERT(rc == 0);
1552 : : }
1553 : 5 : CU_ASSERT(TAILQ_EMPTY(&shared_resource->nomem_io));
1554 : :
1555 : : /*
1556 : : * Now submit I/O through the bdev. This should fail with ENOMEM
1557 : : * and then go onto the nomem_io list.
1558 : : */
1559 : 5 : status[AVAIL] = SPDK_BDEV_IO_STATUS_PENDING;
1560 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, enomem_done, &status[AVAIL]);
1561 : 5 : CU_ASSERT(rc == 0);
1562 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&shared_resource->nomem_io));
1563 : :
1564 : : /* Unregister the bdev to abort the IOs from nomem_io queue. */
1565 : 5 : unregister_bdev(&g_bdev);
1566 : 5 : CU_ASSERT(status[AVAIL] == SPDK_BDEV_IO_STATUS_FAILED);
1567 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&shared_resource->nomem_io));
1568 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(shared_resource->io_outstanding == AVAIL);
1569 : :
1570 : : /* Complete the bdev's I/O. */
1571 : 5 : stub_complete_io(g_bdev.io_target, AVAIL);
1572 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(shared_resource->io_outstanding == 0);
1573 : :
1574 : 5 : spdk_put_io_channel(io_ch);
1575 : 5 : poll_threads();
1576 : 5 : teardown_test();
1577 : 5 : }
1578 : :
1579 : : static void
1580 : 5 : enomem_multi_io_target(void)
1581 : 5 : {
1582 : : struct spdk_io_channel *io_ch;
1583 : : struct spdk_bdev_channel *bdev_ch;
1584 : : struct ut_bdev_channel *ut_ch;
1585 : 5 : const uint32_t IO_ARRAY_SIZE = 64;
1586 : 5 : const uint32_t AVAIL = 20;
1587 [ - + ]: 5 : enum spdk_bdev_io_status status[IO_ARRAY_SIZE];
1588 : : uint32_t i;
1589 : 4 : int new_io_device;
1590 : : struct ut_bdev *second_bdev;
1591 : 5 : struct spdk_bdev_desc *second_desc = NULL;
1592 : : struct spdk_bdev_channel *second_bdev_ch;
1593 : : struct spdk_io_channel *second_ch;
1594 : : int rc;
1595 : :
1596 : 5 : setup_test();
1597 : :
1598 : : /* Create new io_target and a second bdev using it */
1599 : 5 : spdk_io_device_register(&new_io_device, stub_create_ch, stub_destroy_ch,
1600 : : sizeof(struct ut_bdev_channel), NULL);
1601 : 5 : second_bdev = calloc(1, sizeof(*second_bdev));
1602 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(second_bdev != NULL);
1603 : 5 : register_bdev(second_bdev, "ut_bdev2", &new_io_device);
1604 : 5 : spdk_bdev_open_ext("ut_bdev2", true, _bdev_event_cb, NULL, &second_desc);
1605 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(second_desc != NULL);
1606 : :
1607 : 5 : set_thread(0);
1608 : 5 : io_ch = spdk_bdev_get_io_channel(g_desc);
1609 : 5 : bdev_ch = spdk_io_channel_get_ctx(io_ch);
1610 : 5 : ut_ch = spdk_io_channel_get_ctx(bdev_ch->channel);
1611 : 5 : ut_ch->avail_cnt = AVAIL;
1612 : :
1613 : : /* Different io_target should imply a different shared_resource */
1614 : 5 : second_ch = spdk_bdev_get_io_channel(second_desc);
1615 : 5 : second_bdev_ch = spdk_io_channel_get_ctx(second_ch);
1616 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(bdev_ch->shared_resource != second_bdev_ch->shared_resource);
1617 : :
1618 : : /* Saturate io_target through bdev A. */
1619 [ + + ]: 105 : for (i = 0; i < AVAIL; i++) {
1620 : 100 : status[i] = SPDK_BDEV_IO_STATUS_PENDING;
1621 : 100 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, enomem_done, &status[i]);
1622 : 100 : CU_ASSERT(rc == 0);
1623 : : }
1624 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch->shared_resource->nomem_io));
1625 : :
1626 : : /* Issue one more I/O to fill ENOMEM list. */
1627 : 5 : status[AVAIL] = SPDK_BDEV_IO_STATUS_PENDING;
1628 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch, NULL, 0, 1, enomem_done, &status[AVAIL]);
1629 : 5 : CU_ASSERT(rc == 0);
1630 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&bdev_ch->shared_resource->nomem_io));
1631 : :
1632 : : /*
1633 : : * Now submit I/O through the second bdev. This should go through and complete
1634 : : * successfully because we're using a different io_device underneath.
1635 : : */
1636 : 5 : status[AVAIL] = SPDK_BDEV_IO_STATUS_PENDING;
1637 : 5 : rc = spdk_bdev_read_blocks(second_desc, second_ch, NULL, 0, 1, enomem_done, &status[AVAIL]);
1638 : 5 : CU_ASSERT(rc == 0);
1639 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&second_bdev_ch->shared_resource->nomem_io));
1640 : 5 : stub_complete_io(second_bdev->io_target, 1);
1641 : :
1642 : : /* Cleanup; Complete outstanding I/O. */
1643 : 5 : stub_complete_io(g_bdev.io_target, AVAIL);
1644 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&bdev_ch->shared_resource->nomem_io));
1645 : : /* Complete the ENOMEM I/O */
1646 : 5 : stub_complete_io(g_bdev.io_target, 1);
1647 : 5 : CU_ASSERT(bdev_ch->shared_resource->io_outstanding == 0);
1648 : :
1649 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&bdev_ch->shared_resource->nomem_io));
1650 : 5 : CU_ASSERT(bdev_ch->shared_resource->io_outstanding == 0);
1651 : 5 : spdk_put_io_channel(io_ch);
1652 : 5 : spdk_put_io_channel(second_ch);
1653 : 5 : spdk_bdev_close(second_desc);
1654 : 5 : unregister_bdev(second_bdev);
1655 : 5 : spdk_io_device_unregister(&new_io_device, NULL);
1656 : 5 : poll_threads();
1657 : 5 : free(second_bdev);
1658 : 5 : teardown_test();
1659 : 5 : }
1660 : :
1661 : : static void
1662 : 45 : qos_dynamic_enable_done(void *cb_arg, int status)
1663 : : {
1664 : 45 : int *rc = cb_arg;
1665 : 45 : *rc = status;
1666 : 45 : }
1667 : :
1668 : : static void
1669 : 5 : qos_dynamic_enable(void)
1670 : : {
1671 : : struct spdk_io_channel *io_ch[2];
1672 : : struct spdk_bdev_channel *bdev_ch[2];
1673 : : struct spdk_bdev *bdev;
1674 : 4 : enum spdk_bdev_io_status bdev_io_status[2];
1675 : 5 : uint64_t limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES] = {};
1676 : 4 : int status, second_status, rc, i;
1677 : :
1678 : 5 : setup_test();
1679 : 5 : MOCK_SET(spdk_get_ticks, 0);
1680 : :
1681 [ + + ]: 25 : for (i = 0; i < SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES; i++) {
1682 : 20 : limits[i] = UINT64_MAX;
1683 : : }
1684 : :
1685 : 5 : bdev = &g_bdev.bdev;
1686 : :
1687 : 5 : g_get_io_channel = true;
1688 : :
1689 : : /* Create channels */
1690 : 5 : set_thread(0);
1691 : 5 : io_ch[0] = spdk_bdev_get_io_channel(g_desc);
1692 : 5 : bdev_ch[0] = spdk_io_channel_get_ctx(io_ch[0]);
1693 : 5 : CU_ASSERT(bdev_ch[0]->flags == 0);
1694 : :
1695 : 5 : set_thread(1);
1696 : 5 : io_ch[1] = spdk_bdev_get_io_channel(g_desc);
1697 : 5 : bdev_ch[1] = spdk_io_channel_get_ctx(io_ch[1]);
1698 : 5 : CU_ASSERT(bdev_ch[1]->flags == 0);
1699 : :
1700 : 5 : set_thread(0);
1701 : :
1702 : : /*
1703 : : * Enable QoS: Read/Write IOPS, Read/Write byte,
1704 : : * Read only byte and Write only byte per second
1705 : : * rate limits.
1706 : : * More than 10 I/Os allowed per timeslice.
1707 : : */
1708 : 5 : status = -1;
1709 : 5 : limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT] = 10000;
1710 : 5 : limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT] = 100;
1711 : 5 : limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT] = 100;
1712 : 5 : limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT] = 10;
1713 : 5 : spdk_bdev_set_qos_rate_limits(bdev, limits, qos_dynamic_enable_done, &status);
1714 : 5 : poll_threads();
1715 : 5 : CU_ASSERT(status == 0);
1716 : 5 : CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) != 0);
1717 : 5 : CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) != 0);
1718 : :
1719 : : /*
1720 : : * Submit and complete 10 I/O to fill the QoS allotment for this timeslice.
1721 : : * Additional I/O will then be queued.
1722 : : */
1723 : 5 : set_thread(0);
1724 [ + + ]: 55 : for (i = 0; i < 10; i++) {
1725 : 50 : bdev_io_status[0] = SPDK_BDEV_IO_STATUS_PENDING;
1726 : 50 : rc = spdk_bdev_read_blocks(g_desc, io_ch[0], NULL, 0, 1, io_during_io_done, &bdev_io_status[0]);
1727 : 50 : CU_ASSERT(rc == 0);
1728 : 50 : CU_ASSERT(bdev_io_status[0] == SPDK_BDEV_IO_STATUS_PENDING);
1729 : 50 : poll_thread(0);
1730 : 50 : stub_complete_io(g_bdev.io_target, 0);
1731 : 50 : CU_ASSERT(bdev_io_status[0] == SPDK_BDEV_IO_STATUS_SUCCESS);
1732 : : }
1733 : :
1734 : : /*
1735 : : * Send two more I/O. These I/O will be queued since the current timeslice allotment has been
1736 : : * filled already. We want to test that when QoS is disabled that these two I/O:
1737 : : * 1) are not aborted
1738 : : * 2) are sent back to their original thread for resubmission
1739 : : */
1740 : 5 : bdev_io_status[0] = SPDK_BDEV_IO_STATUS_PENDING;
1741 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[0], NULL, 0, 1, io_during_io_done, &bdev_io_status[0]);
1742 : 5 : CU_ASSERT(rc == 0);
1743 : 5 : CU_ASSERT(bdev_io_status[0] == SPDK_BDEV_IO_STATUS_PENDING);
1744 : 5 : set_thread(1);
1745 : 5 : bdev_io_status[1] = SPDK_BDEV_IO_STATUS_PENDING;
1746 : 5 : rc = spdk_bdev_read_blocks(g_desc, io_ch[1], NULL, 0, 1, io_during_io_done, &bdev_io_status[1]);
1747 : 5 : CU_ASSERT(rc == 0);
1748 : 5 : CU_ASSERT(bdev_io_status[1] == SPDK_BDEV_IO_STATUS_PENDING);
1749 : 5 : poll_threads();
1750 : :
1751 : : /*
1752 : : * Disable QoS: Read/Write IOPS, Read/Write byte,
1753 : : * Read only byte rate limits
1754 : : */
1755 : 5 : status = -1;
1756 : 5 : limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT] = 0;
1757 : 5 : limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT] = 0;
1758 : 5 : limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT] = 0;
1759 : 5 : spdk_bdev_set_qos_rate_limits(bdev, limits, qos_dynamic_enable_done, &status);
1760 : 5 : poll_threads();
1761 : 5 : CU_ASSERT(status == 0);
1762 : 5 : CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) != 0);
1763 : 5 : CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) != 0);
1764 : :
1765 : : /* Disable QoS: Write only Byte per second rate limit */
1766 : 5 : status = -1;
1767 : 5 : limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT] = 0;
1768 : 5 : spdk_bdev_set_qos_rate_limits(bdev, limits, qos_dynamic_enable_done, &status);
1769 : 5 : poll_threads();
1770 : 5 : CU_ASSERT(status == 0);
1771 : 5 : CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) == 0);
1772 : 5 : CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) == 0);
1773 : :
1774 : : /*
1775 : : * All I/O should have been resubmitted back on their original thread. Complete
1776 : : * all I/O on thread 0, and ensure that only the thread 0 I/O was completed.
1777 : : */
1778 : 5 : set_thread(0);
1779 : 5 : stub_complete_io(g_bdev.io_target, 0);
1780 : 5 : poll_threads();
1781 : 5 : CU_ASSERT(bdev_io_status[0] == SPDK_BDEV_IO_STATUS_SUCCESS);
1782 : 5 : CU_ASSERT(bdev_io_status[1] == SPDK_BDEV_IO_STATUS_PENDING);
1783 : :
1784 : : /* Now complete all I/O on thread 1 and ensure the thread 1 I/O was completed. */
1785 : 5 : set_thread(1);
1786 : 5 : stub_complete_io(g_bdev.io_target, 0);
1787 : 5 : poll_threads();
1788 : 5 : CU_ASSERT(bdev_io_status[1] == SPDK_BDEV_IO_STATUS_SUCCESS);
1789 : :
1790 : : /* Disable QoS again */
1791 : 5 : status = -1;
1792 : 5 : limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT] = 0;
1793 : 5 : spdk_bdev_set_qos_rate_limits(bdev, limits, qos_dynamic_enable_done, &status);
1794 : 5 : poll_threads();
1795 : 5 : CU_ASSERT(status == 0); /* This should succeed */
1796 : 5 : CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) == 0);
1797 : 5 : CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) == 0);
1798 : :
1799 : : /* Enable QoS on thread 0 */
1800 : 5 : status = -1;
1801 : 5 : limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT] = 10000;
1802 : 5 : spdk_bdev_set_qos_rate_limits(bdev, limits, qos_dynamic_enable_done, &status);
1803 : 5 : poll_threads();
1804 : 5 : CU_ASSERT(status == 0);
1805 : 5 : CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) != 0);
1806 : 5 : CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) != 0);
1807 : :
1808 : : /* Disable QoS on thread 1 */
1809 : 5 : set_thread(1);
1810 : 5 : status = -1;
1811 : 5 : limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT] = 0;
1812 : 5 : spdk_bdev_set_qos_rate_limits(bdev, limits, qos_dynamic_enable_done, &status);
1813 : : /* Don't poll yet. This should leave the channels with QoS enabled */
1814 : 5 : CU_ASSERT(status == -1);
1815 : 5 : CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) != 0);
1816 : 5 : CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) != 0);
1817 : :
1818 : : /* Enable QoS. This should immediately fail because the previous disable QoS hasn't completed. */
1819 : 5 : second_status = 0;
1820 : 5 : limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT] = 10;
1821 : 5 : spdk_bdev_set_qos_rate_limits(bdev, limits, qos_dynamic_enable_done, &second_status);
1822 : 5 : poll_threads();
1823 : 5 : CU_ASSERT(status == 0); /* The disable should succeed */
1824 : 5 : CU_ASSERT(second_status < 0); /* The enable should fail */
1825 : 5 : CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) == 0);
1826 : 5 : CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) == 0);
1827 : :
1828 : : /* Enable QoS on thread 1. This should succeed now that the disable has completed. */
1829 : 5 : status = -1;
1830 : 5 : limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT] = 10000;
1831 : 5 : spdk_bdev_set_qos_rate_limits(bdev, limits, qos_dynamic_enable_done, &status);
1832 : 5 : poll_threads();
1833 : 5 : CU_ASSERT(status == 0);
1834 : 5 : CU_ASSERT((bdev_ch[0]->flags & BDEV_CH_QOS_ENABLED) != 0);
1835 : 5 : CU_ASSERT((bdev_ch[1]->flags & BDEV_CH_QOS_ENABLED) != 0);
1836 : :
1837 : : /* Tear down the channels */
1838 : 5 : set_thread(0);
1839 : 5 : spdk_put_io_channel(io_ch[0]);
1840 : 5 : set_thread(1);
1841 : 5 : spdk_put_io_channel(io_ch[1]);
1842 : 5 : poll_threads();
1843 : :
1844 : 5 : set_thread(0);
1845 : 5 : teardown_test();
1846 : 5 : }
1847 : :
1848 : : static void
1849 : 10 : histogram_status_cb(void *cb_arg, int status)
1850 : : {
1851 : 10 : g_status = status;
1852 : 10 : }
1853 : :
1854 : : static void
1855 : 10 : histogram_data_cb(void *cb_arg, int status, struct spdk_histogram_data *histogram)
1856 : : {
1857 : 10 : g_status = status;
1858 : 10 : g_histogram = histogram;
1859 : 10 : }
1860 : :
1861 : : static void
1862 : 74240 : histogram_io_count(void *ctx, uint64_t start, uint64_t end, uint64_t count,
1863 : : uint64_t total, uint64_t so_far)
1864 : : {
1865 : 74240 : g_count += count;
1866 : 74240 : }
1867 : :
1868 : : static void
1869 : 5 : bdev_histograms_mt(void)
1870 : : {
1871 : : struct spdk_io_channel *ch[2];
1872 : : struct spdk_histogram_data *histogram;
1873 : 4 : uint8_t buf[4096];
1874 : 5 : int status = false;
1875 : : int rc;
1876 : :
1877 : :
1878 : 5 : setup_test();
1879 : :
1880 : 5 : set_thread(0);
1881 : 5 : ch[0] = spdk_bdev_get_io_channel(g_desc);
1882 : 5 : CU_ASSERT(ch[0] != NULL);
1883 : :
1884 : 5 : set_thread(1);
1885 : 5 : ch[1] = spdk_bdev_get_io_channel(g_desc);
1886 : 5 : CU_ASSERT(ch[1] != NULL);
1887 : :
1888 : :
1889 : : /* Enable histogram */
1890 : 5 : spdk_bdev_histogram_enable(&g_bdev.bdev, histogram_status_cb, NULL, true);
1891 : 5 : poll_threads();
1892 : 5 : CU_ASSERT(g_status == 0);
1893 [ - + ]: 5 : CU_ASSERT(g_bdev.bdev.internal.histogram_enabled == true);
1894 : :
1895 : : /* Allocate histogram */
1896 : 5 : histogram = spdk_histogram_data_alloc();
1897 : :
1898 : : /* Check if histogram is zeroed */
1899 : 5 : spdk_bdev_histogram_get(&g_bdev.bdev, histogram, histogram_data_cb, NULL);
1900 : 5 : poll_threads();
1901 : 5 : CU_ASSERT(g_status == 0);
1902 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(g_histogram != NULL);
1903 : :
1904 : 5 : g_count = 0;
1905 : 5 : spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL);
1906 : :
1907 : 5 : CU_ASSERT(g_count == 0);
1908 : :
1909 : 5 : set_thread(0);
1910 : 5 : rc = spdk_bdev_write_blocks(g_desc, ch[0], &buf, 0, 1, io_during_io_done, &status);
1911 : 5 : CU_ASSERT(rc == 0);
1912 : :
1913 : 5 : spdk_delay_us(10);
1914 : 5 : stub_complete_io(g_bdev.io_target, 1);
1915 : 5 : poll_threads();
1916 : 5 : CU_ASSERT(status == true);
1917 : :
1918 : :
1919 : 5 : set_thread(1);
1920 : 5 : rc = spdk_bdev_read_blocks(g_desc, ch[1], &buf, 0, 1, io_during_io_done, &status);
1921 : 5 : CU_ASSERT(rc == 0);
1922 : :
1923 : 5 : spdk_delay_us(10);
1924 : 5 : stub_complete_io(g_bdev.io_target, 1);
1925 : 5 : poll_threads();
1926 : 5 : CU_ASSERT(status == true);
1927 : :
1928 : 5 : set_thread(0);
1929 : :
1930 : : /* Check if histogram gathered data from all I/O channels */
1931 : 5 : spdk_bdev_histogram_get(&g_bdev.bdev, histogram, histogram_data_cb, NULL);
1932 : 5 : poll_threads();
1933 : 5 : CU_ASSERT(g_status == 0);
1934 [ - + ]: 5 : CU_ASSERT(g_bdev.bdev.internal.histogram_enabled == true);
1935 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(g_histogram != NULL);
1936 : :
1937 : 5 : g_count = 0;
1938 : 5 : spdk_histogram_data_iterate(g_histogram, histogram_io_count, NULL);
1939 : 5 : CU_ASSERT(g_count == 2);
1940 : :
1941 : : /* Disable histogram */
1942 : 5 : spdk_bdev_histogram_enable(&g_bdev.bdev, histogram_status_cb, NULL, false);
1943 : 5 : poll_threads();
1944 : 5 : CU_ASSERT(g_status == 0);
1945 [ - + ]: 5 : CU_ASSERT(g_bdev.bdev.internal.histogram_enabled == false);
1946 : :
1947 : 5 : spdk_histogram_data_free(histogram);
1948 : :
1949 : : /* Tear down the channels */
1950 : 5 : set_thread(0);
1951 : 5 : spdk_put_io_channel(ch[0]);
1952 : 5 : set_thread(1);
1953 : 5 : spdk_put_io_channel(ch[1]);
1954 : 5 : poll_threads();
1955 : 5 : set_thread(0);
1956 : 5 : teardown_test();
1957 : :
1958 : 5 : }
1959 : :
1960 : : struct timeout_io_cb_arg {
1961 : : struct iovec iov;
1962 : : uint8_t type;
1963 : : };
1964 : :
1965 : : static int
1966 : 35 : bdev_channel_count_submitted_io(struct spdk_bdev_channel *ch)
1967 : : {
1968 : : struct spdk_bdev_io *bdev_io;
1969 : 35 : int n = 0;
1970 : :
1971 [ - + ]: 35 : if (!ch) {
1972 : 0 : return -1;
1973 : : }
1974 : :
1975 [ + + ]: 70 : TAILQ_FOREACH(bdev_io, &ch->io_submitted, internal.ch_link) {
1976 : 35 : n++;
1977 : : }
1978 : :
1979 : 35 : return n;
1980 : : }
1981 : :
1982 : : static void
1983 : 20 : bdev_channel_io_timeout_cb(void *cb_arg, struct spdk_bdev_io *bdev_io)
1984 : : {
1985 : 20 : struct timeout_io_cb_arg *ctx = cb_arg;
1986 : :
1987 : 20 : ctx->type = bdev_io->type;
1988 : 20 : ctx->iov.iov_base = bdev_io->iov.iov_base;
1989 : 20 : ctx->iov.iov_len = bdev_io->iov.iov_len;
1990 : 20 : }
1991 : :
1992 : : static bool g_io_done;
1993 : :
1994 : : static void
1995 : 45 : io_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
1996 : : {
1997 : 45 : g_io_done = true;
1998 : 45 : spdk_bdev_free_io(bdev_io);
1999 : 45 : }
2000 : :
2001 : : static void
2002 : 5 : bdev_set_io_timeout_mt(void)
2003 : : {
2004 : : struct spdk_io_channel *ch[3];
2005 : : struct spdk_bdev_channel *bdev_ch[3];
2006 : 4 : struct timeout_io_cb_arg cb_arg;
2007 : :
2008 : 5 : setup_test();
2009 : :
2010 : 5 : g_bdev.bdev.optimal_io_boundary = 16;
2011 : 5 : g_bdev.bdev.split_on_optimal_io_boundary = true;
2012 : :
2013 : 5 : set_thread(0);
2014 : 5 : ch[0] = spdk_bdev_get_io_channel(g_desc);
2015 : 5 : CU_ASSERT(ch[0] != NULL);
2016 : :
2017 : 5 : set_thread(1);
2018 : 5 : ch[1] = spdk_bdev_get_io_channel(g_desc);
2019 : 5 : CU_ASSERT(ch[1] != NULL);
2020 : :
2021 : 5 : set_thread(2);
2022 : 5 : ch[2] = spdk_bdev_get_io_channel(g_desc);
2023 : 5 : CU_ASSERT(ch[2] != NULL);
2024 : :
2025 : : /* Multi-thread mode
2026 : : * 1, Check the poller was registered successfully
2027 : : * 2, Check the timeout IO and ensure the IO was the submitted by user
2028 : : * 3, Check the link int the bdev_ch works right.
2029 : : * 4, Close desc and put io channel during the timeout poller is polling
2030 : : */
2031 : :
2032 : : /* In desc thread set the timeout */
2033 : 5 : set_thread(0);
2034 : 5 : CU_ASSERT(spdk_bdev_set_timeout(g_desc, 5, bdev_channel_io_timeout_cb, &cb_arg) == 0);
2035 : 5 : CU_ASSERT(g_desc->io_timeout_poller != NULL);
2036 : 5 : CU_ASSERT(g_desc->cb_fn == bdev_channel_io_timeout_cb);
2037 : 5 : CU_ASSERT(g_desc->cb_arg == &cb_arg);
2038 : :
2039 : : /* check the IO submitted list and timeout handler */
2040 : 5 : CU_ASSERT(spdk_bdev_read_blocks(g_desc, ch[0], (void *)0x2000, 0, 1, io_done, NULL) == 0);
2041 : 5 : bdev_ch[0] = spdk_io_channel_get_ctx(ch[0]);
2042 : 5 : CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch[0]) == 1);
2043 : :
2044 : 5 : set_thread(1);
2045 : 5 : CU_ASSERT(spdk_bdev_write_blocks(g_desc, ch[1], (void *)0x1000, 0, 1, io_done, NULL) == 0);
2046 : 5 : bdev_ch[1] = spdk_io_channel_get_ctx(ch[1]);
2047 : 5 : CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch[1]) == 1);
2048 : :
2049 : : /* Now test that a single-vector command is split correctly.
2050 : : * Offset 14, length 8, payload 0xF000
2051 : : * Child - Offset 14, length 2, payload 0xF000
2052 : : * Child - Offset 16, length 6, payload 0xF000 + 2 * 512
2053 : : *
2054 : : * Set up the expected values before calling spdk_bdev_read_blocks
2055 : : */
2056 : 5 : set_thread(2);
2057 : 5 : CU_ASSERT(spdk_bdev_read_blocks(g_desc, ch[2], (void *)0xF000, 14, 8, io_done, NULL) == 0);
2058 : 5 : bdev_ch[2] = spdk_io_channel_get_ctx(ch[2]);
2059 : 5 : CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch[2]) == 3);
2060 : :
2061 : 5 : set_thread(0);
2062 [ - + ]: 5 : memset(&cb_arg, 0, sizeof(cb_arg));
2063 : 5 : spdk_delay_us(3 * spdk_get_ticks_hz());
2064 : 5 : poll_threads();
2065 : 5 : CU_ASSERT(cb_arg.type == 0);
2066 : 5 : CU_ASSERT(cb_arg.iov.iov_base == (void *)0x0);
2067 : 5 : CU_ASSERT(cb_arg.iov.iov_len == 0);
2068 : :
2069 : : /* Now the time reach the limit */
2070 : 5 : spdk_delay_us(3 * spdk_get_ticks_hz());
2071 : 5 : poll_thread(0);
2072 : 5 : CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_READ);
2073 : 5 : CU_ASSERT(cb_arg.iov.iov_base == (void *)0x2000);
2074 : 5 : CU_ASSERT(cb_arg.iov.iov_len == 1 * g_bdev.bdev.blocklen);
2075 : 5 : stub_complete_io(g_bdev.io_target, 1);
2076 : 5 : CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch[0]) == 0);
2077 : :
2078 [ - + ]: 5 : memset(&cb_arg, 0, sizeof(cb_arg));
2079 : 5 : set_thread(1);
2080 : 5 : poll_thread(1);
2081 : 5 : CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_WRITE);
2082 : 5 : CU_ASSERT(cb_arg.iov.iov_base == (void *)0x1000);
2083 : 5 : CU_ASSERT(cb_arg.iov.iov_len == 1 * g_bdev.bdev.blocklen);
2084 : 5 : stub_complete_io(g_bdev.io_target, 1);
2085 : 5 : CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch[1]) == 0);
2086 : :
2087 [ - + ]: 5 : memset(&cb_arg, 0, sizeof(cb_arg));
2088 : 5 : set_thread(2);
2089 : 5 : poll_thread(2);
2090 : 5 : CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_READ);
2091 : 5 : CU_ASSERT(cb_arg.iov.iov_base == (void *)0xF000);
2092 : 5 : CU_ASSERT(cb_arg.iov.iov_len == 8 * g_bdev.bdev.blocklen);
2093 : 5 : stub_complete_io(g_bdev.io_target, 1);
2094 : 5 : CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch[2]) == 2);
2095 : 5 : stub_complete_io(g_bdev.io_target, 1);
2096 : 5 : CU_ASSERT(bdev_channel_count_submitted_io(bdev_ch[2]) == 0);
2097 : :
2098 : : /* Run poll_timeout_done() it means complete the timeout poller */
2099 : 5 : set_thread(0);
2100 : 5 : poll_thread(0);
2101 : 5 : CU_ASSERT(g_desc->refs == 0);
2102 : 5 : CU_ASSERT(spdk_bdev_read_blocks(g_desc, ch[0], (void *)0x1000, 0, 1, io_done, NULL) == 0);
2103 : 5 : set_thread(1);
2104 : 5 : CU_ASSERT(spdk_bdev_write_blocks(g_desc, ch[1], (void *)0x2000, 0, 2, io_done, NULL) == 0);
2105 : 5 : set_thread(2);
2106 : 5 : CU_ASSERT(spdk_bdev_read_blocks(g_desc, ch[2], (void *)0x3000, 0, 3, io_done, NULL) == 0);
2107 : :
2108 : : /* Trigger timeout poller to run again, desc->refs is incremented.
2109 : : * In thread 0 we destroy the io channel before timeout poller runs.
2110 : : * Timeout callback is not called on thread 0.
2111 : : */
2112 : 5 : spdk_delay_us(6 * spdk_get_ticks_hz());
2113 [ - + ]: 5 : memset(&cb_arg, 0, sizeof(cb_arg));
2114 : 5 : set_thread(0);
2115 : 5 : stub_complete_io(g_bdev.io_target, 1);
2116 : 5 : spdk_put_io_channel(ch[0]);
2117 : 5 : poll_thread(0);
2118 : 5 : CU_ASSERT(g_desc->refs == 1)
2119 : 5 : CU_ASSERT(cb_arg.type == 0);
2120 : 5 : CU_ASSERT(cb_arg.iov.iov_base == (void *)0x0);
2121 : 5 : CU_ASSERT(cb_arg.iov.iov_len == 0);
2122 : :
2123 : : /* In thread 1 timeout poller runs then we destroy the io channel
2124 : : * Timeout callback is called on thread 1.
2125 : : */
2126 [ - + ]: 5 : memset(&cb_arg, 0, sizeof(cb_arg));
2127 : 5 : set_thread(1);
2128 : 5 : poll_thread(1);
2129 : 5 : stub_complete_io(g_bdev.io_target, 1);
2130 : 5 : spdk_put_io_channel(ch[1]);
2131 : 5 : poll_thread(1);
2132 : 5 : CU_ASSERT(cb_arg.type == SPDK_BDEV_IO_TYPE_WRITE);
2133 : 5 : CU_ASSERT(cb_arg.iov.iov_base == (void *)0x2000);
2134 : 5 : CU_ASSERT(cb_arg.iov.iov_len == 2 * g_bdev.bdev.blocklen);
2135 : :
2136 : : /* Close the desc.
2137 : : * Unregister the timeout poller first.
2138 : : * Then decrement desc->refs but it's not zero yet so desc is not freed.
2139 : : */
2140 : 5 : set_thread(0);
2141 : 5 : spdk_bdev_close(g_desc);
2142 : 5 : CU_ASSERT(g_desc->refs == 1);
2143 : 5 : CU_ASSERT(g_desc->io_timeout_poller == NULL);
2144 : :
2145 : : /* Timeout poller runs on thread 2 then we destroy the io channel.
2146 : : * Desc is closed so we would exit the timeout poller directly.
2147 : : * timeout callback is not called on thread 2.
2148 : : */
2149 [ - + ]: 5 : memset(&cb_arg, 0, sizeof(cb_arg));
2150 : 5 : set_thread(2);
2151 : 5 : poll_thread(2);
2152 : 5 : stub_complete_io(g_bdev.io_target, 1);
2153 : 5 : spdk_put_io_channel(ch[2]);
2154 : 5 : poll_thread(2);
2155 : 5 : CU_ASSERT(cb_arg.type == 0);
2156 : 5 : CU_ASSERT(cb_arg.iov.iov_base == (void *)0x0);
2157 : 5 : CU_ASSERT(cb_arg.iov.iov_len == 0);
2158 : :
2159 : 5 : set_thread(0);
2160 : 5 : poll_thread(0);
2161 : 5 : g_teardown_done = false;
2162 : 5 : unregister_bdev(&g_bdev);
2163 : 5 : spdk_io_device_unregister(&g_io_device, NULL);
2164 : 5 : spdk_bdev_finish(finish_cb, NULL);
2165 : 5 : spdk_iobuf_finish(finish_cb, NULL);
2166 : 5 : poll_threads();
2167 [ - + ]: 5 : memset(&g_bdev, 0, sizeof(g_bdev));
2168 [ - + ]: 5 : CU_ASSERT(g_teardown_done == true);
2169 : 5 : g_teardown_done = false;
2170 : 5 : free_threads();
2171 : 5 : free_cores();
2172 : 5 : }
2173 : :
2174 : : static bool g_io_done2;
2175 : : static bool g_lock_lba_range_done;
2176 : : static bool g_unlock_lba_range_done;
2177 : :
2178 : : static void
2179 : 5 : io_done2(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
2180 : : {
2181 : 5 : g_io_done2 = true;
2182 : 5 : spdk_bdev_free_io(bdev_io);
2183 : 5 : }
2184 : :
2185 : : static void
2186 : 5 : lock_lba_range_done(struct lba_range *range, void *ctx, int status)
2187 : : {
2188 : 5 : g_lock_lba_range_done = true;
2189 : 5 : }
2190 : :
2191 : : static void
2192 : 5 : unlock_lba_range_done(struct lba_range *range, void *ctx, int status)
2193 : : {
2194 : 5 : g_unlock_lba_range_done = true;
2195 : 5 : }
2196 : :
2197 : : static uint32_t
2198 : 30 : stub_channel_outstanding_cnt(void *io_target)
2199 : : {
2200 : 30 : struct spdk_io_channel *_ch = spdk_get_io_channel(io_target);
2201 : 30 : struct ut_bdev_channel *ch = spdk_io_channel_get_ctx(_ch);
2202 : : uint32_t outstanding_cnt;
2203 : :
2204 : 30 : outstanding_cnt = ch->outstanding_cnt;
2205 : :
2206 : 30 : spdk_put_io_channel(_ch);
2207 : 30 : return outstanding_cnt;
2208 : : }
2209 : :
2210 : : static void
2211 : 5 : lock_lba_range_then_submit_io(void)
2212 : : {
2213 : 5 : struct spdk_bdev_desc *desc = NULL;
2214 : : void *io_target;
2215 : : struct spdk_io_channel *io_ch[3];
2216 : : struct spdk_bdev_channel *bdev_ch[3];
2217 : : struct lba_range *range;
2218 : 4 : char buf[4096];
2219 : 4 : int ctx0, ctx1, ctx2;
2220 : : int rc;
2221 : :
2222 : 5 : setup_test();
2223 : :
2224 : 5 : io_target = g_bdev.io_target;
2225 : 5 : desc = g_desc;
2226 : :
2227 : 5 : set_thread(0);
2228 : 5 : io_ch[0] = spdk_bdev_get_io_channel(desc);
2229 : 5 : bdev_ch[0] = spdk_io_channel_get_ctx(io_ch[0]);
2230 : 5 : CU_ASSERT(io_ch[0] != NULL);
2231 : :
2232 : 5 : set_thread(1);
2233 : 5 : io_ch[1] = spdk_bdev_get_io_channel(desc);
2234 : 5 : bdev_ch[1] = spdk_io_channel_get_ctx(io_ch[1]);
2235 : 5 : CU_ASSERT(io_ch[1] != NULL);
2236 : :
2237 : 5 : set_thread(0);
2238 : 5 : g_lock_lba_range_done = false;
2239 : 5 : rc = bdev_lock_lba_range(desc, io_ch[0], 20, 10, lock_lba_range_done, &ctx0);
2240 : 5 : CU_ASSERT(rc == 0);
2241 : 5 : poll_threads();
2242 : :
2243 : : /* The lock should immediately become valid, since there are no outstanding
2244 : : * write I/O.
2245 : : */
2246 [ - + ]: 5 : CU_ASSERT(g_lock_lba_range_done == true);
2247 : 5 : range = TAILQ_FIRST(&bdev_ch[0]->locked_ranges);
2248 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(range != NULL);
2249 : 5 : CU_ASSERT(range->offset == 20);
2250 : 5 : CU_ASSERT(range->length == 10);
2251 : 5 : CU_ASSERT(range->owner_ch == bdev_ch[0]);
2252 : :
2253 : 5 : g_io_done = false;
2254 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch[0]->io_locked));
2255 : 5 : rc = spdk_bdev_read_blocks(desc, io_ch[0], buf, 20, 1, io_done, &ctx0);
2256 : 5 : CU_ASSERT(rc == 0);
2257 : 5 : CU_ASSERT(stub_channel_outstanding_cnt(io_target) == 1);
2258 : :
2259 : 5 : stub_complete_io(io_target, 1);
2260 : 5 : poll_threads();
2261 [ - + ]: 5 : CU_ASSERT(g_io_done == true);
2262 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch[0]->io_locked));
2263 : :
2264 : : /* Try a write I/O. This should actually be allowed to execute, since the channel
2265 : : * holding the lock is submitting the write I/O.
2266 : : */
2267 : 5 : g_io_done = false;
2268 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch[0]->io_locked));
2269 : 5 : rc = spdk_bdev_write_blocks(desc, io_ch[0], buf, 20, 1, io_done, &ctx0);
2270 : 5 : CU_ASSERT(rc == 0);
2271 : 5 : CU_ASSERT(stub_channel_outstanding_cnt(io_target) == 1);
2272 : :
2273 : 5 : stub_complete_io(io_target, 1);
2274 : 5 : poll_threads();
2275 [ - + ]: 5 : CU_ASSERT(g_io_done == true);
2276 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch[0]->io_locked));
2277 : :
2278 : : /* Try a write I/O. This should get queued in the io_locked tailq. */
2279 : 5 : set_thread(1);
2280 : 5 : g_io_done = false;
2281 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch[1]->io_locked));
2282 : 5 : rc = spdk_bdev_write_blocks(desc, io_ch[1], buf, 20, 1, io_done, &ctx1);
2283 : 5 : CU_ASSERT(rc == 0);
2284 : 5 : poll_threads();
2285 : 5 : CU_ASSERT(stub_channel_outstanding_cnt(io_target) == 0);
2286 : 5 : CU_ASSERT(!TAILQ_EMPTY(&bdev_ch[1]->io_locked));
2287 [ - + ]: 5 : CU_ASSERT(g_io_done == false);
2288 : :
2289 : : /* Try to unlock the lba range using thread 1's io_ch. This should fail. */
2290 : 5 : rc = bdev_unlock_lba_range(desc, io_ch[1], 20, 10, unlock_lba_range_done, &ctx1);
2291 : 5 : CU_ASSERT(rc == -EINVAL);
2292 : :
2293 : : /* Now create a new channel and submit a write I/O with it. This should also be queued.
2294 : : * The new channel should inherit the active locks from the bdev's internal list.
2295 : : */
2296 : 5 : set_thread(2);
2297 : 5 : io_ch[2] = spdk_bdev_get_io_channel(desc);
2298 : 5 : bdev_ch[2] = spdk_io_channel_get_ctx(io_ch[2]);
2299 : 5 : CU_ASSERT(io_ch[2] != NULL);
2300 : :
2301 : 5 : g_io_done2 = false;
2302 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch[2]->io_locked));
2303 : 5 : rc = spdk_bdev_write_blocks(desc, io_ch[2], buf, 22, 2, io_done2, &ctx2);
2304 : 5 : CU_ASSERT(rc == 0);
2305 : 5 : poll_threads();
2306 : 5 : CU_ASSERT(stub_channel_outstanding_cnt(io_target) == 0);
2307 : 5 : CU_ASSERT(!TAILQ_EMPTY(&bdev_ch[2]->io_locked));
2308 [ - + ]: 5 : CU_ASSERT(g_io_done2 == false);
2309 : :
2310 : 5 : set_thread(0);
2311 : 5 : rc = bdev_unlock_lba_range(desc, io_ch[0], 20, 10, unlock_lba_range_done, &ctx0);
2312 : 5 : CU_ASSERT(rc == 0);
2313 : 5 : poll_threads();
2314 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch[0]->locked_ranges));
2315 : :
2316 : : /* The LBA range is unlocked, so the write IOs should now have started execution. */
2317 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch[1]->io_locked));
2318 : 5 : CU_ASSERT(TAILQ_EMPTY(&bdev_ch[2]->io_locked));
2319 : :
2320 : 5 : set_thread(1);
2321 : 5 : CU_ASSERT(stub_channel_outstanding_cnt(io_target) == 1);
2322 : 5 : stub_complete_io(io_target, 1);
2323 : 5 : set_thread(2);
2324 : 5 : CU_ASSERT(stub_channel_outstanding_cnt(io_target) == 1);
2325 : 5 : stub_complete_io(io_target, 1);
2326 : :
2327 : 5 : poll_threads();
2328 [ - + ]: 5 : CU_ASSERT(g_io_done == true);
2329 [ - + ]: 5 : CU_ASSERT(g_io_done2 == true);
2330 : :
2331 : : /* Tear down the channels */
2332 : 5 : set_thread(0);
2333 : 5 : spdk_put_io_channel(io_ch[0]);
2334 : 5 : set_thread(1);
2335 : 5 : spdk_put_io_channel(io_ch[1]);
2336 : 5 : set_thread(2);
2337 : 5 : spdk_put_io_channel(io_ch[2]);
2338 : 5 : poll_threads();
2339 : 5 : set_thread(0);
2340 : 5 : teardown_test();
2341 : 5 : }
2342 : :
2343 : : /* spdk_bdev_reset() freezes and unfreezes I/O channels by using spdk_for_each_channel().
2344 : : * spdk_bdev_unregister() calls spdk_io_device_unregister() in the end. However
2345 : : * spdk_io_device_unregister() fails if it is called while executing spdk_for_each_channel().
2346 : : * Hence, in this case, spdk_io_device_unregister() is deferred until spdk_bdev_reset()
2347 : : * completes. Test this behavior.
2348 : : */
2349 : : static void
2350 : 5 : unregister_during_reset(void)
2351 : : {
2352 : : struct spdk_io_channel *io_ch[2];
2353 : 5 : bool done_reset = false, done_unregister = false;
2354 : : int rc;
2355 : :
2356 : 5 : setup_test();
2357 : 5 : set_thread(0);
2358 : :
2359 : 5 : io_ch[0] = spdk_bdev_get_io_channel(g_desc);
2360 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(io_ch[0] != NULL);
2361 : :
2362 : 5 : set_thread(1);
2363 : :
2364 : 5 : io_ch[1] = spdk_bdev_get_io_channel(g_desc);
2365 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(io_ch[1] != NULL);
2366 : :
2367 : 5 : set_thread(0);
2368 : :
2369 : 5 : CU_ASSERT(g_bdev.bdev.internal.reset_in_progress == NULL);
2370 : :
2371 : 5 : rc = spdk_bdev_reset(g_desc, io_ch[0], reset_done, &done_reset);
2372 : 5 : CU_ASSERT(rc == 0);
2373 : :
2374 : 5 : set_thread(0);
2375 : :
2376 : 5 : poll_thread_times(0, 1);
2377 : :
2378 : 5 : spdk_bdev_close(g_desc);
2379 : 5 : spdk_bdev_unregister(&g_bdev.bdev, _bdev_unregistered, &done_unregister);
2380 : :
2381 [ - + ]: 5 : CU_ASSERT(done_reset == false);
2382 [ - + ]: 5 : CU_ASSERT(done_unregister == false);
2383 : :
2384 : 5 : poll_threads();
2385 : :
2386 : 5 : stub_complete_io(g_bdev.io_target, 0);
2387 : :
2388 : 5 : poll_threads();
2389 : :
2390 [ - + ]: 5 : CU_ASSERT(done_reset == true);
2391 [ - + ]: 5 : CU_ASSERT(done_unregister == false);
2392 : :
2393 : 5 : spdk_put_io_channel(io_ch[0]);
2394 : :
2395 : 5 : set_thread(1);
2396 : :
2397 : 5 : spdk_put_io_channel(io_ch[1]);
2398 : :
2399 : 5 : poll_threads();
2400 : :
2401 [ - + ]: 5 : CU_ASSERT(done_unregister == true);
2402 : :
2403 : : /* Restore the original g_bdev so that we can use teardown_test(). */
2404 : 5 : set_thread(0);
2405 : 5 : register_bdev(&g_bdev, "ut_bdev", &g_io_device);
2406 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &g_desc);
2407 : 5 : teardown_test();
2408 : 5 : }
2409 : :
2410 : : static void
2411 : 5 : bdev_init_wt_cb(void *done, int rc)
2412 : : {
2413 : 5 : }
2414 : :
2415 : : static int
2416 : 5 : wrong_thread_setup(void)
2417 : : {
2418 : 5 : allocate_cores(1);
2419 : 5 : allocate_threads(2);
2420 : 5 : set_thread(0);
2421 : :
2422 : 5 : spdk_io_device_register(&g_accel_io_device, ut_accel_ch_create_cb,
2423 : : ut_accel_ch_destroy_cb, 0, NULL);
2424 : 5 : spdk_bdev_initialize(bdev_init_wt_cb, NULL);
2425 : 5 : spdk_io_device_register(&g_io_device, stub_create_ch, stub_destroy_ch,
2426 : : sizeof(struct ut_bdev_channel), NULL);
2427 : :
2428 : 5 : set_thread(1);
2429 : :
2430 : 5 : return 0;
2431 : : }
2432 : :
2433 : : static int
2434 : 5 : wrong_thread_teardown(void)
2435 : : {
2436 : 5 : int rc = 0;
2437 : :
2438 : 5 : set_thread(0);
2439 : :
2440 : 5 : g_teardown_done = false;
2441 : 5 : spdk_io_device_unregister(&g_io_device, NULL);
2442 : 5 : spdk_bdev_finish(finish_cb, NULL);
2443 : 5 : poll_threads();
2444 [ - + ]: 5 : memset(&g_bdev, 0, sizeof(g_bdev));
2445 [ - + - + ]: 5 : if (!g_teardown_done) {
2446 [ # # # # ]: 0 : fprintf(stderr, "%s:%d %s: teardown not done\n", __FILE__, __LINE__, __func__);
2447 : 0 : rc = -1;
2448 : : }
2449 : 5 : g_teardown_done = false;
2450 : :
2451 : 5 : spdk_io_device_unregister(&g_accel_io_device, NULL);
2452 : 5 : free_threads();
2453 : 5 : free_cores();
2454 : :
2455 : 5 : return rc;
2456 : : }
2457 : :
2458 : : static void
2459 : 10 : _bdev_unregistered_wt(void *ctx, int rc)
2460 : : {
2461 : 10 : struct spdk_thread **threadp = ctx;
2462 : :
2463 : 10 : *threadp = spdk_get_thread();
2464 : 10 : }
2465 : :
2466 : : static void
2467 : 5 : spdk_bdev_register_wt(void)
2468 : : {
2469 : 5 : struct spdk_bdev bdev = { 0 };
2470 : : int rc;
2471 : 4 : struct spdk_thread *unreg_thread;
2472 : :
2473 : 5 : bdev.name = "wt_bdev";
2474 : 5 : bdev.fn_table = &fn_table;
2475 : 5 : bdev.module = &bdev_ut_if;
2476 : 5 : bdev.blocklen = 4096;
2477 : 5 : bdev.blockcnt = 1024;
2478 : :
2479 : : /* Can register only on app thread */
2480 : 5 : rc = spdk_bdev_register(&bdev);
2481 : 5 : CU_ASSERT(rc == -EINVAL);
2482 : :
2483 : : /* Can unregister on any thread */
2484 : 5 : set_thread(0);
2485 : 5 : rc = spdk_bdev_register(&bdev);
2486 : 5 : CU_ASSERT(rc == 0);
2487 : 5 : set_thread(1);
2488 : 5 : unreg_thread = NULL;
2489 : 5 : spdk_bdev_unregister(&bdev, _bdev_unregistered_wt, &unreg_thread);
2490 : 5 : poll_threads();
2491 : 5 : CU_ASSERT(unreg_thread == spdk_get_thread());
2492 : :
2493 : : /* Can unregister by name on any thread */
2494 : 5 : set_thread(0);
2495 : 5 : rc = spdk_bdev_register(&bdev);
2496 : 5 : CU_ASSERT(rc == 0);
2497 : 5 : set_thread(1);
2498 : 5 : unreg_thread = NULL;
2499 : 5 : rc = spdk_bdev_unregister_by_name(bdev.name, bdev.module, _bdev_unregistered_wt,
2500 : : &unreg_thread);
2501 : 5 : CU_ASSERT(rc == 0);
2502 : 5 : poll_threads();
2503 : 5 : CU_ASSERT(unreg_thread == spdk_get_thread());
2504 : 5 : }
2505 : :
2506 : : static void
2507 : 10 : wait_for_examine_cb(void *arg)
2508 : : {
2509 : 10 : struct spdk_thread **thread = arg;
2510 : :
2511 : 10 : *thread = spdk_get_thread();
2512 : 10 : }
2513 : :
2514 : : static void
2515 : 5 : spdk_bdev_examine_wt(void)
2516 : : {
2517 : : int rc;
2518 [ - + ]: 5 : bool save_auto_examine = g_bdev_opts.bdev_auto_examine;
2519 : 4 : struct spdk_thread *thread;
2520 : :
2521 : 5 : g_bdev_opts.bdev_auto_examine = false;
2522 : :
2523 : 5 : set_thread(0);
2524 : 5 : register_bdev(&g_bdev, "ut_bdev_wt", &g_io_device);
2525 : 5 : CU_ASSERT(spdk_bdev_get_by_name("ut_bdev_wt") != NULL);
2526 : 5 : set_thread(1);
2527 : :
2528 : : /* Can examine only on the app thread */
2529 : 5 : rc = spdk_bdev_examine("ut_bdev_wt");
2530 : 5 : CU_ASSERT(rc == -EINVAL);
2531 : 5 : unregister_bdev(&g_bdev);
2532 : 5 : CU_ASSERT(spdk_bdev_get_by_name("ut_bdev_wt") == NULL);
2533 : :
2534 : : /* Can wait for examine on app thread, callback called on app thread. */
2535 : 5 : set_thread(0);
2536 : 5 : register_bdev(&g_bdev, "ut_bdev_wt", &g_io_device);
2537 : 5 : CU_ASSERT(spdk_bdev_get_by_name("ut_bdev_wt") != NULL);
2538 : 5 : thread = NULL;
2539 : 5 : rc = spdk_bdev_wait_for_examine(wait_for_examine_cb, &thread);
2540 : 5 : CU_ASSERT(rc == 0);
2541 : 5 : poll_threads();
2542 : 5 : CU_ASSERT(thread == spdk_get_thread());
2543 : 5 : unregister_bdev(&g_bdev);
2544 : 5 : CU_ASSERT(spdk_bdev_get_by_name("ut_bdev_wt") == NULL);
2545 : :
2546 : : /* Can wait for examine on non-app thread, callback called on same thread. */
2547 : 5 : set_thread(0);
2548 : 5 : register_bdev(&g_bdev, "ut_bdev_wt", &g_io_device);
2549 : 5 : CU_ASSERT(spdk_bdev_get_by_name("ut_bdev_wt") != NULL);
2550 : 5 : thread = NULL;
2551 : 5 : rc = spdk_bdev_wait_for_examine(wait_for_examine_cb, &thread);
2552 : 5 : CU_ASSERT(rc == 0);
2553 : 5 : poll_threads();
2554 : 5 : CU_ASSERT(thread == spdk_get_thread());
2555 : 5 : unregister_bdev(&g_bdev);
2556 : 5 : CU_ASSERT(spdk_bdev_get_by_name("ut_bdev_wt") == NULL);
2557 : :
2558 : 5 : unregister_bdev(&g_bdev);
2559 : 5 : g_bdev_opts.bdev_auto_examine = save_auto_examine;
2560 : 5 : }
2561 : :
2562 : : static void
2563 : 5 : event_notify_and_close(void)
2564 : : {
2565 : 5 : int resize_notify_count = 0;
2566 : 5 : struct spdk_bdev_desc *desc = NULL;
2567 : : struct spdk_bdev *bdev;
2568 : : int rc;
2569 : :
2570 : 5 : setup_test();
2571 : 5 : set_thread(0);
2572 : :
2573 : : /* setup_test() automatically opens the bdev, but this test needs to do
2574 : : * that in a different way. */
2575 : 5 : spdk_bdev_close(g_desc);
2576 : 5 : poll_threads();
2577 : :
2578 : 5 : set_thread(1);
2579 : :
2580 : 5 : rc = spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, &resize_notify_count, &desc);
2581 : 5 : CU_ASSERT(rc == 0);
2582 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(desc != NULL);
2583 : :
2584 : 5 : bdev = spdk_bdev_desc_get_bdev(desc);
2585 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(bdev != NULL);
2586 : :
2587 : : /* Test a normal case that a resize event is notified. */
2588 : 5 : set_thread(0);
2589 : :
2590 : 5 : rc = spdk_bdev_notify_blockcnt_change(bdev, 1024 * 2);
2591 : 5 : CU_ASSERT(rc == 0);
2592 : 5 : CU_ASSERT(bdev->blockcnt == 1024 * 2);
2593 : 5 : CU_ASSERT(desc->refs == 1);
2594 : 5 : CU_ASSERT(resize_notify_count == 0);
2595 : :
2596 : 5 : poll_threads();
2597 : :
2598 : 5 : CU_ASSERT(desc->refs == 0);
2599 : 5 : CU_ASSERT(resize_notify_count == 1);
2600 : :
2601 : : /* Test a complex case if the bdev is closed after two event_notify messages are sent,
2602 : : * then both event_notify messages are discarded and the desc is freed.
2603 : : */
2604 : 5 : rc = spdk_bdev_notify_blockcnt_change(bdev, 1024 * 3);
2605 : 5 : CU_ASSERT(rc == 0);
2606 : 5 : CU_ASSERT(bdev->blockcnt == 1024 * 3);
2607 : 5 : CU_ASSERT(desc->refs == 1);
2608 : 5 : CU_ASSERT(resize_notify_count == 1);
2609 : :
2610 : 5 : rc = spdk_bdev_notify_blockcnt_change(bdev, 1024 * 4);
2611 : 5 : CU_ASSERT(rc == 0);
2612 : 5 : CU_ASSERT(bdev->blockcnt == 1024 * 4);
2613 : 5 : CU_ASSERT(desc->refs == 2);
2614 : 5 : CU_ASSERT(resize_notify_count == 1);
2615 : :
2616 : 5 : set_thread(1);
2617 : :
2618 : 5 : spdk_bdev_close(desc);
2619 [ - + ]: 5 : CU_ASSERT(desc->closed == true);
2620 : 5 : CU_ASSERT(desc->refs == 2);
2621 : 5 : CU_ASSERT(resize_notify_count == 1);
2622 : :
2623 : 5 : poll_threads();
2624 : :
2625 : 5 : CU_ASSERT(resize_notify_count == 1);
2626 : :
2627 : 5 : set_thread(0);
2628 : :
2629 : : /* Restore g_desc. Then, we can execute teardown_test(). */
2630 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &g_desc);
2631 : 5 : teardown_test();
2632 : 5 : }
2633 : :
2634 : : /* There was a bug that bdev_channel_poll_qos() called spdk_for_each_channel()
2635 : : * after spdk_io_device_unregister() is called for a bdev.
2636 : : *
2637 : : * This occurred in the following sequence.
2638 : : * - There was a bdev and a channel for it.
2639 : : * - QoS was enabled and started.
2640 : : * - spdk_bdev_unregister() was called. However, there was a open descriptor.
2641 : : * Hence, remove notification was sent and unregistration was pending.
2642 : : * - Receiving a event notification, spdk_put_io_channel() and spdk_bdev_close() were
2643 : : * called. In spdk_bdev_close(), the existing QoS was unbound and a message was sent
2644 : : * to it, and then the pending spdk_io_device_unregister() was finally executed.
2645 : : * - If bdev_channel_poll_qos() was executed before the message was processed,
2646 : : * bdev_channel_poll_qos() called spdk_bdev_for_each_channel() and hit assert().
2647 : : *
2648 : : * The fix was in this case bdev_channel_poll_qos() returned immediately because QoS
2649 : : * was not enabled. bdev_qos_destroy() created a new disabled QoS and swapped it with
2650 : : * the existing QoS.
2651 : : *
2652 : : * This test case was added to avoid degradation in future.
2653 : : */
2654 : : static void
2655 : 5 : unregister_and_qos_poller(void)
2656 : : {
2657 : : struct spdk_io_channel *io_ch;
2658 : : struct spdk_bdev_channel *bdev_ch;
2659 : 5 : struct spdk_bdev_desc *desc = NULL;
2660 : : struct spdk_bdev_qos *old_qos;
2661 : 5 : uint64_t limits[SPDK_BDEV_QOS_NUM_RATE_LIMIT_TYPES] = {};
2662 : 5 : bool remove_notify = false, done_unregister = false;
2663 : 5 : int status = -1, rc;
2664 : :
2665 : 5 : setup_test();
2666 : 5 : set_thread(0);
2667 : :
2668 : 5 : MOCK_SET(spdk_get_ticks, 10);
2669 : :
2670 : : /* setup_test() automatically opens the bdev, but this test needs to do
2671 : : * that in a different way.
2672 : : */
2673 : 5 : spdk_bdev_close(g_desc);
2674 : 5 : poll_threads();
2675 : :
2676 : : /* We want to get remove event notification to check if unregistration
2677 : : * is deferred.
2678 : : */
2679 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, &remove_notify, &desc);
2680 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(desc != NULL);
2681 [ - + ]: 5 : CU_ASSERT(remove_notify == false);
2682 : :
2683 : 5 : io_ch = spdk_bdev_get_io_channel(desc);
2684 [ - + ]: 5 : SPDK_CU_ASSERT_FATAL(io_ch != NULL);
2685 : 5 : bdev_ch = spdk_io_channel_get_ctx(io_ch);
2686 : :
2687 : 5 : limits[SPDK_BDEV_QOS_RW_IOPS_RATE_LIMIT] = 10000;
2688 : 5 : limits[SPDK_BDEV_QOS_RW_BPS_RATE_LIMIT] = 0;
2689 : 5 : limits[SPDK_BDEV_QOS_R_BPS_RATE_LIMIT] = 0;
2690 : 5 : limits[SPDK_BDEV_QOS_W_BPS_RATE_LIMIT] = 0;
2691 : 5 : spdk_bdev_set_qos_rate_limits(&g_bdev.bdev, limits, qos_dynamic_enable_done, &status);
2692 : 5 : poll_threads();
2693 : 5 : CU_ASSERT(status == 0);
2694 : 5 : CU_ASSERT((bdev_ch->flags & BDEV_CH_QOS_ENABLED) != 0);
2695 : :
2696 : 5 : old_qos = g_bdev.bdev.internal.qos;
2697 : 5 : CU_ASSERT(old_qos != NULL);
2698 : :
2699 : 5 : spdk_bdev_unregister(&g_bdev.bdev, _bdev_unregistered, &done_unregister);
2700 [ - + ]: 5 : CU_ASSERT(done_unregister == false);
2701 [ - + ]: 5 : CU_ASSERT(remove_notify == false);
2702 : :
2703 : 5 : poll_threads();
2704 [ - + ]: 5 : CU_ASSERT(done_unregister == false);
2705 [ - + ]: 5 : CU_ASSERT(remove_notify == true);
2706 : :
2707 : 5 : spdk_put_io_channel(io_ch);
2708 : 5 : spdk_bdev_close(desc);
2709 : :
2710 : 5 : CU_ASSERT(g_bdev.bdev.internal.qos != NULL);
2711 : 5 : CU_ASSERT(g_bdev.bdev.internal.qos->thread == NULL);
2712 : 5 : CU_ASSERT(old_qos != g_bdev.bdev.internal.qos);
2713 : :
2714 : : /* bdev_channel_poll_qos() has a chance to be executed in this small window. */
2715 : 5 : spdk_delay_us(SPDK_BDEV_QOS_TIMESLICE_IN_USEC);
2716 : :
2717 : 5 : rc = bdev_channel_poll_qos(&g_bdev.bdev);
2718 : 5 : CU_ASSERT(rc == SPDK_POLLER_IDLE);
2719 : :
2720 : 5 : poll_threads();
2721 : :
2722 [ - + ]: 5 : CU_ASSERT(done_unregister == true);
2723 : :
2724 : : /* Restore the original g_bdev so that we can use teardown_test(). */
2725 : 5 : set_thread(0);
2726 : 5 : register_bdev(&g_bdev, "ut_bdev", &g_io_device);
2727 : 5 : spdk_bdev_open_ext("ut_bdev", true, _bdev_event_cb, NULL, &g_desc);
2728 : 5 : teardown_test();
2729 : 5 : }
2730 : :
2731 : : int
2732 : 5 : main(int argc, char **argv)
2733 : : {
2734 : 5 : CU_pSuite suite = NULL;
2735 : 5 : CU_pSuite suite_wt = NULL;
2736 : : unsigned int num_failures;
2737 : :
2738 : 5 : CU_initialize_registry();
2739 : :
2740 : 5 : suite = CU_add_suite("bdev", NULL, NULL);
2741 : 5 : suite_wt = CU_add_suite("bdev_wrong_thread", wrong_thread_setup, wrong_thread_teardown);
2742 : :
2743 : 5 : CU_ADD_TEST(suite, basic);
2744 : 5 : CU_ADD_TEST(suite, unregister_and_close);
2745 : 5 : CU_ADD_TEST(suite, unregister_and_close_different_threads);
2746 : 5 : CU_ADD_TEST(suite, basic_qos);
2747 : 5 : CU_ADD_TEST(suite, put_channel_during_reset);
2748 : 5 : CU_ADD_TEST(suite, aborted_reset);
2749 : 5 : CU_ADD_TEST(suite, aborted_reset_no_outstanding_io);
2750 : 5 : CU_ADD_TEST(suite, io_during_reset);
2751 : 5 : CU_ADD_TEST(suite, reset_completions);
2752 : 5 : CU_ADD_TEST(suite, io_during_qos_queue);
2753 : 5 : CU_ADD_TEST(suite, io_during_qos_reset);
2754 : 5 : CU_ADD_TEST(suite, enomem);
2755 : 5 : CU_ADD_TEST(suite, enomem_multi_bdev);
2756 : 5 : CU_ADD_TEST(suite, enomem_multi_bdev_unregister);
2757 : 5 : CU_ADD_TEST(suite, enomem_multi_io_target);
2758 : 5 : CU_ADD_TEST(suite, qos_dynamic_enable);
2759 : 5 : CU_ADD_TEST(suite, bdev_histograms_mt);
2760 : 5 : CU_ADD_TEST(suite, bdev_set_io_timeout_mt);
2761 : 5 : CU_ADD_TEST(suite, lock_lba_range_then_submit_io);
2762 : 5 : CU_ADD_TEST(suite, unregister_during_reset);
2763 : 5 : CU_ADD_TEST(suite_wt, spdk_bdev_register_wt);
2764 : 5 : CU_ADD_TEST(suite_wt, spdk_bdev_examine_wt);
2765 : 5 : CU_ADD_TEST(suite, event_notify_and_close);
2766 : 5 : CU_ADD_TEST(suite, unregister_and_qos_poller);
2767 : :
2768 : 5 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
2769 : 5 : CU_cleanup_registry();
2770 : 5 : return num_failures;
2771 : : }
|