Following changes will implement fine-grained range locks for the MM locking API, using a data structure to represent the existing locks, and a mutex to protect that data structure. As a result, we need to prepare for the possibility that unlocking a memory range may need to sleep when acquiring that mutex. Signed-off-by: Michel Lespinasse <walken@xxxxxxxxxx> --- kernel/bpf/stackmap.c | 6 +++++- kernel/exit.c | 2 +- mm/mm_lock_rwsem_checked.c | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git kernel/bpf/stackmap.c kernel/bpf/stackmap.c index ba2399ce00e4..0f483abeb94c 100644 --- kernel/bpf/stackmap.c +++ kernel/bpf/stackmap.c @@ -308,8 +308,12 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs, * * Same fallback is used for kernel stack (!user) on a stackmap * with build_id. + * + * FIXME - currently disabling the build_id lookup feature + * as mm_read_range_unlock() may block, which is not always + * possible to do here. */ - if (!user || !current || !current->mm || irq_work_busy || + if (true || !user || !current || !current->mm || irq_work_busy || !mm_read_range_trylock(current->mm, mm_range_ptr)) { /* cannot access current->mm, fall back to ips */ for (i = 0; i < trace_nr; i++) { diff --git kernel/exit.c kernel/exit.c index 9a0b72562adb..60ec6efb4e2c 100644 --- kernel/exit.c +++ kernel/exit.c @@ -478,9 +478,9 @@ static void exit_mm(void) /* more a memory barrier than a real lock */ task_lock(current); current->mm = NULL; - mm_read_unlock(mm); enter_lazy_tlb(mm, current); task_unlock(current); + mm_read_unlock(mm); mm_update_next_owner(mm); mmput(mm); if (test_thread_flag(TIF_MEMDIE)) diff --git mm/mm_lock_rwsem_checked.c mm/mm_lock_rwsem_checked.c index 3551deb85e3d..e45d1a598c87 100644 --- mm/mm_lock_rwsem_checked.c +++ mm/mm_lock_rwsem_checked.c @@ -61,6 +61,7 @@ EXPORT_SYMBOL(mm_write_range_trylock); void mm_write_range_unlock(struct mm_struct *mm, struct mm_lock_range *range) { + might_sleep(); if (range->mm != mm) mm_lock_dump("mm_write_range_unlock"); range->mm = NULL; @@ -113,6 +114,7 @@ EXPORT_SYMBOL(mm_read_range_trylock); void mm_read_range_unlock(struct mm_struct *mm, struct mm_lock_range *range) { + might_sleep(); if (range->mm != mm) mm_lock_dump("mm_read_range_unlock"); range->mm = NULL; @@ -123,6 +125,7 @@ EXPORT_SYMBOL(mm_read_range_unlock); void mm_read_range_unlock_non_owner(struct mm_struct *mm, struct mm_lock_range *range) { + might_sleep(); if (range->mm != mm) mm_lock_dump("mm_read_range_unlock_non_owner"); range->mm = NULL; -- 2.25.0.341.g760bfbb309-goog