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