-
Notifications
You must be signed in to change notification settings - Fork 143
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
Add UringCmd opcode #133
Add UringCmd opcode #133
Conversation
Wow, that's pretty complicated, and frankly I don't like this.
I guess linus has the same reaction. |
Indeed. An alternative design would be to have separate "BigEntry" types, and parameterize
We would be using this in libblkio for NVMe passthrough (https://gitlab.com/libblkio/libblkio/-/merge_requests/117), but we can use the kernel UAPI directly for now and switch to io-uring when support is added. |
|
v2:
The two |
Although generics make things a more complicated, but I still prefer v2 over v1. I think the impl SubmissionQueue<'_, Entry16> {
pub unsafe fn push(&mut self, entry: &Entry16) -> Result<(), PushError> { ... }
} and impl IoUring<squeue::Entry64, cqueue::Entry16> {
pub fn builder() -> Builder<squeue::Entry64, cqueue::Entry16> { ... }
} maybe we can make there are currently only 4 combinations, and I think enumerating their builder methods is acceptable. Hopefully the kernel will not have more types of |
Providing separate Perhaps we could just remove all methods from Also, I'm unsure whether it would be best to |
This seems to work, it can be define as pub trait EntryMarker: Copy + Sealed {} I will consider |
v3:
|
I think we can do backwards compatibility like giving the generics builder method a new name. struct Bar<S = ()> {
s: S
}
impl Bar<()> {
pub fn new() -> Self {
Bar { s: () }
}
}
impl<S: Default> Bar<S> {
pub fn new2() -> Self {
Bar { s: S::default() }
}
}
fn main() {
let bar = Bar::new();
let bar: Bar<u32> = Bar::new2();
} |
Other than that, are we sure that adding default type parameters to |
I believe methods like |
The trouble is that the compiler can no longer use the type of those methods' arguments for type inference, see for instance the changes required to io-uring-test/src/tests/queue.rs (10f20c2#diff-d0a68ef9fac5d4f6bf1873905a7b3b83bbe153fc356af15d3c3da510de186836). |
This is because for normal cases, it should work. https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d53b9587467696272906296a7c6c1cc6 |
v4:
I'm not knowledgeable enough to know for sure whether adding default type parameters to |
I believe that all generics must be given default parameters, otherwise compatibility will be broken. |
v5:
|
This looks good, could you add some tests to it and put the new method behind the |
Signed-off-by: Alberto Faria <[email protected]>
Which of these should be behind
Testing the new opcodes in CI will be difficult, as uring_cmd can only currently be used for NVMe passthrough. I can make the existing tests generic over |
I think all should be marked unstable. We don't need to test it on ci because kernel on ci doesn't support it yet. you can use |
The difficulty is that NVMe passthrough requires CAP_SYS_ADMIN and an actual NVMe device, which can also be a problem for local testing. |
v6:
|
io-uring-test/src/main.rs
Outdated
|
||
test::<squeue::Entry, cqueue::Entry>(IoUring::new(entries)?)?; | ||
|
||
#[cfg(feature = "unstable")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it also adds not(feature = "ci")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, fixed.
src/cqueue.rs
Outdated
unsafe { std::slice::from_raw_parts_mut(entries as *mut _ as *mut E, len) } | ||
} | ||
|
||
fn pop(&mut self) -> E { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be marked unsafe
and inline
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this needs unsafe
: it is just reading some bytes from a region of memory we know is valid. There is no additional contract the caller must follow to avoid undefined behavior.
Should I make it unsafe
nonetheless?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure it's always a valid memory region, if kernel doesn't write an entry into it, it's probably uninitialized memory.
} | ||
|
||
Ok(()) | ||
} | ||
|
||
unsafe fn push_unchecked(&mut self, entry: &E) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be marked inline
.
Provide separate squeue::Entry and squeue::Entry128 types for 64-byte and 128-byte SQEs, and a sealed squeue::EntryMarker trait implemented for both. Analogously provide cqueue::Entry, cqueue::Entry32, and cqueue::EntryMarker for CQEs. Parameterize IoUring with the SQE and CQE type, bound by squeue::EntryMarker and cqueue::EntryMarker. These type parameters default to squeue::Entry and cqueue::Entry to make the common case less verbose. When 128-byte SQEs and/or 32-byte CQEs are used, the IORING_SETUP_SQE128 and/or IORING_SETUP_CQE32 flags respectively are automatically set. These changes are a necessary step to support io_uring's NVMe passthrough feature [1], which requires 128-byte SQEs and 32-byte CQEs. Existing opcodes build squeue::Entry values, which implement Into<squeue::Entry128> so that less user code needs to be generic over the two SQE types. Similarly, cqueue::Entry implements Into<cqueue::Entry32>. [1] https://lore.kernel.org/all/[email protected] Signed-off-by: Alberto Faria <[email protected]>
Signed-off-by: Alberto Faria <[email protected]>
These corresponds to IORING_OP_URING_CMD, for use with 64-byte or 128-byte io_uring SQEs respectively, and in particular enable the use of io_uring's NVMe passthrough feature [1] introduced in Linux 5.19. [1] https://lore.kernel.org/all/[email protected] Signed-off-by: Alberto Faria <[email protected]>
Thank you! |
Add support for IORING_SETUP_SQE128 and IORING_SETUP_CQE32, and add an
UringCmd
opcode corresponding to IORING_OP_URING_CMD.These changes should be backward-compatible.