| /* SPDX-License-Identifier: MIT */ |
| /* |
| * 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 "helpers.h" |
| #include "liburing.h" |
| |
| static void close_files(int *files, int nr_files, int add) |
| { |
| char fname[32]; |
| int i; |
| |
| for (i = 0; i < nr_files; i++) { |
| if (files) |
| close(files[i]); |
| if (!add) |
| sprintf(fname, ".reg.%d", i); |
| else |
| sprintf(fname, ".add.%d", i + add); |
| unlink(fname); |
| } |
| if (files) |
| free(files); |
| } |
| |
| static int *open_files(int nr_files, int extra, int add) |
| { |
| char fname[32]; |
| int *files; |
| int i; |
| |
| files = t_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 + add); |
| 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_update_multiring(struct io_uring *r1, struct io_uring *r2, |
| struct io_uring *r3, int do_unreg) |
| { |
| int *fds, *newfds; |
| |
| fds = open_files(10, 0, 0); |
| newfds = open_files(10, 0, 1); |
| |
| if (io_uring_register_files(r1, fds, 10) || |
| io_uring_register_files(r2, fds, 10) || |
| io_uring_register_files(r3, fds, 10)) { |
| fprintf(stderr, "%s: register files failed\n", __FUNCTION__); |
| goto err; |
| } |
| |
| if (io_uring_register_files_update(r1, 0, newfds, 10) != 10 || |
| io_uring_register_files_update(r2, 0, newfds, 10) != 10 || |
| io_uring_register_files_update(r3, 0, newfds, 10) != 10) { |
| fprintf(stderr, "%s: update files failed\n", __FUNCTION__); |
| goto err; |
| } |
| |
| if (!do_unreg) |
| goto done; |
| |
| if (io_uring_unregister_files(r1) || |
| io_uring_unregister_files(r2) || |
| io_uring_unregister_files(r3)) { |
| fprintf(stderr, "%s: unregister files failed\n", __FUNCTION__); |
| goto err; |
| } |
| |
| done: |
| close_files(fds, 10, 0); |
| close_files(newfds, 10, 1); |
| return 0; |
| err: |
| close_files(fds, 10, 0); |
| close_files(newfds, 10, 1); |
| return 1; |
| } |
| |
| static int test_sqe_update(struct io_uring *ring) |
| { |
| struct io_uring_sqe *sqe; |
| struct io_uring_cqe *cqe; |
| int *fds, i, ret; |
| |
| fds = t_malloc(sizeof(int) * 10); |
| for (i = 0; i < 10; i++) |
| fds[i] = -1; |
| |
| sqe = io_uring_get_sqe(ring); |
| io_uring_prep_files_update(sqe, fds, 10, 0); |
| ret = io_uring_submit(ring); |
| if (ret != 1) { |
| fprintf(stderr, "submit: %d\n", ret); |
| return 1; |
| } |
| |
| ret = io_uring_wait_cqe(ring, &cqe); |
| if (ret) { |
| fprintf(stderr, "wait: %d\n", ret); |
| return 1; |
| } |
| |
| ret = cqe->res; |
| io_uring_cqe_seen(ring, cqe); |
| if (ret == -EINVAL) { |
| fprintf(stdout, "IORING_OP_FILES_UPDATE not supported, skipping\n"); |
| return 0; |
| } |
| return ret != 10; |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| struct io_uring r1, r2, r3; |
| int ret; |
| |
| if (argc > 1) |
| return 0; |
| |
| if (io_uring_queue_init(8, &r1, 0) || |
| io_uring_queue_init(8, &r2, 0) || |
| io_uring_queue_init(8, &r3, 0)) { |
| fprintf(stderr, "ring setup failed\n"); |
| return 1; |
| } |
| |
| ret = test_update_multiring(&r1, &r2, &r3, 1); |
| if (ret) { |
| fprintf(stderr, "test_update_multiring w/unreg\n"); |
| return ret; |
| } |
| |
| ret = test_update_multiring(&r1, &r2, &r3, 0); |
| if (ret) { |
| fprintf(stderr, "test_update_multiring wo/unreg\n"); |
| return ret; |
| } |
| |
| ret = test_sqe_update(&r1); |
| if (ret) { |
| fprintf(stderr, "test_sqe_update failed\n"); |
| return ret; |
| } |
| |
| return 0; |
| } |