Re: Suppress pte soft-dirty bit with UFFDIO_COPY?
Kyle Huey <[email protected]>
| Newsgroups | dev.linux.lists.criu,org.kernel.vger.linux-kernel,org.kvack.linux-mm |
|---|---|
| Message-ID | <CAP045ArAVtR6_Y-WWcqpB54Z+fwNYSWSyrTZKjctocwA0sK5eg@mail.gmail.com> |
On Mon, May 5, 2025 at 1:05 PM Peter Xu <[email protected]> wrote: > > Hi, Kyle, > > On Mon, May 05, 2025 at 09:37:01AM -0700, Kyle Huey wrote: > > tl;dr I'd like to add UFFDIO_COPY_MODE_DONTSOFTDIRTY that does not add > > the _PAGE_SOFT_DIRTY bit to the relevant pte flags. Any > > thoughts/objections? > > > > The kernel has a "soft-dirty" bit on ptes which tracks if they've been > > written to since the last time /proc/pid/clear_refs was used to clear > > the soft-dirty bit. CRIU uses this to track which pages have been > > modified since a previous checkpoint and reduce the size of the > > checkpoints taken. I would like to use this in my debugger[0] to track > > which pages a program function dirties when that function is invoked > > from the debugger. > > > > However, the runtime environment for this function is rather unusual. > > In my debugger, the process being debugged doesn't actually exist > > while it's being debugged. Instead, we have a database of all program > > state (including registers and memory values) from when the process > > was executed. It's in some sense a giant core dump that spans multiple > > points in time. To execute a program function from the debugger we > > rematerialize the program state at the desired point in time from our > > database. > > > > For performance reasons, we fill in the memory lazily[1] via > > userfaultfd. This makes it difficult to use the soft-dirty bit to > > track the writes the function triggers, because UFFDIO_COPY (and > > friends) mark every page they touch as soft-dirty. Because we have the > > canonical source of truth for the pages we materialize via UFFDIO_COPY > > we're only interested in what happens after the userfaultfd operation. > > > > Clearing the soft-dirty bit is complicated by two things: > > 1. There's no way to clear the soft-dirty bit on a single pte, so > > instead we have to clear the soft-dirty bits for the entire process. > > That requires us to process all the soft-dirty bits on every other pte > > immediately to avoid data loss. > > 2. We need to clear the soft-dirty bits after the userfaultfd > > operation, but in order to avoid racing with the task that triggered > > the page fault we have to do a non-waking copy, then clear the bits, > > and then separately wake up the task. > > > > To work around all of this, we currently have a 4 step process: > > 1. Read /proc/pid/pagemap and note all ptes that are soft-dirty. > > 2. Do the UFFDIO_COPY with UFFDIO_COPY_MODE_DONTWAKE. > > 3. Write to /proc/pid/clear_refs to clear soft-dirty bits across the process. > > 4. Do a UFFDIO_WAKE. > > > > The overhead of all of this (particularly step 1) is a millisecond or > > two *per page* that we lazily materialize, and while that's not > > crippling for our purposes, it is rather undesirable. What I would > > like to have instead is a UFFDIO_COPY mode that leaves the soft-dirty > > bit unchanged, i.e. a UFFDIO_COPY_MODE_DONTSOFTDIRTY. Since we clear > > all the soft-dirty bits once after setting up all the mmaps in the > > process the relevant ptes would then "just do the right thing" from > > our perspective. > > > > But I do want to get some feedback on this before I spend time writing > > any code. Is there a reason not to do this? Or an alternate way to > > achieve the same goal? > > Have you looked at the wr-protect mode, and UFFDIO_COPY_MODE_WP for _COPY? > > If sync fault is a perf concern for frequent writes, just to mention at > least latest Linux also supports async tracking (UFFD_FEATURE_WP_ASYNC), > which is almost exactly soft dirty bits to me, though it solves a few > issues it has on e.g. false positives over vma merging and swapping, or > like you said missing of finer granule reset mechanisms. > > Maybe you also want to have a look at the pagemap ioctl introduced some > time ago ("Pagemap Scan IOCTL", which, IIRC was trying to use uffd-wp in > soft-dirty-like way): > > https://www.kernel.org/doc/Documentation/admin-guide/mm/pagemap.rst Thanks. This is all very helpful and I think I can construct what I need out of these building blocks. - Kyle > > If this is generally sensible, then a couple questions: > > 1. Do I need a UFFD_FEATURE flag for this, or is it enough for a > > program to be able to detect the existence of a > > UFFDIO_COPY_MODE_DONTSOFTDIRTY by whether the ioctl accepts the flag > > or returns EINVAL? I would tend to think the latter. > > The latter requires all the setups needed, and an useless ioctl to probe. > Not a huge issue, but since userfaultfd is extensible, a feature flag might > be better as long as a new feature is well defined. > > > 2. Should I add this mode for the other UFFDIO variants (ZEROPAGE, > > MOVE, etc) at the same time even if I don't have any use for them? > > Probably not. I don't see a need to implement something just to make the > API look good.. If any chunk of code in the Linux kernel has no plan to be > used, we should probably not adding them since the start.. > > Thanks, > > -- > Peter Xu >