Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ioctl: get_log_page by nvme uring cmd #927

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

996refuse
Copy link

@996refuse 996refuse commented Dec 7, 2024

hello libnvme master,

io_uring on linux is pretty mature now, for the system with liburing, do the batch nvme_get_log by nvme uring cmd.
This change could gain about 10% performance improvement for some large log pages on my lab.

i believe the performance can be better if implement producer and consumer in two separated threads, if it's worth and acceptable, i can spend some time on this later.

thanks

src/nvme/ioctl.c Show resolved Hide resolved
src/nvme/ioctl.c Outdated
@@ -344,14 +431,30 @@ int nvme_get_log_page(int fd, __u32 xfer_len, struct nvme_get_log_args *args)
args->len = xfer;
args->log = ptr;
args->rae = offset + xfer < data_len || retain;
#ifdef CONFIG_LIBURING
if (n >= NVME_URING_ENTRIES) {
nvme_uring_cmd_wait_complete(&ring, n);
Copy link
Collaborator

@igaw igaw Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with using uring but would it be possible to have it fallback during runtime to the ioctl interface when uring is not available, like on older kernels?

src/nvme/ioctl.c Outdated
struct io_uring_probe *probe = io_uring_get_probe();
if (!io_uring_opcode_supported(probe, IORING_OP_URING_CMD)) {
perror("IORING_OP_URING_CMD is not supported for the kernel version below 5.19, failback ioctl interface.");
return -1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we hook this up on library load time, so it only tests once if the io_uring is available?

Also it should not print an error at all, this would spam the logs when io_uring is not available. Internal function shouldn't use the POSIX style of error propagation (setting errno and return -1). The plan is to fix this once we work on the next major version.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for your clarification.

Could we hook this up on library load time, so it only tests once if the io_uring is available?

correct me if i'm wrong, i think it's not possible to catch the error on .so library loading time in an ordinary way.
nvme: error while loading shared libraries: liburing.so.2: cannot open shared object file: No such file or directory
ld.so looks for the .so from the ELF dynamic section then load the .so, then run the ELF .text code.
when the error is occurs, the program has not started yet.
we can hack to load the .so on program runtime, but it's not recommended.

what if add a parameter for get-log to give an explicit instruction to use io_uring? and by default, this feature is not enabled, what do you think?
nvme get-log /dev/nvme2 --log-id=0x00 --log-len=0x1000 --uring-cmd

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, my idea doesn't work. We don't have a nvme_init_lib function yet. So the simplest thing is to introduce a global static variable which tracks if io_uring is available. That doesn't need to be race free, so no locks or so are necessary. Worst case if two threads are figuring out that io_uring is available or not at the same time and both should come to the same conclusion.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what the two threads are, could help explain it please? two threads do same task is inefficient, increasing the libnvme runtime complexity.

maybe we too overcomplicated the thing. by default, compile time disabled the feature, remove liburing.so and io_uring syscall dependencies. waiting for liburing being accepted by main linux distributions widely, then switch it to auto.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just leave the meson auto detection in place. This part is fine.

No, it's very simple. If a library is loaded into process context, the application could run several threads using libnvme. This is perfectly fine, e.g. if there are multiple devices. So we don't want to have the detection everytime for each single command send out. So this part just needs to be done once. The io_uring detection though can't be made 'thread safe' without using global locks which is not really a good idea. So my point, it doesn't matter. We just need eventually consistency.

With this in mind, something like this is good enough:

enum io_uring_state {
  io_uring_state_detect, 
  io_uring_state_available,
  io_uring_state_not_available,
};
enum io_uring_state io_uring_state = io_uring_state_detect;


if (io_uring_state == io_uring_detetct) {
  if (io_uring_opcode_supported(probe, IORING_OP_URING_CMD))
    io_uring_state =  io_uring_available;
  else
    io_uring_state = io_uring_not_available;
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

brilliant idea, got it

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i prefer constructor, which is a gcc specific attribute, the function attached is called when libnvme.so is loaded.

i tested the fallback mechanism manually by io_uring_disabled sysctl, it works well
sysctl -w kernel.io_uring_disabled=2

src/nvme/ioctl.c Outdated Show resolved Hide resolved
1. add a global variable io_uring_kernel_support to track status
2. run nvme_uring_cmd_probe once on the library loading time

Signed-off-by: letli <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants