From 49c322d5e62ee3722b3a325862b081b079bbc896 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Thu, 3 Dec 2020 19:38:39 +0800 Subject: [PATCH 2447/2944] alinux: mm: Fix the vma merge warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix #31645768 When enabling the CONFIG_DEBUG_VM, and set the /proc/unevictable/add_pid or del_pid to lock/unlock one thread's vma, we can always get below vma merging warning. The reason is we did not set a valid previous vma (always use the first vma in mmap list) to check if we can merge the current vma with the predecessor to lock or unlock one vma, which will break the vma merge rules in vma_merge(). Thus we can set the correct prev vma when trying to lock and unlock one vma to remove below warning, moreover the other benefit is we can try to merge contious vma as much as possile if they can be merged. [ 77.648124] WARNING: CPU: 0 PID: 182 at mm/mmap.c:1145 vma_merge+0x39d/0xcc0   [ 77.649815] Modules linked in:   [ 77.650565] CPU: 0 PID: 182 Comm: kworker/0:3 Not tainted 4.19.91 #1   [ 77.651771] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011   [ 77.652877] Workqueue: events execute_vm_lock   [ 77.653728] RIP: 0010:vma_merge+0x39d/0xcc0   [ 77.657777] RSP: 0018:ffff88811159fba0 EFLAGS: 00010282   [ 77.658758] RAX: 0000000000000024 RBX: 0000000000000000 RCX: ffffffff81f3ff0c   [ 77.660051] RDX: 0000000000000000 RSI: ffffffff8132297e RDI: ffff88811a026f2c   [ 77.661392] RBP: ffff888116dc9128 R08: ffffed10234051d9 R09: ffffed10234051d8   [ 77.662941] R10: 1ffff11022dc3fd4 R11: ffffed10234051d9 R12: ffff888116dc9128   [ 77.664233] R13: 00007fca96efd000 R14: 00007fca96f01000 R15: 0000000000082075   [ 77.665544] FS: 0000000000000000(0000) GS:ffff88811a000000(0000) knlGS:0000000000000000   [ 77.667015] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033   [ 77.668098] CR2: 00007f9c9640ee70 CR3: 0000000003c14001 CR4: 00000000003606f0   [ 77.669478] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000   [ 77.671302] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400   [ 77.673140] Call Trace:   [ 77.674202] mlock_fixup+0x29e/0x590   [ 77.675501] execute_vm_lock+0x665/0xb20   [ 77.676786] ? proc_read_add_pid+0x800/0x800   [ 77.678211] process_one_work+0x8d6/0x14f0   [ 77.679563] ? wq_pool_ids_show+0x2a0/0x2a0   [ 77.680939] worker_thread+0x9b/0xd30   [ 77.682233] ? rescuer_thread+0xbb0/0xbb0   [ 77.683536] kthread+0x300/0x400   [ 77.684676] ? kthread_create_worker_on_cpu+0x100/0x100   [ 77.686210] ret_from_fork+0x24/0x30   [ 77.687452] irq event stamp: 13428   [ 77.688672] hardirqs last enabled at (13427): [] console_unlock+0x87a/0xbe0   [ 77.691180] hardirqs last disabled at (13428): [] trace_hardirqs_off_thunk+0x1a/0x1c   [ 77.693861] softirqs last enabled at (13424): [] __do_softirq+0x644/0x87b   [ 77.696400] softirqs last disabled at (13413): [] irq_exit+0x22a/0x250 Fixes: 7e96dda3f5d9 ("alios: mm: Pin code section of process in memory") Reported-by: Abaci Signed-off-by: Baolin Wang Reviewed-by: Alex Shi --- mm/unevictable.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mm/unevictable.c b/mm/unevictable.c index 4e5d296..2f0e613 100644 --- a/mm/unevictable.c +++ b/mm/unevictable.c @@ -93,17 +93,19 @@ static void __evict_pid(struct evict_pid_entry *pid) mm = get_task_mm(tsk); if (mm) { if (!(mm->def_flags & VM_LOCKED)) { - struct vm_area_struct *vma, *prev; + struct vm_area_struct *vma, *next, *prev = NULL; vm_flags_t flag; down_write(&mm->mmap_sem); - for (vma = mm->mmap; vma; vma = vma->vm_next) { + for (vma = mm->mmap; vma; prev = vma, vma = next) { + next = vma->vm_next; if (vma->vm_file && (vma->vm_flags & VM_EXEC) && (vma->vm_flags & VM_READ)) { flag = vma->vm_flags & VM_LOCKED_CLEAR_MASK; - prev = NULL; mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, flag); + vma = prev; + next = prev->vm_next; } } up_write(&mm->mmap_sem); @@ -383,17 +385,19 @@ static void execute_vm_lock(struct work_struct *unused) mm = get_task_mm(tsk); if (mm && !(mm->def_flags & VM_LOCKED)) { if (down_write_trylock(&mm->mmap_sem)) { - struct vm_area_struct *vma, *prev; + struct vm_area_struct *vma, *next, *prev = NULL; vm_flags_t flag; - for (vma = mm->mmap; vma; vma = vma->vm_next) { + for (vma = mm->mmap; vma; prev = vma, vma = next) { + next = vma->vm_next; if (vma->vm_file && (vma->vm_flags & VM_EXEC) && (vma->vm_flags & VM_READ)) { flag = vma->vm_flags & VM_LOCKED_CLEAR_MASK; flag |= (VM_LOCKED | VM_LOCKONFAULT); - prev = NULL; mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, flag); + vma = prev; + next = prev->vm_next; } } -- 1.8.3.1