Add a method to `block::mq::bio::Segment` to copy a bounded amount of bytes to a page. Signed-off-by: Andreas Hindborg --- rust/kernel/block/bio/vec.rs | 27 ++++++++++++++++++++++++++- rust/kernel/block/mq/request.rs | 3 +-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/rust/kernel/block/bio/vec.rs b/rust/kernel/block/bio/vec.rs index 20cea478050b9..ed1c1374c9c76 100644 --- a/rust/kernel/block/bio/vec.rs +++ b/rust/kernel/block/bio/vec.rs @@ -79,13 +79,38 @@ pub fn advance(&mut self, count: u32) -> Result { /// Returns the number of bytes copied. #[inline(always)] pub fn copy_to_page(&mut self, dst_page: Pin<&mut SafePage>, dst_offset: usize) -> usize { + self.copy_to_page_limit(dst_page, dst_offset, 0) + } + + /// Copy data of this segment into `dst_page`. + /// + /// Copies at most `limit` bytes of data from the current offset to the next page boundary. That + /// is `PAGE_SIZE - (self.offeset() % PAGE_SIZE)` bytes of data. Data is placed at offset + /// `self.offset()` in the target page. This call will advance offset and reduce length of + /// `self`. + /// + /// If `limit` is zero it is ignored. + /// + /// Returns the number of bytes copied. + #[inline(always)] + pub fn copy_to_page_limit( + &mut self, + dst_page: Pin<&mut SafePage>, + dst_offset: usize, + limit: usize, + ) -> usize { // SAFETY: We are not moving out of `dst_page`. let dst_page = unsafe { Pin::into_inner_unchecked(dst_page) }; let src_offset = self.offset() % PAGE_SIZE; debug_assert!(dst_offset <= PAGE_SIZE); - let length = (PAGE_SIZE - src_offset) + let mut length = (PAGE_SIZE - src_offset) .min(self.len() as usize) .min(PAGE_SIZE - dst_offset); + + if limit > 0 { + length = length.min(limit); + } + let page_idx = self.offset() / PAGE_SIZE; // SAFETY: self.bio_vec is valid and thus bv_page must be a valid diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs index cebb30fe9b3bc..bc655d202ca01 100644 --- a/rust/kernel/block/mq/request.rs +++ b/rust/kernel/block/mq/request.rs @@ -7,7 +7,6 @@ use crate::{ bindings, block::mq::Operations, - prelude::*, sync::{ aref::{ARef, RefCounted}, atomic::ordering, @@ -18,7 +17,7 @@ }, types::{ForeignOwnable, Opaque, Ownable, OwnableRefCounted, Owned}, }; -use core::{ffi::c_void, marker::PhantomData, ops::Deref, ptr::NonNull}; +use core::{ffi::c_void, marker::PhantomData, ops::Deref, pin::Pin, ptr::NonNull}; use super::RequestQueue; use crate::block::bio::Bio; -- 2.51.2