All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support
@ 2021-06-03  5:28 Dmitry Kadashev
  2021-06-03  5:28 ` [PATCH liburing v2 01/11] liburing.h: add mkdirat prep helper Dmitry Kadashev
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:28 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

This started as an attempt to add mkdir support to io_uring, but in the
end more ops were added. Heavily based on a series that added unlinkat
support (commit: 44db0f437a2b ("io_uring.h: add renameat and unlinkat
opcodes") and a couple of subsequent ones).

The kernel side of the change:
https://lore.kernel.org/io-uring/20210603051836.2614535-1-dkadashev@gmail.com/T/

1-2 adds mkdirat support (the opcode is already there) and test
3-5 adds symlinkat support and test
6-8 adds linkat support and test
9-11 adds mknodat support and test

v2:
- add symlinkat, linkat, mknodat

Dmitry Kadashev (11):
  liburing.h: add mkdirat prep helper
  Add mkdirat test case
  io_uring.h: add symlinkat opcode
  liburing.h: add symlinkat prep helper
  Add symlinkat test case
  io_uring.h: add linkat opcode
  liburing.h: add linkat prep helper
  Add linkat test case
  io_uring.h: add mknodat opcode
  liburing.h: add mknodat prep helper
  Add mknod test case

 .gitignore                      |   4 +
 src/include/liburing.h          |  29 ++++++
 src/include/liburing/io_uring.h |   5 ++
 test/Makefile                   |   8 ++
 test/hardlink.c                 | 133 +++++++++++++++++++++++++++
 test/mkdir.c                    | 105 ++++++++++++++++++++++
 test/mknod.c                    | 155 ++++++++++++++++++++++++++++++++
 test/symlink.c                  | 113 +++++++++++++++++++++++
 8 files changed, 552 insertions(+)
 create mode 100644 test/hardlink.c
 create mode 100644 test/mkdir.c
 create mode 100644 test/mknod.c
 create mode 100644 test/symlink.c

-- 
2.30.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 01/11] liburing.h: add mkdirat prep helper
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
@ 2021-06-03  5:28 ` Dmitry Kadashev
  2021-06-03  5:28 ` [PATCH liburing v2 02/11] Add mkdirat test case Dmitry Kadashev
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:28 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 src/include/liburing.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/include/liburing.h b/src/include/liburing.h
index d3f8f91..b7f3bea 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -548,6 +548,12 @@ static inline void io_uring_prep_sync_file_range(struct io_uring_sqe *sqe,
 	sqe->sync_range_flags = flags;
 }
 
+static inline void io_uring_prep_mkdirat(struct io_uring_sqe *sqe, int dfd,
+					const char *path, mode_t mode)
+{
+	io_uring_prep_rw(IORING_OP_MKDIRAT, sqe, dfd, path, mode, 0);
+}
+
 /*
  * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
  * the SQ ring
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 02/11] Add mkdirat test case
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
  2021-06-03  5:28 ` [PATCH liburing v2 01/11] liburing.h: add mkdirat prep helper Dmitry Kadashev
@ 2021-06-03  5:28 ` Dmitry Kadashev
  2021-06-03  5:28 ` [PATCH liburing v2 03/11] io_uring.h: add symlinkat opcode Dmitry Kadashev
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:28 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

The test is relative basic: tests only success, EEXISTS, ENOENT (no
parent dir).

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 .gitignore    |   1 +
 test/Makefile |   2 +
 test/mkdir.c  | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 test/mkdir.c

diff --git a/.gitignore b/.gitignore
index 17ec415..a9ae5bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,7 @@
 /test/link-timeout
 /test/link_drain
 /test/madvise
+/test/mkdir
 /test/nop
 /test/nop-all-sizes
 /test/open-close
diff --git a/test/Makefile b/test/Makefile
index a312409..86437d5 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -65,6 +65,7 @@ test_targets += \
 	link-timeout \
 	link_drain \
 	madvise \
+	mkdir \
 	multicqes_drain \
 	nop \
 	nop-all-sizes \
@@ -202,6 +203,7 @@ test_srcs := \
 	link.c \
 	link_drain.c \
 	madvise.c \
+	mkdir.c \
 	multicqes_drain.c \
 	nop-all-sizes.c \
 	nop.c \
diff --git a/test/mkdir.c b/test/mkdir.c
new file mode 100644
index 0000000..c044652
--- /dev/null
+++ b/test/mkdir.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Description: test io_uring mkdirat handling
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "liburing.h"
+
+static int do_mkdirat(struct io_uring *ring, const char *fn)
+{
+	int ret;
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "sqe get failed\n");
+		goto err;
+	}
+	io_uring_prep_mkdirat(sqe, AT_FDCWD, fn, 0700);
+
+	ret = io_uring_submit(ring);
+	if (ret != 1) {
+		fprintf(stderr, "submit failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = io_uring_wait_cqes(ring, &cqe, 1, 0, 0);
+	if (ret) {
+		fprintf(stderr, "wait_cqe failed: %d\n", ret);
+		goto err;
+	}
+	ret = cqe->res;
+	io_uring_cqe_seen(ring, cqe);
+	return ret;
+err:
+	return 1;
+}
+
+static int stat_file(const char *fn)
+{
+	struct stat sb;
+
+	if (!stat(fn, &sb))
+		return 0;
+
+	return errno;
+}
+
+int main(int argc, char *argv[])
+{
+	static const char fn[] = "io_uring-mkdirat-test";
+	int ret;
+	struct io_uring ring;
+
+	ret = io_uring_queue_init(8, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "queue init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = do_mkdirat(&ring, fn);
+	if (ret < 0) {
+		if (ret == -EBADF || ret == -EINVAL) {
+			fprintf(stdout, "mkdirat not supported, skipping\n");
+			goto out;
+		}
+		fprintf(stderr, "mkdirat: %s\n", strerror(-ret));
+		goto err;
+	} else if (ret) {
+		goto err;
+	}
+
+	if (stat_file(fn)) {
+		perror("stat");
+		goto err;
+	}
+
+	ret = do_mkdirat(&ring, fn);
+	if (ret != -EEXIST) {
+		fprintf(stderr, "do_mkdirat already exists failed: %d\n", ret);
+		goto err1;
+	}
+
+	ret = do_mkdirat(&ring, "surely/this/wont/exist");
+	if (ret != -ENOENT) {
+		fprintf(stderr, "do_mkdirat no parent failed: %d\n", ret);
+		goto err1;
+	}
+
+out:
+	unlinkat(AT_FDCWD, fn, AT_REMOVEDIR);
+	io_uring_queue_exit(&ring);
+	return 0;
+err1:
+	unlinkat(AT_FDCWD, fn, AT_REMOVEDIR);
+err:
+	io_uring_queue_exit(&ring);
+	return 1;
+}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 03/11] io_uring.h: add symlinkat opcode
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
  2021-06-03  5:28 ` [PATCH liburing v2 01/11] liburing.h: add mkdirat prep helper Dmitry Kadashev
  2021-06-03  5:28 ` [PATCH liburing v2 02/11] Add mkdirat test case Dmitry Kadashev
@ 2021-06-03  5:28 ` Dmitry Kadashev
  2021-06-03  5:28 ` [PATCH liburing v2 04/11] liburing.h: add symlinkat prep helper Dmitry Kadashev
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:28 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 src/include/liburing/io_uring.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index 5a3cb90..439a515 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -142,6 +142,7 @@ enum {
 	IORING_OP_RENAMEAT,
 	IORING_OP_UNLINKAT,
 	IORING_OP_MKDIRAT,
+	IORING_OP_SYMLINKAT,
 
 	/* this goes last, obviously */
 	IORING_OP_LAST,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 04/11] liburing.h: add symlinkat prep helper
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
                   ` (2 preceding siblings ...)
  2021-06-03  5:28 ` [PATCH liburing v2 03/11] io_uring.h: add symlinkat opcode Dmitry Kadashev
@ 2021-06-03  5:28 ` Dmitry Kadashev
  2021-06-03  5:29 ` [PATCH liburing v2 05/11] Add symlinkat test case Dmitry Kadashev
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:28 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 src/include/liburing.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/include/liburing.h b/src/include/liburing.h
index b7f3bea..e033543 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -554,6 +554,13 @@ static inline void io_uring_prep_mkdirat(struct io_uring_sqe *sqe, int dfd,
 	io_uring_prep_rw(IORING_OP_MKDIRAT, sqe, dfd, path, mode, 0);
 }
 
+static inline void io_uring_prep_symlinkat(struct io_uring_sqe *sqe,
+					const char *target, int newdirfd, const char *linkpath)
+{
+	io_uring_prep_rw(IORING_OP_SYMLINKAT, sqe, newdirfd, target, 0,
+				(uint64_t) (uintptr_t) linkpath);
+}
+
 /*
  * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
  * the SQ ring
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 05/11] Add symlinkat test case
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
                   ` (3 preceding siblings ...)
  2021-06-03  5:28 ` [PATCH liburing v2 04/11] liburing.h: add symlinkat prep helper Dmitry Kadashev
@ 2021-06-03  5:29 ` Dmitry Kadashev
  2021-06-03  5:29 ` [PATCH liburing v2 06/11] io_uring.h: add linkat opcode Dmitry Kadashev
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:29 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Tests successful creation (using readlink() to verify the contents),
EEXIST, ENOENT cases.

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 .gitignore     |   1 +
 test/Makefile  |   2 +
 test/symlink.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 116 insertions(+)
 create mode 100644 test/symlink.c

diff --git a/.gitignore b/.gitignore
index a9ae5bb..0b336d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -112,6 +112,7 @@
 /test/statx
 /test/stdout
 /test/submit-reuse
+/test/symlink
 /test/teardowns
 /test/thread-exit
 /test/timeout
diff --git a/test/Makefile b/test/Makefile
index 86437d5..4fc78ea 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -108,6 +108,7 @@ test_targets += \
 	sq-space_left \
 	stdout \
 	submit-reuse \
+	symlink \
 	teardowns \
 	thread-exit \
 	timeout \
@@ -248,6 +249,7 @@ test_srcs := \
 	statx.c \
 	stdout.c \
 	submit-reuse.c \
+	symlink.c \
 	teardowns.c \
 	thread-exit.c \
 	timeout-new.c \
diff --git a/test/symlink.c b/test/symlink.c
new file mode 100644
index 0000000..8b5e04a
--- /dev/null
+++ b/test/symlink.c
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Description: test io_uring symlinkat handling
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "liburing.h"
+
+
+static int do_symlinkat(struct io_uring *ring, const char *oldname, const char *newname)
+{
+	int ret;
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "sqe get failed\n");
+		goto err;
+	}
+	io_uring_prep_symlinkat(sqe, oldname, AT_FDCWD, newname);
+
+	ret = io_uring_submit(ring);
+	if (ret != 1) {
+		fprintf(stderr, "submit failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = io_uring_wait_cqes(ring, &cqe, 1, 0, 0);
+	if (ret) {
+		fprintf(stderr, "wait_cqe failed: %d\n", ret);
+		goto err;
+	}
+	ret = cqe->res;
+	io_uring_cqe_seen(ring, cqe);
+	return ret;
+err:
+	return 1;
+}
+
+int test_link_contents(const char* linkname, const char *expected_contents)
+{
+	char buf[128];
+	int ret = readlink(linkname, buf, 127);
+	if (ret < 0) {
+		perror("readlink");
+		return ret;
+	}
+	buf[ret] = 0;
+	if (strncmp(buf, expected_contents, 128)) {
+		fprintf(stderr, "link contents differs from expected: '%s' vs '%s'",
+			buf, expected_contents);
+		return -1;
+	}
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	static const char target[] = "io_uring-symlinkat-test-target";
+	static const char linkname[] = "io_uring-symlinkat-test-link";
+	int ret;
+	struct io_uring ring;
+
+	ret = io_uring_queue_init(8, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "queue init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = do_symlinkat(&ring, target, linkname);
+	if (ret < 0) {
+		if (ret == -EBADF || ret == -EINVAL) {
+			fprintf(stdout, "symlinkat not supported, skipping\n");
+			goto out;
+		}
+		fprintf(stderr, "symlinkat: %s\n", strerror(-ret));
+		goto err;
+	} else if (ret) {
+		goto err;
+	}
+
+	ret = test_link_contents(linkname, target);
+	if (ret < 0)
+		goto err1;
+
+	ret = do_symlinkat(&ring, target, linkname);
+	if (ret != -EEXIST) {
+		fprintf(stderr, "test_symlinkat linkname already exists failed: %d\n", ret);
+		goto err1;
+	}
+
+	ret = do_symlinkat(&ring, target, "surely/this/does/not/exist");
+	if (ret != -ENOENT) {
+		fprintf(stderr, "test_symlinkat no parent failed: %d\n", ret);
+		goto err1;
+	}
+
+out:
+	unlinkat(AT_FDCWD, linkname, 0);
+	io_uring_queue_exit(&ring);
+	return 0;
+err1:
+	unlinkat(AT_FDCWD, linkname, 0);
+err:
+	io_uring_queue_exit(&ring);
+	return 1;
+}
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 06/11] io_uring.h: add linkat opcode
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
                   ` (4 preceding siblings ...)
  2021-06-03  5:29 ` [PATCH liburing v2 05/11] Add symlinkat test case Dmitry Kadashev
@ 2021-06-03  5:29 ` Dmitry Kadashev
  2021-06-03  5:29 ` [PATCH liburing v2 07/11] liburing.h: add linkat prep helper Dmitry Kadashev
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:29 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 src/include/liburing/io_uring.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index 439a515..a5e48e7 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -48,6 +48,7 @@ struct io_uring_sqe {
 		__u32		splice_flags;
 		__u32		rename_flags;
 		__u32		unlink_flags;
+		__u32		hardlink_flags;
 	};
 	__u64	user_data;	/* data to be passed back at completion time */
 	union {
@@ -143,6 +144,7 @@ enum {
 	IORING_OP_UNLINKAT,
 	IORING_OP_MKDIRAT,
 	IORING_OP_SYMLINKAT,
+	IORING_OP_LINKAT,
 
 	/* this goes last, obviously */
 	IORING_OP_LAST,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 07/11] liburing.h: add linkat prep helper
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
                   ` (5 preceding siblings ...)
  2021-06-03  5:29 ` [PATCH liburing v2 06/11] io_uring.h: add linkat opcode Dmitry Kadashev
@ 2021-06-03  5:29 ` Dmitry Kadashev
  2021-06-03  5:29 ` [PATCH liburing v2 08/11] Add linkat test case Dmitry Kadashev
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:29 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 src/include/liburing.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/include/liburing.h b/src/include/liburing.h
index e033543..51dc602 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -561,6 +561,15 @@ static inline void io_uring_prep_symlinkat(struct io_uring_sqe *sqe,
 				(uint64_t) (uintptr_t) linkpath);
 }
 
+static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd,
+					const char *oldpath, int newdfd,
+					const char *newpath, int flags)
+{
+	io_uring_prep_rw(IORING_OP_LINKAT, sqe, olddfd, oldpath, newdfd,
+				(uint64_t) (uintptr_t) newpath);
+	sqe->hardlink_flags = flags;
+}
+
 /*
  * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
  * the SQ ring
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 08/11] Add linkat test case
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
                   ` (6 preceding siblings ...)
  2021-06-03  5:29 ` [PATCH liburing v2 07/11] liburing.h: add linkat prep helper Dmitry Kadashev
@ 2021-06-03  5:29 ` Dmitry Kadashev
  2021-06-03  5:29 ` [PATCH liburing v2 09/11] io_uring.h: add mknodat opcode Dmitry Kadashev
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:29 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Tests success, EEXISTS, ENOENT (no parent dir).

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 .gitignore      |   1 +
 test/Makefile   |   2 +
 test/hardlink.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 136 insertions(+)
 create mode 100644 test/hardlink.c

diff --git a/.gitignore b/.gitignore
index 0b336d6..7a6f75c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@
 /test/files-exit-hang-timeout
 /test/fixed-link
 /test/fsync
+/test/hardlink
 /test/io-cancel
 /test/io_uring_enter
 /test/io_uring_register
diff --git a/test/Makefile b/test/Makefile
index 4fc78ea..2f0a694 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -54,6 +54,7 @@ test_targets += \
 	files-exit-hang-timeout \
 	fixed-link \
 	fsync \
+	hardlink \
 	io-cancel \
 	io_uring_enter \
 	io_uring_register \
@@ -193,6 +194,7 @@ test_srcs := \
 	files-exit-hang-timeout.c \
 	fixed-link.c \
 	fsync.c \
+	hardlink.c \
 	io-cancel.c \
 	io_uring_enter.c \
 	io_uring_register.c \
diff --git a/test/hardlink.c b/test/hardlink.c
new file mode 100644
index 0000000..1c73424
--- /dev/null
+++ b/test/hardlink.c
@@ -0,0 +1,133 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Description: test io_uring linkat handling
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "liburing.h"
+
+
+static int do_linkat(struct io_uring *ring, const char *oldname, const char *newname)
+{
+	int ret;
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "sqe get failed\n");
+		goto err;
+	}
+	io_uring_prep_linkat(sqe, AT_FDCWD, oldname, AT_FDCWD, newname, 0);
+
+	ret = io_uring_submit(ring);
+	if (ret != 1) {
+		fprintf(stderr, "submit failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = io_uring_wait_cqes(ring, &cqe, 1, 0, 0);
+	if (ret) {
+		fprintf(stderr, "wait_cqe failed: %d\n", ret);
+		goto err;
+	}
+	ret = cqe->res;
+	io_uring_cqe_seen(ring, cqe);
+	return ret;
+err:
+	return 1;
+}
+
+int files_linked_ok(const char* fn1, const char *fn2)
+{
+	struct stat s1, s2;
+
+	if (stat(fn1, &s1)) {
+		fprintf(stderr, "stat(%s): %s\n", fn1, strerror(errno));
+		return 0;
+	}
+	if (stat(fn2, &s2)) {
+		fprintf(stderr, "stat(%s): %s\n", fn2, strerror(errno));
+		return 0;
+	}
+	if (s1.st_dev != s2.st_dev || s1.st_ino != s2.st_ino) {
+		fprintf(stderr, "linked files have different device / inode numbers\n");
+		return 0;
+	}
+	if (s1.st_nlink != 2 || s2.st_nlink != 2) {
+		fprintf(stderr, "linked files have unexpected links count\n");
+		return 0;
+	}
+	return 1;
+}
+
+int main(int argc, char *argv[])
+{
+	static const char target[] = "io_uring-linkat-test-target";
+	static const char linkname[] = "io_uring-linkat-test-link";
+	int ret;
+	struct io_uring ring;
+
+	ret = io_uring_queue_init(8, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "queue init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = open(target, O_CREAT | O_RDWR | O_EXCL, 0600);
+	if (ret < 0) {
+		perror("open");
+		goto err;
+	}
+	if (write(ret, "linktest", 8) != 8) {
+		close(ret);
+		goto err1;
+	}
+	close(ret);
+
+	ret = do_linkat(&ring, target, linkname);
+	if (ret < 0) {
+		if (ret == -EBADF || ret == -EINVAL) {
+			fprintf(stdout, "linkat not supported, skipping\n");
+			goto out;
+		}
+		fprintf(stderr, "linkat: %s\n", strerror(-ret));
+		goto err1;
+	} else if (ret) {
+		goto err1;
+	}
+
+	if (!files_linked_ok(linkname, target))
+		goto err2;
+
+	ret = do_linkat(&ring, target, linkname);
+	if (ret != -EEXIST) {
+		fprintf(stderr, "test_linkat linkname already exists failed: %d\n", ret);
+		goto err2;
+	}
+
+	ret = do_linkat(&ring, target, "surely/this/does/not/exist");
+	if (ret != -ENOENT) {
+		fprintf(stderr, "test_linkat no parent failed: %d\n", ret);
+		goto err2;
+	}
+
+out:
+	unlinkat(AT_FDCWD, linkname, 0);
+	unlinkat(AT_FDCWD, target, 0);
+	io_uring_queue_exit(&ring);
+	return 0;
+err2:
+	unlinkat(AT_FDCWD, linkname, 0);
+err1:
+	unlinkat(AT_FDCWD, target, 0);
+err:
+	io_uring_queue_exit(&ring);
+	return 1;
+}
+
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 09/11] io_uring.h: add mknodat opcode
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
                   ` (7 preceding siblings ...)
  2021-06-03  5:29 ` [PATCH liburing v2 08/11] Add linkat test case Dmitry Kadashev
@ 2021-06-03  5:29 ` Dmitry Kadashev
  2021-06-03  5:29 ` [PATCH liburing v2 10/11] liburing.h: add mknodat prep helper Dmitry Kadashev
  2021-06-03  5:29 ` [PATCH liburing v2 11/11] Add mknod test case Dmitry Kadashev
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:29 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 src/include/liburing/io_uring.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index a5e48e7..46cd2fc 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -49,6 +49,7 @@ struct io_uring_sqe {
 		__u32		rename_flags;
 		__u32		unlink_flags;
 		__u32		hardlink_flags;
+		__u32		mknod_dev;
 	};
 	__u64	user_data;	/* data to be passed back at completion time */
 	union {
@@ -145,6 +146,7 @@ enum {
 	IORING_OP_MKDIRAT,
 	IORING_OP_SYMLINKAT,
 	IORING_OP_LINKAT,
+	IORING_OP_MKNODAT,
 
 	/* this goes last, obviously */
 	IORING_OP_LAST,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 10/11] liburing.h: add mknodat prep helper
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
                   ` (8 preceding siblings ...)
  2021-06-03  5:29 ` [PATCH liburing v2 09/11] io_uring.h: add mknodat opcode Dmitry Kadashev
@ 2021-06-03  5:29 ` Dmitry Kadashev
  2021-06-03  5:29 ` [PATCH liburing v2 11/11] Add mknod test case Dmitry Kadashev
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:29 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 src/include/liburing.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/include/liburing.h b/src/include/liburing.h
index 51dc602..c6ef0e8 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -570,6 +570,13 @@ static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd,
 	sqe->hardlink_flags = flags;
 }
 
+static inline void io_uring_prep_mknodat(struct io_uring_sqe *sqe, int dfd,
+					const char *pathname, mode_t mode, dev_t dev)
+{
+	io_uring_prep_rw(IORING_OP_MKNODAT, sqe, dfd, pathname, mode, 0);
+	sqe->mknod_dev = dev;
+}
+
 /*
  * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
  * the SQ ring
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH liburing v2 11/11] Add mknod test case
  2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
                   ` (9 preceding siblings ...)
  2021-06-03  5:29 ` [PATCH liburing v2 10/11] liburing.h: add mknodat prep helper Dmitry Kadashev
@ 2021-06-03  5:29 ` Dmitry Kadashev
  10 siblings, 0 replies; 12+ messages in thread
From: Dmitry Kadashev @ 2021-06-03  5:29 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Pavel Begunkov, io-uring, Dmitry Kadashev

Tests success (fifo, char dev), EEXISTS, ENOENT (no parent dir).

Signed-off-by: Dmitry Kadashev <dkadashev@gmail.com>
---
 .gitignore    |   1 +
 test/Makefile |   2 +
 test/mknod.c  | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 158 insertions(+)
 create mode 100644 test/mknod.c

diff --git a/.gitignore b/.gitignore
index 7a6f75c..93cc1ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,6 +70,7 @@
 /test/link_drain
 /test/madvise
 /test/mkdir
+/test/mknod
 /test/nop
 /test/nop-all-sizes
 /test/open-close
diff --git a/test/Makefile b/test/Makefile
index 2f0a694..fbc6c0f 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -67,6 +67,7 @@ test_targets += \
 	link_drain \
 	madvise \
 	mkdir \
+	mknod \
 	multicqes_drain \
 	nop \
 	nop-all-sizes \
@@ -207,6 +208,7 @@ test_srcs := \
 	link_drain.c \
 	madvise.c \
 	mkdir.c \
+	mknod.c \
 	multicqes_drain.c \
 	nop-all-sizes.c \
 	nop.c \
diff --git a/test/mknod.c b/test/mknod.c
new file mode 100644
index 0000000..d82e243
--- /dev/null
+++ b/test/mknod.c
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Description: test io_uring mknodat handling
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "liburing.h"
+
+static int do_mknodat(struct io_uring *ring, const char *fn, mode_t mode, dev_t dev)
+{
+	int ret;
+	struct io_uring_sqe *sqe;
+	struct io_uring_cqe *cqe;
+
+	sqe = io_uring_get_sqe(ring);
+	if (!sqe) {
+		fprintf(stderr, "sqe get failed\n");
+		goto err;
+	}
+	io_uring_prep_mknodat(sqe, AT_FDCWD, fn, mode, dev);
+
+	ret = io_uring_submit(ring);
+	if (ret != 1) {
+		fprintf(stderr, "submit failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = io_uring_wait_cqes(ring, &cqe, 1, 0, 0);
+	if (ret) {
+		fprintf(stderr, "wait_cqe failed: %d\n", ret);
+		goto err;
+	}
+	ret = cqe->res;
+	io_uring_cqe_seen(ring, cqe);
+	return ret;
+err:
+	return 1;
+}
+
+int check_fifo(const char* fn)
+{
+	char buf[4];
+	int fd = open(fn, O_RDWR);
+	if (fd < 0) {
+		fprintf(stderr, "failed to open fifo: %s\n", strerror(errno));
+		return 1;
+	}
+	if (write(fd, "42", 2) != 2) {
+		fprintf(stderr, "short write to fifo\n");
+		return 1;
+	}
+	if (read(fd, buf, 2) != 2) {
+		fprintf(stderr, "short read from fifo\n");
+		return 1;
+	}
+	buf[3] = 0;
+	if (strncmp(buf, "42", 2)) {
+		fprintf(stderr, "read unexpected data from fifo: %s\n", buf);
+		return 1;
+	}
+
+	return 0;
+}
+
+int test_device(struct io_uring *ring, const char* fn)
+{
+	// 1, 3 is /dev/null
+	struct stat sb;
+	dev_t dev = makedev(1, 3);
+	int ret = do_mknodat(ring, fn, 0600 | S_IFCHR, dev);
+	if (ret < 0) {
+		fprintf(stderr, "mknodat device: %s\n", strerror(-ret));
+		return ret;
+	} else if (ret) {
+		return ret;
+	}
+	ret = stat(fn, &sb);
+	if (ret) {
+		perror("stat");
+		return ret;
+	}
+	if (sb.st_rdev != dev) {
+		fprintf(stderr, "unexpected device number: %d, %d\n",
+			major(sb.st_rdev), minor(sb.st_rdev));
+		return 1;
+	}
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	static const char fn[] = "io_uring-mknodat-test";
+	int ret;
+	struct io_uring ring;
+
+	ret = io_uring_queue_init(8, &ring, 0);
+	if (ret) {
+		fprintf(stderr, "queue init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = do_mknodat(&ring, fn, 0600 | S_IFIFO, 0);
+	if (ret < 0) {
+		if (ret == -EBADF || ret == -EINVAL) {
+			fprintf(stdout, "mknodat not supported, skipping\n");
+			goto out;
+		}
+		fprintf(stderr, "mknodat: %s\n", strerror(-ret));
+		goto err;
+	} else if (ret) {
+		goto err;
+	}
+
+
+	if (check_fifo(fn))
+		goto err1;
+
+	ret = do_mknodat(&ring, fn, 0600 | S_IFIFO, 0);
+	if (ret != -EEXIST) {
+		fprintf(stderr, "do_mknodat already exists failed: %d\n", ret);
+		goto err1;
+	}
+
+	ret = do_mknodat(&ring, "surely/this/wont/exist", 0600 | S_IFIFO, 0);
+	if (ret != -ENOENT) {
+		fprintf(stderr, "do_mkdirat no parent failed: %d\n", ret);
+		goto err1;
+	}
+
+	unlinkat(AT_FDCWD, fn, 0);
+
+	if (!geteuid()) {
+		if (test_device(&ring, fn))
+			goto err1;
+	}
+	else
+		fprintf(stdout, "skipping the device test which needs root perms\n");
+
+out:
+	unlinkat(AT_FDCWD, fn, 0);
+	io_uring_queue_exit(&ring);
+	return 0;
+err1:
+	unlinkat(AT_FDCWD, fn, 0);
+err:
+	io_uring_queue_exit(&ring);
+	return 1;
+}
+
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-06-03  5:30 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-03  5:28 [PATCH liburing v2 00/11] add mkdir, [sym]linkat, mknodat support Dmitry Kadashev
2021-06-03  5:28 ` [PATCH liburing v2 01/11] liburing.h: add mkdirat prep helper Dmitry Kadashev
2021-06-03  5:28 ` [PATCH liburing v2 02/11] Add mkdirat test case Dmitry Kadashev
2021-06-03  5:28 ` [PATCH liburing v2 03/11] io_uring.h: add symlinkat opcode Dmitry Kadashev
2021-06-03  5:28 ` [PATCH liburing v2 04/11] liburing.h: add symlinkat prep helper Dmitry Kadashev
2021-06-03  5:29 ` [PATCH liburing v2 05/11] Add symlinkat test case Dmitry Kadashev
2021-06-03  5:29 ` [PATCH liburing v2 06/11] io_uring.h: add linkat opcode Dmitry Kadashev
2021-06-03  5:29 ` [PATCH liburing v2 07/11] liburing.h: add linkat prep helper Dmitry Kadashev
2021-06-03  5:29 ` [PATCH liburing v2 08/11] Add linkat test case Dmitry Kadashev
2021-06-03  5:29 ` [PATCH liburing v2 09/11] io_uring.h: add mknodat opcode Dmitry Kadashev
2021-06-03  5:29 ` [PATCH liburing v2 10/11] liburing.h: add mknodat prep helper Dmitry Kadashev
2021-06-03  5:29 ` [PATCH liburing v2 11/11] Add mknod test case Dmitry Kadashev

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.