On Mon, Jul 06, 2026 at 05:57:24AM -0700, Usama Arif wrote:
> > @@ -2443,8 +2443,12 @@ static unsigned long pagemap_page_category(struct
> > pagemap_scan_private *p,
> >
> > categories = PAGE_IS_PRESENT;
> >
> > - if (!pte_uffd(pte))
> > - categories |= PAGE_IS_WRITTEN;
> > + if (!pte_uffd(pte)) {
> > + if (userfaultfd_wp(vma))
> > + categories |= PAGE_IS_WRITTEN;
> > + if (userfaultfd_rwp(vma))
> > + categories |= PAGE_IS_ACCESSED;
> > + }
>
> The above is an ABI change for existing PAGEMAP_SCAN users although not
> sure if there is someone that cares. Would below be a better alternative
> to limit the ABI change?
>
> if (!pte_uffd(pte)) {
> if (userfaultfd_rwp(vma))
> categories |= PAGE_IS_ACCESSED;
> else
> categories |= PAGE_IS_WRITTEN;
> }
You're right that it changes what PAGEMAP_SCAN returns outside a
VM_UFFD_WP VMA. I think that is the intent rather than a side effect --
the commit message calls it out explicitly as a UAPI narrowing.
PAGE_IS_WRITTEN is documented as "Page has been written to from the time
it was write protected". Outside a write-protected VMA there is no such
point in time, so the flag has no defined meaning there -- and the
current code sets it unconditionally on every present, non-uffd PTE,
which makes it a constant duplicate of PAGE_IS_PRESENT. A caller cannot
use it to tell written pages from merely-present ones.
Scoping it to VM_UFFD_WP makes the bit mean what it is documented to
mean. A consumer that read PAGE_IS_WRITTEN on a non-WP range was reading
a value that never carried write information, so I don't think there is a
meaningful user to regress.
And in the unlikely event an actual user turns up that depends on the
current behaviour, we can always switch to your else-form -- it is a
small change and keeps the old value.
--
Kiryl Shutsemau / Kirill A. Shutemov