vma_start_read can successfully lock a detached VMA relying on its caller to check for vma->detached. Change vma_start_read to include that check and fail if the VMA got detached. Suggested-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxx> Signed-off-by: Suren Baghdasaryan <surenb@xxxxxxxxxx> --- include/linux/mm.h | 4 ++-- include/linux/vm_event_item.h | 1 - mm/memory.c | 10 +--------- mm/vmstat.c | 1 - 4 files changed, 3 insertions(+), 13 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 8410da79c570..74e3033c9fc2 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -651,8 +651,8 @@ static inline bool vma_start_read(struct vm_area_struct *vma) if (unlikely(down_read_trylock(&vma->vm_lock->lock) == 0)) return false; - /* Fail if VMA was write-locked after we checked it earlier */ - if (unlikely(vm_lock_seq != READ_ONCE(vma->vm_lock_seq))) { + /* Fail if VMA is detached or was write-locked after we checked it earlier */ + if (unlikely(vma->detached || vm_lock_seq != READ_ONCE(vma->vm_lock_seq))) { up_read(&vma->vm_lock->lock); return false; } diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h index 8abfa1240040..e741098954ff 100644 --- a/include/linux/vm_event_item.h +++ b/include/linux/vm_event_item.h @@ -154,7 +154,6 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, VMA_LOCK_SUCCESS, VMA_LOCK_ABORT, VMA_LOCK_RETRY, - VMA_LOCK_MISS, #endif NR_VM_EVENT_ITEMS }; diff --git a/mm/memory.c b/mm/memory.c index f69fbc251198..bd666fa20748 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -5275,7 +5275,7 @@ struct vm_area_struct *lock_vma_under_rcu(struct mm_struct *mm, struct vm_area_struct *vma; rcu_read_lock(); -retry: + vma = mas_walk(&mas); if (!vma) goto inval; @@ -5306,14 +5306,6 @@ struct vm_area_struct *lock_vma_under_rcu(struct mm_struct *mm, goto inval; } - /* Check if the VMA got isolated after we found it */ - if (vma->detached) { - vma_end_read(vma); - count_vm_vma_lock_event(VMA_LOCK_MISS); - /* The area was replaced with another one */ - goto retry; - } - rcu_read_unlock(); return vma; inval: diff --git a/mm/vmstat.c b/mm/vmstat.c index c28046371b45..5d6acdb1b611 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1403,7 +1403,6 @@ const char * const vmstat_text[] = { "vma_lock_success", "vma_lock_abort", "vma_lock_retry", - "vma_lock_miss", #endif #endif /* CONFIG_VM_EVENT_COUNTERS || CONFIG_MEMCG */ }; -- 2.41.0.162.gfafddb0af9-goog