• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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