2 * Copyright (c) 2018 Benjamin Marzinski, Redhat
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
28 #include "../libmultipath/checkers/directio.c"
32 struct io_event mock_events[AIO_GROUP_SIZE]; /* same as the checker max */
34 struct timespec zero_timeout = {0};
35 struct timespec full_timeout = { .tv_sec = -1 };
37 int __real_ioctl(int fd, unsigned long request, void *argp);
39 int __wrap_ioctl(int fd, unsigned long request, void *argp)
43 return __real_ioctl(fd, request, argp);
45 int *blocksize = (int *)argp;
47 assert_int_equal(fd, test_fd);
48 assert_int_equal(request, BLKBSZGET);
49 assert_non_null(blocksize);
50 *blocksize = mock_type(int);
55 int __real_fcntl(int fd, int cmd, long arg);
57 int __wrap_fcntl(int fd, int cmd, long arg)
60 return __real_fcntl(fd, cmd, arg);
62 assert_int_equal(fd, test_fd);
63 assert_int_equal(cmd, F_GETFL);
68 int __real___fxstat(int ver, int fd, struct stat *statbuf);
70 int __wrap___fxstat(int ver, int fd, struct stat *statbuf)
73 return __real___fxstat(ver, fd, statbuf);
75 assert_int_equal(fd, test_fd);
76 assert_non_null(statbuf);
77 memset(statbuf, 0, sizeof(struct stat));
82 int __real_io_setup(int maxevents, io_context_t *ctxp);
84 int __wrap_io_setup(int maxevents, io_context_t *ctxp)
88 int ret = mock_type(int);
89 assert_int_equal(ret, __real_io_setup(maxevents, ctxp));
92 return mock_type(int);
96 int __real_io_destroy(io_context_t ctx);
98 int __wrap_io_destroy(io_context_t ctx)
102 int ret = mock_type(int);
103 assert_int_equal(ret, __real_io_destroy(ctx));
106 return mock_type(int);
110 int __real_io_submit(io_context_t ctx, long nr, struct iocb *ios[]);
112 int __wrap_io_submit(io_context_t ctx, long nr, struct iocb *ios[])
115 struct timespec dev_delay = { .tv_nsec = 100000 };
116 int ret = mock_type(int);
117 assert_int_equal(ret, __real_io_submit(ctx, nr, ios));
118 nanosleep(&dev_delay, NULL);
121 return mock_type(int);
125 int __real_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt);
127 int __wrap_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt)
131 return __real_io_cancel(ctx, iocb, evt);
133 return mock_type(int);
137 int __real_io_getevents(io_context_t ctx, long min_nr, long nr,
138 struct io_event *events, struct timespec *timeout);
140 int __wrap_io_getevents(io_context_t ctx, long min_nr, long nr,
141 struct io_event *events, struct timespec *timeout)
145 struct timespec *sleep_tmo;
147 struct io_event *evs;
150 assert_non_null(timeout);
151 nr_evs = mock_type(int);
152 assert_true(nr_evs <= nr);
156 mock_ptr_type(struct timespec *);
157 mock_ptr_type(struct io_event *);
158 assert_int_equal(nr_evs, __real_io_getevents(ctx, min_nr, nr_evs,
161 sleep_tmo = mock_ptr_type(struct timespec *);
163 if (sleep_tmo->tv_sec < 0)
164 nanosleep(timeout, NULL);
166 nanosleep(sleep_tmo, NULL);
172 evs = mock_ptr_type(struct io_event *);
173 for (i = 0; i < nr_evs; i++)
180 static void return_io_getevents_none(void)
182 will_return(__wrap_io_getevents, 0);
185 static void return_io_getevents_nr(struct timespec *ts, int nr,
186 struct async_req **reqs, int *res)
190 for(i = 0; i < nr; i++) {
191 mock_events[i + ev_off].obj = &reqs[i]->io;
193 mock_events[i + ev_off].res = reqs[i]->blksize;
196 will_return(__wrap_io_getevents, (nr > 128)? 128 : nr);
197 will_return(__wrap_io_getevents, ts);
198 will_return(__wrap_io_getevents, &mock_events[off + ev_off]);
204 will_return(__wrap_io_getevents, 0);
208 void do_check_state(struct checker *c, int sync, int timeout, int chk_state)
210 struct directio_context * ct = (struct directio_context *)c->context;
213 will_return(__wrap_io_submit, 1);
214 assert_int_equal(check_state(test_fd, ct, sync, timeout), chk_state);
215 assert_int_equal(ev_off, 0);
216 memset(mock_events, 0, sizeof(mock_events));
219 void do_libcheck_reset(int nr_aio_grps)
222 struct aio_group *aio_grp;
224 list_for_each_entry(aio_grp, &aio_grp_list, node)
226 assert_int_equal(count, nr_aio_grps);
227 for (count = 0; count < nr_aio_grps; count++)
228 will_return(__wrap_io_destroy, 0);
230 assert_true(list_empty(&aio_grp_list));
231 assert_int_equal(ioctx_count, 0);
234 static void do_libcheck_init(struct checker *c, int blocksize,
235 struct async_req **req)
237 struct directio_context * ct;
240 will_return(__wrap_ioctl, blocksize);
241 assert_int_equal(libcheck_init(c), 0);
242 ct = (struct directio_context *)c->context;
244 assert_non_null(ct->aio_grp);
245 assert_non_null(ct->req);
249 /* don't check fake blocksize on real devices */
250 assert_int_equal(ct->req->blksize, blocksize);
254 static int is_checker_running(struct checker *c)
256 struct directio_context * ct = (struct directio_context *)c->context;
260 static struct aio_group *get_aio_grp(struct checker *c)
262 struct directio_context * ct = (struct directio_context *)c->context;
268 static void check_aio_grp(struct aio_group *aio_grp, int holders,
272 struct list_head *item;
274 list_for_each(item, &aio_grp->orphans)
276 assert_int_equal(holders, aio_grp->holders);
277 assert_int_equal(orphans, count);
280 /* simple resetting test */
281 static void test_reset(void **state)
283 assert_true(list_empty(&aio_grp_list));
284 do_libcheck_reset(0);
287 /* tests initializing, then resetting, and then initializing again */
288 static void test_init_reset_init(void **state)
290 struct checker c = {0};
291 struct aio_group *aio_grp, *tmp_grp;
293 assert_true(list_empty(&aio_grp_list));
294 will_return(__wrap_io_setup, 0);
295 do_libcheck_init(&c, 4096, NULL);
296 aio_grp = get_aio_grp(&c);
297 check_aio_grp(aio_grp, 1, 0);
298 list_for_each_entry(tmp_grp, &aio_grp_list, node)
299 assert_ptr_equal(aio_grp, tmp_grp);
301 check_aio_grp(aio_grp, 0, 0);
302 do_libcheck_reset(1);
303 will_return(__wrap_io_setup, 0);
304 do_libcheck_init(&c, 4096, NULL);
305 aio_grp = get_aio_grp(&c);
306 check_aio_grp(aio_grp, 1, 0);
307 list_for_each_entry(tmp_grp, &aio_grp_list, node)
308 assert_ptr_equal(aio_grp, tmp_grp);
310 check_aio_grp(aio_grp, 0, 0);
311 do_libcheck_reset(1);
314 /* test initializing and then freeing 4096 checkers */
315 static void test_init_free(void **state)
318 struct checker c[4096] = {0};
319 struct aio_group *aio_grp;
321 assert_true(list_empty(&aio_grp_list));
322 will_return(__wrap_io_setup, 0);
323 will_return(__wrap_io_setup, 0);
324 will_return(__wrap_io_setup, 0);
325 will_return(__wrap_io_setup, 0);
326 for (i = 0; i < 4096; i++) {
327 struct directio_context * ct;
330 do_libcheck_init(&c[i], 512, NULL);
332 do_libcheck_init(&c[i], 1024, NULL);
334 do_libcheck_init(&c[i], 4096, NULL);
335 ct = (struct directio_context *)c[i].context;
336 assert_non_null(ct->aio_grp);
338 aio_grp = ct->aio_grp;
340 assert_ptr_equal(ct->aio_grp, aio_grp);
341 assert_int_equal(aio_grp->holders, (i & 1023) + 1);
345 list_for_each_entry(aio_grp, &aio_grp_list, node)
347 assert_int_equal(count, 4);
348 for (i = 0; i < 4096; i++) {
349 struct directio_context * ct = (struct directio_context *)c[i].context;
351 aio_grp = ct->aio_grp;
352 libcheck_free(&c[i]);
353 assert_int_equal(aio_grp->holders, 1023 - (i & 1023));
355 list_for_each_entry(aio_grp, &aio_grp_list, node)
356 assert_int_equal(aio_grp->holders, 0);
357 do_libcheck_reset(4);
360 /* check mixed initializing and freeing 4096 checkers */
361 static void test_multi_init_free(void **state)
364 struct checker c[4096] = {0};
365 struct aio_group *aio_grp;
367 assert_true(list_empty(&aio_grp_list));
368 will_return(__wrap_io_setup, 0);
369 will_return(__wrap_io_setup, 0);
370 will_return(__wrap_io_setup, 0);
371 will_return(__wrap_io_setup, 0);
372 for (count = 0, i = 0; i < 4096; count++) {
373 /* usually init, but occasionally free checkers */
374 if (count == 0 || (count % 5 != 0 && count % 7 != 0)) {
375 do_libcheck_init(&c[i], 4096, NULL);
379 libcheck_free(&c[i]);
383 list_for_each_entry(aio_grp, &aio_grp_list, node) {
384 assert_int_equal(aio_grp->holders, 1024);
387 assert_int_equal(count, 4);
388 for (count = 0, i = 4096; i > 0; count++) {
389 /* usually free, but occasionally init checkers */
390 if (count == 0 || (count % 5 != 0 && count % 7 != 0)) {
392 libcheck_free(&c[i]);
394 do_libcheck_init(&c[i], 4096, NULL);
398 do_libcheck_reset(4);
401 /* simple single checker sync test */
402 static void test_check_state_simple(void **state)
404 struct checker c = {0};
405 struct async_req *req;
408 assert_true(list_empty(&aio_grp_list));
409 will_return(__wrap_io_setup, 0);
410 do_libcheck_init(&c, 4096, &req);
411 return_io_getevents_nr(NULL, 1, &req, &res);
412 do_check_state(&c, 1, 30, PATH_UP);
414 do_libcheck_reset(1);
417 /* test sync timeout */
418 static void test_check_state_timeout(void **state)
420 struct checker c = {0};
421 struct aio_group *aio_grp;
423 assert_true(list_empty(&aio_grp_list));
424 will_return(__wrap_io_setup, 0);
425 do_libcheck_init(&c, 4096, NULL);
426 aio_grp = get_aio_grp(&c);
427 return_io_getevents_none();
428 will_return(__wrap_io_cancel, 0);
429 do_check_state(&c, 1, 30, PATH_DOWN);
430 check_aio_grp(aio_grp, 1, 0);
432 /* io_cancel will return negative value on timeout, so it happens again
433 * when freeing the checker */
434 will_return(__wrap_io_cancel, 0);
437 do_libcheck_reset(1);
440 /* test async timeout */
441 static void test_check_state_async_timeout(void **state)
443 struct checker c = {0};
444 struct aio_group *aio_grp;
446 assert_true(list_empty(&aio_grp_list));
447 will_return(__wrap_io_setup, 0);
448 do_libcheck_init(&c, 4096, NULL);
449 aio_grp = get_aio_grp(&c);
450 return_io_getevents_none();
451 do_check_state(&c, 0, 3, PATH_PENDING);
452 return_io_getevents_none();
453 do_check_state(&c, 0, 3, PATH_PENDING);
454 return_io_getevents_none();
455 do_check_state(&c, 0, 3, PATH_PENDING);
456 return_io_getevents_none();
457 will_return(__wrap_io_cancel, 0);
458 do_check_state(&c, 0, 3, PATH_DOWN);
459 check_aio_grp(aio_grp, 1, 0);
461 will_return(__wrap_io_cancel, 0);
464 do_libcheck_reset(1);
467 /* test freeing checkers with outstanding requests */
468 static void test_free_with_pending(void **state)
470 struct checker c[2] = {0};
471 struct aio_group *aio_grp;
472 struct async_req *req;
475 assert_true(list_empty(&aio_grp_list));
476 will_return(__wrap_io_setup, 0);
477 do_libcheck_init(&c[0], 4096, &req);
478 do_libcheck_init(&c[1], 4096, NULL);
479 aio_grp = get_aio_grp(c);
480 return_io_getevents_none();
481 do_check_state(&c[0], 0, 30, PATH_PENDING);
482 return_io_getevents_nr(NULL, 1, &req, &res);
483 return_io_getevents_none();
484 do_check_state(&c[1], 0, 30, PATH_PENDING);
485 assert_true(is_checker_running(&c[0]));
486 assert_true(is_checker_running(&c[1]));
487 check_aio_grp(aio_grp, 2, 0);
488 libcheck_free(&c[0]);
489 check_aio_grp(aio_grp, 1, 0);
490 will_return(__wrap_io_cancel, 0);
491 libcheck_free(&c[1]);
493 check_aio_grp(aio_grp, 1, 1); /* real cancel doesn't remove request */
495 check_aio_grp(aio_grp, 0, 0);
497 do_libcheck_reset(1);
500 /* test removing orpahed aio_group on free */
501 static void test_orphaned_aio_group(void **state)
503 struct checker c[AIO_GROUP_SIZE] = {0};
504 struct aio_group *aio_grp, *tmp_grp;
507 assert_true(list_empty(&aio_grp_list));
508 will_return(__wrap_io_setup, 0);
509 for (i = 0; i < AIO_GROUP_SIZE; i++) {
510 do_libcheck_init(&c[i], 4096, NULL);
511 return_io_getevents_none();
512 do_check_state(&c[i], 0, 30, PATH_PENDING);
514 aio_grp = get_aio_grp(c);
515 check_aio_grp(aio_grp, AIO_GROUP_SIZE, 0);
517 list_for_each_entry(tmp_grp, &aio_grp_list, node)
519 assert_int_equal(i, 1);
520 for (i = 0; i < AIO_GROUP_SIZE; i++) {
521 assert_true(is_checker_running(&c[i]));
522 will_return(__wrap_io_cancel, -1);
523 if (i == AIO_GROUP_SIZE - 1) {
524 /* remove the orphaned group and create a new one */
525 will_return(__wrap_io_destroy, 0);
527 libcheck_free(&c[i]);
529 do_libcheck_reset(0);
532 /* test sync timeout with failed cancel and cleanup by another
534 static void test_timeout_cancel_failed(void **state)
536 struct checker c[2] = {0};
537 struct aio_group *aio_grp;
538 struct async_req *reqs[2];
542 assert_true(list_empty(&aio_grp_list));
543 will_return(__wrap_io_setup, 0);
544 for (i = 0; i < 2; i++)
545 do_libcheck_init(&c[i], 4096, &reqs[i]);
546 aio_grp = get_aio_grp(c);
547 return_io_getevents_none();
548 will_return(__wrap_io_cancel, -1);
549 do_check_state(&c[0], 1, 30, PATH_DOWN);
550 assert_true(is_checker_running(&c[0]));
551 check_aio_grp(aio_grp, 2, 0);
552 return_io_getevents_none();
553 will_return(__wrap_io_cancel, -1);
554 do_check_state(&c[0], 1, 30, PATH_DOWN);
555 assert_true(is_checker_running(&c[0]));
556 return_io_getevents_nr(NULL, 1, &reqs[0], &res[0]);
557 return_io_getevents_nr(NULL, 1, &reqs[1], &res[1]);
558 do_check_state(&c[1], 1, 30, PATH_UP);
559 do_check_state(&c[0], 1, 30, PATH_UP);
560 for (i = 0; i < 2; i++) {
561 assert_false(is_checker_running(&c[i]));
562 libcheck_free(&c[i]);
564 do_libcheck_reset(1);
567 /* test async timeout with failed cancel and cleanup by another
569 static void test_async_timeout_cancel_failed(void **state)
571 struct checker c[2] = {0};
572 struct async_req *reqs[2];
576 assert_true(list_empty(&aio_grp_list));
577 will_return(__wrap_io_setup, 0);
578 for (i = 0; i < 2; i++)
579 do_libcheck_init(&c[i], 4096, &reqs[i]);
580 return_io_getevents_none();
581 do_check_state(&c[0], 0, 2, PATH_PENDING);
582 return_io_getevents_none();
583 do_check_state(&c[1], 0, 2, PATH_PENDING);
584 return_io_getevents_none();
585 do_check_state(&c[0], 0, 2, PATH_PENDING);
586 return_io_getevents_none();
587 do_check_state(&c[1], 0, 2, PATH_PENDING);
588 return_io_getevents_none();
589 will_return(__wrap_io_cancel, -1);
590 do_check_state(&c[0], 0, 2, PATH_DOWN);
592 /* can't pick which even gets returned on real devices */
593 return_io_getevents_nr(NULL, 1, &reqs[1], &res[1]);
594 do_check_state(&c[1], 0, 2, PATH_UP);
596 return_io_getevents_none();
597 will_return(__wrap_io_cancel, -1);
598 do_check_state(&c[0], 0, 2, PATH_DOWN);
599 assert_true(is_checker_running(&c[0]));
600 return_io_getevents_nr(NULL, 2, reqs, res);
601 do_check_state(&c[1], 0, 2, PATH_UP);
602 do_check_state(&c[0], 0, 2, PATH_UP);
603 for (i = 0; i < 2; i++) {
604 assert_false(is_checker_running(&c[i]));
605 libcheck_free(&c[i]);
607 do_libcheck_reset(1);
610 /* test orphaning a request, and having another checker clean it up */
611 static void test_orphan_checker_cleanup(void **state)
613 struct checker c[2] = {0};
614 struct async_req *reqs[2];
616 struct aio_group *aio_grp;
619 assert_true(list_empty(&aio_grp_list));
620 will_return(__wrap_io_setup, 0);
621 for (i = 0; i < 2; i++)
622 do_libcheck_init(&c[i], 4096, &reqs[i]);
623 aio_grp = get_aio_grp(c);
624 return_io_getevents_none();
625 do_check_state(&c[0], 0, 30, PATH_PENDING);
626 will_return(__wrap_io_cancel, -1);
627 check_aio_grp(aio_grp, 2, 0);
628 libcheck_free(&c[0]);
629 check_aio_grp(aio_grp, 2, 1);
630 return_io_getevents_nr(NULL, 2, reqs, res);
631 do_check_state(&c[1], 0, 2, PATH_UP);
632 check_aio_grp(aio_grp, 1, 0);
633 libcheck_free(&c[1]);
634 check_aio_grp(aio_grp, 0, 0);
635 do_libcheck_reset(1);
638 /* test orphaning a request, and having reset clean it up */
639 static void test_orphan_reset_cleanup(void **state)
642 struct aio_group *orphan_aio_grp, *tmp_aio_grp;
645 assert_true(list_empty(&aio_grp_list));
646 will_return(__wrap_io_setup, 0);
647 do_libcheck_init(&c, 4096, NULL);
648 orphan_aio_grp = get_aio_grp(&c);
649 return_io_getevents_none();
650 do_check_state(&c, 0, 30, PATH_PENDING);
651 will_return(__wrap_io_cancel, -1);
652 check_aio_grp(orphan_aio_grp, 1, 0);
654 check_aio_grp(orphan_aio_grp, 1, 1);
656 list_for_each_entry(tmp_aio_grp, &aio_grp_list, node) {
658 if (tmp_aio_grp == orphan_aio_grp)
661 assert_int_equal(count, 1);
662 assert_int_equal(found, 1);
663 do_libcheck_reset(1);
666 /* test checkers with different blocksizes */
667 static void test_check_state_blksize(void **state)
670 struct checker c[3] = {0};
671 int blksize[] = {4096, 1024, 512};
672 struct async_req *reqs[3];
675 /* can't pick event return state on real devices */
676 int chk_state[] = {PATH_UP, PATH_UP, PATH_UP};
678 int chk_state[] = {PATH_UP, PATH_DOWN, PATH_UP};
681 assert_true(list_empty(&aio_grp_list));
682 will_return(__wrap_io_setup, 0);
683 for (i = 0; i < 3; i++)
684 do_libcheck_init(&c[i], blksize[i], &reqs[i]);
685 for (i = 0; i < 3; i++) {
686 return_io_getevents_nr(NULL, 1, &reqs[i], &res[i]);
687 do_check_state(&c[i], 1, 30, chk_state[i]);
689 for (i = 0; i < 3; i++) {
690 assert_false(is_checker_running(&c[i]));
691 libcheck_free(&c[i]);
693 do_libcheck_reset(1);
696 /* test async checkers pending and getting resovled by another checker
697 * as well as the loops for getting multiple events */
698 static void test_check_state_async(void **state)
701 struct checker c[257] = {0};
702 struct async_req *reqs[257];
705 assert_true(list_empty(&aio_grp_list));
706 will_return(__wrap_io_setup, 0);
707 for (i = 0; i < 257; i++)
708 do_libcheck_init(&c[i], 4096, &reqs[i]);
709 for (i = 0; i < 256; i++) {
710 return_io_getevents_none();
711 do_check_state(&c[i], 0, 30, PATH_PENDING);
712 assert_true(is_checker_running(&c[i]));
714 return_io_getevents_nr(&full_timeout, 256, reqs, res);
715 return_io_getevents_nr(NULL, 1, &reqs[256], &res[256]);
716 do_check_state(&c[256], 0, 30, PATH_UP);
717 assert_false(is_checker_running(&c[256]));
718 libcheck_free(&c[256]);
719 for (i = 0; i < 256; i++) {
720 do_check_state(&c[i], 0, 30, PATH_UP);
721 assert_false(is_checker_running(&c[i]));
722 libcheck_free(&c[i]);
724 do_libcheck_reset(1);
727 static int setup(void **state)
730 test_fd = open(DIO_TEST_DEV, O_RDONLY);
732 fail_msg("cannot open %s: %m", DIO_TEST_DEV);
737 static int teardown(void **state)
740 assert_true(test_fd > 0);
741 assert_int_equal(close(test_fd), 0);
746 int test_directio(void)
748 const struct CMUnitTest tests[] = {
749 cmocka_unit_test(test_reset),
750 cmocka_unit_test(test_init_reset_init),
751 cmocka_unit_test(test_init_free),
752 cmocka_unit_test(test_multi_init_free),
753 cmocka_unit_test(test_check_state_simple),
754 cmocka_unit_test(test_check_state_timeout),
755 cmocka_unit_test(test_check_state_async_timeout),
756 cmocka_unit_test(test_free_with_pending),
757 cmocka_unit_test(test_timeout_cancel_failed),
758 cmocka_unit_test(test_async_timeout_cancel_failed),
759 cmocka_unit_test(test_orphan_checker_cleanup),
760 cmocka_unit_test(test_orphan_reset_cleanup),
761 cmocka_unit_test(test_check_state_blksize),
762 cmocka_unit_test(test_check_state_async),
763 cmocka_unit_test(test_orphaned_aio_group),
766 return cmocka_run_group_tests(tests, setup, teardown);
774 ret += test_directio();