Skip to content

Commit

Permalink
test/read-inc-file: test incremental consumption with regular file
Browse files Browse the repository at this point in the history
Incremental buffer usage on non-pollable files will commit the buffer
upfront. Nothing wrong with that, except the kernel had a bug where
it would commit the buffer and return the current buffer address.
After incrementing, the current address it the next read point, not
the current one. This caused the kernel to place the data later in
the userspace buffer than what the application expected.

Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
axboe committed Jan 3, 2025
1 parent 1437be0 commit 4776a04
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 0 deletions.
1 change: 1 addition & 0 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ test_srcs := \
pollfree.c \
probe.c \
read-before-exit.c \
read-inc-file.c \
read-mshot.c \
read-mshot-empty.c \
read-mshot-stdin.c \
Expand Down
147 changes: 147 additions & 0 deletions test/read-inc-file.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/* SPDX-License-Identifier: MIT */
/*
* Description: test reading a normal file with incremental buffer
* consumption. Some kernels had a bug where the initial part
* of the buffer got skipped, test for that.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "liburing.h"
#include "helpers.h"

#define BUF_BGID 4
#define BUF_BID 8

static void arm_read(struct io_uring *ring, int fd, int offset)
{
struct io_uring_sqe *sqe;

sqe = io_uring_get_sqe(ring);
io_uring_prep_read(sqe, fd, NULL, 80, offset);
sqe->flags = IOSQE_BUFFER_SELECT;
sqe->buf_group = BUF_BGID;
io_uring_submit(ring);
}

static int create_test_file(const char *fname)
{
char buf[80], c;
int fd, i, ret;

fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
perror("open");
return T_EXIT_FAIL;
}

c = 'a';
for (i = 0; i < 8; i++) {
memset(buf, c, sizeof(buf));
ret = write(fd, buf, sizeof(buf));
if (ret < 0) {
perror("write");
unlink(fname);
return T_EXIT_FAIL;
} else if (ret != sizeof(buf)) {
fprintf(stderr, "Short write: %d\n", ret);
unlink(fname);
return T_EXIT_FAIL;
}
c++;
}

close(fd);
return 0;
}

int main(int argc, char *argv[])
{
struct io_uring_buf_ring *br;
struct io_uring_params p = { };
struct io_uring_cqe *cqe;
struct io_uring ring;
int tret, ret, fd, i;
char fname[64];
char c = 'a';
char *buf;
void *ptr;

sprintf(fname, ".buf-inc-file.%d", getpid());
if (create_test_file(fname))
return T_EXIT_FAIL;

fd = open(fname, O_RDONLY);
if (fd < 0) {
perror("open");
goto err;
}

ret = io_uring_queue_init_params(64, &ring, &p);
if (ret) {
fprintf(stderr, "ring setup failed: %d\n", ret);
goto err;
}

if (posix_memalign((void **) &buf, 4096, 65536))
goto err;

tret = T_EXIT_SKIP;
br = io_uring_setup_buf_ring(&ring, 32, BUF_BGID, IOU_PBUF_RING_INC, &ret);
if (!br) {
if (ret == -EINVAL)
goto out;
fprintf(stderr, "Buffer ring register failed %d\n", ret);
goto err;
}

tret = T_EXIT_PASS;
io_uring_buf_ring_add(br, buf, 65536, BUF_BID, 31, 0);
io_uring_buf_ring_advance(br, 1);

memset(buf, 0, 65536);

ptr = buf;
for (i = 0; i < 4; i++) {
int bid;

arm_read(&ring, fd, i * 80);
ret = io_uring_wait_cqe(&ring, &cqe);
if (ret) {
fprintf(stderr, "wait %d\n", ret);
goto err;
}
if (!(cqe->flags & IORING_CQE_F_BUFFER)) {
fprintf(stderr, "buffer not assigned\n");
goto err;
}
bid = cqe->flags >> IORING_CQE_BUFFER_SHIFT;
if (bid != BUF_BID) {
fprintf(stderr, "got wrong buffer bid %d\n", bid);
goto err;
}
if (cqe->res != 80) {
fprintf(stderr, "bad read size %d\n", ret);
goto err;
}
io_uring_cqe_seen(&ring, cqe);
if (!memchr(ptr, c, cqe->res)) {
fprintf(stderr, "fail buffer check loop %d\n", i);
goto err;
}
c++;
ptr += cqe->res;
}

io_uring_free_buf_ring(&ring, br, 32, BUF_BGID);
io_uring_queue_exit(&ring);
out:
free(buf);
unlink(fname);
return tret;
err:
unlink(fname);
return T_EXIT_FAIL;
}

0 comments on commit 4776a04

Please sign in to comment.