[BUG] ->flush and links

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There is a problem with io_uring_cancel_files -- it doesn't care about
links. If a request with ->files is not a head of a link, it won't be
found it in io-wq or elsewhere, and will wait for the head to be completed.
The problem is when the head won't ever complete.

e.g. req1: read empty pipe -> req2: openat
This leaves an uninterruptedly and indefinitely sleeping process.
see liburing patch below.

I was thinking about making dependant links traversable by io-wq cancel().

The similar problem can manifest itself with pending drained requests,
but solving this one would need cancellation of every prior request
in the drain queue, that's kind of nasty side effect for closing an
fd alias.

Any thoughts how to better deal with it?

diff --git a/test/lfs-openat.c b/test/lfs-openat.c
index d69096e..9fb96b7 100644
--- a/test/lfs-openat.c
+++ b/test/lfs-openat.c
@@ -75,6 +75,58 @@ static int prepare_file(int dfd, const char* fn)
 	return res < 0 ? res : 0;
 }
 
+static int test_linked_files(int dfd, const char *fn)
+{
+	struct io_uring ring;
+	struct io_uring_sqe *sqe;
+	char buffer[128];
+	struct iovec iov = {.iov_base = buffer, .iov_len = sizeof(buffer), };
+	int ret, fd;
+	int fds[2];
+
+	ret = io_uring_queue_init(10, &ring, 0);
+	if (ret < 0)
+		DIE("failed to init io_uring: %s\n", strerror(-ret));
+
+	if (pipe(fds)) {
+		perror("pipe");
+		return 1;
+	}
+
+	sqe = io_uring_get_sqe(&ring);
+	if (!sqe) {
+		printf("get sqe failed\n");
+		return -1;
+	}
+	io_uring_prep_readv(sqe, fds[0], &iov, 1, 0);
+	sqe->flags |= IOSQE_IO_LINK;
+
+	sqe = io_uring_get_sqe(&ring);
+	if (!sqe) {
+		fprintf(stderr, "failed to get sqe\n");
+		return 1;
+	}
+	io_uring_prep_openat(sqe, dfd, fn, OPEN_FLAGS, OPEN_MODE);
+
+	ret = io_uring_submit(&ring);
+	if (ret != 2) {
+		fprintf(stderr, "failed to submit openat: %s\n", strerror(-ret));
+		return 1;
+	}
+
+	fd = dup(ring.ring_fd);
+	if (fd < 0) {
+		fprintf(stderr, "dup() failed: %s\n", strerror(-fd));
+		return 1;
+	}
+
+	/* io_uring->flush() */
+	close(fd);
+
+	io_uring_queue_exit(&ring);
+	return 0;
+}
+
 int main(int argc, char *argv[])
 {
 	const char *fn = "io_uring_openat_test";
@@ -93,7 +145,17 @@ int main(int argc, char *argv[])
 		return 1;
 
 	ret = open_io_uring(&ring, dfd, fn);
+	if (ret) {
+		fprintf(stderr, "open_io_uring() failed\n");
+		goto out;
+	}
 
+	ret = test_linked_files(dfd, fn);
+	if (ret) {
+		fprintf(stderr, "test_linked_files() failed\n");
+		goto out;
+	}
+out:
 	io_uring_queue_exit(&ring);
 	close(dfd);
 	unlink("/tmp/io_uring_openat_test");


-- 
Pavel Begunkov



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux