I'm not quite familiar with this side of the MM yet, but it seems to me like we're encoding four page states in three bits: - !PageLRU (not an LRU page) - PageLRU (on the inactive list) - PageLRU + PageActive (on the active list) - PageLRU + PageUnevictable (on the unevictable list) Can we neaten this up into two bits? - 00 (not an LRU page) - 01 (active list) - 10 (inactive list) - 11 (unevictable) People who free up page flags are always popular, right? I don't think the missing combos are used: !LRU + Active !LRU + Active + Unevictable !LRU + Unevictable LRU + Active + Unevictable It seems fairly straightforward to add these macros: bool PageLRU(struct page *page) { page->flags & PAGE_FLAGS_LRU_MASK; } bool PageActive(struct page *page) { page->flags & PAGE_FLAGS_LRU_MASK == PAGE_FLAGS_ACTIVE; } bool PageInactive(struct page *page) { page->flags & PAGE_FLAGS_LRU_MASK == PAGE_FLAGS_INACTIVE; } bool PageUnevictable(struct page *page) { page->flags & PAGE_FLAGS_LRU_MASK == PAGE_FLAGS_UNEVICTABLE; } SetPageActive seems a little more tricky to do atomically. A cmpxchg() loop, perhaps? If we changed the API to be PageUnevictableToActive(page) then it's an atomic subtraction / addition (although it's now twelve macro instead of six Set/Clear for three bits). Then I'm not sure how to do TestClearPageActive(). Maybe TryPageActiveToInactive()? That'd be another twelve macros if all those state transitions are possible.