diff --git a/fs/src/io_uring/memory.rs b/fs/src/io_uring/memory.rs index 3f42c316c1b..f9b07b01100 100644 --- a/fs/src/io_uring/memory.rs +++ b/fs/src/io_uring/memory.rs @@ -201,15 +201,18 @@ impl IoBufferChunk { registered_buffer: bool, ) -> impl Iterator + use<'_> { assert!( - (buffer.len() / FIXED_BUFFER_LEN as usize) <= u16::MAX as usize, - "buffer too large to register in io_uring" + chunk_size <= FIXED_BUFFER_LEN, + "chunk size {chunk_size} is too large" + ); + assert!( + (buffer.len() / chunk_size as usize) <= u16::MAX as usize, + "buffer too large (yields too many chunks at size={chunk_size})" ); let buf_start = buffer.as_ptr().addr(); - buffer .chunks_exact_mut(chunk_size as usize) .map(move |buf| { - let io_buf_index = (buf.as_ptr() as usize - buf_start) / FIXED_BUFFER_LEN as usize; + let io_buf_index = (buf.as_ptr().addr() - buf_start) / FIXED_BUFFER_LEN as usize; Self { ptr: buf.as_mut_ptr(), size: buf.len() as IoSize, diff --git a/fs/src/io_uring/sequential_file_reader.rs b/fs/src/io_uring/sequential_file_reader.rs index f2deb889d6a..e9f3f911609 100644 --- a/fs/src/io_uring/sequential_file_reader.rs +++ b/fs/src/io_uring/sequential_file_reader.rs @@ -602,6 +602,7 @@ impl FileState { } } +/// Tracks usage stages of single `IoBufferChunk` as it goes through io-uring operation #[derive(Debug)] enum ReadBufState { /// The buffer is pending submission to read queue (on initialization and @@ -628,11 +629,13 @@ impl ReadBufState { } #[inline] - fn slice(&self, start_pos: u32, end_pos: u32) -> &[u8] { + fn slice(&self, start_pos: IoSize, end_pos: IoSize) -> &[u8] { match self { Self::Full { buf, eof_pos } => { debug_assert!(eof_pos.unwrap_or(buf.len()) >= end_pos); let limit = (end_pos - start_pos) as usize; + // Safety: `limit` is at most `buf.len() - start_pos` (as asserted for `end_pos`), + // so the slice is valid given buffer's validity unsafe { slice::from_raw_parts(buf.as_ptr().add(start_pos as usize), limit) } } Self::Uninit(_) | Self::Reading => { @@ -697,15 +700,13 @@ impl RingOp for ReadOp { // Safety: we assert that the buffer is large enough to hold the read. let buf_ptr = unsafe { buf.as_mut_ptr().byte_add(*buf_offset as usize) }; - let offset = *file_offset; - let entry = match buf.io_buf_index() { Some(io_buf_index) => opcode::ReadFixed::new(*fd, buf_ptr, *read_len, io_buf_index) - .offset(offset) + .offset(*file_offset) .ioprio(IO_PRIO_BE_HIGHEST) .build(), None => opcode::Read::new(*fd, buf_ptr, *read_len) - .offset(offset) + .offset(*file_offset) .ioprio(IO_PRIO_BE_HIGHEST) .build(), };