1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org>
4 *
5 * Description:
6 * Basic io_pgetevents() test to check various failures.
7 */
8 #include "time64_variants.h"
9 #include "tst_test.h"
10 #include "tst_timer.h"
11 #include "lapi/io_pgetevents.h"
12
13 #ifdef HAVE_LIBAIO
14 static sigset_t sigmask;
15 static struct io_event events[1];
16 static io_context_t ctx, invalid_ctx = 0;
17 static int fd, ctx_initialized;
18
19 static struct tst_ts to;
20 static void *bad_addr;
21
22 static struct tcase {
23 char *name;
24 io_context_t *ctx;
25 long min_nr;
26 long max_nr;
27 struct io_event *events;
28 struct tst_ts *timeout;
29 sigset_t *sigmask;
30 int exp_errno;
31 } tcases[] = {
32 {"invalid ctx", &invalid_ctx, 1, 1, events, &to, &sigmask, EINVAL},
33 {"invalid min_nr", &ctx, -1, 1, events, &to, &sigmask, EINVAL},
34 {"invalid max_nr", &ctx, 1, -1, events, &to, &sigmask, EINVAL},
35 {"invalid events", &ctx, 1, 1, NULL, &to, &sigmask, EFAULT},
36 {"invalid timeout", &ctx, 1, 1, events, NULL, &sigmask, EFAULT},
37 {"invalid sigmask", &ctx, 1, 1, events, &to, NULL, EFAULT},
38 };
39
40 static struct time64_variants variants[] = {
41 #if (__NR_io_pgetevents != __LTP__NR_INVALID_SYSCALL)
42 { .io_pgetevents = sys_io_pgetevents, .ts_type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
43 #endif
44
45 #if (__NR_io_pgetevents_time64 != __LTP__NR_INVALID_SYSCALL)
46 { .io_pgetevents = sys_io_pgetevents_time64, .ts_type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
47 #endif
48 };
49
setup(void)50 static void setup(void)
51 {
52 struct time64_variants *tv = &variants[tst_variant];
53 struct iocb cb, *cbs[1];
54 char data[4096];
55 int ret;
56
57 tst_res(TINFO, "Testing variant: %s", tv->desc);
58 bad_addr = tst_get_bad_addr(NULL);
59 to = tst_ts_from_ns(tv->ts_type, 10000);
60
61 cbs[0] = &cb;
62
63 sigemptyset(&sigmask);
64
65 fd = SAFE_OPEN("io_pgetevents_file", O_RDWR | O_CREAT, 0644);
66 io_prep_pwrite(&cb, fd, data, 4096, 0);
67
68 TEST(io_setup(1, &ctx));
69 if (TST_RET == -ENOSYS)
70 tst_brk(TCONF | TRERRNO, "io_setup(): AIO not supported by kernel");
71 if (TST_RET < 0)
72 tst_brk(TBROK | TRERRNO, "io_setup() failed");
73
74 ctx_initialized = 1;
75
76 ret = io_submit(ctx, 1, cbs);
77 if (ret != 1)
78 tst_brk(TBROK | TERRNO, "io_submit() failed");
79 }
80
cleanup(void)81 static void cleanup(void)
82 {
83 if (ctx_initialized) {
84 if (io_destroy(ctx) < 0)
85 tst_res(TWARN | TERRNO, "io_destroy() failed");
86 }
87
88 if (fd > 0)
89 SAFE_CLOSE(fd);
90 }
91
run(unsigned int n)92 static void run(unsigned int n)
93 {
94 struct time64_variants *tv = &variants[tst_variant];
95 struct tcase *tc = &tcases[n];
96 void *const to = tc->timeout ? tst_ts_get(tc->timeout) : bad_addr;
97 sigset_t *const sigmask = tc->sigmask ? tc->sigmask : bad_addr;
98
99 TEST(tv->io_pgetevents(*tc->ctx, tc->min_nr, tc->max_nr, tc->events, to,
100 sigmask));
101
102 if (TST_RET == 1) {
103 tst_res(TFAIL, "%s: io_pgetevents() passed unexpectedly",
104 tc->name);
105 return;
106 }
107
108 if (tc->exp_errno != TST_ERR) {
109 tst_res(TFAIL | TTERRNO, "%s: io_pgetevents() should fail with %s",
110 tc->name, tst_strerrno(tc->exp_errno));
111 return;
112 }
113
114 tst_res(TPASS | TTERRNO, "%s: io_pgetevents() failed as expected",
115 tc->name);
116 }
117
118 static struct tst_test test = {
119 .min_kver = "4.18",
120 .needs_tmpdir = 1,
121 .tcnt = ARRAY_SIZE(tcases),
122 .test = run,
123 .test_variants = ARRAY_SIZE(variants),
124 .setup = setup,
125 .cleanup = cleanup,
126 };
127
128 #else
129 TST_TEST_TCONF("test requires libaio and it's development packages");
130 #endif
131