On Tue, Mar 08, 2022 at 03:14:32PM +0100, David Hildenbrand wrote: > The basic question we would like to have a reliable and efficient answer > to is: is this anonymous page exclusive to a single process or might it > be shared? Is this supposed to be for PAGE_SIZE pages as well, or is it only used on pages > PAGE_SIZE? > In an ideal world, we'd have a spare pageflag. Unfortunately, pageflags > don't grow on trees, so we have to get a little creative for the time > being. This feels a little _too_ creative to me. There's now an implicit requirement that SL[AOU]B doesn't use the bottom two bits of ->slab_cache, which is probably OK but would need to be documented. I have plans to get rid of PageError and PagePrivate, but those are going to be too late for you. I don't think mappedtodisk has meaning for anon pages, even if they're in the swapcache. It would need PG_has_hwpoisoned to shift to another bit ... but almost any bit will do for has_hwpoisoned. Or have I overlooked something? > @@ -920,6 +976,70 @@ extern bool is_free_buddy_page(struct page *page); > > __PAGEFLAG(Isolated, isolated, PF_ANY); > > +static __always_inline bool folio_test_slab(struct folio *folio) > +{ > + return !folio_test_anon(folio) && > + test_bit(PG_slab, folio_flags(folio, FOLIO_PF_NO_TAIL)); > +} > + > +static __always_inline int PageSlab(struct page *page) > +{ > + return !PageAnon(page) && > + test_bit(PG_slab, &PF_NO_TAIL(page, 0)->flags); > +} In case we do end up using this, this would be better implemented as static __always_inline int PageSlab(struct page *page) { return folio_test_slab(page_folio(page)); } since PageAnon already has a page_folio() call embedded in it. > +static __always_inline void __SetPageSlab(struct page *page) > +{ > + VM_BUG_ON_PGFLAGS(PageAnon(page), page); > + __set_bit(PG_slab, &PF_NO_TAIL(page, 1)->flags); > +} There's only one caller of __SetPageSlab() left, in kfence. And that code looks ... weird. for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) { if (!i || (i % 2)) continue; /* Verify we do not have a compound head page. */ if (WARN_ON(compound_head(&pages[i]) != &pages[i])) goto err; __SetPageSlab(&pages[i]); I think the author probably intended WARN_ON(PageCompound(page)) because they're actually verifying that it's not a tail page, rather than head page. > +static __always_inline void __ClearPageSlab(struct page *page) > +{ > + VM_BUG_ON_PGFLAGS(PageAnon(page), page); > + __clear_bit(PG_slab, &PF_NO_TAIL(page, 1)->flags); > +} There are no remaining callers of __ClearPageSlab(). yay.