On Fri, Jan 21, 2022 at 10:04:45AM +0100, David Hildenbrand wrote: > On 21.01.22 09:59, Peter Zijlstra wrote: > > However, I'm not quite sure what fork() does with pages that have a pin. > > We COW the anon pages always, and we protect against concurrent GUP > using the > * mmap_lock in exclusive mode for ordinary GUP > * mm->write_protect_seq for GUP-fast Right, but neither the mmap_sem nor the write_protect_seq help anything at all vs already extant page pins. But I just found copy_present_page()'s page_needs_cow_for_dma(), which I think deals with exactly that case, it avoids doing CoW on pinned pages and instead feeds the child a full copy while keeping the pinned page in the original process. > > Naively, a page that has async DMA activity should not be CoW'ed, or if > > it is, care must be taken to ensure the original pages stays in the > > original process, but I realize that's somewhat hard. > > That's precisely what I'm working on fixing ... and yes, it's hard. > > Let me know if you need any other information, I've spent way too much > time on this than I ever panned. So let me try and get this right: - GUP post-fork breaks CoW for FOLL_WRITE/FOLL_PIN, without either there's a problem where one task might observe changes by another. - GUP pre-fork prevents CoW and does a full copy. And that all mostly works, except for a fair amount of 'fun' cases?