1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2019 SUSE LLC
4f08c3bdfSopenharmony_ci * Author: Jorik Cronenberg <jcronenberg@suse.de>
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * Test vmsplice() to a full pipe with SPLICE_F_NONBLOCK and without.
7f08c3bdfSopenharmony_ci *
8f08c3bdfSopenharmony_ci * With SPLICE_F_NONBLOCK vmsplice() should return with errno EAGAIN
9f08c3bdfSopenharmony_ci * Without SPLICE_F_NONBLOCK it should block.
10f08c3bdfSopenharmony_ci */
11f08c3bdfSopenharmony_ci
12f08c3bdfSopenharmony_ci#define _GNU_SOURCE
13f08c3bdfSopenharmony_ci
14f08c3bdfSopenharmony_ci#include "tst_test.h"
15f08c3bdfSopenharmony_ci#include "lapi/vmsplice.h"
16f08c3bdfSopenharmony_ci#include "lapi/fcntl.h"
17f08c3bdfSopenharmony_ci#include <stdlib.h>
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_cistatic int pipes[2];
20f08c3bdfSopenharmony_cistatic ssize_t pipe_max_size;
21f08c3bdfSopenharmony_cistatic char *write_buffer;
22f08c3bdfSopenharmony_cistatic struct iovec iov;
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_cistatic void vmsplice_test(void)
25f08c3bdfSopenharmony_ci{
26f08c3bdfSopenharmony_ci	int status;
27f08c3bdfSopenharmony_ci	int pid;
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_ci	TEST(vmsplice(pipes[1], &iov, 1, SPLICE_F_NONBLOCK));
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_ci	if (TST_RET < 0 && TST_ERR == EAGAIN) {
32f08c3bdfSopenharmony_ci		tst_res(TPASS | TTERRNO,
33f08c3bdfSopenharmony_ci		    "vmsplice(..., SPLICE_F_NONBLOCK) failed as expected");
34f08c3bdfSopenharmony_ci	} else if (TST_RET < 0) {
35f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO,
36f08c3bdfSopenharmony_ci		    "vmsplice(..., SPLICE_F_NONBLOCK) shall fail with EAGAIN");
37f08c3bdfSopenharmony_ci	} else {
38f08c3bdfSopenharmony_ci		tst_res(TFAIL,
39f08c3bdfSopenharmony_ci		    "vmsplice(..., SPLICE_F_NONBLOCK) wrote to a full pipe");
40f08c3bdfSopenharmony_ci	}
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_ci	pid = SAFE_FORK();
43f08c3bdfSopenharmony_ci	if (!pid) {
44f08c3bdfSopenharmony_ci		TEST(vmsplice(pipes[1], &iov, 1, 0));
45f08c3bdfSopenharmony_ci		if (TST_RET < 0)
46f08c3bdfSopenharmony_ci			tst_res(TFAIL | TTERRNO, "vmsplice(..., 0) failed");
47f08c3bdfSopenharmony_ci		else
48f08c3bdfSopenharmony_ci			tst_res(TFAIL,
49f08c3bdfSopenharmony_ci			    "vmsplice(..., 0) wrote to a full pipe");
50f08c3bdfSopenharmony_ci		exit(0);
51f08c3bdfSopenharmony_ci	}
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_ci	if (TST_PROCESS_STATE_WAIT(pid, 'S', 1000) < 0)
54f08c3bdfSopenharmony_ci		return;
55f08c3bdfSopenharmony_ci	else
56f08c3bdfSopenharmony_ci		tst_res(TPASS, "vmsplice(..., 0) blocked");
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci	SAFE_KILL(pid, SIGKILL);
59f08c3bdfSopenharmony_ci	SAFE_WAIT(&status);
60f08c3bdfSopenharmony_ci}
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_cistatic void cleanup(void)
63f08c3bdfSopenharmony_ci{
64f08c3bdfSopenharmony_ci	if (pipes[1] > 0)
65f08c3bdfSopenharmony_ci		SAFE_CLOSE(pipes[1]);
66f08c3bdfSopenharmony_ci	if (pipes[0] > 0)
67f08c3bdfSopenharmony_ci		SAFE_CLOSE(pipes[0]);
68f08c3bdfSopenharmony_ci}
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_cistatic void setup(void)
71f08c3bdfSopenharmony_ci{
72f08c3bdfSopenharmony_ci	SAFE_PIPE(pipes);
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_ci	pipe_max_size = SAFE_FCNTL(pipes[1], F_GETPIPE_SZ);
75f08c3bdfSopenharmony_ci	write_buffer = tst_alloc(pipe_max_size);
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci	iov.iov_base = write_buffer;
78f08c3bdfSopenharmony_ci	iov.iov_len = pipe_max_size;
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	TEST(vmsplice(pipes[1], &iov, 1, 0));
81f08c3bdfSopenharmony_ci	if (TST_RET < 0) {
82f08c3bdfSopenharmony_ci		tst_brk(TBROK | TTERRNO,
83f08c3bdfSopenharmony_ci		    "Initial vmsplice() to fill pipe failed");
84f08c3bdfSopenharmony_ci	}
85f08c3bdfSopenharmony_ci}
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_cistatic struct tst_test test = {
88f08c3bdfSopenharmony_ci	.setup = setup,
89f08c3bdfSopenharmony_ci	.cleanup = cleanup,
90f08c3bdfSopenharmony_ci	.test_all = vmsplice_test,
91f08c3bdfSopenharmony_ci	.forks_child = 1,
92f08c3bdfSopenharmony_ci};
93