xref: /linux/drivers/android/binder/page_range.rs (revision 6093a688a07da07808f0122f9aa2a3eed250d853)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 // Copyright (C) 2025 Google LLC.
4 
5 //! This module has utilities for managing a page range where unused pages may be reclaimed by a
6 //! vma shrinker.
7 
8 // To avoid deadlocks, locks are taken in the order:
9 //
10 //  1. mmap lock
11 //  2. spinlock
12 //  3. lru spinlock
13 //
14 // The shrinker will use trylock methods because it locks them in a different order.
15 
16 use core::{
17     marker::PhantomPinned,
18     mem::{size_of, size_of_val, MaybeUninit},
19     ptr,
20 };
21 
22 use kernel::{
23     bindings,
24     error::Result,
25     ffi::{c_ulong, c_void},
26     mm::{virt, Mm, MmWithUser},
27     new_mutex, new_spinlock,
28     page::{Page, PAGE_SHIFT, PAGE_SIZE},
29     prelude::*,
30     str::CStr,
31     sync::{aref::ARef, Mutex, SpinLock},
32     task::Pid,
33     transmute::FromBytes,
34     types::Opaque,
35     uaccess::UserSliceReader,
36 };
37 
38 /// Represents a shrinker that can be registered with the kernel.
39 ///
40 /// Each shrinker can be used by many `ShrinkablePageRange` objects.
41 #[repr(C)]
42 pub(crate) struct Shrinker {
43     inner: Opaque<*mut bindings::shrinker>,
44     list_lru: Opaque<bindings::list_lru>,
45 }
46 
47 // SAFETY: The shrinker and list_lru are thread safe.
48 unsafe impl Send for Shrinker {}
49 // SAFETY: The shrinker and list_lru are thread safe.
50 unsafe impl Sync for Shrinker {}
51 
52 impl Shrinker {
53     /// Create a new shrinker.
54     ///
55     /// # Safety
56     ///
57     /// Before using this shrinker with a `ShrinkablePageRange`, the `register` method must have
58     /// been called exactly once, and it must not have returned an error.
59     pub(crate) const unsafe fn new() -> Self {
60         Self {
61             inner: Opaque::uninit(),
62             list_lru: Opaque::uninit(),
63         }
64     }
65 
66     /// Register this shrinker with the kernel.
67     pub(crate) fn register(&'static self, name: &CStr) -> Result<()> {
68         // SAFETY: These fields are not yet used, so it's okay to zero them.
69         unsafe {
70             self.inner.get().write(ptr::null_mut());
71             self.list_lru.get().write_bytes(0, 1);
72         }
73 
74         // SAFETY: The field is not yet used, so we can initialize it.
75         let ret = unsafe { bindings::__list_lru_init(self.list_lru.get(), false, ptr::null_mut()) };
76         if ret != 0 {
77             return Err(Error::from_errno(ret));
78         }
79 
80         // SAFETY: The `name` points at a valid c string.
81         let shrinker = unsafe { bindings::shrinker_alloc(0, name.as_char_ptr()) };
82         if shrinker.is_null() {
83             // SAFETY: We initialized it, so its okay to destroy it.
84             unsafe { bindings::list_lru_destroy(self.list_lru.get()) };
85             return Err(Error::from_errno(ret));
86         }
87 
88         // SAFETY: We're about to register the shrinker, and these are the fields we need to
89         // initialize. (All other fields are already zeroed.)
90         unsafe {
91             (&raw mut (*shrinker).count_objects).write(Some(rust_shrink_count));
92             (&raw mut (*shrinker).scan_objects).write(Some(rust_shrink_scan));
93             (&raw mut (*shrinker).private_data).write(self.list_lru.get().cast());
94         }
95 
96         // SAFETY: The new shrinker has been fully initialized, so we can register it.
97         unsafe { bindings::shrinker_register(shrinker) };
98 
99         // SAFETY: This initializes the pointer to the shrinker so that we can use it.
100         unsafe { self.inner.get().write(shrinker) };
101 
102         Ok(())
103     }
104 }
105 
106 /// A container that manages a page range in a vma.
107 ///
108 /// The pages can be thought of as an array of booleans of whether the pages are usable. The
109 /// methods `use_range` and `stop_using_range` set all booleans in a range to true or false
110 /// respectively. Initially, no pages are allocated. When a page is not used, it is not freed
111 /// immediately. Instead, it is made available to the memory shrinker to free it if the device is
112 /// under memory pressure.
113 ///
114 /// It's okay for `use_range` and `stop_using_range` to race with each other, although there's no
115 /// way to know whether an index ends up with true or false if a call to `use_range` races with
116 /// another call to `stop_using_range` on a given index.
117 ///
118 /// It's also okay for the two methods to race with themselves, e.g. if two threads call
119 /// `use_range` on the same index, then that's fine and neither call will return until the page is
120 /// allocated and mapped.
121 ///
122 /// The methods that read or write to a range require that the page is marked as in use. So it is
123 /// _not_ okay to call `stop_using_range` on a page that is in use by the methods that read or
124 /// write to the page.
125 #[pin_data(PinnedDrop)]
126 pub(crate) struct ShrinkablePageRange {
127     /// Shrinker object registered with the kernel.
128     shrinker: &'static Shrinker,
129     /// Pid using this page range. Only used as debugging information.
130     pid: Pid,
131     /// The mm for the relevant process.
132     mm: ARef<Mm>,
133     /// Used to synchronize calls to `vm_insert_page` and `zap_page_range_single`.
134     #[pin]
135     mm_lock: Mutex<()>,
136     /// Spinlock protecting changes to pages.
137     #[pin]
138     lock: SpinLock<Inner>,
139 
140     /// Must not move, since page info has pointers back.
141     #[pin]
142     _pin: PhantomPinned,
143 }
144 
145 struct Inner {
146     /// Array of pages.
147     ///
148     /// Since this is also accessed by the shrinker, we can't use a `Box`, which asserts exclusive
149     /// ownership. To deal with that, we manage it using raw pointers.
150     pages: *mut PageInfo,
151     /// Length of the `pages` array.
152     size: usize,
153     /// The address of the vma to insert the pages into.
154     vma_addr: usize,
155 }
156 
157 // SAFETY: proper locking is in place for `Inner`
158 unsafe impl Send for Inner {}
159 
160 type StableMmGuard =
161     kernel::sync::lock::Guard<'static, (), kernel::sync::lock::mutex::MutexBackend>;
162 
163 /// An array element that describes the current state of a page.
164 ///
165 /// There are three states:
166 ///
167 ///  * Free. The page is None. The `lru` element is not queued.
168 ///  * Available. The page is Some. The `lru` element is queued to the shrinker's lru.
169 ///  * Used. The page is Some. The `lru` element is not queued.
170 ///
171 /// When an element is available, the shrinker is able to free the page.
172 #[repr(C)]
173 struct PageInfo {
174     lru: bindings::list_head,
175     page: Option<Page>,
176     range: *const ShrinkablePageRange,
177 }
178 
179 impl PageInfo {
180     /// # Safety
181     ///
182     /// The caller ensures that writing to `me.page` is ok, and that the page is not currently set.
183     unsafe fn set_page(me: *mut PageInfo, page: Page) {
184         // SAFETY: This pointer offset is in bounds.
185         let ptr = unsafe { &raw mut (*me).page };
186 
187         // SAFETY: The pointer is valid for writing, so also valid for reading.
188         if unsafe { (*ptr).is_some() } {
189             pr_err!("set_page called when there is already a page");
190             // SAFETY: We will initialize the page again below.
191             unsafe { ptr::drop_in_place(ptr) };
192         }
193 
194         // SAFETY: The pointer is valid for writing.
195         unsafe { ptr::write(ptr, Some(page)) };
196     }
197 
198     /// # Safety
199     ///
200     /// The caller ensures that reading from `me.page` is ok for the duration of 'a.
201     unsafe fn get_page<'a>(me: *const PageInfo) -> Option<&'a Page> {
202         // SAFETY: This pointer offset is in bounds.
203         let ptr = unsafe { &raw const (*me).page };
204 
205         // SAFETY: The pointer is valid for reading.
206         unsafe { (*ptr).as_ref() }
207     }
208 
209     /// # Safety
210     ///
211     /// The caller ensures that writing to `me.page` is ok for the duration of 'a.
212     unsafe fn take_page(me: *mut PageInfo) -> Option<Page> {
213         // SAFETY: This pointer offset is in bounds.
214         let ptr = unsafe { &raw mut (*me).page };
215 
216         // SAFETY: The pointer is valid for reading.
217         unsafe { (*ptr).take() }
218     }
219 
220     /// Add this page to the lru list, if not already in the list.
221     ///
222     /// # Safety
223     ///
224     /// The pointer must be valid, and it must be the right shrinker and nid.
225     unsafe fn list_lru_add(me: *mut PageInfo, nid: i32, shrinker: &'static Shrinker) {
226         // SAFETY: This pointer offset is in bounds.
227         let lru_ptr = unsafe { &raw mut (*me).lru };
228         // SAFETY: The lru pointer is valid, and we're not using it with any other lru list.
229         unsafe { bindings::list_lru_add(shrinker.list_lru.get(), lru_ptr, nid, ptr::null_mut()) };
230     }
231 
232     /// Remove this page from the lru list, if it is in the list.
233     ///
234     /// # Safety
235     ///
236     /// The pointer must be valid, and it must be the right shrinker and nid.
237     unsafe fn list_lru_del(me: *mut PageInfo, nid: i32, shrinker: &'static Shrinker) {
238         // SAFETY: This pointer offset is in bounds.
239         let lru_ptr = unsafe { &raw mut (*me).lru };
240         // SAFETY: The lru pointer is valid, and we're not using it with any other lru list.
241         unsafe { bindings::list_lru_del(shrinker.list_lru.get(), lru_ptr, nid, ptr::null_mut()) };
242     }
243 }
244 
245 impl ShrinkablePageRange {
246     /// Create a new `ShrinkablePageRange` using the given shrinker.
247     pub(crate) fn new(shrinker: &'static Shrinker) -> impl PinInit<Self, Error> {
248         try_pin_init!(Self {
249             shrinker,
250             pid: kernel::current!().pid(),
251             mm: ARef::from(&**kernel::current!().mm().ok_or(ESRCH)?),
252             mm_lock <- new_mutex!((), "ShrinkablePageRange::mm"),
253             lock <- new_spinlock!(Inner {
254                 pages: ptr::null_mut(),
255                 size: 0,
256                 vma_addr: 0,
257             }, "ShrinkablePageRange"),
258             _pin: PhantomPinned,
259         })
260     }
261 
262     pub(crate) fn stable_trylock_mm(&self) -> Option<StableMmGuard> {
263         // SAFETY: This extends the duration of the reference. Since this call happens before
264         // `mm_lock` is taken in the destructor of `ShrinkablePageRange`, the destructor will block
265         // until the returned guard is dropped. This ensures that the guard is valid until dropped.
266         let mm_lock = unsafe { &*ptr::from_ref(&self.mm_lock) };
267 
268         mm_lock.try_lock()
269     }
270 
271     /// Register a vma with this page range. Returns the size of the region.
272     pub(crate) fn register_with_vma(&self, vma: &virt::VmaNew) -> Result<usize> {
273         let num_bytes = usize::min(vma.end() - vma.start(), bindings::SZ_4M as usize);
274         let num_pages = num_bytes >> PAGE_SHIFT;
275 
276         if !ptr::eq::<Mm>(&*self.mm, &**vma.mm()) {
277             pr_debug!("Failed to register with vma: invalid vma->vm_mm");
278             return Err(EINVAL);
279         }
280         if num_pages == 0 {
281             pr_debug!("Failed to register with vma: size zero");
282             return Err(EINVAL);
283         }
284 
285         let mut pages = KVVec::<PageInfo>::with_capacity(num_pages, GFP_KERNEL)?;
286 
287         // SAFETY: This just initializes the pages array.
288         unsafe {
289             let self_ptr = self as *const ShrinkablePageRange;
290             for i in 0..num_pages {
291                 let info = pages.as_mut_ptr().add(i);
292                 (&raw mut (*info).range).write(self_ptr);
293                 (&raw mut (*info).page).write(None);
294                 let lru = &raw mut (*info).lru;
295                 (&raw mut (*lru).next).write(lru);
296                 (&raw mut (*lru).prev).write(lru);
297             }
298         }
299 
300         let mut inner = self.lock.lock();
301         if inner.size > 0 {
302             pr_debug!("Failed to register with vma: already registered");
303             drop(inner);
304             return Err(EBUSY);
305         }
306 
307         inner.pages = pages.into_raw_parts().0;
308         inner.size = num_pages;
309         inner.vma_addr = vma.start();
310 
311         Ok(num_pages)
312     }
313 
314     /// Make sure that the given pages are allocated and mapped.
315     ///
316     /// Must not be called from an atomic context.
317     pub(crate) fn use_range(&self, start: usize, end: usize) -> Result<()> {
318         if start >= end {
319             return Ok(());
320         }
321         let mut inner = self.lock.lock();
322         assert!(end <= inner.size);
323 
324         for i in start..end {
325             // SAFETY: This pointer offset is in bounds.
326             let page_info = unsafe { inner.pages.add(i) };
327 
328             // SAFETY: The pointer is valid, and we hold the lock so reading from the page is okay.
329             if let Some(page) = unsafe { PageInfo::get_page(page_info) } {
330                 // Since we're going to use the page, we should remove it from the lru list so that
331                 // the shrinker will not free it.
332                 //
333                 // SAFETY: The pointer is valid, and this is the right shrinker.
334                 //
335                 // The shrinker can't free the page between the check and this call to
336                 // `list_lru_del` because we hold the lock.
337                 unsafe { PageInfo::list_lru_del(page_info, page.nid(), self.shrinker) };
338             } else {
339                 // We have to allocate a new page. Use the slow path.
340                 drop(inner);
341                 // SAFETY: `i < end <= inner.size` so `i` is in bounds.
342                 match unsafe { self.use_page_slow(i) } {
343                     Ok(()) => {}
344                     Err(err) => {
345                         pr_warn!("Error in use_page_slow: {:?}", err);
346                         return Err(err);
347                     }
348                 }
349                 inner = self.lock.lock();
350             }
351         }
352         Ok(())
353     }
354 
355     /// Mark the given page as in use, slow path.
356     ///
357     /// Must not be called from an atomic context.
358     ///
359     /// # Safety
360     ///
361     /// Assumes that `i` is in bounds.
362     #[cold]
363     unsafe fn use_page_slow(&self, i: usize) -> Result<()> {
364         let new_page = Page::alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO)?;
365 
366         let mm_mutex = self.mm_lock.lock();
367         let inner = self.lock.lock();
368 
369         // SAFETY: This pointer offset is in bounds.
370         let page_info = unsafe { inner.pages.add(i) };
371 
372         // SAFETY: The pointer is valid, and we hold the lock so reading from the page is okay.
373         if let Some(page) = unsafe { PageInfo::get_page(page_info) } {
374             // The page was already there, or someone else added the page while we didn't hold the
375             // spinlock.
376             //
377             // SAFETY: The pointer is valid, and this is the right shrinker.
378             //
379             // The shrinker can't free the page between the check and this call to
380             // `list_lru_del` because we hold the lock.
381             unsafe { PageInfo::list_lru_del(page_info, page.nid(), self.shrinker) };
382             return Ok(());
383         }
384 
385         let vma_addr = inner.vma_addr;
386         // Release the spinlock while we insert the page into the vma.
387         drop(inner);
388 
389         // No overflow since we stay in bounds of the vma.
390         let user_page_addr = vma_addr + (i << PAGE_SHIFT);
391 
392         // We use `mmput_async` when dropping the `mm` because `use_page_slow` is usually used from
393         // a remote process. If the call to `mmput` races with the process shutting down, then the
394         // caller of `use_page_slow` becomes responsible for cleaning up the `mm`, which doesn't
395         // happen until it returns to userspace. However, the caller might instead go to sleep and
396         // wait for the owner of the `mm` to wake it up, which doesn't happen because it's in the
397         // middle of a shutdown process that won't complete until the `mm` is dropped. This can
398         // amount to a deadlock.
399         //
400         // Using `mmput_async` avoids this, because then the `mm` cleanup is instead queued to a
401         // workqueue.
402         MmWithUser::into_mmput_async(self.mm.mmget_not_zero().ok_or(ESRCH)?)
403             .mmap_read_lock()
404             .vma_lookup(vma_addr)
405             .ok_or(ESRCH)?
406             .as_mixedmap_vma()
407             .ok_or(ESRCH)?
408             .vm_insert_page(user_page_addr, &new_page)
409             .inspect_err(|err| {
410                 pr_warn!(
411                     "Failed to vm_insert_page({}): vma_addr:{} i:{} err:{:?}",
412                     user_page_addr,
413                     vma_addr,
414                     i,
415                     err
416                 )
417             })?;
418 
419         let inner = self.lock.lock();
420 
421         // SAFETY: The `page_info` pointer is valid and currently does not have a page. The page
422         // can be written to since we hold the lock.
423         //
424         // We released and reacquired the spinlock since we checked that the page is null, but we
425         // always hold the mm_lock mutex when setting the page to a non-null value, so it's not
426         // possible for someone else to have changed it since our check.
427         unsafe { PageInfo::set_page(page_info, new_page) };
428 
429         drop(inner);
430         drop(mm_mutex);
431 
432         Ok(())
433     }
434 
435     /// If the given page is in use, then mark it as available so that the shrinker can free it.
436     ///
437     /// May be called from an atomic context.
438     pub(crate) fn stop_using_range(&self, start: usize, end: usize) {
439         if start >= end {
440             return;
441         }
442         let inner = self.lock.lock();
443         assert!(end <= inner.size);
444 
445         for i in (start..end).rev() {
446             // SAFETY: The pointer is in bounds.
447             let page_info = unsafe { inner.pages.add(i) };
448 
449             // SAFETY: Okay for reading since we have the lock.
450             if let Some(page) = unsafe { PageInfo::get_page(page_info) } {
451                 // SAFETY: The pointer is valid, and it's the right shrinker.
452                 unsafe { PageInfo::list_lru_add(page_info, page.nid(), self.shrinker) };
453             }
454         }
455     }
456 
457     /// Helper for reading or writing to a range of bytes that may overlap with several pages.
458     ///
459     /// # Safety
460     ///
461     /// All pages touched by this operation must be in use for the duration of this call.
462     unsafe fn iterate<T>(&self, mut offset: usize, mut size: usize, mut cb: T) -> Result
463     where
464         T: FnMut(&Page, usize, usize) -> Result,
465     {
466         if size == 0 {
467             return Ok(());
468         }
469 
470         let (pages, num_pages) = {
471             let inner = self.lock.lock();
472             (inner.pages, inner.size)
473         };
474         let num_bytes = num_pages << PAGE_SHIFT;
475 
476         // Check that the request is within the buffer.
477         if offset.checked_add(size).ok_or(EFAULT)? > num_bytes {
478             return Err(EFAULT);
479         }
480 
481         let mut page_index = offset >> PAGE_SHIFT;
482         offset &= PAGE_SIZE - 1;
483         while size > 0 {
484             let available = usize::min(size, PAGE_SIZE - offset);
485             // SAFETY: The pointer is in bounds.
486             let page_info = unsafe { pages.add(page_index) };
487             // SAFETY: The caller guarantees that this page is in the "in use" state for the
488             // duration of this call to `iterate`, so nobody will change the page.
489             let page = unsafe { PageInfo::get_page(page_info) };
490             if page.is_none() {
491                 pr_warn!("Page is null!");
492             }
493             let page = page.ok_or(EFAULT)?;
494             cb(page, offset, available)?;
495             size -= available;
496             page_index += 1;
497             offset = 0;
498         }
499         Ok(())
500     }
501 
502     /// Copy from userspace into this page range.
503     ///
504     /// # Safety
505     ///
506     /// All pages touched by this operation must be in use for the duration of this call.
507     pub(crate) unsafe fn copy_from_user_slice(
508         &self,
509         reader: &mut UserSliceReader,
510         offset: usize,
511         size: usize,
512     ) -> Result {
513         // SAFETY: `self.iterate` has the same safety requirements as `copy_from_user_slice`.
514         unsafe {
515             self.iterate(offset, size, |page, offset, to_copy| {
516                 page.copy_from_user_slice_raw(reader, offset, to_copy)
517             })
518         }
519     }
520 
521     /// Copy from this page range into kernel space.
522     ///
523     /// # Safety
524     ///
525     /// All pages touched by this operation must be in use for the duration of this call.
526     pub(crate) unsafe fn read<T: FromBytes>(&self, offset: usize) -> Result<T> {
527         let mut out = MaybeUninit::<T>::uninit();
528         let mut out_offset = 0;
529         // SAFETY: `self.iterate` has the same safety requirements as `read`.
530         unsafe {
531             self.iterate(offset, size_of::<T>(), |page, offset, to_copy| {
532                 // SAFETY: The sum of `offset` and `to_copy` is bounded by the size of T.
533                 let obj_ptr = (out.as_mut_ptr() as *mut u8).add(out_offset);
534                 // SAFETY: The pointer points is in-bounds of the `out` variable, so it is valid.
535                 page.read_raw(obj_ptr, offset, to_copy)?;
536                 out_offset += to_copy;
537                 Ok(())
538             })?;
539         }
540         // SAFETY: We just initialised the data.
541         Ok(unsafe { out.assume_init() })
542     }
543 
544     /// Copy from kernel space into this page range.
545     ///
546     /// # Safety
547     ///
548     /// All pages touched by this operation must be in use for the duration of this call.
549     pub(crate) unsafe fn write<T: ?Sized>(&self, offset: usize, obj: &T) -> Result {
550         let mut obj_offset = 0;
551         // SAFETY: `self.iterate` has the same safety requirements as `write`.
552         unsafe {
553             self.iterate(offset, size_of_val(obj), |page, offset, to_copy| {
554                 // SAFETY: The sum of `offset` and `to_copy` is bounded by the size of T.
555                 let obj_ptr = (obj as *const T as *const u8).add(obj_offset);
556                 // SAFETY: We have a reference to the object, so the pointer is valid.
557                 page.write_raw(obj_ptr, offset, to_copy)?;
558                 obj_offset += to_copy;
559                 Ok(())
560             })
561         }
562     }
563 
564     /// Write zeroes to the given range.
565     ///
566     /// # Safety
567     ///
568     /// All pages touched by this operation must be in use for the duration of this call.
569     pub(crate) unsafe fn fill_zero(&self, offset: usize, size: usize) -> Result {
570         // SAFETY: `self.iterate` has the same safety requirements as `copy_into`.
571         unsafe {
572             self.iterate(offset, size, |page, offset, len| {
573                 page.fill_zero_raw(offset, len)
574             })
575         }
576     }
577 }
578 
579 #[pinned_drop]
580 impl PinnedDrop for ShrinkablePageRange {
581     fn drop(self: Pin<&mut Self>) {
582         let (pages, size) = {
583             let lock = self.lock.lock();
584             (lock.pages, lock.size)
585         };
586 
587         if size == 0 {
588             return;
589         }
590 
591         // Note: This call is also necessary for the safety of `stable_trylock_mm`.
592         let mm_lock = self.mm_lock.lock();
593 
594         // This is the destructor, so unlike the other methods, we only need to worry about races
595         // with the shrinker here. Since we hold the `mm_lock`, we also can't race with the
596         // shrinker, and after this loop, the shrinker will not access any of our pages since we
597         // removed them from the lru list.
598         for i in 0..size {
599             // SAFETY: Loop is in-bounds of the size.
600             let p_ptr = unsafe { pages.add(i) };
601             // SAFETY: No other readers, so we can read.
602             if let Some(p) = unsafe { PageInfo::get_page(p_ptr) } {
603                 // SAFETY: The pointer is valid and it's the right shrinker.
604                 unsafe { PageInfo::list_lru_del(p_ptr, p.nid(), self.shrinker) };
605             }
606         }
607 
608         drop(mm_lock);
609 
610         // SAFETY: `pages` was allocated as an `KVVec<PageInfo>` with capacity `size`. Furthermore,
611         // all `size` elements are initialized. Also, the array is no longer shared with the
612         // shrinker due to the above loop.
613         drop(unsafe { KVVec::from_raw_parts(pages, size, size) });
614     }
615 }
616 
617 /// # Safety
618 /// Called by the shrinker.
619 #[no_mangle]
620 unsafe extern "C" fn rust_shrink_count(
621     shrink: *mut bindings::shrinker,
622     _sc: *mut bindings::shrink_control,
623 ) -> c_ulong {
624     // SAFETY: We can access our own private data.
625     let list_lru = unsafe { (*shrink).private_data.cast::<bindings::list_lru>() };
626     // SAFETY: Accessing the lru list is okay. Just an FFI call.
627     unsafe { bindings::list_lru_count(list_lru) }
628 }
629 
630 /// # Safety
631 /// Called by the shrinker.
632 #[no_mangle]
633 unsafe extern "C" fn rust_shrink_scan(
634     shrink: *mut bindings::shrinker,
635     sc: *mut bindings::shrink_control,
636 ) -> c_ulong {
637     // SAFETY: We can access our own private data.
638     let list_lru = unsafe { (*shrink).private_data.cast::<bindings::list_lru>() };
639     // SAFETY: Caller guarantees that it is safe to read this field.
640     let nr_to_scan = unsafe { (*sc).nr_to_scan };
641     // SAFETY: Accessing the lru list is okay. Just an FFI call.
642     unsafe {
643         bindings::list_lru_walk(
644             list_lru,
645             Some(bindings::rust_shrink_free_page_wrap),
646             ptr::null_mut(),
647             nr_to_scan,
648         )
649     }
650 }
651 
652 const LRU_SKIP: bindings::lru_status = bindings::lru_status_LRU_SKIP;
653 const LRU_REMOVED_ENTRY: bindings::lru_status = bindings::lru_status_LRU_REMOVED_RETRY;
654 
655 /// # Safety
656 /// Called by the shrinker.
657 #[no_mangle]
658 unsafe extern "C" fn rust_shrink_free_page(
659     item: *mut bindings::list_head,
660     lru: *mut bindings::list_lru_one,
661     _cb_arg: *mut c_void,
662 ) -> bindings::lru_status {
663     // Fields that should survive after unlocking the lru lock.
664     let page;
665     let page_index;
666     let mm;
667     let mmap_read;
668     let mm_mutex;
669     let vma_addr;
670 
671     {
672         // CAST: The `list_head` field is first in `PageInfo`.
673         let info = item as *mut PageInfo;
674         // SAFETY: The `range` field of `PageInfo` is immutable.
675         let range = unsafe { &*((*info).range) };
676 
677         mm = match range.mm.mmget_not_zero() {
678             Some(mm) => MmWithUser::into_mmput_async(mm),
679             None => return LRU_SKIP,
680         };
681 
682         mm_mutex = match range.stable_trylock_mm() {
683             Some(guard) => guard,
684             None => return LRU_SKIP,
685         };
686 
687         mmap_read = match mm.mmap_read_trylock() {
688             Some(guard) => guard,
689             None => return LRU_SKIP,
690         };
691 
692         // We can't lock it normally here, since we hold the lru lock.
693         let inner = match range.lock.try_lock() {
694             Some(inner) => inner,
695             None => return LRU_SKIP,
696         };
697 
698         // SAFETY: The item is in this lru list, so it's okay to remove it.
699         unsafe { bindings::list_lru_isolate(lru, item) };
700 
701         // SAFETY: Both pointers are in bounds of the same allocation.
702         page_index = unsafe { info.offset_from(inner.pages) } as usize;
703 
704         // SAFETY: We hold the spinlock, so we can take the page.
705         //
706         // This sets the page pointer to zero before we unmap it from the vma. However, we call
707         // `zap_page_range` before we release the mmap lock, so `use_page_slow` will not be able to
708         // insert a new page until after our call to `zap_page_range`.
709         page = unsafe { PageInfo::take_page(info) };
710         vma_addr = inner.vma_addr;
711 
712         // From this point on, we don't access this PageInfo or ShrinkablePageRange again, because
713         // they can be freed at any point after we unlock `lru_lock`. This is with the exception of
714         // `mm_mutex` which is kept alive by holding the lock.
715     }
716 
717     // SAFETY: The lru lock is locked when this method is called.
718     unsafe { bindings::spin_unlock(&raw mut (*lru).lock) };
719 
720     if let Some(vma) = mmap_read.vma_lookup(vma_addr) {
721         let user_page_addr = vma_addr + (page_index << PAGE_SHIFT);
722         vma.zap_page_range_single(user_page_addr, PAGE_SIZE);
723     }
724 
725     drop(mmap_read);
726     drop(mm_mutex);
727     drop(mm);
728     drop(page);
729 
730     // SAFETY: We just unlocked the lru lock, but it should be locked when we return.
731     unsafe { bindings::spin_lock(&raw mut (*lru).lock) };
732 
733     LRU_REMOVED_ENTRY
734 }
735