summary refs log tree commit diff
path: root/io_uring
diff options
context:
space:
mode:
authorDylan Reid <dgreid@chromium.org>2020-04-08 00:47:45 +0000
committerCommit Bot <commit-bot@chromium.org>2020-04-10 00:13:08 +0000
commit03164ca9d8baca09f4d8afedc25d57ddeb2361e6 (patch)
tree123b38c2a6c5955af3623fea9d4b015683a3bc4f /io_uring
parent23a2b7b8a22a4ca589a58c804596eddfbceab4e3 (diff)
downloadcrosvm-03164ca9d8baca09f4d8afedc25d57ddeb2361e6.tar
crosvm-03164ca9d8baca09f4d8afedc25d57ddeb2361e6.tar.gz
crosvm-03164ca9d8baca09f4d8afedc25d57ddeb2361e6.tar.bz2
crosvm-03164ca9d8baca09f4d8afedc25d57ddeb2361e6.tar.lz
crosvm-03164ca9d8baca09f4d8afedc25d57ddeb2361e6.tar.xz
crosvm-03164ca9d8baca09f4d8afedc25d57ddeb2361e6.tar.zst
crosvm-03164ca9d8baca09f4d8afedc25d57ddeb2361e6.zip
io_uring: allocate iovecs based on returned count from the kernel
The kernel is allowed to not only limit the number of requested entries,
but also provide more than is requested. If a non-power-of-2 is
requested, it will be rounded up to the next power of 2.

Ensure that there are enough iovecs by allocating them based on the
number returned from io_uring_setup instead of the number of entries
requested.

TEST=cargo test read_parallel

Change-Id: If92e0a31858d1af53b99af8415002a4f26b48230
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2140915
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Tested-by: Dylan Reid <dgreid@chromium.org>
Commit-Queue: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'io_uring')
-rw-r--r--io_uring/src/uring.rs41
1 files changed, 38 insertions, 3 deletions
diff --git a/io_uring/src/uring.rs b/io_uring/src/uring.rs
index 4d401e6..8d569aa 100644
--- a/io_uring/src/uring.rs
+++ b/io_uring/src/uring.rs
@@ -125,6 +125,7 @@ impl URingContext {
                 &ring_params,
             );
 
+            let num_sqe = ring_params.sq_entries as usize;
             let submit_queue_entries = SubmitQueueEntries {
                 mmap: MemoryMapping::from_fd_offset_populate(
                     &ring_file,
@@ -132,7 +133,7 @@ impl URingContext {
                     u64::from(IORING_OFF_SQES),
                 )
                 .map_err(Error::MappingSubmitEntries)?,
-                len: ring_params.sq_entries as usize,
+                len: num_sqe,
             };
 
             let complete_ring = CompleteQueueState::new(
@@ -156,7 +157,7 @@ impl URingContext {
                         iov_base: null_mut(),
                         iov_len: 0
                     };
-                    num_entries
+                    num_sqe
                 ],
                 added: 0,
                 in_flight: 0,
@@ -700,6 +701,40 @@ mod tests {
     }
 
     #[test]
+    // Queue as many reads as possible and then collect the completions.
+    fn read_parallel() {
+        let temp_dir = TempDir::new().unwrap();
+        const QUEUE_SIZE: usize = 10;
+        const BUF_SIZE: usize = 0x1000;
+
+        let mut uring = URingContext::new(QUEUE_SIZE).unwrap();
+        let mut buf = [0u8; BUF_SIZE * QUEUE_SIZE];
+        let f = create_test_file(&temp_dir, (BUF_SIZE * QUEUE_SIZE) as u64);
+
+        // check that the whole file can be read and that the queues wrapping is handled by reading
+        // double the quue depth of buffers.
+        for i in 0..QUEUE_SIZE * 64 {
+            let index = i as u64;
+            unsafe {
+                let offset = (i % QUEUE_SIZE) * BUF_SIZE;
+                match uring.add_read(
+                    buf[offset..].as_mut_ptr(),
+                    BUF_SIZE,
+                    f.as_raw_fd(),
+                    offset as u64,
+                    index,
+                ) {
+                    Ok(_) => (),
+                    Err(Error::NoSpace) => {
+                        let _ = uring.wait().unwrap().next().unwrap();
+                    }
+                    Err(_) => panic!("unexpected error from uring wait"),
+                }
+            }
+        }
+    }
+
+    #[test]
     fn read_readv() {
         let temp_dir = TempDir::new().unwrap();
         let queue_size = 128;
@@ -708,7 +743,7 @@ mod tests {
         let mut buf = [0u8; 0x1000];
         let f = create_test_file(&temp_dir, 0x1000 * 2);
 
-        // check that the whoe file can be read and that the queues wrapping is handled by reading
+        // check that the whole file can be read and that the queues wrapping is handled by reading
         // double the quue depth of buffers.
         for i in 0..queue_size * 2 {
             let index = i as u64;