8000 rust: folio: add `with_slice_into_page()` · Rust-for-Linux/linux@c27e2e3 · GitHub
[go: up one dir, main page]

Skip to content

Commit c27e2e3

Browse files
committed
rust: folio: add with_slice_into_page()
Add methods to `Folio` that allows access to page data through slices. This patch delegates to functionality in `Page`. Signed-off-by: Andreas Hindborg <a.hindborg@samsung.com>
1 parent 34adb73 commit c27e2e3

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

rust/kernel/folio.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
//! C headers: [`include/linux/mm.h`](../../include/linux/mm.h)
66
77
use crate::error::{code::*, Result};
8+
use crate::page::Page;
89
use crate::types::{ARef, AlwaysRefCounted, Opaque, ScopeGuard};
10+
use core::mem::ManuallyDrop;
911
use core::{cmp::min, ptr};
1012

1113
/// Wraps the kernel's `struct folio`.
@@ -88,6 +90,59 @@ impl UniqueFolio {
8890

8991
Ok(MapGuard { data, page })
9092
}
93+
94+
/// Map a page into memory and run a function with a shared slice pointing
95+
/// to a mapped page.
96+
///
97+
/// The page is mapped for the duration fo the function.
98+
pub fn with_slice_into_page<T>(
99+
&self,
100+
page_index: usize,
101+
f: impl FnOnce(&[u8]) -> Result<T>,
102+
) -> Result<T> {
103+
if page_index >= self.0.size() / bindings::PAGE_SIZE {
104+
return Err(EDOM);
105+
}
106+
107+
// SAFETY: We just checked that the index is within bounds of the folio.
108+
let page_ptr = unsafe { bindings::folio_page(self.0 .0.get(), page_index) };
109+
110+
ManuallyDrop::new(
111+
// SAFETY: `page_ptr` points to a page that we own. We take care not
112+
// free the page when we are done with it, by wrapping in
113+
// `ManuallyDrop`. We also do no mutable access through this `Page`.
114+
unsafe { Page::from_raw(page_ptr) },
115+
)
116+
.with_slice_into_page(f)
117+
}
118+
119+
/// Map a page into memory and run a function with a mutable slice pointing
120+
/// to a mapped page.
121+
///
122+
/// The page is mapped for the duration fo the function.
123+
pub fn with_slice_into_page_mut<T>(
124+
&mut self,
125+
page_index: usize,
126+
f: impl FnOnce(&mut [u8]) -> Result<T>,
127+
) -> Result<T> {
128+
if page_index >= self.0.size() / bindings::PAGE_SIZE {
129+
return Err(EDOM);
130+
}
131+
132+
// SAFETY: We just checked that the index is within bounds of the folio.
133+
let page_ptr = unsafe { bindings::folio_page(self.0 .0.get(), page_index) };
134+
135+
ManuallyDrop::new(
136+
// SAFETY: `page_ptr` points to a page that we own. By existence of
137+
// `&mut self` we have exclusive access to the page. We take care
138+
// not free the page when we are done with it, by wrapping in
139+
// `ManuallyDrop`. We forget the page as soone as we are donw with
140+
// our access so as to allow no further mutable access through the
141+
// `Page` we are creating.
142+
unsafe { Page::from_raw(page_ptr) },
143+
)
144+
.with_slice_into_page_mut(f)
145+
}
91146
}
92147

93148
/// A mapped [`UniqueFolio`].

0 commit comments

Comments
 (0)
0