Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

page-flags: introduce page flags policies wrt compound pages

This patch adds a third argument to macros which create function
definitions for page flags. This argument defines how page-flags
helpers behave on compound functions.

For now we define four policies:

- PF_ANY: the helper function operates on the page it gets, regardless
if it's non-compound, head or tail.

- PF_HEAD: the helper function operates on the head page of the
compound page if it gets tail page.

- PF_NO_TAIL: only head and non-compond pages are acceptable for this
helper function.

- PF_NO_COMPOUND: only non-compound pages are acceptable for this
helper function.

For now we use policy PF_ANY for all helpers, which matches current
behaviour.

We do not enforce the policy for TESTPAGEFLAG, because we have flags
checked for random pages all over the kernel. Noticeable exception to
this is PageTransHuge() which triggers VM_BUG_ON() for tail page.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Rik van Riel <riel@redhat.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Christoph Lameter <cl@linux.com>
Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Steve Capper <steve.capper@linaro.org>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Jerome Marchand <jmarchan@redhat.com>
Cc: Jérôme Glisse <jglisse@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Kirill A. Shutemov and committed by
Linus Torvalds
95ad9755 0e6d31a7

+115 -63
+6
include/linux/mmdebug.h
··· 56 56 #define VIRTUAL_BUG_ON(cond) do { } while (0) 57 57 #endif 58 58 59 + #ifdef CONFIG_DEBUG_VM_PGFLAGS 60 + #define VM_BUG_ON_PGFLAGS(cond, page) VM_BUG_ON_PAGE(cond, page) 61 + #else 62 + #define VM_BUG_ON_PGFLAGS(cond, page) BUILD_BUG_ON_INVALID(cond) 63 + #endif 64 + 59 65 #endif
+101 -63
include/linux/page-flags.h
··· 155 155 } 156 156 157 157 /* 158 + * Page flags policies wrt compound pages 159 + * 160 + * PF_ANY: 161 + * the page flag is relevant for small, head and tail pages. 162 + * 163 + * PF_HEAD: 164 + * for compound page all operations related to the page flag applied to 165 + * head page. 166 + * 167 + * PF_NO_TAIL: 168 + * modifications of the page flag must be done on small or head pages, 169 + * checks can be done on tail pages too. 170 + * 171 + * PF_NO_COMPOUND: 172 + * the page flag is not relevant for compound pages. 173 + */ 174 + #define PF_ANY(page, enforce) page 175 + #define PF_HEAD(page, enforce) compound_head(page) 176 + #define PF_NO_TAIL(page, enforce) ({ \ 177 + VM_BUG_ON_PGFLAGS(enforce && PageTail(page), page); \ 178 + compound_head(page);}) 179 + #define PF_NO_COMPOUND(page, enforce) ({ \ 180 + VM_BUG_ON_PGFLAGS(enforce && PageCompound(page), page); \ 181 + page;}) 182 + 183 + /* 158 184 * Macros to create function definitions for page flags 159 185 */ 160 - #define TESTPAGEFLAG(uname, lname) \ 161 - static inline int Page##uname(const struct page *page) \ 162 - { return test_bit(PG_##lname, &page->flags); } 186 + #define TESTPAGEFLAG(uname, lname, policy) \ 187 + static inline int Page##uname(struct page *page) \ 188 + { return test_bit(PG_##lname, &policy(page, 0)->flags); } 163 189 164 - #define SETPAGEFLAG(uname, lname) \ 190 + #define SETPAGEFLAG(uname, lname, policy) \ 165 191 static inline void SetPage##uname(struct page *page) \ 166 - { set_bit(PG_##lname, &page->flags); } 192 + { set_bit(PG_##lname, &policy(page, 1)->flags); } 167 193 168 - #define CLEARPAGEFLAG(uname, lname) \ 194 + #define CLEARPAGEFLAG(uname, lname, policy) \ 169 195 static inline void ClearPage##uname(struct page *page) \ 170 - { clear_bit(PG_##lname, &page->flags); } 196 + { clear_bit(PG_##lname, &policy(page, 1)->flags); } 171 197 172 - #define __SETPAGEFLAG(uname, lname) \ 198 + #define __SETPAGEFLAG(uname, lname, policy) \ 173 199 static inline void __SetPage##uname(struct page *page) \ 174 - { __set_bit(PG_##lname, &page->flags); } 200 + { __set_bit(PG_##lname, &policy(page, 1)->flags); } 175 201 176 - #define __CLEARPAGEFLAG(uname, lname) \ 202 + #define __CLEARPAGEFLAG(uname, lname, policy) \ 177 203 static inline void __ClearPage##uname(struct page *page) \ 178 - { __clear_bit(PG_##lname, &page->flags); } 204 + { __clear_bit(PG_##lname, &policy(page, 1)->flags); } 179 205 180 - #define TESTSETFLAG(uname, lname) \ 206 + #define TESTSETFLAG(uname, lname, policy) \ 181 207 static inline int TestSetPage##uname(struct page *page) \ 182 - { return test_and_set_bit(PG_##lname, &page->flags); } 208 + { return test_and_set_bit(PG_##lname, &policy(page, 1)->flags); } 183 209 184 - #define TESTCLEARFLAG(uname, lname) \ 210 + #define TESTCLEARFLAG(uname, lname, policy) \ 185 211 static inline int TestClearPage##uname(struct page *page) \ 186 - { return test_and_clear_bit(PG_##lname, &page->flags); } 212 + { return test_and_clear_bit(PG_##lname, &policy(page, 1)->flags); } 187 213 188 - #define __TESTCLEARFLAG(uname, lname) \ 214 + #define __TESTCLEARFLAG(uname, lname, policy) \ 189 215 static inline int __TestClearPage##uname(struct page *page) \ 190 - { return __test_and_clear_bit(PG_##lname, &page->flags); } 216 + { return __test_and_clear_bit(PG_##lname, &policy(page, 1)->flags); } 191 217 192 - #define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \ 193 - SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname) 218 + #define PAGEFLAG(uname, lname, policy) \ 219 + TESTPAGEFLAG(uname, lname, policy) \ 220 + SETPAGEFLAG(uname, lname, policy) \ 221 + CLEARPAGEFLAG(uname, lname, policy) 194 222 195 - #define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \ 196 - __SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname) 223 + #define __PAGEFLAG(uname, lname, policy) \ 224 + TESTPAGEFLAG(uname, lname, policy) \ 225 + __SETPAGEFLAG(uname, lname, policy) \ 226 + __CLEARPAGEFLAG(uname, lname, policy) 197 227 198 - #define TESTSCFLAG(uname, lname) \ 199 - TESTSETFLAG(uname, lname) TESTCLEARFLAG(uname, lname) 228 + #define TESTSCFLAG(uname, lname, policy) \ 229 + TESTSETFLAG(uname, lname, policy) \ 230 + TESTCLEARFLAG(uname, lname, policy) 200 231 201 232 #define TESTPAGEFLAG_FALSE(uname) \ 202 233 static inline int Page##uname(const struct page *page) { return 0; } ··· 256 225 #define TESTSCFLAG_FALSE(uname) \ 257 226 TESTSETFLAG_FALSE(uname) TESTCLEARFLAG_FALSE(uname) 258 227 228 + TESTPAGEFLAG(Locked, locked, PF_ANY) 229 + PAGEFLAG(Error, error, PF_ANY) TESTCLEARFLAG(Error, error, PF_ANY) 230 + PAGEFLAG(Referenced, referenced, PF_ANY) TESTCLEARFLAG(Referenced, referenced, PF_ANY) 231 + __SETPAGEFLAG(Referenced, referenced, PF_ANY) 232 + PAGEFLAG(Dirty, dirty, PF_ANY) TESTSCFLAG(Dirty, dirty, PF_ANY) 233 + __CLEARPAGEFLAG(Dirty, dirty, PF_ANY) 234 + PAGEFLAG(LRU, lru, PF_ANY) __CLEARPAGEFLAG(LRU, lru, PF_ANY) 235 + PAGEFLAG(Active, active, PF_ANY) __CLEARPAGEFLAG(Active, active, PF_ANY) 236 + TESTCLEARFLAG(Active, active, PF_ANY) 237 + __PAGEFLAG(Slab, slab, PF_ANY) 238 + PAGEFLAG(Checked, checked, PF_ANY) /* Used by some filesystems */ 239 + PAGEFLAG(Pinned, pinned, PF_ANY) TESTSCFLAG(Pinned, pinned, PF_ANY) /* Xen */ 240 + PAGEFLAG(SavePinned, savepinned, PF_ANY); /* Xen */ 241 + PAGEFLAG(Foreign, foreign, PF_ANY); /* Xen */ 242 + PAGEFLAG(Reserved, reserved, PF_ANY) __CLEARPAGEFLAG(Reserved, reserved, PF_ANY) 243 + PAGEFLAG(SwapBacked, swapbacked, PF_ANY) 244 + __CLEARPAGEFLAG(SwapBacked, swapbacked, PF_ANY) 245 + __SETPAGEFLAG(SwapBacked, swapbacked, PF_ANY) 259 246 260 - TESTPAGEFLAG(Locked, locked) 261 - PAGEFLAG(Error, error) TESTCLEARFLAG(Error, error) 262 - PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced) 263 - __SETPAGEFLAG(Referenced, referenced) 264 - PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty) 265 - PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru) 266 - PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active) 267 - TESTCLEARFLAG(Active, active) 268 - __PAGEFLAG(Slab, slab) 269 - PAGEFLAG(Checked, checked) /* Used by some filesystems */ 270 - PAGEFLAG(Pinned, pinned) TESTSCFLAG(Pinned, pinned) /* Xen */ 271 - PAGEFLAG(SavePinned, savepinned); /* Xen */ 272 - PAGEFLAG(Foreign, foreign); /* Xen */ 273 - PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved) 274 - PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked) 275 - __SETPAGEFLAG(SwapBacked, swapbacked) 276 - 277 - __PAGEFLAG(SlobFree, slob_free) 247 + __PAGEFLAG(SlobFree, slob_free, PF_ANY) 278 248 279 249 /* 280 250 * Private page markings that may be used by the filesystem that owns the page 281 251 * for its own purposes. 282 252 * - PG_private and PG_private_2 cause releasepage() and co to be invoked 283 253 */ 284 - PAGEFLAG(Private, private) __SETPAGEFLAG(Private, private) 285 - __CLEARPAGEFLAG(Private, private) 286 - PAGEFLAG(Private2, private_2) TESTSCFLAG(Private2, private_2) 287 - PAGEFLAG(OwnerPriv1, owner_priv_1) TESTCLEARFLAG(OwnerPriv1, owner_priv_1) 254 + PAGEFLAG(Private, private, PF_ANY) __SETPAGEFLAG(Private, private, PF_ANY) 255 + __CLEARPAGEFLAG(Private, private, PF_ANY) 256 + PAGEFLAG(Private2, private_2, PF_ANY) TESTSCFLAG(Private2, private_2, PF_ANY) 257 + PAGEFLAG(OwnerPriv1, owner_priv_1, PF_ANY) 258 + TESTCLEARFLAG(OwnerPriv1, owner_priv_1, PF_ANY) 288 259 289 260 /* 290 261 * Only test-and-set exist for PG_writeback. The unconditional operators are 291 262 * risky: they bypass page accounting. 292 263 */ 293 - TESTPAGEFLAG(Writeback, writeback) TESTSCFLAG(Writeback, writeback) 294 - PAGEFLAG(MappedToDisk, mappedtodisk) 264 + TESTPAGEFLAG(Writeback, writeback, PF_ANY) TESTSCFLAG(Writeback, writeback, PF_ANY) 265 + PAGEFLAG(MappedToDisk, mappedtodisk, PF_ANY) 295 266 296 267 /* PG_readahead is only used for reads; PG_reclaim is only for writes */ 297 - PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim) 298 - PAGEFLAG(Readahead, reclaim) TESTCLEARFLAG(Readahead, reclaim) 268 + PAGEFLAG(Reclaim, reclaim, PF_ANY) TESTCLEARFLAG(Reclaim, reclaim, PF_ANY) 269 + PAGEFLAG(Readahead, reclaim, PF_ANY) TESTCLEARFLAG(Readahead, reclaim, PF_ANY) 299 270 300 271 #ifdef CONFIG_HIGHMEM 301 272 /* ··· 310 277 #endif 311 278 312 279 #ifdef CONFIG_SWAP 313 - PAGEFLAG(SwapCache, swapcache) 280 + PAGEFLAG(SwapCache, swapcache, PF_ANY) 314 281 #else 315 282 PAGEFLAG_FALSE(SwapCache) 316 283 #endif 317 284 318 - PAGEFLAG(Unevictable, unevictable) __CLEARPAGEFLAG(Unevictable, unevictable) 319 - TESTCLEARFLAG(Unevictable, unevictable) 285 + PAGEFLAG(Unevictable, unevictable, PF_ANY) 286 + __CLEARPAGEFLAG(Unevictable, unevictable, PF_ANY) 287 + TESTCLEARFLAG(Unevictable, unevictable, PF_ANY) 320 288 321 289 #ifdef CONFIG_MMU 322 - PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked) 323 - TESTSCFLAG(Mlocked, mlocked) __TESTCLEARFLAG(Mlocked, mlocked) 290 + PAGEFLAG(Mlocked, mlocked, PF_ANY) __CLEARPAGEFLAG(Mlocked, mlocked, PF_ANY) 291 + TESTSCFLAG(Mlocked, mlocked, PF_ANY) __TESTCLEARFLAG(Mlocked, mlocked, PF_ANY) 324 292 #else 325 293 PAGEFLAG_FALSE(Mlocked) __CLEARPAGEFLAG_NOOP(Mlocked) 326 294 TESTSCFLAG_FALSE(Mlocked) __TESTCLEARFLAG_FALSE(Mlocked) 327 295 #endif 328 296 329 297 #ifdef CONFIG_ARCH_USES_PG_UNCACHED 330 - PAGEFLAG(Uncached, uncached) 298 + PAGEFLAG(Uncached, uncached, PF_ANY) 331 299 #else 332 300 PAGEFLAG_FALSE(Uncached) 333 301 #endif 334 302 335 303 #ifdef CONFIG_MEMORY_FAILURE 336 - PAGEFLAG(HWPoison, hwpoison) 337 - TESTSCFLAG(HWPoison, hwpoison) 304 + PAGEFLAG(HWPoison, hwpoison, PF_ANY) 305 + TESTSCFLAG(HWPoison, hwpoison, PF_ANY) 338 306 #define __PG_HWPOISON (1UL << PG_hwpoison) 339 307 #else 340 308 PAGEFLAG_FALSE(HWPoison) ··· 343 309 #endif 344 310 345 311 #if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT) 346 - TESTPAGEFLAG(Young, young) 347 - SETPAGEFLAG(Young, young) 348 - TESTCLEARFLAG(Young, young) 349 - PAGEFLAG(Idle, idle) 312 + TESTPAGEFLAG(Young, young, PF_ANY) 313 + SETPAGEFLAG(Young, young, PF_ANY) 314 + TESTCLEARFLAG(Young, young, PF_ANY) 315 + PAGEFLAG(Idle, idle, PF_ANY) 350 316 #endif 351 317 352 318 /* ··· 427 393 set_bit(PG_uptodate, &(page)->flags); 428 394 } 429 395 430 - CLEARPAGEFLAG(Uptodate, uptodate) 396 + CLEARPAGEFLAG(Uptodate, uptodate, PF_ANY) 431 397 432 398 int test_clear_page_writeback(struct page *page); 433 399 int __test_set_page_writeback(struct page *page, bool keep_write); ··· 447 413 test_set_page_writeback_keepwrite(page); 448 414 } 449 415 450 - __PAGEFLAG(Head, head) CLEARPAGEFLAG(Head, head) 416 + __PAGEFLAG(Head, head, PF_ANY) CLEARPAGEFLAG(Head, head, PF_ANY) 451 417 452 418 static inline void set_compound_head(struct page *page, struct page *head) 453 419 { ··· 649 615 return !!(page->flags & PAGE_FLAGS_PRIVATE); 650 616 } 651 617 618 + #undef PF_ANY 619 + #undef PF_HEAD 620 + #undef PF_NO_TAIL 621 + #undef PF_NO_COMPOUND 652 622 #endif /* !__GENERATING_BOUNDS_H */ 653 623 654 624 #endif /* PAGE_FLAGS_H */
+8
lib/Kconfig.debug
··· 580 580 581 581 If unsure, say N. 582 582 583 + config DEBUG_VM_PGFLAGS 584 + bool "Debug page-flags operations" 585 + depends on DEBUG_VM 586 + help 587 + Enables extra validation on page flags operations. 588 + 589 + If unsure, say N. 590 + 583 591 config DEBUG_VIRTUAL 584 592 bool "Debug VM translations" 585 593 depends on DEBUG_KERNEL && X86