mirror of
https://github.com/openharmony/third_party_liburing.git
synced 2026-07-20 22:58:41 -04:00
4b8f3098a5
Co-authored-by: Pavel Begunkov<asml.silence@gmail.com> Co-authored-by: Guillem Jover<guillem@hadrons.org> Co-authored-by: Jens Axboe<axboe@kernel.dk> Co-authored-by: Khem Raj<raj.khem@gmail.com> Co-authored-by: Michael de Lang<kingoipo@gmail.com> Co-authored-by: David Disseldorp<ddiss@suse.de> Co-authored-by: Ming Lei<ming.lei@redhat.com>
147 lines
3.4 KiB
C
147 lines
3.4 KiB
C
/* SPDX-License-Identifier: MIT */
|
|
/*
|
|
* Description: test that importing a buffer node ties the lifetime to the
|
|
* notification io_kiocb, not the normal request.
|
|
*
|
|
* Based on a test case from Google Big Sleep.
|
|
*
|
|
*/
|
|
#include <arpa/inet.h>
|
|
#include <err.h>
|
|
#include <fcntl.h>
|
|
#include <netinet/in.h>
|
|
#include <poll.h>
|
|
#include <pthread.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/syscall.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
#include "liburing.h"
|
|
#include "helpers.h"
|
|
|
|
#define BUF_SIZE (1024 * 1024)
|
|
static uint8_t read_buffer[BUF_SIZE] = { 0 };
|
|
|
|
/* Creates a pair of connected TCP sockets. */
|
|
static void tcp_socketpair(int sv[2])
|
|
{
|
|
struct sockaddr_in addr_in = {
|
|
.sin_family = AF_INET,
|
|
.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
|
|
.sin_port = 0,
|
|
};
|
|
struct sockaddr *addr = (struct sockaddr *) &addr_in;
|
|
socklen_t addr_len = sizeof(addr_in);
|
|
int listener_fd;
|
|
|
|
listener_fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (listener_fd < 0)
|
|
err(EXIT_FAILURE, "listener socket");
|
|
|
|
if (bind(listener_fd, addr, addr_len) < 0)
|
|
err(EXIT_FAILURE, "bind");
|
|
|
|
if (listen(listener_fd, 1) < 0)
|
|
err(EXIT_FAILURE, "listen");
|
|
|
|
if (getsockname(listener_fd, addr, &addr_len) < 0)
|
|
err(EXIT_FAILURE, "getsockname");
|
|
|
|
sv[0] = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (sv[0] < 0)
|
|
err(EXIT_FAILURE, "socket(AF_INET, SOCK_STREAM, 0)");
|
|
|
|
if (connect(sv[0], addr, addr_len) < 0)
|
|
err(EXIT_FAILURE, "connect");
|
|
|
|
sv[1] = accept(listener_fd, NULL, NULL);
|
|
if (sv[1] == -1)
|
|
err(EXIT_FAILURE, "accept");
|
|
|
|
close(listener_fd);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct io_uring_sqe *sqe;
|
|
struct io_uring_cqe* cqe;
|
|
struct iovec send_iov;
|
|
struct io_uring ring;
|
|
struct iovec iov_reg;
|
|
struct msghdr msg = {
|
|
.msg_iov = &send_iov,
|
|
.msg_iovlen = 1,
|
|
};
|
|
void *send_buffer;
|
|
int sockets[2];
|
|
int val, ret;
|
|
|
|
if (argc > 1)
|
|
return T_EXIT_SKIP;
|
|
|
|
tcp_socketpair(sockets);
|
|
|
|
val = 1;
|
|
if (setsockopt(sockets[0], SOL_SOCKET, SO_ZEROCOPY, &val, sizeof(val)))
|
|
err(EXIT_FAILURE, "setsockopt(SO_ZEROCOPY)");
|
|
|
|
ret = io_uring_queue_init(1, &ring, 0);
|
|
if (ret < 0)
|
|
errx(EXIT_FAILURE, "io_uring_queue_init: %s", strerror(-ret));
|
|
|
|
/* mmap send_buffer so we can unmap it later. */
|
|
send_buffer = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE,
|
|
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
if (send_buffer == MAP_FAILED)
|
|
err(EXIT_FAILURE, "mapping iouring buffer");
|
|
|
|
iov_reg.iov_base = send_buffer;
|
|
iov_reg.iov_len = BUF_SIZE;
|
|
ret = io_uring_register_buffers(&ring, &iov_reg, 1);
|
|
if (ret < 0)
|
|
errx(EXIT_FAILURE, "io_uring_register_buffers: %s", strerror(-ret));
|
|
|
|
sqe = io_uring_get_sqe(&ring);
|
|
|
|
send_iov.iov_base = send_buffer;
|
|
send_iov.iov_len = BUF_SIZE;
|
|
|
|
io_uring_prep_sendmsg_zc(sqe, sockets[0], &msg, 0);
|
|
sqe->ioprio = IORING_RECVSEND_FIXED_BUF;
|
|
sqe->buf_index = 0;
|
|
|
|
memset(send_buffer, 'B', BUF_SIZE);
|
|
|
|
io_uring_submit(&ring);
|
|
|
|
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
if (ret < 0)
|
|
errx(EXIT_FAILURE, "io_uring_wait_cqe: %s", strerror(-ret));
|
|
|
|
if (cqe->res < 0) {
|
|
if (cqe->res == -EINVAL)
|
|
return T_EXIT_SKIP;
|
|
errx(EXIT_FAILURE, "readv failed: %s", strerror(-cqe->res));
|
|
}
|
|
|
|
io_uring_cqe_seen(&ring, cqe);
|
|
|
|
io_uring_unregister_buffers(&ring);
|
|
munmap(send_buffer, BUF_SIZE);
|
|
|
|
ret = read(sockets[1], read_buffer, BUF_SIZE);
|
|
if (ret < 0)
|
|
err(EXIT_FAILURE, "read");
|
|
|
|
io_uring_queue_exit(&ring);
|
|
return T_EXIT_PASS;
|
|
}
|