Skip to content

Commit 170e28b

Browse files
committed
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 <[email protected]>
1 parent 766a400 commit 170e28b

1 file changed

Lines changed: 14 additions & 13 deletions

File tree

rust/kernel/page.rs

Lines changed: 14 additions & 13 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
@@ -71,19 +69,20 @@ impl Page {
7169
/// let page = Page::alloc_page(GFP_KERNEL | __GFP_ZERO)?;
7270
/// # Ok(()) }
7371
/// ```
74-
pub fn alloc_page(flags: Flags) -> Result<Self, AllocError> {
72+
pub fn alloc_page(flags: Flags) -> Result<Owned<Self>, AllocError> {
7573
// SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it
7674
// is always safe to call this method.
7775
let page = unsafe { bindings::alloc_pages(flags.as_raw(), 0) };
7876
let page = NonNull::new(page).ok_or(AllocError)?;
7977
// INVARIANT: We just successfully allocated a page, so we now have ownership of the newly
80-
// allocated page. We transfer that ownership to the new `Page` object.
81-
Ok(Self { page })
78+
// allocated page. We transfer that ownership to the new `Owned<Page>` object.
79+
// Since `Page` is transparent, we can cast the pointer directly.
80+
Ok(unsafe { Owned::from_raw(page.cast()) })
8281
}
8382

8483
/// Returns a raw pointer to the page.
8584
pub fn as_ptr(&self) -> *mut bindings::page {
86-
self.page.as_ptr()
85+
Opaque::raw_get(&self.page)
8786
}
8887

8988
/// Runs a piece of code with this page mapped to an address.
@@ -252,9 +251,11 @@ impl Page {
252251
}
253252
}
254253

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

0 commit comments

Comments
 (0)