Ok, so here's a slightly different approach. It still makes the FOLL_MLOCK be unconditional in the mlock path, but it really just pushes down the - gup_flags = FOLL_TOUCH; + gup_flags = FOLL_TOUCH | FOLL_MLOCK; ... - if (vma->vm_flags & VM_LOCKED) - gup_flags |= FOLL_MLOCK; from __mlock_vma_pages_range(), and moves the conditional into 'follow_page()' (which is the only _user_ of that flag) instead: - if (flags & FOLL_MLOCK) { + if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) { so semantically this changes nothing at all. But now, because __get_user_pages() can look at FOLL_MLOCK to see that it's a mlock access, we can do that whole "skip stack guard page" based on that flag: - if (!pages && stack_guard_page(vma, start)) + if ((gup_flags & FOLL_MLOCK) && stack_guard_page(vma, start)) which means that other uses will try to page in the stack guard page. I seriously considered making that "skip stack guard page" and the "mlock lookup" be two separate bits, because conceptually they are really pretty independent, but right now the only _users_ seem to be tied together, so I kept it as one single bit (FOLL_MLOCK). But as far as I can tell, the attached patch is 100% equivalent to what we do now, except for that "skip stack guard pages only for mlock" change. Comments? I like this patch because it seems to make the logic more straightforward. But somebody else should double-check my logic. Linus