Add test/file-register
Tests both existing functionality, but also the new sparse maps,
update/remove/add functionality.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index ea57526..4f532d9 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -150,5 +150,11 @@
#define IORING_UNREGISTER_FILES 3
#define IORING_REGISTER_EVENTFD 4
#define IORING_UNREGISTER_EVENTFD 5
+#define IORING_REGISTER_FILES_UPDATE 6
+
+struct io_uring_files_update {
+ __u32 offset;
+ __s32 *fds;
+};
#endif
diff --git a/test/Makefile b/test/Makefile
index 4710b30..3987f89 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -6,7 +6,7 @@
io_uring_enter nop sq-full cq-full 35fa71a030ca-test \
917257daa0fe-test b19062a56726-test eeed8b54e0df-test link \
send_recvmsg a4c0b3decb33-test 500f9fbadef8-test timeout \
- sq-space_left stdout cq-ready cq-peek-batch
+ sq-space_left stdout cq-ready cq-peek-batch file-register
include ../Makefile.quiet
@@ -20,7 +20,7 @@
35fa71a030ca-test.c 917257daa0fe-test.c b19062a56726-test.c \
eeed8b54e0df-test.c link.c send_recvmsg.c a4c0b3decb33-test.c \
500f9fbadef8-test.c timeout.c sq-space_left.c stdout.c cq-ready.c\
- cq-peek-batch.c
+ cq-peek-batch.c file-register.c
test_objs := $(patsubst %.c,%.ol,$(test_srcs))
diff --git a/test/file-register.c b/test/file-register.c
new file mode 100644
index 0000000..f50e32e
--- /dev/null
+++ b/test/file-register.c
@@ -0,0 +1,332 @@
+/*
+ * Description: run various file registration tests
+ *
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "liburing.h"
+
+static int no_update = 0;
+
+static void close_files(int *files, int nr_files, int add)
+{
+ char fname[32];
+ int i;
+
+ for (i = 0; i < nr_files; i++) {
+ close(files[i]);
+ if (!add)
+ sprintf(fname, ".reg.%d", i);
+ else
+ sprintf(fname, ".add.%d", i);
+ unlink(fname);
+ }
+ free(files);
+}
+
+static int *open_files(int nr_files, int extra, int add)
+{
+ char fname[32];
+ int *files;
+ int i;
+
+ files = calloc(nr_files + extra, sizeof(int));
+
+ for (i = 0; i < nr_files; i++) {
+ if (!add)
+ sprintf(fname, ".reg.%d", i);
+ else
+ sprintf(fname, ".add.%d", i);
+ files[i] = open(fname, O_RDWR | O_CREAT, 0644);
+ if (files[i] < 0) {
+ perror("open");
+ free(files);
+ files = NULL;
+ break;
+ }
+ }
+ if (extra) {
+ for (i = nr_files; i < nr_files + extra; i++)
+ files[i] = -1;
+ }
+
+ return files;
+}
+
+static int test_replace_all(struct io_uring *ring)
+{
+ struct io_uring_files_update up;
+ int *files;
+ int ret, i;
+
+ files = open_files(100, 0, 0);
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES, files, 100);
+ if (ret) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ up.fds = malloc(100 * sizeof(int));
+ for (i = 0; i < 100; i++)
+ up.fds[i] = -1;
+ up.offset = 0;
+
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES_UPDATE, &up, 100);
+ if (ret != 100) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ ret = io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, NULL, 0);
+ if (ret) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ close_files(files, 100, 0);
+ return 0;
+err:
+ close_files(files, 100, 0);
+ return 1;
+}
+
+static int test_replace(struct io_uring *ring)
+{
+ struct io_uring_files_update up;
+ int *files;
+ int ret;
+
+ files = open_files(100, 0, 0);
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES, files, 100);
+ if (ret) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ up.fds = open_files(10, 0, 1);
+ up.offset = 90;
+
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES_UPDATE, &up, 10);
+ if (ret != 10) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ ret = io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, NULL, 0);
+ if (ret) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ close_files(files, 100, 0);
+ close_files(up.fds, 10, 1);
+ return 0;
+err:
+ close_files(files, 100, 0);
+ close_files(up.fds, 10, 1);
+ return 1;
+}
+
+static int test_removals(struct io_uring *ring)
+{
+ struct io_uring_files_update up;
+ int *files;
+ int ret, i;
+
+ files = open_files(100, 0, 0);
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES, files, 100);
+ if (ret) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ up.fds = calloc(10, sizeof(int));
+ for (i = 0; i < 10; i++)
+ up.fds[i] = -1;
+ up.offset = 50;
+
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES_UPDATE, &up, 10);
+ if (ret != 10) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ ret = io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, NULL, 0);
+ if (ret) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ close_files(files, 100, 0);
+ return 0;
+err:
+ close_files(files, 100, 0);
+ return 1;
+}
+
+static int test_additions(struct io_uring *ring)
+{
+ struct io_uring_files_update up;
+ int *files;
+ int ret;
+
+ files = open_files(100, 100, 0);
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES, files, 200);
+ if (ret) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ up.fds = open_files(2, 0, 1);
+ up.offset = 100;
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES_UPDATE, &up, 2);
+ if (ret != 2) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ ret = io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, NULL, 0);
+ if (ret) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+
+ close_files(files, 100, 0);
+ close_files(up.fds, 2, 1);
+ return 0;
+err:
+ close_files(files, 100, 0);
+ close_files(up.fds, 2, 1);
+ return 1;
+}
+
+static int test_sparse(struct io_uring *ring)
+{
+ int *files;
+ int ret;
+
+ files = open_files(100, 100, 0);
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES, files, 200);
+ if (ret) {
+ if (errno == EBADF) {
+ printf("Sparse files not supported\n");
+ no_update = 1;
+ goto done;
+ }
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+ ret = io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, NULL, 0);
+ if (ret) {
+ printf("ret=%d, errno=%d\n", ret, errno);
+ goto err;
+ }
+done:
+ close_files(files, 100, 0);
+ return 0;
+err:
+ close_files(files, 100, 0);
+ return 1;
+}
+
+static int test_basic_many(struct io_uring *ring)
+{
+ int *files;
+ int ret;
+
+ files = open_files(768, 0, 0);
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES, files, 768);
+ if (ret)
+ goto err;
+ ret = io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, NULL, 0);
+ if (ret)
+ goto err;
+ close_files(files, 768, 0);
+ return 0;
+err:
+ close_files(files, 768, 0);
+ return 1;
+}
+
+static int test_basic(struct io_uring *ring)
+{
+ int *files;
+ int ret;
+
+ files = open_files(100, 0, 0);
+ ret = io_uring_register(ring->ring_fd, IORING_REGISTER_FILES, files, 100);
+ if (ret)
+ goto err;
+ ret = io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, NULL, 0);
+ if (ret)
+ goto err;
+ close_files(files, 100, 0);
+ return 0;
+err:
+ close_files(files, 100, 0);
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ struct io_uring ring;
+ int ret;
+
+ ret = io_uring_queue_init(8, &ring, 0);
+ if (ret) {
+ printf("ring setup failed\n");
+ return 1;
+ }
+
+ ret = test_basic(&ring);
+ if (ret) {
+ printf("test_basic failed\n");
+ return ret;
+ }
+
+ ret = test_basic_many(&ring);
+ if (ret) {
+ printf("test_basic_many failed\n");
+ return ret;
+ }
+
+ ret = test_sparse(&ring);
+ if (ret) {
+ printf("test_sparse failed\n");
+ return ret;
+ }
+
+ if (no_update)
+ return 0;
+
+ ret = test_additions(&ring);
+ if (ret) {
+ printf("test_additions failed\n");
+ return ret;
+ }
+
+ ret = test_removals(&ring);
+ if (ret) {
+ printf("test_removals failed\n");
+ return ret;
+ }
+
+ ret = test_replace(&ring);
+ if (ret) {
+ printf("test_replace failed\n");
+ return ret;
+ }
+
+ ret = test_replace_all(&ring);
+ if (ret) {
+ printf("test_replace_all failed\n");
+ return ret;
+ }
+
+ return 0;
+}