@@ -7,6 +7,7 @@ use crate::{
77 bindings,
88 error:: code:: * ,
99 error:: Result ,
10+ types:: { Opaque , Ownable , Owned } ,
1011 uaccess:: UserSliceReader ,
1112} ;
1213use core:: {
@@ -77,7 +78,7 @@ pub const fn page_align(addr: usize) -> usize {
7778///
7879/// [`VBox`]: kernel::alloc::VBox
7980/// [`Vmalloc`]: kernel::alloc::allocator::Vmalloc
80- pub struct BorrowedPage < ' a > ( ManuallyDrop < Page > , PhantomData < & ' a Page > ) ;
81+ pub struct BorrowedPage < ' a > ( ManuallyDrop < Owned < Page > > , PhantomData < & ' a Page > ) ;
8182
8283impl < ' a > BorrowedPage < ' a > {
8384 /// Constructs a [`BorrowedPage`] from a raw pointer to a `struct page`.
@@ -87,7 +88,7 @@ impl<'a> BorrowedPage<'a> {
8788 /// - `ptr` must point to a valid `bindings::page`.
8889 /// - `ptr` must remain valid for the entire lifetime `'a`.
8990 pub unsafe fn from_raw ( ptr : NonNull < bindings:: page > ) -> Self {
90- let page = Page { page : ptr } ;
91+ let page = unsafe { Page :: from_phys ( bindings :: page_to_phys ( ptr. as_ptr ( ) ) ) } ;
9192
9293 // INVARIANT: The safety requirements guarantee that `ptr` is valid for the entire lifetime
9394 // `'a`.
@@ -120,8 +121,9 @@ pub trait AsPageIter {
120121/// # Invariants
121122///
122123/// The pointer is valid, and has ownership over the page.
124+ #[ repr( transparent) ]
123125pub struct Page {
124- page : NonNull < bindings:: page > ,
126+ page : Opaque < bindings:: page > ,
125127}
126128
127129// SAFETY: Pages have no logic that relies on them staying on a given thread, so moving them across
@@ -155,19 +157,20 @@ impl Page {
155157 /// # Ok::<(), kernel::alloc::AllocError>(())
156158 /// ```
157159 #[ inline]
158- pub fn alloc_page ( flags : Flags ) -> Result < Self , AllocError > {
160+ pub fn alloc_page ( flags : Flags ) -> Result < Owned < Self > , AllocError > {
159161 // SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it
160162 // is always safe to call this method.
161163 let page = unsafe { bindings:: alloc_pages ( flags. as_raw ( ) , 0 ) } ;
162164 let page = NonNull :: new ( page) . ok_or ( AllocError ) ?;
163- // INVARIANT: We just successfully allocated a page, so we now have ownership of the newly
164- // allocated page. We transfer that ownership to the new `Page` object.
165- Ok ( Self { page } )
165+ // SAFETY: We just successfully allocated a page, so we now have ownership of the newly
166+ // allocated page. We transfer that ownership to the new `Owned<Page>` object.
167+ // Since `Page` is transparent, we can cast the pointer directly.
168+ Ok ( unsafe { Owned :: from_raw ( page. cast ( ) ) } )
166169 }
167170
168171 /// Returns a raw pointer to the page.
169172 pub fn as_ptr ( & self ) -> * mut bindings:: page {
170- self . page . as_ptr ( )
173+ Opaque :: cast_into ( & self . page )
171174 }
172175
173176 /// Get the node id containing this page.
@@ -342,10 +345,12 @@ impl Page {
342345 }
343346}
344347
345- impl Drop for Page {
348+ // SAFETY: See below.
349+ unsafe impl Ownable for Page {
346350 #[ inline]
347- fn drop ( & mut self ) {
351+ unsafe fn release ( this : NonNull < Self > ) {
348352 // SAFETY: By the type invariants, we have ownership of the page and can free it.
349- unsafe { bindings:: __free_pages ( self . page . as_ptr ( ) , 0 ) } ;
353+ // Since Page is transparent, we can cast the raw pointer directly.
354+ unsafe { bindings:: __free_pages ( this. cast ( ) . as_ptr ( ) , 0 ) } ;
350355 }
351356}
0 commit comments