0

I wanted to send requests to a ring with io_uring_enter, however the syscall fails because of a bad file descriptor. I double checked that the correct fd was used.

#define _GNU_SOURCE
#include <stdio.h>
#include <liburing.h>
#include <pthread.h>
#include <string.h>

#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427

#define QUEUE_DEPTH 2
#define REQ_F_FORCE_ASYNC 16

int uring_setup(unsigned int entries, unsigned int flags) {
  struct io_uring_params p;

    memset(&p, 0, sizeof(p));
    p.flags = flags;

  return syscall(__NR_io_uring_setup, entries, &p);
}

int uring_enter(int f, unsigned int n_queues, unsigned int flags) {
  return syscall(__NR_io_uring_enter, f, n_queues, 0, IORING_ENTER_GETEVENTS|flags, NULL);
}

int main() {
  pthread_t thrd;

  int fd = uring_setup(QUEUE_DEPTH, IORING_SETUP_IOPOLL);
  printf("fd: %d\n", fd);

  printf("uring_enter: %d\n", uring_enter(fd, 2, REQ_F_FORCE_ASYNC));

  return 0;
}

output:

fd: 3
uring_enter: -1

strace said: io_uring_enter(3, 2, 0, IORING_ENTER_GETEVENTS|0x10, NULL, 68719476736) = -1 EBADF (Bad file descriptor)

can someone help?

BitFriends
  • 379
  • 5
  • 18

1 Answers1

2

You pass REQ_F_FORCE_ASYNC, i.e 16 into io_uring_enter as a flag, which is unfortunately the value for IORING_ENTER_REGISTERED_RING, to be used with a previously registered ring.

In this case, the kernel treats this as a ring offset instead of an fd, and since you didn't register such a ring, this returns EBADF.

Hasturkun
  • 35,395
  • 6
  • 71
  • 104