mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
binder: remove mmap_lock fallback
Previously, the per-VMA locking could fail in the face of writers which necessitate a fallback to mmap_lock. The new vma_start_read_unlocked() will wait for writers instead of failing. Use the new helper. Wait for writers. Remove the fallback to mmap_lock. Link: https://lore.kernel.org/20260831203056.838265-5-surenb@google.com Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Suren Baghdasaryan <surenb@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Shakeel Butt <shakeel.butt@linux.dev> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Todd Kjos <tkjos@android.com> Cc: Christian Brauner <christian@brauner.io> Cc: Carlos Llamas <cmllamas@google.com> Cc: David S. Miller <davem@davemloft.net> Cc: David Ahern <dsahern@kernel.org> Cc: Arve Hjønnevåg <arve@android.com> Cc: David Hildenbrand (Arm) <david@kernel.org>
This commit is contained in:
parent
d96082aa35
commit
a3bbbd68bf
|
|
@ -439,22 +439,9 @@ unsafe fn use_page_slow(&self, i: usize) -> Result<()> {
|
|||
// workqueue.
|
||||
let mm = MmWithUser::into_mmput_async(self.mm.mmget_not_zero().ok_or(ESRCH)?);
|
||||
{
|
||||
let vma_read;
|
||||
let mmap_read;
|
||||
let vma = if let Some(ret) = mm.lock_vma_under_rcu(vma_addr) {
|
||||
vma_read = ret;
|
||||
check_vma(&vma_read, self)
|
||||
} else {
|
||||
mmap_read = mm.mmap_read_lock();
|
||||
mmap_read
|
||||
.vma_lookup(vma_addr)
|
||||
.and_then(|vma| check_vma(vma, self))
|
||||
};
|
||||
|
||||
match vma {
|
||||
Some(vma) => vma.vm_insert_page(user_page_addr, &new_page)?,
|
||||
None => return Err(ESRCH),
|
||||
}
|
||||
let vma_read_guard = mm.vma_start_read_unlocked(vma_addr).ok_or(ESRCH)?;
|
||||
let vma = check_vma(&vma_read_guard, self).ok_or(ESRCH)?;
|
||||
vma.vm_insert_page(user_page_addr, &new_page)?;
|
||||
}
|
||||
|
||||
let inner = self.lock.lock();
|
||||
|
|
|
|||
|
|
@ -259,21 +259,14 @@ static int binder_page_insert(struct binder_alloc *alloc,
|
|||
struct vm_area_struct *vma;
|
||||
int ret = -ESRCH;
|
||||
|
||||
/* attempt per-vma lock first */
|
||||
vma = lock_vma_under_rcu(mm, addr);
|
||||
if (vma) {
|
||||
if (binder_alloc_is_mapped(alloc))
|
||||
ret = vm_insert_page(vma, addr, page);
|
||||
vma_end_read(vma);
|
||||
vma = vma_start_read_unlocked(mm, addr);
|
||||
if (!vma)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* fall back to mmap_lock */
|
||||
mmap_read_lock(mm);
|
||||
vma = vma_lookup(mm, addr);
|
||||
if (vma && binder_alloc_is_mapped(alloc))
|
||||
if (binder_alloc_is_mapped(alloc))
|
||||
ret = vm_insert_page(vma, addr, page);
|
||||
mmap_read_unlock(mm);
|
||||
|
||||
vma_end_read(vma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,6 +186,34 @@ pub fn lock_vma_under_rcu(&self, vma_addr: usize) -> Option<VmaReadGuard<'_>> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Find the VMA covering 'address' and read-lock it.
|
||||
///
|
||||
/// The fast path does not take mmap_lock. Waits for writers to finish if the
|
||||
/// VMA is being modified by taking mmap_lock.
|
||||
/// Use when mmap_lock is not held, otherwise use vma_start_read_locked().
|
||||
/// Nothing prevents VMAs being unmapped/mapped before or after the VMA is
|
||||
/// looked up, if a stronger guarantee is required, take an mmap_lock.
|
||||
///
|
||||
/// Return: If a VMA exists which spans @address, return that VMA, read-locked.
|
||||
/// If no VMA is mapped there or, very unlikely, a reference count overflow
|
||||
/// occurred, return NULL.
|
||||
#[inline]
|
||||
pub fn vma_start_read_unlocked(&self, vma_addr: usize) -> Option<VmaReadGuard<'_>> {
|
||||
// SAFETY: We may invoke `vma_start_read_unlocked` because we know this `mm` has non-zero
|
||||
// `mm_users`.
|
||||
let vma = unsafe { bindings::vma_start_read_unlocked(self.as_raw(), vma_addr) };
|
||||
if vma.is_null() {
|
||||
return None;
|
||||
}
|
||||
// INVARIANT: We just acquired the VMA read lock.
|
||||
Some(VmaReadGuard {
|
||||
// SAFETY: If `vma_start_read_unlocked` returns a non-null ptr, then it points at a
|
||||
// valid vma. The vma is stable for as long as the vma read lock is held.
|
||||
vma: unsafe { VmaRef::from_raw(vma) },
|
||||
_nts: NotThreadSafe,
|
||||
})
|
||||
}
|
||||
|
||||
/// Lock the mmap read lock.
|
||||
#[inline]
|
||||
pub fn mmap_read_lock(&self) -> MmapReadGuard<'_> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user