I've tried to register a set of buffers by io_uring_register_buffers() but I couldn't register buffers big enough. Either one buffer bigger than 32768 bytes or a few buffers with the total size bigger 32768 lead to the ENOMEM error. I've read the maximum buffer size is 1GB for one buffer.
There is an example:
#include <stdlib.h>
#include <stdio.h>
#include <liburing.h>
#define LEN 4096
#define CNT 9
int main()
{
struct io_uring ring;
struct iovec iov[CNT];
char *buf;
int res;
if (io_uring_queue_init(64, &ring, 0) != 0)
return -1;
buf = malloc(LEN*CNT);
for (int i = 0; i < CNT; i++) {
iov[i].iov_base = buf + (i * LEN);
iov[i].iov_len = LEN;
}
res = io_uring_register_buffers(&ring, iov, CNT);
printf("%d\n", res);
io_uring_queue_exit(&ring);
return 0;
}
If I define CNT as 9, I have ENOMEM error. What is wrong?
I've got an answer from a liburing contributor.
Pavel Begunkov (isilence):
You hit RLIMIT_MEMLOCK. The limit is usually 64KB, but I guess you stumble on 32KB because malloc returns a not aligned chunk, but registration works with pages, so for each buffer it registers 2 adjacent pages, that's twice as much.
In my system the hard limit for unprivileged users is 64kB. Using aligned_alloc(4096, LENCNT) instead malloc(LENCNT), I have 64kB limit.
So there are at least two ways: