[PATCH] slightly reworked

From: Lorenzo Stoakes

Date: Fri Apr 10 2026 - 09:37:23 EST


---
mm/madvise.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/mm/madvise.c b/mm/madvise.c
index 69708e953cf5..4af0565809f2 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -269,9 +269,8 @@ static void shmem_swapin_range(struct vm_area_struct *vma,
}
#endif /* CONFIG_SWAP */

-static void mark_mmap_lock_dropped(struct madvise_behavior *madv_behavior)
+static void mark_lock_dropped(struct madvise_behavior *madv_behavior)
{
- VM_WARN_ON_ONCE(madv_behavior->lock_mode == MADVISE_VMA_READ_LOCK);
madv_behavior->lock_dropped = true;
}

@@ -315,7 +314,7 @@ static long madvise_willneed(struct madvise_behavior *madv_behavior)
* vma's reference to the file) can go away as soon as we drop
* mmap_lock.
*/
- mark_mmap_lock_dropped(madv_behavior);
+ mark_lock_dropped(madv_behavior);
get_file(file);
offset = (loff_t)(start - vma->vm_start)
+ ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
@@ -909,7 +908,7 @@ static long madvise_dontneed_free(struct madvise_behavior *madv_behavior)
if (!userfaultfd_remove(madv_behavior->vma, range->start, range->end)) {
struct vm_area_struct *vma;

- mark_mmap_lock_dropped(madv_behavior);
+ mark_lock_dropped(madv_behavior);
mmap_read_lock(mm);
madv_behavior->vma = vma = vma_lookup(mm, range->start);
if (!vma)
@@ -1005,10 +1004,9 @@ static long madvise_remove(struct madvise_behavior *madv_behavior)
struct file *f;
struct mm_struct *mm = madv_behavior->mm;
struct vm_area_struct *vma = madv_behavior->vma;
- unsigned long start = madv_behavior->range.start;
- unsigned long end = madv_behavior->range.end;
-
- mark_mmap_lock_dropped(madv_behavior);
+ const unsigned long start = madv_behavior->range.start;
+ const unsigned long end = madv_behavior->range.end;
+ const bool vma_locked = madv_behavior->lock_mode == MADVISE_VMA_READ_LOCK;

if (vma->vm_flags & VM_LOCKED)
return -EINVAL;
@@ -1029,18 +1027,20 @@ static long madvise_remove(struct madvise_behavior *madv_behavior)
* Filesystem's fallocate may need to take i_rwsem. We need to
* explicitly grab a reference because the vma (and hence the
* vma's reference to the file) can go away as soon as we drop
- * mmap_lock.
+ * its lock.
*/
get_file(f);
- if (userfaultfd_remove(vma, start, end)) {
- /* mmap_lock was not released by userfaultfd_remove() */
+ mark_lock_dropped(madv_behavior);
+ if (vma_locked)
+ vma_end_read(vma);
+ else if (userfaultfd_remove(vma, start, end)) /* uffd didn't drop? */
mmap_read_unlock(mm);
- }
error = vfs_fallocate(f,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
offset, end - start);
fput(f);
- mmap_read_lock(mm);
+ if (!vma_locked)
+ mmap_read_lock(mm);
return error;
}

@@ -1677,7 +1677,8 @@ int madvise_walk_vmas(struct madvise_behavior *madv_behavior)
if (madv_behavior->lock_mode == MADVISE_VMA_READ_LOCK &&
try_vma_read_lock(madv_behavior)) {
error = madvise_vma_behavior(madv_behavior);
- vma_end_read(madv_behavior->vma);
+ if (!madv_behavior->lock_dropped)
+ vma_end_read(madv_behavior->vma);
return error;
}

@@ -1746,7 +1747,6 @@ static enum madvise_lock_mode get_lock_mode(struct madvise_behavior *madv_behavi
return MADVISE_NO_LOCK;

switch (madv_behavior->behavior) {
- case MADV_REMOVE:
case MADV_WILLNEED:
case MADV_COLD:
case MADV_PAGEOUT:
@@ -1754,6 +1754,7 @@ static enum madvise_lock_mode get_lock_mode(struct madvise_behavior *madv_behavi
case MADV_POPULATE_WRITE:
case MADV_COLLAPSE:
return MADVISE_MMAP_READ_LOCK;
+ case MADV_REMOVE:
case MADV_GUARD_INSTALL:
case MADV_GUARD_REMOVE:
case MADV_DONTNEED:
--
2.53.0