io-uring.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 0/4] liburing: add getdents64 support
@ 2021-11-23 18:07 Stefan Roesch
  2021-11-23 18:07 ` [PATCH v1 1/4] liburing: update io_uring.h header file Stefan Roesch
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Stefan Roesch @ 2021-11-23 18:07 UTC (permalink / raw)
  To: io-uring; +Cc: shr

This adds the getdents support to liburing.

Patch 1: liburing: update io_uring.h header file
  This updates the io_uring header file with the new enum for
  the getdents support.

Patch 2: liburing: add prepare function for getdents
  Adds the io_uring_prep_getdents() function.

Patch 3: liburing: add test program for getdents
  Adds a new test program to test the getdents support. It queries
  the current directory and all its subdirectories.

Patch 4: liburing: add new man page
  Adds a new man page for the io_uring_prep_getdents call.


Stefan Roesch (4):
  liburing: update io_uring.h header file
  liburing: add prepare function for getdents64
  liburing: Add test program for getdents call
  liburing: Add man page for io_uring_prep_getdents call

 man/io_uring_prep_getdents.3    |  64 ++++++++
 src/include/liburing.h          |   6 +
 src/include/liburing/io_uring.h |   1 +
 test/Makefile                   |   1 +
 test/getdents.c                 | 258 ++++++++++++++++++++++++++++++++
 5 files changed, 330 insertions(+)
 create mode 100644 man/io_uring_prep_getdents.3
 create mode 100644 test/getdents.c

Signed-off-by: Stefan Roesch <shr@fb.com>
-- 
2.30.2


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

* [PATCH v1 1/4] liburing: update io_uring.h header file
  2021-11-23 18:07 [PATCH v1 0/4] liburing: add getdents64 support Stefan Roesch
@ 2021-11-23 18:07 ` Stefan Roesch
  2021-11-23 18:07 ` [PATCH v1 2/4] liburing: add prepare function for getdents64 Stefan Roesch
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Stefan Roesch @ 2021-11-23 18:07 UTC (permalink / raw)
  To: io-uring; +Cc: shr

Update io_uring.h header file with new op code for getdents64.

Signed-off-by: Stefan Roesch <shr@fb.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 61683bd..5a1f9f9 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -144,6 +144,7 @@ enum {
 	IORING_OP_MKDIRAT,
 	IORING_OP_SYMLINKAT,
 	IORING_OP_LINKAT,
+	IORING_OP_GETDENTS,
 
 	/* this goes last, obviously */
 	IORING_OP_LAST,
-- 
2.30.2


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

* [PATCH v1 2/4] liburing: add prepare function for getdents64
  2021-11-23 18:07 [PATCH v1 0/4] liburing: add getdents64 support Stefan Roesch
  2021-11-23 18:07 ` [PATCH v1 1/4] liburing: update io_uring.h header file Stefan Roesch
@ 2021-11-23 18:07 ` Stefan Roesch
  2021-11-23 18:07 ` [PATCH v1 3/4] liburing: Add test program for getdents call Stefan Roesch
  2021-11-23 18:07 ` [PATCH v1 4/4] liburing: Add man page for io_uring_prep_getdents call Stefan Roesch
  3 siblings, 0 replies; 5+ messages in thread
From: Stefan Roesch @ 2021-11-23 18:07 UTC (permalink / raw)
  To: io-uring; +Cc: shr

Adds the io_uring_prep_getdents() function to setup a getdents64 call.

Signed-off-by: Stefan Roesch <shr@fb.com>
---
 src/include/liburing.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/include/liburing.h b/src/include/liburing.h
index 169e098..8deae5a 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -672,6 +672,12 @@ static inline void io_uring_prep_linkat(struct io_uring_sqe *sqe, int olddfd,
 	sqe->hardlink_flags = (__u32) flags;
 }
 
+static inline void io_uring_prep_getdents(struct io_uring_sqe *sqe, int fd,
+					  void *buf, unsigned int count, uint64_t offset)
+{
+	io_uring_prep_rw(IORING_OP_GETDENTS, sqe, fd, buf, count, offset);
+}
+
 /*
  * Returns number of unconsumed (if SQPOLL) or unsubmitted entries exist in
  * the SQ ring
-- 
2.30.2


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

* [PATCH v1 3/4] liburing: Add test program for getdents call
  2021-11-23 18:07 [PATCH v1 0/4] liburing: add getdents64 support Stefan Roesch
  2021-11-23 18:07 ` [PATCH v1 1/4] liburing: update io_uring.h header file Stefan Roesch
  2021-11-23 18:07 ` [PATCH v1 2/4] liburing: add prepare function for getdents64 Stefan Roesch
@ 2021-11-23 18:07 ` Stefan Roesch
  2021-11-23 18:07 ` [PATCH v1 4/4] liburing: Add man page for io_uring_prep_getdents call Stefan Roesch
  3 siblings, 0 replies; 5+ messages in thread
From: Stefan Roesch @ 2021-11-23 18:07 UTC (permalink / raw)
  To: io-uring; +Cc: shr

Add test program for getdents64 call.

Signed-off-by: Stefan Roesch <shr@fb.com>
---
 test/Makefile   |   1 +
 test/getdents.c | 258 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 259 insertions(+)
 create mode 100644 test/getdents.c

diff --git a/test/Makefile b/test/Makefile
index d6e7227..3e29a1f 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -77,6 +77,7 @@ test_srcs := \
 	file-verify.c \
 	fixed-link.c \
 	fsync.c \
+	getdents.c \
 	hardlink.c \
 	io-cancel.c \
 	iopoll.c \
diff --git a/test/getdents.c b/test/getdents.c
new file mode 100644
index 0000000..81da36c
--- /dev/null
+++ b/test/getdents.c
@@ -0,0 +1,258 @@
+#include <assert.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include "helpers.h"
+#include "liburing.h"
+
+#define BUFFER_SIZE 512
+
+#define LIST_INIT(name) { &(name), &(name) }
+
+#define CONTAINER_OF(ptr, type, member) (					\
+	{									\
+		const typeof(((type *)0)->member) *__ptr = (ptr);		\
+		(type *)((char *)__ptr - (intptr_t)(&((type *)0)->member)); 	\
+	})
+
+struct list {
+	struct list	*next;
+	struct list	*prev;
+};
+
+struct dir {
+	struct list	list;
+	int		ret;
+
+	struct dir	*parent;
+	int		fd;
+	uint64_t	off;
+	uint8_t		buf[BUFFER_SIZE];
+	char		name[0];
+};
+
+struct linux_dirent64 {
+	int64_t		d_ino;    /* 64-bit inode number */
+	int64_t		d_off;    /* 64-bit offset to next structure */
+	unsigned short	d_reclen; /* Size of this dirent */
+	unsigned char	d_type;   /* File type */
+	char		d_name[]; /* Filename (null-terminated) */
+};
+
+/* Define global variables. */
+static struct io_uring ring;
+static struct list active = LIST_INIT(active);
+static int sqes_in_flight = 0;
+static int num_dir_entries = 0;
+
+/* Forward declarations. */
+static void drain_cqes(void);
+static void schedule_readdir(struct dir *dir);
+
+/* List helper functions. */
+static inline void
+list_add_tail(struct list *l, struct list *head)
+{
+	l->next = head;
+	l->prev = head->prev;
+	head->prev->next = l;
+	head->prev = l;
+}
+
+static inline void list_del(struct list *l)
+{
+	l->prev->next = l->next;
+	l->next->prev = l->prev;
+	l->prev = NULL;
+	l->next = NULL;
+}
+
+static inline int is_list_empty(const struct list *l)
+{
+	return l->next == l;
+}
+
+static struct io_uring_sqe *get_sqe(void)
+{
+	struct io_uring_sqe *sqe;
+
+	sqe = io_uring_get_sqe(&ring);
+	while (sqe == NULL) {
+		drain_cqes();
+
+		int ret = io_uring_submit(&ring);
+		if (ret < 0 && errno != EBUSY) {
+			perror("io_uring_submit");
+			exit(EXIT_FAILURE);
+		}
+
+		sqe = io_uring_get_sqe(&ring);
+	}
+
+	sqes_in_flight++;
+	return sqe;
+}
+
+static void drain_cqes(void)
+{
+	int 			count;
+	uint32_t 		head;
+	struct io_uring_cqe 	*cqe;
+
+	count = 0;
+	io_uring_for_each_cqe (&ring, head, cqe) {
+		struct dir *dir;
+
+		dir = io_uring_cqe_get_data(cqe);
+
+		list_add_tail(&dir->list, &active);
+		dir->ret = cqe->res;
+
+		count++;
+	}
+
+	sqes_in_flight -= count;
+	io_uring_cq_advance(&ring, count);
+}
+
+static void schedule_opendir(struct dir *parent, const char *name)
+{
+	int 			len = strlen(name);
+	struct dir 		*dir;
+	struct io_uring_sqe 	*sqe;
+
+	dir = malloc(sizeof(*dir) + len + 1);
+	if (dir == NULL) {
+		fprintf(stderr, "out of memory\n");
+		exit(EXIT_FAILURE);
+	}
+
+	dir->parent = parent;
+	dir->fd = -1;
+	memcpy(dir->name, name, len);
+	dir->name[len] = 0;
+
+	sqe = get_sqe();
+	io_uring_prep_openat(sqe,
+			     (parent != NULL) ? parent->fd : AT_FDCWD,
+			     dir->name,
+			     O_DIRECTORY,
+			     0);
+	io_uring_sqe_set_data(sqe, dir);
+}
+
+static void opendir_completion(struct dir *dir, int ret)
+{
+	if (ret < 0) {
+		fprintf(stderr, "error opening ");
+		fprintf(stderr, ": %s\n", strerror(-ret));
+		return;
+	}
+
+	dir->fd = ret;
+	dir->off = 0;
+	schedule_readdir(dir);
+}
+
+static void schedule_readdir(struct dir *dir)
+{
+	struct io_uring_sqe *sqe;
+
+	sqe = get_sqe();
+	io_uring_prep_getdents(sqe, dir->fd, dir->buf, sizeof(dir->buf), dir->off);
+	io_uring_sqe_set_data(sqe, dir);
+}
+
+static void readdir_completion(struct dir *dir, int ret)
+{
+	uint8_t *bufp;
+	uint8_t *end;
+
+	if (ret < 0) {
+		fprintf(stderr, "error reading ");
+		fprintf(stderr, ": %s (%d)\n", strerror(-ret), ret);
+		return;
+	}
+
+	if (ret == 0) {
+		free(dir);
+		return;
+	}
+
+	bufp = dir->buf;
+	end = bufp + ret;
+
+	while (bufp < end) {
+		struct linux_dirent64 *dent;
+
+		dent = (struct linux_dirent64 *)bufp;
+
+		if (strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
+			if (dent->d_type == DT_DIR)
+				schedule_opendir(dir, dent->d_name);
+		}
+
+		dir->off = dent->d_off;
+		bufp += dent->d_reclen;
+		++num_dir_entries;
+	}
+
+	schedule_readdir(dir);
+}
+
+int main(int argc, char *argv[])
+{
+	struct rlimit rlim;
+
+	/* Increase number of files rlimit to 1M. */
+	if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
+		perror("getrlimit");
+		return 1;
+	}
+
+	if (geteuid() == 0 && rlim.rlim_max < 1048576)
+		rlim.rlim_max = 1048576;
+
+	if (rlim.rlim_cur < rlim.rlim_max) {
+		rlim.rlim_cur = rlim.rlim_max;
+		setrlimit(RLIMIT_NOFILE, &rlim);
+	}
+
+	if (io_uring_queue_init(256, &ring, 0) < 0) {
+		perror("io_uring_queue_init");
+		return 1;
+	}
+
+	/* Submit and handle requests. */
+	schedule_opendir(NULL, ".");
+	while (sqes_in_flight) {
+		int ret = io_uring_submit_and_wait(&ring, 1);
+		if (ret < 0 && errno != EBUSY) {
+			perror("io_uring_submit_and_wait");
+			return 1;
+		}
+
+		drain_cqes();
+
+		while (!is_list_empty(&active)) {
+			struct dir *dir;
+
+			dir = CONTAINER_OF(active.next, struct dir, list);
+			list_del(&dir->list);
+
+			if (dir->fd == -1)
+				opendir_completion(dir, dir->ret);
+			else
+				readdir_completion(dir, dir->ret);
+		}
+	}
+
+	io_uring_queue_exit(&ring);
+	return num_dir_entries < 50;
+}
-- 
2.30.2


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

* [PATCH v1 4/4] liburing: Add man page for io_uring_prep_getdents call
  2021-11-23 18:07 [PATCH v1 0/4] liburing: add getdents64 support Stefan Roesch
                   ` (2 preceding siblings ...)
  2021-11-23 18:07 ` [PATCH v1 3/4] liburing: Add test program for getdents call Stefan Roesch
@ 2021-11-23 18:07 ` Stefan Roesch
  3 siblings, 0 replies; 5+ messages in thread
From: Stefan Roesch @ 2021-11-23 18:07 UTC (permalink / raw)
  To: io-uring; +Cc: shr

Adds the man page for the io_uring_prep_getdents call.

Signed-off-by: Stefan Roesch <shr@fb.com>
---
 man/io_uring_prep_getdents.3 | 64 ++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 man/io_uring_prep_getdents.3

diff --git a/man/io_uring_prep_getdents.3 b/man/io_uring_prep_getdents.3
new file mode 100644
index 0000000..15279f6
--- /dev/null
+++ b/man/io_uring_prep_getdents.3
@@ -0,0 +1,64 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+.TH io_uring_prep_getdents 3 "November 19, 2021" "liburing-2.1" "liburing Manual"
+.SH NAME
+io_uring_prep_getdents   - prepare getdents64 call
+
+.SH SYNOPSIS
+.nf
+.BR "#include <liburing.h>"
+.PP
+.BI "void io_uring_prep_getdents(struct io_uring_sqe *sqe,"
+.BI "                            int fd,"
+.BI "                            void *buf,"
+.BI "                            unsigned int count,"
+.BI "                            uint64_t offset)"
+
+.SH DESCRIPTION
+.PP
+The io_uring_prep_getdents() prepares a getdents64 request. The submission queue
+entry
+.I sqe
+is setup to use the file descriptor
+.I fd
+to start writing up to
+.I count
+bytes into the buffer
+.I buf
+starting at
+.I offset.
+
+After the getdents call has been prepared it can be submitted with one of the submit
+functions.
+
+.SH RETURN VALUE
+None
+
+.SH EXAMPLE
+A getdents io_uring call can be prepared like in the following code snippet.
+The io_uring_sqe_set_data(3) call is not necessary, but it helps to correlate the
+request with the results.
+
+.BI "void schedule_readdir(struct io_uring_sqe *sqe, struct dir *dir)"
+.fi
+.BI "{"
+.fi
+.BI "   io_uring_prep_getdents(sqe,"
+.fi
+.BI "                          dir->fd,"
+.fi
+.BI "                          dir->buf,"
+.fi
+.BI "                          sizeof(dir->buf),"
+.fi
+.BI "                          dir->off);"
+.fi
+.BI "   io_uring_sqe_set_data(sqe, dir);
+.fi
+.BI "}"
+
+
+.SH SEE ALSO
+.BR io_uring_get_sqe (3), io_uring_sqe_set_data (3), io_uring_submit (3), io_uring_sqe_get_data (3)
-- 
2.30.2


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

end of thread, other threads:[~2021-11-23 18:08 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-23 18:07 [PATCH v1 0/4] liburing: add getdents64 support Stefan Roesch
2021-11-23 18:07 ` [PATCH v1 1/4] liburing: update io_uring.h header file Stefan Roesch
2021-11-23 18:07 ` [PATCH v1 2/4] liburing: add prepare function for getdents64 Stefan Roesch
2021-11-23 18:07 ` [PATCH v1 3/4] liburing: Add test program for getdents call Stefan Roesch
2021-11-23 18:07 ` [PATCH v1 4/4] liburing: Add man page for io_uring_prep_getdents call Stefan Roesch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).