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