Skip to content

Commit 6d5c94d

Browse files
hoshinolinajannau
authored andcommitted
rust: page: Convert to Ownable
This allows Page references to be returned as borrowed references, without necessarily owning the struct page. Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 72d9950 commit 6d5c94d

1 file changed

Lines changed: 15 additions & 14 deletions

File tree

rust/kernel/page.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{
77
bindings,
88
error::code::*,
99
error::Result,
10+
types::{Opaque, Ownable, Owned},
1011
uaccess::UserSliceReader,
1112
};
1213
use core::ptr::{self, NonNull};
@@ -30,13 +31,10 @@ pub const fn page_align(addr: usize) -> usize {
3031
(addr + (PAGE_SIZE - 1)) & PAGE_MASK
3132
}
3233

33-
/// A pointer to a page that owns the page allocation.
34-
///
35-
/// # Invariants
36-
///
37-
/// The pointer is valid, and has ownership over the page.
34+
/// A struct page.
35+
#[repr(transparent)]
3836
pub struct Page {
39-
page: NonNull<bindings::page>,
37+
page: Opaque<bindings::page>,
4038
}
4139

4240
// SAFETY: Pages have no logic that relies on them staying on a given thread, so moving them across
@@ -69,19 +67,20 @@ impl Page {
6967
/// let page = Page::alloc_page(GFP_KERNEL | __GFP_ZERO)?;
7068
/// # Ok::<(), kernel::alloc::AllocError>(())
7169
/// ```
72-
pub fn alloc_page(flags: Flags) -> Result<Self, AllocError> {
70+
pub fn alloc_page(flags: Flags) -> Result<Owned<Self>, AllocError> {
7371
// SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it
7472
// is always safe to call this method.
7573
let page = unsafe { bindings::alloc_pages(flags.as_raw(), 0) };
7674
let page = NonNull::new(page).ok_or(AllocError)?;
77-
// INVARIANT: We just successfully allocated a page, so we now have ownership of the newly
78-
// allocated page. We transfer that ownership to the new `Page` object.
79-
Ok(Self { page })
75+
// SAFETY: We just successfully allocated a page, so we now have ownership of the newly
76+
// allocated page. We transfer that ownership to the new `Owned<Page>` object.
77+
// Since `Page` is transparent, we can cast the pointer directly.
78+
Ok(unsafe { Owned::from_raw(page.cast()) })
8079
}
8180

8281
/// Returns a raw pointer to the page.
8382
pub fn as_ptr(&self) -> *mut bindings::page {
84-
self.page.as_ptr()
83+
Opaque::raw_get(&self.page)
8584
}
8685

8786
/// Runs a piece of code with this page mapped to an address.
@@ -250,9 +249,11 @@ impl Page {
250249
}
251250
}
252251

253-
impl Drop for Page {
254-
fn drop(&mut self) {
252+
// SAFETY: See below.
253+
unsafe impl Ownable for Page {
254+
unsafe fn release(this: NonNull<Self>) {
255255
// SAFETY: By the type invariants, we have ownership of the page and can free it.
256-
unsafe { bindings::__free_pages(self.page.as_ptr(), 0) };
256+
// Since Page is transparent, we can cast the raw pointer directly.
257+
unsafe { bindings::__free_pages(this.cast().as_ptr(), 0) };
257258
}
258259
}

0 commit comments

Comments
 (0)