Re: [QUESTION] mmap lock in khugepaged

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




+the list and Zi Yan.

On 28/11/24 5:04 pm, David Hildenbrand wrote:


Maybe, we'd have to do the isolation+copy under the PMD lock. And
currently, we have to drop the PMD lock in order to have the
pte_offset_map_lock() work IIRC.


Is there a problem in holding two page table locks simultaneously?

Depending on CONFIG_SPLIT_PTE_PTLOCKS, it might not even be two locks (I assume we could have such configs with khugepaged).

Not sure if there could be an issue with lock inversion.

So I suspect this no not be 100% trivial :)




Most importantly, the copy that currently runs under no spinlocks
would now run under spinlock. Up to 512 MiB on arm64 64K, not sure if
that can be a problem ... we currently seem to take care of that

But we already are taking mmap_write_lock(), so that should not matter?

We are dealing with a spinlock vs. a rwsem.

We usually want to avoid holding spinlocks for an excessive amount of time, because all other CPUs waiting for that lock will ... spin with preemption disabled instead of rescheduling and doing something useful.


Ah okay.



Further, without CONFIG_SPLIT_PMD_PTLOCKS, in fact everybody who wnats to take a PMD lock in that process would be spinning on the same PMD lock :)


I mean, if we can get rid of the mmap exclusive lock, then the copying
would still be a bottleneck, and all fault handlers will back off, but

I'm trying to digest it once again, but I'm afraid I don't see how fault handlers will back off.

Won't they either see pmd_none(), to then either call pte_alloc_one() where they would spin on the PMD lock, or try allocating a PMD THP to insert it, and then spin on the PMD lock, to figure out later that it was all in vain?

Ya that's what I meant when I said "back off", sorry I wasn't clear, I didn't mean VM_FAULT_FALLBACK/RETRY or something...yes, the work will be in vain and the MMU will refault...


Thinking about it, I am also not sure if most other code can deal with temporary pmd_none(). These don't necessarily take the PMD lock, because "why would they" right now.

See walk_pmd_range() as one example, if it spots pmd_none() it assumes "there really is nothing" without checking the PMD lock.

As a more concrete example, assume someone calls MADV_DONTNEED and we end up in zap_pmd_range(). If we assume "pmd_none() == really nothing" we'll skip that entry without getting the PMD lock involved. That would mean that you would be breaking MADV_DONTNEED if you managed to collapse or not -- memory would not get discarded.

This is a real problem with anonymous memory.

Yes, I thought of different locking fashions but the problem seems to be that any pagetable walker will choose an action path according to the value
it sees.


Unless I am missing something it's all very tricky and there might be a lot of such code that assumes "if I hold a mmap lock / VMA lock in read mode, pmd_none() means there is nothing even without holding the PMD lock when checking".

Yes, I was betting on the fact that, if the code assumes that pmd_none() means there is nothing, eventually when it will take the PMD lock to write to it, it will check whether the PMD changed, and back off. I wasn't aware of the MADV_DONTNEED thingy, thanks.


at least processes will be able to mmap() and do stuff with their VMAs,
and I would guess that this is worth optimizing...

It would certainly be interesting to get rid of the mmap lock in write mode here, but it's all rater tricky (and the code has rather nasty hidden implications).


pte = pte_offset_map_lock(mm, &_pmd, address, &pte_ptl);
if (pte) {
     ...
     spun_unlock(pte);
} ...

result = __collapse_huge_page_copy(...);
pte_unmap(pte);


Deep in __collapse_huge_page_copy() we seem to re-rake the PTL lock.
No-split-spinlock confiogs might be problematic ...

Could you elaborate a little? I haven't read about the older config...

See above regarding CONFIG_SPLIT_PTE_PTLOCKS and friends.



I recall that for shmem that's "easier", because we don't have to
reinstall a PMD immediately, we cna be sure that the page table is
kept empty/unmodified, ...



All in all, the general solution seems to be that, if I can take all pagetable walkers into an invalid state and make them backoff, then I am safe. For example, we do not zero out the PMD, we take the pte PTL, we do stuff, then instead of setting the PTEs to zero, we set it to a universal invalid state upon which no pagetable walker can take an action; an instance of that can be to set the PTE to a swap entry such that the fault handler ends up in do_swap_page() ->print_bad_pte(). So now we can take the PMD lock (in fact we don't need it since any pagetable walking is rendered useless) and populate the PMD to resume the new pagetable walking. Another *ridiculous* idea may be to remember the PGD we came from and nuke it (but I guess there is an alternate path for that in walk_pgd_range() and so on?)








[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux