That idea works when the page is swapped in, but I don't think you're accounting for the case where the only copy of the contents is in the file that's backing the mapped region.
back
1 comments
I'm sure we're boring everybody, but yes, I am accounting for the case where the only copy is in the file. The OS knows that there are live references to the non-resident, file-backed page, marked as such in one or more process page tables. For any change to happen to the actual page on disk, from any program in user-space or not, and even if they think they're using write(2) rather than mmap, under the covers the OS does the moral equivalent of mapping the page, and the modification happens in memory, and the page eventually gets written back to the physical disk, but it's all unified between write() and mmap() pages, and all the wonderful semantics of mmap and sharing happen here as well. I'm not sure that this goes all the way back to the original implementation of mmap(), but as you point out, it's a pretty useless observation given the unfortunate backsliding in the Posix specification (perhaps some vendor didn't manage to get up to speed on the unified page scheme?)
All of this relies on the rest of the system playing well and only using POSIX rename() to replace files. So to do it safely, you need to make a swap file copy (a'la vim) to do the paginated mmap() + page-replacement cache on the swap file.
However, often times you also need to do encoding conversion, and you can do this at the same time as the copy to the swap file.
If you detect you have btrfs/xfs w/ reflink support, and no encoding change is necessary, you can cheat and just do a CoW of the underlying block ranges and let the FS garbage collect it afterwards (just unlink() your reflink copy immediately).
Another convenient thing you can do with the swap file, is use the tail of it for a write ahead log of the changes in a piecetable and crash recovery.
Believe me, I'm not bored.