* [PATCH liburing 0/4] zerocopy send API changes
@ 2022-09-02 11:12 Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 1/4] tests: verify that send addr is copied when async Pavel Begunkov
` (5 more replies)
0 siblings, 6 replies; 11+ messages in thread
From: Pavel Begunkov @ 2022-09-02 11:12 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
Fix up helpers and tests to match API changes and also add some more tests.
Pavel Begunkov (4):
tests: verify that send addr is copied when async
zc: adjust sendzc to the simpler uapi
test: test iowq zc sends
examples: adjust zc bench to the new uapi
examples/send-zerocopy.c | 72 ++--
src/include/liburing.h | 39 +-
src/include/liburing/io_uring.h | 28 +-
src/register.c | 20 -
test/send-zerocopy.c | 667 +++++++-------------------------
5 files changed, 178 insertions(+), 648 deletions(-)
--
2.37.2
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH liburing 1/4] tests: verify that send addr is copied when async
2022-09-02 11:12 [PATCH liburing 0/4] zerocopy send API changes Pavel Begunkov
@ 2022-09-02 11:12 ` Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 2/4] zc: adjust sendzc to the simpler uapi Pavel Begunkov
` (4 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2022-09-02 11:12 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
The kernel should not be touching timespec after returning from submit
syscall, make sure it's not reloaded after a request goes async.
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/send-zerocopy.c | 69 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/test/send-zerocopy.c b/test/send-zerocopy.c
index 307c114..97727e3 100644
--- a/test/send-zerocopy.c
+++ b/test/send-zerocopy.c
@@ -836,6 +836,69 @@ static int test_inet_send(struct io_uring *ring)
return 0;
}
+static int test_async_addr(struct io_uring *ring)
+{
+ struct io_uring_sqe *sqe;
+ struct io_uring_cqe *cqe;
+ struct sockaddr_storage addr;
+ int sock_tx = -1, sock_rx = -1;
+ struct __kernel_timespec ts;
+ int ret;
+
+ ret = prepare_ip(&addr, &sock_tx, &sock_rx, true, false, false, false);
+ if (ret) {
+ fprintf(stderr, "sock prep failed %d\n", ret);
+ return 1;
+ }
+
+ sqe = io_uring_get_sqe(ring);
+ ts.tv_sec = 1;
+ ts.tv_nsec = 0;
+ io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_ETIME_SUCCESS);
+ sqe->user_data = 1;
+ sqe->flags |= IOSQE_IO_LINK;
+
+ sqe = io_uring_get_sqe(ring);
+ io_uring_prep_sendzc(sqe, sock_tx, tx_buffer, 1, 0, 0, 0);
+ sqe->user_data = 2;
+ io_uring_prep_sendzc_set_addr(sqe, (const struct sockaddr *)&addr,
+ sizeof(struct sockaddr_in6));
+
+ ret = io_uring_submit(ring);
+ assert(ret == 2);
+ memset(&addr, 0, sizeof(addr));
+
+ ret = io_uring_wait_cqe(ring, &cqe);
+ if (ret) {
+ fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret);
+ return 1;
+ }
+ if (cqe->user_data != 1 || cqe->res != -ETIME) {
+ fprintf(stderr, "invalid timeout res %i %i\n",
+ (int)cqe->user_data, cqe->res);
+ return 1;
+ }
+ io_uring_cqe_seen(ring, cqe);
+
+ ret = io_uring_wait_cqe(ring, &cqe);
+ if (ret) {
+ fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret);
+ return 1;
+ }
+ if (cqe->user_data != 2 || cqe->res != 1) {
+ fprintf(stderr, "invalid send %i %i\n",
+ (int)cqe->user_data, cqe->res);
+ return 1;
+ }
+ io_uring_cqe_seen(ring, cqe);
+ ret = recv(sock_rx, rx_buffer, 1, MSG_TRUNC);
+ assert(ret == 1);
+
+ close(sock_tx);
+ close(sock_rx);
+ return 0;
+}
+
int main(int argc, char *argv[])
{
struct io_uring ring;
@@ -973,6 +1036,12 @@ int main(int argc, char *argv[])
fprintf(stderr, "test_inet_send() failed\n");
return ret;
}
+
+ ret = test_async_addr(&ring);
+ if (ret) {
+ fprintf(stderr, "test_async_addr() failed\n");
+ return ret;
+ }
out:
io_uring_queue_exit(&ring);
close(sp[0]);
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH liburing 2/4] zc: adjust sendzc to the simpler uapi
2022-09-02 11:12 [PATCH liburing 0/4] zerocopy send API changes Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 1/4] tests: verify that send addr is copied when async Pavel Begunkov
@ 2022-09-02 11:12 ` Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 3/4] test: test iowq zc sends Pavel Begunkov
` (3 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2022-09-02 11:12 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
We update the zerocopy API, reflect it in liburing, this includes
removing the whole notification story, updating headers and fixing
up tests.
Signed-off-by: Pavel Begunkov <[email protected]>
---
src/include/liburing.h | 39 +-
src/include/liburing/io_uring.h | 28 +-
src/register.c | 20 --
test/send-zerocopy.c | 611 ++++----------------------------
4 files changed, 91 insertions(+), 607 deletions(-)
diff --git a/src/include/liburing.h b/src/include/liburing.h
index 68a1646..c672440 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -199,10 +199,6 @@ int io_uring_register_sync_cancel(struct io_uring *ring,
int io_uring_register_file_alloc_range(struct io_uring *ring,
unsigned off, unsigned len);
-int io_uring_register_notifications(struct io_uring *ring, unsigned nr,
- struct io_uring_notification_slot *slots);
-int io_uring_unregister_notifications(struct io_uring *ring);
-
/*
* io_uring syscalls.
*/
@@ -702,44 +698,23 @@ static inline void io_uring_prep_send(struct io_uring_sqe *sqe, int sockfd,
sqe->msg_flags = (__u32) flags;
}
-static inline void io_uring_prep_sendzc(struct io_uring_sqe *sqe, int sockfd,
- const void *buf, size_t len, int flags,
- unsigned slot_idx, unsigned zc_flags)
+static inline void io_uring_prep_send_zc(struct io_uring_sqe *sqe, int sockfd,
+ const void *buf, size_t len, int flags,
+ unsigned zc_flags)
{
- io_uring_prep_rw(IORING_OP_SENDZC_NOTIF, sqe, sockfd, buf, (__u32) len, 0);
+ io_uring_prep_rw(IORING_OP_SEND_ZC, sqe, sockfd, buf, (__u32) len, 0);
sqe->msg_flags = (__u32) flags;
- sqe->notification_idx = slot_idx;
sqe->ioprio = zc_flags;
}
-static inline void io_uring_prep_sendzc_fixed(struct io_uring_sqe *sqe, int sockfd,
- const void *buf, size_t len,
- int flags, unsigned slot_idx,
- unsigned zc_flags, unsigned buf_idx)
-{
- io_uring_prep_sendzc(sqe, sockfd, buf, len, flags, slot_idx, zc_flags);
- sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
- sqe->buf_index = buf_idx;
-}
-
-static inline void io_uring_prep_sendzc_set_addr(struct io_uring_sqe *sqe,
- const struct sockaddr *dest_addr,
- __u16 addr_len)
+static inline void io_uring_prep_send_set_addr(struct io_uring_sqe *sqe,
+ const struct sockaddr *dest_addr,
+ __u16 addr_len)
{
sqe->addr2 = (unsigned long)(void *)dest_addr;
sqe->addr_len = addr_len;
}
-static inline void io_uring_prep_notif_update(struct io_uring_sqe *sqe,
- __u64 new_tag, /* 0 to ignore */
- unsigned offset, unsigned nr)
-{
- io_uring_prep_rw(IORING_OP_FILES_UPDATE, sqe, -1, 0, nr,
- (__u64)offset);
- sqe->addr = new_tag;
- sqe->ioprio = IORING_RSRC_UPDATE_NOTIF;
-}
-
static inline void io_uring_prep_recv(struct io_uring_sqe *sqe, int sockfd,
void *buf, size_t len, int flags)
{
diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index 9e0b5c8..6b83177 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -71,8 +71,8 @@ struct io_uring_sqe {
__s32 splice_fd_in;
__u32 file_index;
struct {
- __u16 notification_idx;
__u16 addr_len;
+ __u16 __pad3[1];
};
};
union {
@@ -178,8 +178,7 @@ enum io_uring_op {
IORING_OP_FALLOCATE,
IORING_OP_OPENAT,
IORING_OP_CLOSE,
- IORING_OP_RSRC_UPDATE,
- IORING_OP_FILES_UPDATE = IORING_OP_RSRC_UPDATE,
+ IORING_OP_FILES_UPDATE,
IORING_OP_STATX,
IORING_OP_READ,
IORING_OP_WRITE,
@@ -206,7 +205,7 @@ enum io_uring_op {
IORING_OP_GETXATTR,
IORING_OP_SOCKET,
IORING_OP_URING_CMD,
- IORING_OP_SENDZC_NOTIF,
+ IORING_OP_SEND_ZC,
/* this goes last, obviously */
IORING_OP_LAST,
@@ -228,7 +227,6 @@ enum io_uring_op {
#define IORING_TIMEOUT_ETIME_SUCCESS (1U << 5)
#define IORING_TIMEOUT_CLOCK_MASK (IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME)
#define IORING_TIMEOUT_UPDATE_MASK (IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE)
-
/*
* sqe->splice_flags
* extends splice(2) flags
@@ -281,29 +279,16 @@ enum io_uring_op {
*
* IORING_RECVSEND_FIXED_BUF Use registered buffers, the index is stored in
* the buf_index field.
- *
- * IORING_RECVSEND_NOTIF_FLUSH Flush a notification after a successful
- * successful. Only for zerocopy sends.
*/
#define IORING_RECVSEND_POLL_FIRST (1U << 0)
#define IORING_RECV_MULTISHOT (1U << 1)
#define IORING_RECVSEND_FIXED_BUF (1U << 2)
-#define IORING_RECVSEND_NOTIF_FLUSH (1U << 3)
/*
* accept flags stored in sqe->ioprio
*/
#define IORING_ACCEPT_MULTISHOT (1U << 0)
-
-/*
- * IORING_OP_RSRC_UPDATE flags
- */
-enum {
- IORING_RSRC_UPDATE_FILES,
- IORING_RSRC_UPDATE_NOTIF,
-};
-
/*
* IORING_OP_MSG_RING command types, stored in sqe->addr
*/
@@ -341,10 +326,13 @@ struct io_uring_cqe {
* IORING_CQE_F_BUFFER If set, the upper 16 bits are the buffer ID
* IORING_CQE_F_MORE If set, parent SQE will generate more CQE entries
* IORING_CQE_F_SOCK_NONEMPTY If set, more data to read after socket recv
+ * IORING_CQE_F_NOTIF Set for notification CQEs. Can be used to distinct
+ * them from sends.
*/
#define IORING_CQE_F_BUFFER (1U << 0)
#define IORING_CQE_F_MORE (1U << 1)
#define IORING_CQE_F_SOCK_NONEMPTY (1U << 2)
+#define IORING_CQE_F_NOTIF (1U << 3)
enum {
IORING_CQE_BUFFER_SHIFT = 16,
@@ -485,10 +473,6 @@ enum {
/* register a range of fixed file slots for automatic slot allocation */
IORING_REGISTER_FILE_ALLOC_RANGE = 25,
- /* zerocopy notification API */
- IORING_REGISTER_NOTIFIERS = 26,
- IORING_UNREGISTER_NOTIFIERS = 27,
-
/* this goes last */
IORING_REGISTER_LAST
};
diff --git a/src/register.c b/src/register.c
index 7482112..2b37e5f 100644
--- a/src/register.c
+++ b/src/register.c
@@ -364,23 +364,3 @@ int io_uring_register_file_alloc_range(struct io_uring *ring,
IORING_REGISTER_FILE_ALLOC_RANGE, &range,
0);
}
-
-int io_uring_register_notifications(struct io_uring *ring, unsigned nr,
- struct io_uring_notification_slot *slots)
-{
- struct io_uring_notification_register r = {
- .nr_slots = nr,
- .data = (unsigned long)slots,
- };
-
- return __sys_io_uring_register(ring->ring_fd,
- IORING_REGISTER_NOTIFIERS,
- &r, sizeof(r));
-}
-
-int io_uring_unregister_notifications(struct io_uring *ring)
-{
- return __sys_io_uring_register(ring->ring_fd,
- IORING_UNREGISTER_NOTIFIERS,
- NULL, 0);
-}
diff --git a/test/send-zerocopy.c b/test/send-zerocopy.c
index 97727e3..7b58ae7 100644
--- a/test/send-zerocopy.c
+++ b/test/send-zerocopy.c
@@ -44,7 +44,6 @@
#define HOST "127.0.0.1"
#define HOSTV6 "::1"
-#define NR_SLOTS 5
#define ZC_TAG 10000
#define BUFFER_OFFSET 41
@@ -52,15 +51,9 @@
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
#endif
-static int seqs[NR_SLOTS];
static char *tx_buffer, *rx_buffer;
static struct iovec buffers_iov[3];
-static inline bool tag_userdata(__u64 user_data)
-{
- return ZC_TAG <= user_data && user_data < ZC_TAG + NR_SLOTS;
-}
-
static bool check_cq_empty(struct io_uring *ring)
{
struct io_uring_cqe *cqe = NULL;
@@ -70,41 +63,18 @@ static bool check_cq_empty(struct io_uring *ring)
return ret == -EAGAIN;
}
-static int register_notifications(struct io_uring *ring)
-{
- struct io_uring_notification_slot slots[NR_SLOTS] = {};
- int i;
-
- memset(seqs, 0, sizeof(seqs));
- for (i = 0; i < NR_SLOTS; i++)
- slots[i].tag = ZC_TAG + i;
- return io_uring_register_notifications(ring, NR_SLOTS, slots);
-}
-
-static int reregister_notifications(struct io_uring *ring)
-{
- int ret;
-
- ret = io_uring_unregister_notifications(ring);
- if (ret) {
- fprintf(stderr, "unreg notifiers failed %i\n", ret);
- return ret;
- }
-
- return register_notifications(ring);
-}
-
-static int do_one(struct io_uring *ring, int sock_tx, int slot_idx)
+static int test_basic_send(struct io_uring *ring, int sock_tx, int sock_rx)
{
struct io_uring_sqe *sqe;
struct io_uring_cqe *cqe;
int msg_flags = 0;
unsigned zc_flags = 0;
+ int payload_size = 100;
int ret;
sqe = io_uring_get_sqe(ring);
- io_uring_prep_sendzc(sqe, sock_tx, tx_buffer, 1, msg_flags,
- slot_idx, zc_flags);
+ io_uring_prep_send_zc(sqe, sock_tx, tx_buffer, payload_size,
+ msg_flags, zc_flags);
sqe->user_data = 1;
ret = io_uring_submit(ring);
@@ -112,434 +82,61 @@ static int do_one(struct io_uring *ring, int sock_tx, int slot_idx)
ret = io_uring_wait_cqe(ring, &cqe);
assert(!ret);
assert(cqe->user_data == 1);
- ret = cqe->res;
+ if (ret == -EINVAL) {
+ assert(!(cqe->flags & IORING_CQE_F_MORE));
+ return T_EXIT_SKIP;
+ }
+ assert(cqe->res == payload_size);
+ assert(cqe->flags & IORING_CQE_F_MORE);
io_uring_cqe_seen(ring, cqe);
- assert(check_cq_empty(ring));
- return ret;
-}
-
-static int test_invalid_slot(struct io_uring *ring, int sock_tx, int sock_rx)
-{
- int ret;
-
- ret = do_one(ring, sock_tx, NR_SLOTS);
- assert(ret == -EINVAL);
- return 0;
-}
-
-static int test_basic_send(struct io_uring *ring, int sock_tx, int sock_rx)
-{
- struct io_uring_sqe *sqe;
- struct io_uring_cqe *cqe;
- int msg_flags = 0;
- int slot_idx = 0;
- unsigned zc_flags = 0;
- int payload_size = 100;
- int ret;
-
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_sendzc(sqe, sock_tx, tx_buffer, payload_size, msg_flags,
- slot_idx, zc_flags);
- sqe->user_data = 1;
- ret = io_uring_submit(ring);
- assert(ret == 1);
ret = io_uring_wait_cqe(ring, &cqe);
assert(!ret);
- assert(cqe->user_data == 1 && cqe->res >= 0);
+ assert(cqe->user_data == 1);
+ assert(cqe->flags & IORING_CQE_F_NOTIF);
+ assert(!(cqe->flags & IORING_CQE_F_MORE));
io_uring_cqe_seen(ring, cqe);
assert(check_cq_empty(ring));
ret = recv(sock_rx, rx_buffer, payload_size, MSG_TRUNC);
assert(ret == payload_size);
- return 0;
+ return T_EXIT_PASS;
}
-static int test_send_flush(struct io_uring *ring, int sock_tx, int sock_rx)
+static int test_send_faults(struct io_uring *ring, int sock_tx, int sock_rx)
{
struct io_uring_sqe *sqe;
struct io_uring_cqe *cqe;
int msg_flags = 0;
- int slot_idx = 0;
unsigned zc_flags = 0;
int payload_size = 100;
- int ret, i, j;
- int req_cqes, notif_cqes;
-
- /* now do send+flush, do many times to verify seqs */
- for (j = 0; j < NR_SLOTS * 5; j++) {
- zc_flags = IORING_RECVSEND_NOTIF_FLUSH;
- slot_idx = rand() % NR_SLOTS;
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_sendzc(sqe, sock_tx, tx_buffer, payload_size,
- msg_flags, slot_idx, zc_flags);
- sqe->user_data = 1;
-
- ret = io_uring_submit(ring);
- assert(ret == 1);
-
- req_cqes = notif_cqes = 1;
- for (i = 0; i < 2; i ++) {
- ret = io_uring_wait_cqe(ring, &cqe);
- assert(!ret);
-
- if (cqe->user_data == 1) {
- assert(req_cqes > 0);
- req_cqes--;
- assert(cqe->res == payload_size);
- } else if (cqe->user_data == ZC_TAG + slot_idx) {
- assert(notif_cqes > 0);
- notif_cqes--;
- assert(cqe->res == 0 && cqe->flags == seqs[slot_idx]);
- seqs[slot_idx]++;
- } else {
- fprintf(stderr, "invalid cqe %lu %i\n",
- (unsigned long)cqe->user_data, cqe->res);
- return -1;
- }
- io_uring_cqe_seen(ring, cqe);
- }
- assert(check_cq_empty(ring));
-
- ret = recv(sock_rx, rx_buffer, payload_size, MSG_TRUNC);
- assert(ret == payload_size);
- }
- return 0;
-}
-
-static int test_multireq_notif(struct io_uring *ring, int sock_tx, int sock_rx)
-{
- bool slot_seen[NR_SLOTS] = {};
- struct io_uring_sqe *sqe;
- struct io_uring_cqe *cqe;
- int msg_flags = 0;
- int slot_idx = 0;
- unsigned zc_flags = 0;
- int payload_size = 1;
- int ret, j, i = 0;
- int nr = NR_SLOTS * 21;
-
- while (i < nr) {
- int nr_per_wave = 23;
-
- for (j = 0; j < nr_per_wave && i < nr; j++, i++) {
- slot_idx = rand() % NR_SLOTS;
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_sendzc(sqe, sock_tx, tx_buffer, payload_size,
- msg_flags, slot_idx, zc_flags);
- sqe->user_data = i;
- }
- ret = io_uring_submit(ring);
- assert(ret == j);
- }
-
- for (i = 0; i < nr; i++) {
- ret = io_uring_wait_cqe(ring, &cqe);
- assert(!ret);
- assert(cqe->user_data < nr && cqe->res == payload_size);
- io_uring_cqe_seen(ring, cqe);
-
- ret = recv(sock_rx, rx_buffer, payload_size, MSG_TRUNC);
- assert(ret == payload_size);
- }
- assert(check_cq_empty(ring));
-
- zc_flags = IORING_RECVSEND_NOTIF_FLUSH;
- for (slot_idx = 0; slot_idx < NR_SLOTS; slot_idx++) {
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_sendzc(sqe, sock_tx, tx_buffer, payload_size,
- msg_flags, slot_idx, zc_flags);
- sqe->user_data = slot_idx;
- /* just to simplify cqe handling */
- sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
- }
- ret = io_uring_submit(ring);
- assert(ret == NR_SLOTS);
-
- for (i = 0; i < NR_SLOTS; i++) {
- int slot_idx;
-
- ret = io_uring_wait_cqe(ring, &cqe);
- assert(!ret);
- assert(tag_userdata(cqe->user_data));
-
- slot_idx = cqe->user_data - ZC_TAG;
- assert(!slot_seen[slot_idx]);
- slot_seen[slot_idx] = true;
-
- assert(cqe->res == 0 && cqe->flags == seqs[slot_idx]);
- seqs[slot_idx]++;
- io_uring_cqe_seen(ring, cqe);
-
- ret = recv(sock_rx, rx_buffer, payload_size, MSG_TRUNC);
- assert(ret == payload_size);
- }
- assert(check_cq_empty(ring));
-
- for (i = 0; i < NR_SLOTS; i++)
- assert(slot_seen[i]);
- return 0;
-}
-
-static int test_multi_send_flushing(struct io_uring *ring, int sock_tx, int sock_rx)
-{
- struct io_uring_sqe *sqe;
- struct io_uring_cqe *cqe;
- unsigned zc_flags = IORING_RECVSEND_NOTIF_FLUSH;
- int msg_flags = 0, slot_idx = 0;
- int payload_size = 1;
- int ret, j, i = 0;
- int nr = NR_SLOTS * 30;
- unsigned long long check = 0, expected = 0;
-
- while (i < nr) {
- int nr_per_wave = 25;
-
- for (j = 0; j < nr_per_wave && i < nr; j++, i++) {
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_sendzc(sqe, sock_tx, tx_buffer, payload_size,
- msg_flags, slot_idx, zc_flags);
- sqe->user_data = 1;
- sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
- }
- ret = io_uring_submit(ring);
- assert(ret == j);
- }
-
- for (i = 0; i < nr; i++) {
- int seq;
-
- ret = io_uring_wait_cqe(ring, &cqe);
- assert(!ret);
- assert(!cqe->res);
- assert(tag_userdata(cqe->user_data));
-
- seq = cqe->flags;
- check += seq * 100007UL;
- io_uring_cqe_seen(ring, cqe);
-
- ret = recv(sock_rx, rx_buffer, payload_size, MSG_TRUNC);
- assert(ret == payload_size);
- }
- assert(check_cq_empty(ring));
-
- for (i = 0; i < nr; i++)
- expected += (i + seqs[slot_idx]) * 100007UL;
- assert(check == expected);
- seqs[slot_idx] += nr;
- return 0;
-}
-
-static int do_one_fail_notif_flush(struct io_uring *ring, int off, int nr)
-{
- struct io_uring_cqe *cqe;
- struct io_uring_sqe *sqe;
- int ret;
-
- /* single out-of-bounds slot */
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_notif_update(sqe, 0, off, nr);
- sqe->user_data = 1;
- ret = io_uring_submit(ring);
- assert(ret == 1);
- ret = io_uring_wait_cqe(ring, &cqe);
- assert(!ret && cqe->user_data == 1);
- ret = cqe->res;
- io_uring_cqe_seen(ring, cqe);
- return ret;
-}
-
-static int test_update_flush_fail(struct io_uring *ring)
-{
- int ret;
-
- /* single out-of-bounds slot */
- ret = do_one_fail_notif_flush(ring, NR_SLOTS, 1);
- assert(ret == -EINVAL);
-
- /* out-of-bounds range */
- ret = do_one_fail_notif_flush(ring, 0, NR_SLOTS + 3);
- assert(ret == -EINVAL);
- ret = do_one_fail_notif_flush(ring, NR_SLOTS - 1, 2);
- assert(ret == -EINVAL);
-
- /* overflow checks, note it's u32 internally */
- ret = do_one_fail_notif_flush(ring, ~(__u32)0, 1);
- assert(ret == -EOVERFLOW);
- ret = do_one_fail_notif_flush(ring, NR_SLOTS - 1, ~(__u32)0);
- assert(ret == -EOVERFLOW);
- return 0;
-}
-
-static void do_one_consume(struct io_uring *ring, int sock_tx, int sock_rx,
- int slot_idx)
-{
- int ret;
-
- ret = do_one(ring, sock_tx, slot_idx);
- assert(ret == 1);
-
- ret = recv(sock_rx, rx_buffer, 1, MSG_TRUNC);
- assert(ret == 1);
-}
-
-static int test_update_flush(struct io_uring *ring, int sock_tx, int sock_rx)
-{
- struct io_uring_sqe *sqe;
- struct io_uring_cqe *cqe;
- int offset = 1, nr_to_flush = 3;
- int ret, i, slot_idx;
-
- /*
- * Flush will be skipped for unused slots, so attached at least 1 req
- * to each active notifier / slot
- */
- for (slot_idx = 0; slot_idx < NR_SLOTS; slot_idx++)
- do_one_consume(ring, sock_tx, sock_rx, slot_idx);
-
- assert(check_cq_empty(ring));
-
- /* flush first */
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_notif_update(sqe, 0, 0, 1);
- sqe->user_data = 1;
- sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
- ret = io_uring_submit(ring);
- assert(ret == 1);
-
- ret = io_uring_wait_cqe(ring, &cqe);
- assert(!ret && !cqe->res && cqe->user_data == ZC_TAG);
- assert(cqe->flags == seqs[0]);
- seqs[0]++;
- io_uring_cqe_seen(ring, cqe);
- do_one_consume(ring, sock_tx, sock_rx, 0);
- assert(check_cq_empty(ring));
+ int ret, i;
- /* flush last */
sqe = io_uring_get_sqe(ring);
- io_uring_prep_notif_update(sqe, 0, NR_SLOTS - 1, 1);
+ io_uring_prep_send_zc(sqe, sock_tx, (void *)1UL, payload_size,
+ msg_flags, zc_flags);
sqe->user_data = 1;
- sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
- ret = io_uring_submit(ring);
- assert(ret == 1);
-
- ret = io_uring_wait_cqe(ring, &cqe);
- assert(!ret && !cqe->res && cqe->user_data == ZC_TAG + NR_SLOTS - 1);
- assert(cqe->flags == seqs[NR_SLOTS - 1]);
- seqs[NR_SLOTS - 1]++;
- io_uring_cqe_seen(ring, cqe);
- assert(check_cq_empty(ring));
- /* we left the last slot without attached requests, flush should ignore it */
sqe = io_uring_get_sqe(ring);
- io_uring_prep_notif_update(sqe, 0, NR_SLOTS - 1, 1);
- sqe->user_data = 1;
- ret = io_uring_submit(ring);
- assert(ret == 1);
-
- ret = io_uring_wait_cqe(ring, &cqe);
- assert(!ret && !cqe->res && cqe->user_data == 1);
- io_uring_cqe_seen(ring, cqe);
- assert(check_cq_empty(ring));
+ io_uring_prep_send_zc(sqe, sock_tx, (void *)1UL, payload_size,
+ msg_flags, zc_flags);
+ sqe->user_data = 2;
+ io_uring_prep_send_set_addr(sqe, (const struct sockaddr *)1UL,
+ sizeof(struct sockaddr_in6));
- /* flush range */
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_notif_update(sqe, 0, offset, nr_to_flush);
- sqe->user_data = 1;
- sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
ret = io_uring_submit(ring);
- assert(ret == 1);
-
- for (i = 0; i < nr_to_flush; i++) {
- int slot_idx;
+ assert(ret == 2);
+ for (i = 0; i < 2; i++) {
ret = io_uring_wait_cqe(ring, &cqe);
- assert(!ret && !cqe->res);
- assert(ZC_TAG + offset <= cqe->user_data &&
- cqe->user_data < ZC_TAG + offset + nr_to_flush);
- slot_idx = cqe->user_data - ZC_TAG;
- assert(cqe->flags == seqs[slot_idx]);
- seqs[slot_idx]++;
+ assert(!ret);
+ assert(cqe->user_data <= 2);
+ assert(cqe->res == -EFAULT);
+ assert(!(cqe->flags & IORING_CQE_F_MORE));
io_uring_cqe_seen(ring, cqe);
}
assert(check_cq_empty(ring));
- return 0;
-}
-
-static int test_registration(int sock_tx, int sock_rx)
-{
- struct io_uring_notification_slot slots[2] = {
- {.tag = 1}, {.tag = 2},
- };
- void *invalid_slots = (void *)1UL;
- struct io_uring ring;
- int ret, i;
-
- ret = io_uring_queue_init(4, &ring, 0);
- if (ret) {
- fprintf(stderr, "queue init failed: %d\n", ret);
- return 1;
- }
-
- ret = io_uring_unregister_notifications(&ring);
- if (ret != -ENXIO) {
- fprintf(stderr, "unregister nothing: %d\n", ret);
- return 1;
- }
-
- ret = io_uring_register_notifications(&ring, 2, slots);
- if (ret) {
- fprintf(stderr, "io_uring_register_notifications failed: %d\n", ret);
- return 1;
- }
-
- ret = io_uring_register_notifications(&ring, 2, slots);
- if (ret != -EBUSY) {
- fprintf(stderr, "double register: %d\n", ret);
- return 1;
- }
-
- ret = io_uring_unregister_notifications(&ring);
- if (ret) {
- fprintf(stderr, "unregister failed: %d\n", ret);
- return 1;
- }
-
- ret = io_uring_register_notifications(&ring, 2, slots);
- if (ret) {
- fprintf(stderr, "second register failed: %d\n", ret);
- return 1;
- }
-
- ret = test_invalid_slot(&ring, sock_tx, sock_rx);
- if (ret) {
- fprintf(stderr, "test_invalid_slot() failed\n");
- return ret;
- }
-
- for (i = 0; i < 2; i++) {
- ret = do_one(&ring, sock_tx, 0);
- assert(ret == 1);
-
- ret = recv(sock_rx, rx_buffer, 1, MSG_TRUNC);
- assert(ret == 1);
- }
-
- io_uring_queue_exit(&ring);
- ret = io_uring_queue_init(4, &ring, 0);
- if (ret) {
- fprintf(stderr, "queue init failed: %d\n", ret);
- return 1;
- }
-
- ret = io_uring_register_notifications(&ring, 4, invalid_slots);
- if (ret != -EFAULT) {
- fprintf(stderr, "io_uring_register_notifications with invalid ptr: %d\n", ret);
- return 1;
- }
-
- io_uring_queue_exit(&ring);
- return 0;
+ return T_EXIT_PASS;
}
static int prepare_ip(struct sockaddr_storage *addr, int *sock_client, int *sock_server,
@@ -644,12 +241,11 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
size_t send_size, bool cork, bool mix_register,
int buf_idx)
{
- const unsigned slot_idx = 0;
const unsigned zc_flags = 0;
struct io_uring_sqe *sqe;
struct io_uring_cqe *cqe;
int nr_reqs = cork ? 5 : 1;
- int i, ret;
+ int i, ret, nr_cqes;
size_t chunk_size = send_size / nr_reqs;
size_t chunk_size_last = send_size - chunk_size * (nr_reqs - 1);
char *buf = buffers_iov[buf_idx].iov_base;
@@ -660,39 +256,35 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
memset(rx_buffer, 0, send_size);
for (i = 0; i < nr_reqs; i++) {
- bool cur_fixed_buf = fixed_buf;
+ bool real_fixed_buf = fixed_buf;
size_t cur_size = chunk_size;
int msg_flags = MSG_WAITALL;
if (mix_register)
- cur_fixed_buf = rand() & 1;
+ real_fixed_buf = rand() & 1;
if (cork && i != nr_reqs - 1)
- msg_flags = MSG_MORE;
+ msg_flags |= MSG_MORE;
if (i == nr_reqs - 1)
cur_size = chunk_size_last;
sqe = io_uring_get_sqe(ring);
- if (cur_fixed_buf)
- io_uring_prep_sendzc_fixed(sqe, sock_client,
- buf + i * chunk_size,
- cur_size, msg_flags, slot_idx,
- zc_flags, buf_idx);
- else
- io_uring_prep_sendzc(sqe, sock_client,
- buf + i * chunk_size,
- cur_size, msg_flags, slot_idx,
- zc_flags);
+ io_uring_prep_send_zc(sqe, sock_client, buf + i * chunk_size,
+ cur_size, msg_flags, zc_flags);
+ sqe->user_data = i;
+ if (real_fixed_buf) {
+ sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
+ sqe->buf_index = buf_idx;
+ }
if (addr) {
sa_family_t fam = ((struct sockaddr_in *)addr)->sin_family;
int addr_len = fam == AF_INET ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6);
- io_uring_prep_sendzc_set_addr(sqe, (const struct sockaddr *)addr,
- addr_len);
+ io_uring_prep_send_set_addr(sqe, (const struct sockaddr *)addr,
+ addr_len);
}
- sqe->user_data = i;
}
ret = io_uring_submit(ring);
@@ -705,9 +297,7 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
if (p == -1) {
fprintf(stderr, "fork() failed\n");
return 1;
- }
-
- if (p == 0) {
+ } else if (p == 0) {
size_t bytes_received = 0;
while (bytes_received != send_size) {
@@ -732,7 +322,8 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
exit(0);
}
- for (i = 0; i < nr_reqs; i++) {
+ nr_cqes = 2 * nr_reqs;
+ for (i = 0; i < nr_cqes; i++) {
int expected = chunk_size;
ret = io_uring_wait_cqe(ring, &cqe);
@@ -744,11 +335,18 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
fprintf(stderr, "invalid user_data\n");
return 1;
}
- if (cqe->user_data == nr_reqs - 1)
- expected = chunk_size_last;
- if (cqe->res != expected) {
- fprintf(stderr, "invalid cqe->res %d expected %d\n",
- cqe->res, expected);
+ if (!(cqe->flags & IORING_CQE_F_NOTIF)) {
+ if (cqe->user_data == nr_reqs - 1)
+ expected = chunk_size_last;
+ if (cqe->res != expected) {
+ fprintf(stderr, "invalid cqe->res %d expected %d\n",
+ cqe->res, expected);
+ return 1;
+ }
+ }
+ if ((cqe->flags & IORING_CQE_F_MORE) ==
+ (cqe->flags & IORING_CQE_F_NOTIF)) {
+ fprintf(stderr, "unexpected cflags %i\n", cqe->flags);
return 1;
}
io_uring_cqe_seen(ring, cqe);
@@ -845,6 +443,8 @@ static int test_async_addr(struct io_uring *ring)
struct __kernel_timespec ts;
int ret;
+ ts.tv_sec = 1;
+ ts.tv_nsec = 0;
ret = prepare_ip(&addr, &sock_tx, &sock_rx, true, false, false, false);
if (ret) {
fprintf(stderr, "sock prep failed %d\n", ret);
@@ -852,17 +452,15 @@ static int test_async_addr(struct io_uring *ring)
}
sqe = io_uring_get_sqe(ring);
- ts.tv_sec = 1;
- ts.tv_nsec = 0;
io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_ETIME_SUCCESS);
sqe->user_data = 1;
sqe->flags |= IOSQE_IO_LINK;
sqe = io_uring_get_sqe(ring);
- io_uring_prep_sendzc(sqe, sock_tx, tx_buffer, 1, 0, 0, 0);
+ io_uring_prep_send_zc(sqe, sock_tx, tx_buffer, 1, 0, 0);
sqe->user_data = 2;
- io_uring_prep_sendzc_set_addr(sqe, (const struct sockaddr *)&addr,
- sizeof(struct sockaddr_in6));
+ io_uring_prep_send_set_addr(sqe, (const struct sockaddr *)&addr,
+ sizeof(struct sockaddr_in6));
ret = io_uring_submit(ring);
assert(ret == 2);
@@ -894,6 +492,14 @@ static int test_async_addr(struct io_uring *ring)
ret = recv(sock_rx, rx_buffer, 1, MSG_TRUNC);
assert(ret == 1);
+ ret = io_uring_wait_cqe(ring, &cqe);
+ if (ret) {
+ fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret);
+ return 1;
+ }
+ assert(cqe->flags & IORING_CQE_F_NOTIF);
+ io_uring_cqe_seen(ring, cqe);
+
close(sock_tx);
close(sock_rx);
return 0;
@@ -937,15 +543,6 @@ int main(int argc, char *argv[])
return T_EXIT_FAIL;
}
- ret = register_notifications(&ring);
- if (ret == -EINVAL) {
- printf("sendzc is not supported, skip\n");
- return T_EXIT_SKIP;
- } else if (ret) {
- fprintf(stderr, "register notif failed %i\n", ret);
- return T_EXIT_FAIL;
- }
-
srand((unsigned)time(NULL));
for (i = 0; i < len; i++)
tx_buffer[i] = i;
@@ -956,70 +553,24 @@ int main(int argc, char *argv[])
return T_EXIT_FAIL;
}
- ret = test_registration(sp[0], sp[1]);
- if (ret) {
- fprintf(stderr, "test_registration() failed\n");
- return ret;
- }
-
- ret = test_invalid_slot(&ring, sp[0], sp[1]);
- if (ret) {
- fprintf(stderr, "test_invalid_slot() failed\n");
- return T_EXIT_FAIL;
- }
-
ret = test_basic_send(&ring, sp[0], sp[1]);
+ if (ret == T_EXIT_SKIP)
+ return ret;
if (ret) {
fprintf(stderr, "test_basic_send() failed\n");
return T_EXIT_FAIL;
}
- ret = test_send_flush(&ring, sp[0], sp[1]);
- if (ret) {
- fprintf(stderr, "test_send_flush() failed\n");
- return T_EXIT_FAIL;
- }
-
- ret = test_multireq_notif(&ring, sp[0], sp[1]);
- if (ret) {
- fprintf(stderr, "test_multireq_notif() failed\n");
- return T_EXIT_FAIL;
- }
-
- ret = reregister_notifications(&ring);
+ ret = test_send_faults(&ring, sp[0], sp[1]);
if (ret) {
- fprintf(stderr, "reregister notifiers failed %i\n", ret);
- return T_EXIT_FAIL;
- }
- /* retry a few tests after registering notifs */
- ret = test_invalid_slot(&ring, sp[0], sp[1]);
- if (ret) {
- fprintf(stderr, "test_invalid_slot() failed\n");
+ fprintf(stderr, "test_send_faults() failed\n");
return T_EXIT_FAIL;
}
- ret = test_multireq_notif(&ring, sp[0], sp[1]);
- if (ret) {
- fprintf(stderr, "test_multireq_notif2() failed\n");
- return T_EXIT_FAIL;
- }
-
- ret = test_multi_send_flushing(&ring, sp[0], sp[1]);
- if (ret) {
- fprintf(stderr, "test_multi_send_flushing() failed\n");
- return T_EXIT_FAIL;
- }
-
- ret = test_update_flush_fail(&ring);
- if (ret) {
- fprintf(stderr, "test_update_flush_fail() failed\n");
- return T_EXIT_FAIL;
- }
-
- ret = test_update_flush(&ring, sp[0], sp[1]);
+ ret = test_async_addr(&ring);
if (ret) {
- fprintf(stderr, "test_update_flush() failed\n");
- return T_EXIT_FAIL;
+ fprintf(stderr, "test_async_addr() failed\n");
+ return ret;
}
ret = t_register_buffers(&ring, buffers_iov, ARRAY_SIZE(buffers_iov));
@@ -1036,12 +587,6 @@ int main(int argc, char *argv[])
fprintf(stderr, "test_inet_send() failed\n");
return ret;
}
-
- ret = test_async_addr(&ring);
- if (ret) {
- fprintf(stderr, "test_async_addr() failed\n");
- return ret;
- }
out:
io_uring_queue_exit(&ring);
close(sp[0]);
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH liburing 3/4] test: test iowq zc sends
2022-09-02 11:12 [PATCH liburing 0/4] zerocopy send API changes Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 1/4] tests: verify that send addr is copied when async Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 2/4] zc: adjust sendzc to the simpler uapi Pavel Begunkov
@ 2022-09-02 11:12 ` Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 4/4] examples: adjust zc bench to the new uapi Pavel Begunkov
` (2 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2022-09-02 11:12 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
Add tests exercising io-wq paths with zc by setting IOSQE_ASYNC.
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/send-zerocopy.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/test/send-zerocopy.c b/test/send-zerocopy.c
index 7b58ae7..8714b6f 100644
--- a/test/send-zerocopy.c
+++ b/test/send-zerocopy.c
@@ -239,7 +239,7 @@ static int prepare_ip(struct sockaddr_storage *addr, int *sock_client, int *sock
static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_server,
bool fixed_buf, struct sockaddr_storage *addr,
size_t send_size, bool cork, bool mix_register,
- int buf_idx)
+ int buf_idx, bool force_async)
{
const unsigned zc_flags = 0;
struct io_uring_sqe *sqe;
@@ -285,6 +285,8 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
io_uring_prep_send_set_addr(sqe, (const struct sockaddr *)addr,
addr_len);
}
+ if (force_async)
+ sqe->flags |= IOSQE_ASYNC;
}
ret = io_uring_submit(ring);
@@ -389,7 +391,7 @@ static int test_inet_send(struct io_uring *ring)
return 1;
}
- for (i = 0; i < 128; i++) {
+ for (i = 0; i < 256; i++) {
bool fixed_buf = i & 1;
struct sockaddr_storage *addr_arg = (i & 2) ? &addr : NULL;
size_t size = (i & 4) ? 137 : 4096;
@@ -398,6 +400,7 @@ static int test_inet_send(struct io_uring *ring)
bool aligned = i & 32;
bool large_buf = i & 64;
int buf_idx = aligned ? 0 : 1;
+ bool force_async = i & 128;
if (!tcp || !large_buf)
continue;
@@ -418,7 +421,7 @@ static int test_inet_send(struct io_uring *ring)
ret = do_test_inet_send(ring, sock_client, sock_server, fixed_buf,
addr_arg, size, cork, mix_register,
- buf_idx);
+ buf_idx, force_async);
if (ret) {
fprintf(stderr, "send failed fixed buf %i, conn %i, addr %i, "
"cork %i\n",
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH liburing 4/4] examples: adjust zc bench to the new uapi
2022-09-02 11:12 [PATCH liburing 0/4] zerocopy send API changes Pavel Begunkov
` (2 preceding siblings ...)
2022-09-02 11:12 ` [PATCH liburing 3/4] test: test iowq zc sends Pavel Begunkov
@ 2022-09-02 11:12 ` Pavel Begunkov
2022-09-02 11:56 ` [PATCH liburing 0/4] zerocopy send API changes Ammar Faizi
2022-09-02 11:57 ` Jens Axboe
5 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2022-09-02 11:12 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
Signed-off-by: Pavel Begunkov <[email protected]>
---
examples/send-zerocopy.c | 72 +++++++++++++---------------------------
1 file changed, 23 insertions(+), 49 deletions(-)
diff --git a/examples/send-zerocopy.c b/examples/send-zerocopy.c
index e42aa71..4ed0f67 100644
--- a/examples/send-zerocopy.c
+++ b/examples/send-zerocopy.c
@@ -44,7 +44,6 @@
static bool cfg_reg_ringfd = true;
static bool cfg_fixed_files = 1;
static bool cfg_zc = 1;
-static bool cfg_flush = 0;
static int cfg_nr_reqs = 8;
static bool cfg_fixed_buf = 1;
@@ -146,13 +145,6 @@ static void do_tx(int domain, int type, int protocol)
if (ret)
error(1, ret, "io_uring: queue init");
- if (cfg_zc) {
- struct io_uring_notification_slot b[1] = {{.tag = ZC_TAG}};
-
- ret = io_uring_register_notifications(&ring, 1, b);
- if (ret)
- error(1, ret, "io_uring: tx ctx registration");
- }
if (cfg_fixed_files) {
ret = io_uring_register_files(&ring, &fd, 1);
if (ret < 0)
@@ -175,14 +167,8 @@ static void do_tx(int domain, int type, int protocol)
do {
struct io_uring_sqe *sqe;
struct io_uring_cqe *cqe;
- unsigned zc_flags = 0;
unsigned buf_idx = 0;
- unsigned slot_idx = 0;
- unsigned msg_flags = 0;
-
- compl_cqes += cfg_flush ? cfg_nr_reqs : 0;
- if (cfg_flush)
- zc_flags |= IORING_RECVSEND_NOTIF_FLUSH;
+ unsigned msg_flags = MSG_WAITALL;
for (i = 0; i < cfg_nr_reqs; i++) {
sqe = io_uring_get_sqe(&ring);
@@ -190,22 +176,22 @@ static void do_tx(int domain, int type, int protocol)
if (!cfg_zc)
io_uring_prep_send(sqe, fd, payload,
cfg_payload_len, 0);
- else if (cfg_fixed_buf)
- io_uring_prep_sendzc_fixed(sqe, fd, payload,
- cfg_payload_len,
- msg_flags, slot_idx,
- zc_flags, buf_idx);
- else
- io_uring_prep_sendzc(sqe, fd, payload,
- cfg_payload_len, msg_flags,
- slot_idx, zc_flags);
-
+ else {
+ io_uring_prep_send_zc(sqe, fd, payload,
+ cfg_payload_len, msg_flags, 0);
+ if (cfg_fixed_buf) {
+ sqe->ioprio |= IORING_RECVSEND_FIXED_BUF;
+ sqe->buf_index = buf_idx;
+ }
+ }
sqe->user_data = 1;
if (cfg_fixed_files) {
sqe->fd = 0;
sqe->flags |= IOSQE_FIXED_FILE;
}
}
+ if (cfg_zc)
+ compl_cqes += cfg_nr_reqs;
ret = io_uring_submit(&ring);
if (ret != cfg_nr_reqs)
@@ -214,27 +200,26 @@ static void do_tx(int domain, int type, int protocol)
for (i = 0; i < cfg_nr_reqs; i++) {
cqe = wait_cqe_fast(&ring);
- if (cqe->user_data == ZC_TAG) {
+ if (cqe->flags & IORING_CQE_F_NOTIF) {
+ if (cqe->flags & IORING_CQE_F_MORE)
+ error(1, -EINVAL, "F_MORE notif");
compl_cqes--;
i--;
- } else if (cqe->user_data != 1) {
- error(1, cqe->user_data, "invalid user_data");
- } else if (cqe->res > 0) {
+ } else if (cqe->res >= 0) {
+ if (!(cqe->flags & IORING_CQE_F_MORE) && cfg_zc)
+ error(1, -EINVAL, "no F_MORE");
packets++;
bytes += cqe->res;
} else if (cqe->res == -EAGAIN) {
- /* request failed, don't flush */
- if (cfg_flush)
+ if (cfg_zc)
compl_cqes--;
- } else if (cqe->res == -ECONNREFUSED ||
- cqe->res == -ECONNRESET ||
- cqe->res == -EPIPE) {
- fprintf(stderr, "Connection failure\n");
+ } else if (cqe->res == -ECONNREFUSED || cqe->res == -EPIPE ||
+ cqe->res == -ECONNRESET) {
+ fprintf(stderr, "Connection failure");
goto out_fail;
} else {
error(1, cqe->res, "send failed");
}
-
io_uring_cqe_seen(&ring, cqe);
}
} while (gettimeofday_ms() < tstop);
@@ -255,12 +240,6 @@ out_fail:
io_uring_cqe_seen(&ring, cqe);
compl_cqes--;
}
-
- if (cfg_zc) {
- ret = io_uring_unregister_notifications(&ring);
- if (ret)
- error(1, ret, "io_uring: tx ctx unregistration");
- }
io_uring_queue_exit(&ring);
}
@@ -276,7 +255,7 @@ static void do_test(int domain, int type, int protocol)
static void usage(const char *filepath)
{
- error(1, 0, "Usage: %s [-f] [-n<N>] [-z0] [-s<payload size>] "
+ error(1, 0, "Usage: %s [-n<N>] [-z<val>] [-s<payload size>] "
"(-4|-6) [-t<time s>] -D<dst_ip> udp", filepath);
}
@@ -294,7 +273,7 @@ static void parse_opts(int argc, char **argv)
cfg_payload_len = max_payload_len;
- while ((c = getopt(argc, argv, "46D:p:s:t:n:fz:b:k")) != -1) {
+ while ((c = getopt(argc, argv, "46D:p:s:t:n:z:b:k")) != -1) {
switch (c) {
case '4':
if (cfg_family != PF_UNSPEC)
@@ -323,9 +302,6 @@ static void parse_opts(int argc, char **argv)
case 'n':
cfg_nr_reqs = strtoul(optarg, NULL, 0);
break;
- case 'f':
- cfg_flush = 1;
- break;
case 'z':
cfg_zc = strtoul(optarg, NULL, 0);
break;
@@ -337,8 +313,6 @@ static void parse_opts(int argc, char **argv)
if (cfg_nr_reqs > MAX_SUBMIT_NR)
error(1, 0, "-n: submit batch nr exceeds max (%d)", MAX_SUBMIT_NR);
- if (cfg_flush && !cfg_zc)
- error(1, 0, "cfg_flush should be used with zc only");
if (cfg_payload_len > max_payload_len)
error(1, 0, "-s: payload exceeds max (%d)", max_payload_len);
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH liburing 0/4] zerocopy send API changes
2022-09-02 11:12 [PATCH liburing 0/4] zerocopy send API changes Pavel Begunkov
` (3 preceding siblings ...)
2022-09-02 11:12 ` [PATCH liburing 4/4] examples: adjust zc bench to the new uapi Pavel Begunkov
@ 2022-09-02 11:56 ` Ammar Faizi
2022-09-02 12:01 ` Ammar Faizi
2022-09-02 11:57 ` Jens Axboe
5 siblings, 1 reply; 11+ messages in thread
From: Ammar Faizi @ 2022-09-02 11:56 UTC (permalink / raw)
To: Pavel Begunkov, io-uring Mailing List; +Cc: Jens Axboe
On 9/2/22 6:12 PM, Pavel Begunkov wrote:
> Fix up helpers and tests to match API changes and also add some more tests.
>
> Pavel Begunkov (4):
> tests: verify that send addr is copied when async
> zc: adjust sendzc to the simpler uapi
> test: test iowq zc sends
> examples: adjust zc bench to the new uapi
Hi Pavel,
Patch #2 and #3 are broken, but after applying patch #4, everything builds
just fine. Please resend and avoid breakage in the middle.
Thanks!
--------------------------------------------------------------------------------
Patch #2
send-zerocopy.c:152:9: error: call to undeclared function 'io_uring_register_notifications'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
ret = io_uring_register_notifications(&ring, 1, b);
^
send-zerocopy.c:152:9: note: did you mean 'io_uring_register_restrictions'?
../src/include/liburing.h:181:5: note: 'io_uring_register_restrictions' declared here
int io_uring_register_restrictions(struct io_uring *ring,
^
send-zerocopy.c:185:16: error: use of undeclared identifier 'IORING_RECVSEND_NOTIF_FLUSH'
zc_flags |= IORING_RECVSEND_NOTIF_FLUSH;
^
send-zerocopy.c:194:5: error: call to undeclared function 'io_uring_prep_sendzc_fixed'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
io_uring_prep_sendzc_fixed(sqe, fd, payload,
^
send-zerocopy.c:194:5: note: did you mean 'io_uring_prep_read_fixed'?
../src/include/liburing.h:405:20: note: 'io_uring_prep_read_fixed' declared here
static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd,
^
send-zerocopy.c:199:5: error: call to undeclared function 'io_uring_prep_sendzc'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
io_uring_prep_sendzc(sqe, fd, payload,
^
send-zerocopy.c:199:5: note: did you mean 'io_uring_prep_send_zc'?
../src/include/liburing.h:701:20: note: 'io_uring_prep_send_zc' declared here
static inline void io_uring_prep_send_zc(struct io_uring_sqe *sqe, int sockfd,
^
send-zerocopy.c:260:9: error: call to undeclared function 'io_uring_unregister_notifications'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
ret = io_uring_unregister_notifications(&ring);
^
send-zerocopy.c:260:9: note: did you mean 'io_uring_register_restrictions'?
../src/include/liburing.h:181:5: note: 'io_uring_register_restrictions' declared here
int io_uring_register_restrictions(struct io_uring *ring,
^
5 errors generated.
make[1]: *** [Makefile:36: send-zerocopy] Error 1
make[1]: *** Waiting for unfinished jobs....
make[1]: Leaving directory '/home/runner/work/liburing/liburing/examples'
make: *** [Makefile:12: all] Error 2
Error: Process completed with exit code 2.
--------------------------------------------------------------------------------
Patch #3:
send-zerocopy.c: In function ‘do_tx’:
send-zerocopy.c:152:23: error: implicit declaration of function ‘io_uring_register_notifications’; did you mean ‘io_uring_register_restrictions’? [-Werror=implicit-function-declaration]
152 | ret = io_uring_register_notifications(&ring, 1, b);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| io_uring_register_restrictions
send-zerocopy.c:185:37: error: ‘IORING_RECVSEND_NOTIF_FLUSH’ undeclared (first use in this function); did you mean ‘IORING_RECVSEND_POLL_FIRST’?
185 | zc_flags |= IORING_RECVSEND_NOTIF_FLUSH;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
| IORING_RECVSEND_POLL_FIRST
send-zerocopy.c:185:37: note: each undeclared identifier is reported only once for each function it appears in
send-zerocopy.c:194:33: error: implicit declaration of function ‘io_uring_prep_sendzc_fixed’; did you mean ‘io_uring_prep_read_fixed’? [-Werror=implicit-function-declaration]
194 | io_uring_prep_sendzc_fixed(sqe, fd, payload,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
| io_uring_prep_read_fixed
send-zerocopy.c:199:33: error: implicit declaration of function ‘io_uring_prep_sendzc’; did you mean ‘io_uring_prep_send_zc’? [-Werror=implicit-function-declaration]
199 | io_uring_prep_sendzc(sqe, fd, payload,
| ^~~~~~~~~~~~~~~~~~~~
| io_uring_prep_send_zc
send-zerocopy.c:260:23: error: implicit declaration of function ‘io_uring_unregister_notifications’; did you mean ‘io_uring_register_restrictions’? [-Werror=implicit-function-declaration]
260 | ret = io_uring_unregister_notifications(&ring);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| io_uring_register_restrictions
cc1: all warnings being treated as errors
make[1]: *** [Makefile:36: send-zerocopy] Error 1
make[1]: *** Waiting for unfinished jobs....
make[1]: Leaving directory '/home/runner/work/liburing/liburing/examples'
make: *** [Makefile:12: all] Error 2
Error: Process completed with exit code 2.
--
Ammar Faizi
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH liburing 0/4] zerocopy send API changes
2022-09-02 11:12 [PATCH liburing 0/4] zerocopy send API changes Pavel Begunkov
` (4 preceding siblings ...)
2022-09-02 11:56 ` [PATCH liburing 0/4] zerocopy send API changes Ammar Faizi
@ 2022-09-02 11:57 ` Jens Axboe
5 siblings, 0 replies; 11+ messages in thread
From: Jens Axboe @ 2022-09-02 11:57 UTC (permalink / raw)
To: Pavel Begunkov, io-uring
On Fri, 2 Sep 2022 12:12:35 +0100, Pavel Begunkov wrote:
> Fix up helpers and tests to match API changes and also add some more tests.
>
> Pavel Begunkov (4):
> tests: verify that send addr is copied when async
> zc: adjust sendzc to the simpler uapi
> test: test iowq zc sends
> examples: adjust zc bench to the new uapi
>
> [...]
Applied, thanks!
[1/4] tests: verify that send addr is copied when async
commit: 54b16e6cfa489edd1f4f538ae245d98d65d42db7
[2/4] zc: adjust sendzc to the simpler uapi
commit: 880a932c8ae36506b4d5040b9258a91251164589
[3/4] test: test iowq zc sends
commit: 713ecf1cf9ad58ceb19893eead2b704b27367a8a
[4/4] examples: adjust zc bench to the new uapi
commit: 860db521db4c86a1cb5d0b672a8fba83a89f01f0
Best regards,
--
Jens Axboe
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH liburing 0/4] zerocopy send API changes
2022-09-02 11:56 ` [PATCH liburing 0/4] zerocopy send API changes Ammar Faizi
@ 2022-09-02 12:01 ` Ammar Faizi
2022-09-02 12:03 ` Jens Axboe
0 siblings, 1 reply; 11+ messages in thread
From: Ammar Faizi @ 2022-09-02 12:01 UTC (permalink / raw)
To: Pavel Begunkov, io-uring Mailing List; +Cc: Jens Axboe
On 9/2/22 6:56 PM, Ammar Faizi wrote:
> On 9/2/22 6:12 PM, Pavel Begunkov wrote:
>> Fix up helpers and tests to match API changes and also add some more tests.
>>
>> Pavel Begunkov (4):
>> tests: verify that send addr is copied when async
>> zc: adjust sendzc to the simpler uapi
>> test: test iowq zc sends
>> examples: adjust zc bench to the new uapi
>
> Hi Pavel,
>
> Patch #2 and #3 are broken, but after applying patch #4, everything builds
> just fine. Please resend and avoid breakage in the middle.
>
> Thanks!
Nevermind. It's already upstream now.
--
Ammar Faizi
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH liburing 0/4] zerocopy send API changes
2022-09-02 12:01 ` Ammar Faizi
@ 2022-09-02 12:03 ` Jens Axboe
2022-09-02 12:07 ` Pavel Begunkov
0 siblings, 1 reply; 11+ messages in thread
From: Jens Axboe @ 2022-09-02 12:03 UTC (permalink / raw)
To: Ammar Faizi, Pavel Begunkov, io-uring Mailing List
On 9/2/22 6:01 AM, Ammar Faizi wrote:
> On 9/2/22 6:56 PM, Ammar Faizi wrote:
>> On 9/2/22 6:12 PM, Pavel Begunkov wrote:
>>> Fix up helpers and tests to match API changes and also add some more tests.
>>>
>>> Pavel Begunkov (4):
>>> tests: verify that send addr is copied when async
>>> zc: adjust sendzc to the simpler uapi
>>> test: test iowq zc sends
>>> examples: adjust zc bench to the new uapi
>>
>> Hi Pavel,
>>
>> Patch #2 and #3 are broken, but after applying patch #4, everything builds
>> just fine. Please resend and avoid breakage in the middle.
>>
>> Thanks!
>
> Nevermind. It's already upstream now.
Ah shoot, how did I miss that... That's annoying.
--
Jens Axboe
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH liburing 0/4] zerocopy send API changes
2022-09-02 12:03 ` Jens Axboe
@ 2022-09-02 12:07 ` Pavel Begunkov
2022-09-02 12:11 ` Jens Axboe
0 siblings, 1 reply; 11+ messages in thread
From: Pavel Begunkov @ 2022-09-02 12:07 UTC (permalink / raw)
To: Jens Axboe, Ammar Faizi, io-uring Mailing List
On 9/2/22 13:03, Jens Axboe wrote:
> On 9/2/22 6:01 AM, Ammar Faizi wrote:
>> On 9/2/22 6:56 PM, Ammar Faizi wrote:
>>> On 9/2/22 6:12 PM, Pavel Begunkov wrote:
>>>> Fix up helpers and tests to match API changes and also add some more tests.
>>>>
>>>> Pavel Begunkov (4):
>>>> tests: verify that send addr is copied when async
>>>> zc: adjust sendzc to the simpler uapi
>>>> test: test iowq zc sends
>>>> examples: adjust zc bench to the new uapi
>>>
>>> Hi Pavel,
>>>
>>> Patch #2 and #3 are broken, but after applying patch #4, everything builds
>>> just fine. Please resend and avoid breakage in the middle.
>>>
>>> Thanks!
>>
>> Nevermind. It's already upstream now.
>
> Ah shoot, how did I miss that... That's annoying.
We can squash them into a single commit if we care about it.
Don't really want do the disable + fix +e nable dancing here.
--
Pavel Begunkov
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH liburing 0/4] zerocopy send API changes
2022-09-02 12:07 ` Pavel Begunkov
@ 2022-09-02 12:11 ` Jens Axboe
0 siblings, 0 replies; 11+ messages in thread
From: Jens Axboe @ 2022-09-02 12:11 UTC (permalink / raw)
To: Pavel Begunkov, Ammar Faizi, io-uring Mailing List
On 9/2/22 6:07 AM, Pavel Begunkov wrote:
> On 9/2/22 13:03, Jens Axboe wrote:
>> On 9/2/22 6:01 AM, Ammar Faizi wrote:
>>> On 9/2/22 6:56 PM, Ammar Faizi wrote:
>>>> On 9/2/22 6:12 PM, Pavel Begunkov wrote:
>>>>> Fix up helpers and tests to match API changes and also add some more tests.
>>>>>
>>>>> Pavel Begunkov (4):
>>>>> ??? tests: verify that send addr is copied when async
>>>>> ??? zc: adjust sendzc to the simpler uapi
>>>>> ??? test: test iowq zc sends
>>>>> ??? examples: adjust zc bench to the new uapi
>>>>
>>>> Hi Pavel,
>>>>
>>>> Patch #2 and #3 are broken, but after applying patch #4, everything builds
>>>> just fine. Please resend and avoid breakage in the middle.
>>>>
>>>> Thanks!
>>>
>>> Nevermind. It's already upstream now.
>>
>> Ah shoot, how did I miss that... That's annoying.
>
> We can squash them into a single commit if we care about it.
> Don't really want do the disable + fix +e nable dancing here.
It's already pushed out, so whatever is there is set in stone... Not a
huge deal, but would've been nice to avoid. It's problematic when
someone needs to bisect and issue and runs into a non-compiling step.
Makes that process a lot more annoying, so yes we definitely do care
about not introducing build breakage in a series of patches.
--
Jens Axboe
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2022-09-02 12:11 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-09-02 11:12 [PATCH liburing 0/4] zerocopy send API changes Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 1/4] tests: verify that send addr is copied when async Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 2/4] zc: adjust sendzc to the simpler uapi Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 3/4] test: test iowq zc sends Pavel Begunkov
2022-09-02 11:12 ` [PATCH liburing 4/4] examples: adjust zc bench to the new uapi Pavel Begunkov
2022-09-02 11:56 ` [PATCH liburing 0/4] zerocopy send API changes Ammar Faizi
2022-09-02 12:01 ` Ammar Faizi
2022-09-02 12:03 ` Jens Axboe
2022-09-02 12:07 ` Pavel Begunkov
2022-09-02 12:11 ` Jens Axboe
2022-09-02 11:57 ` Jens Axboe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox