* [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 <[email protected]>
--
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 <[email protected]>
---
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 <[email protected]>
---
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 <[email protected]>
---
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 <[email protected]>
---
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 <[email protected]>
+.\"
+.\" 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