107 lines · 2.8 KB · C
RawDownload
#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <unistd.h>#include <errno.h>#include <string.h> #include "liburing.h" static int io_uring_mmap(int fd, struct io_uring_params *p,			 struct io_uring_sq *sq, struct io_uring_cq *cq){	size_t size;	void *ptr;	int ret; 	sq->ring_sz = p->sq_off.array + p->sq_entries * sizeof(unsigned);	ptr = mmap(0, sq->ring_sz, PROT_READ | PROT_WRITE,			MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQ_RING);	if (ptr == MAP_FAILED)		return -errno;	sq->khead = ptr + p->sq_off.head;	sq->ktail = ptr + p->sq_off.tail;	sq->kring_mask = ptr + p->sq_off.ring_mask;	sq->kring_entries = ptr + p->sq_off.ring_entries;	sq->kflags = ptr + p->sq_off.flags;	sq->kdropped = ptr + p->sq_off.dropped;	sq->array = ptr + p->sq_off.array; 	size = p->sq_entries * sizeof(struct io_uring_sqe);	sq->sqes = mmap(0, size, PROT_READ | PROT_WRITE,				MAP_SHARED | MAP_POPULATE, fd,				IORING_OFF_SQES);	if (sq->sqes == MAP_FAILED) {		ret = -errno;err:		munmap(sq->khead, sq->ring_sz);		return ret;	} 	cq->ring_sz = p->cq_off.cqes + p->cq_entries * sizeof(struct io_uring_cqe);	ptr = mmap(0, cq->ring_sz, PROT_READ | PROT_WRITE,			MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_CQ_RING);	if (ptr == MAP_FAILED) {		ret = -errno;		munmap(sq->sqes, p->sq_entries * sizeof(struct io_uring_sqe));		goto err;	}	cq->khead = ptr + p->cq_off.head;	cq->ktail = ptr + p->cq_off.tail;	cq->kring_mask = ptr + p->cq_off.ring_mask;	cq->kring_entries = ptr + p->cq_off.ring_entries;	cq->koverflow = ptr + p->cq_off.overflow;	cq->cqes = ptr + p->cq_off.cqes;	return 0;} /* * For users that want to specify sq_thread_cpu or sq_thread_idle, this * interface is a convenient helper for mmap()ing the rings. * Returns -1 on error, or zero on success.  On success, 'ring' * contains the necessary information to read/write to the rings. */int io_uring_queue_mmap(int fd, struct io_uring_params *p, struct io_uring *ring){	int ret; 	memset(ring, 0, sizeof(*ring));	ret = io_uring_mmap(fd, p, &ring->sq, &ring->cq);	if (!ret)		ring->ring_fd = fd;	return ret;} /* * Returns -1 on error, or zero on success. On success, 'ring' * contains the necessary information to read/write to the rings. */int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags){	struct io_uring_params p;	int fd, ret; 	memset(&p, 0, sizeof(p));	p.flags = flags; 	fd = io_uring_setup(entries, &p);	if (fd < 0)		return fd; 	ret = io_uring_queue_mmap(fd, &p, ring);	if (ret)		close(fd); 	return ret;} void io_uring_queue_exit(struct io_uring *ring){	struct io_uring_sq *sq = &ring->sq;	struct io_uring_cq *cq = &ring->cq; 	munmap(sq->sqes, *sq->kring_entries * sizeof(struct io_uring_sqe));	munmap(sq->khead, sq->ring_sz);	munmap(cq->khead, cq->ring_sz);	close(ring->ring_fd);}