Skip to content

Commit ead7576

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 effd690 commit ead7576

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
@@ -70,19 +68,20 @@ impl Page {
7068
/// # Ok::<(), kernel::alloc::AllocError>(())
7169
/// ```
7270
#[inline]
73-
pub fn alloc_page(flags: Flags) -> Result<Self, AllocError> {
71+
pub fn alloc_page(flags: Flags) -> Result<Owned<Self>, AllocError> {
7472
// SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it
7573
// is always safe to call this method.
7674
let page = unsafe { bindings::alloc_pages(flags.as_raw(), 0) };
7775
let page = NonNull::new(page).ok_or(AllocError)?;
78-
// INVARIANT: We just successfully allocated a page, so we now have ownership of the newly
79-
// allocated page. We transfer that ownership to the new `Page` object.
80-
Ok(Self { page })
76+
// SAFETY: We just successfully allocated a page, so we now have ownership of the newly
77+
// allocated page. We transfer that ownership to the new `Owned<Page>` object.
78+
// Since `Page` is transparent, we can cast the pointer directly.
79+
Ok(unsafe { Owned::from_raw(page.cast()) })
8180
}
8281

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

8887
/// Runs a piece of code with this page mapped to an address.
@@ -251,10 +250,12 @@ impl Page {
251250
}
252251
}
253252

254-
impl Drop for Page {
253+
// SAFETY: See below.
254+
unsafe impl Ownable for Page {
255255
#[inline]
256-
fn drop(&mut self) {
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)