export more page flags in /proc/kpageflags (take 5)
Subsystems (6)
cover export more page flags in /proc/kpageflags (take 5)
Andrew,
This take:
- add page-types tool for querying the exported page flags.
- export all page flags unconditionally and faithfully, and offload complicated filtering works to the user space tool.
This patchset:
Export 10 more flags to end users (and more for kernel developers):
11. KPF_MMAP (pseudo flag) memory mapped page
12. KPF_ANON (pseudo flag) memory mapped page (anonymous)
13. KPF_SWAPCACHE page is in swap cache
14. KPF_SWAPBACKED page is swap/RAM backed
15. KPF_COMPOUND_HEAD (*)
16. KPF_COMPOUND_TAIL (*) 17. KPF_HUGE hugeTLB pages
18. KPF_UNEVICTABLE page is in the unevictable LRU list
19. KPF_HWPOISON hardware detected corruption
20. KPF_NOPAGE (pseudo flag) no page frame at the address
(*) For compound pages, exporting _both_ head/tail info enables
users to tell where a compound page starts/ends, and its order.
Patches:
[PATCH 1/7] mm: introduce PageHuge() for testing huge/gigantic pages [PATCH 2/7] slob: use PG_slab for identifying SLOB pages [PATCH 3/7] proc: kpagecount/kpageflags code cleanup [PATCH 4/7] proc: export more page flags in /proc/kpageflags [PATCH 5/7] pagemap: document clarifications
[PATCH 6/7] pagemap: document 9 more exported page flags [PATCH 7/7] pagemap: add page-types tool
Documentation/vm/Makefile | 2 Documentation/vm/page-types.c | 696 ++++++++++++++++++++++++++++++++ Documentation/vm/pagemap.txt | 72 +++ fs/proc/page.c | 163 +++++-- include/linux/mm.h | 24 + include/linux/page-flags.h | 2 mm/hugetlb.c | 2 mm/page_alloc.c | 11 mm/slob.c | 6 9 files changed, 933 insertions(+), 45 deletions(-)
Thanks,
Fengguang
--
PS. a simple demo of page-types
# ./page-types -h
page-types [options]
-r|--raw Raw mode, for kernel developers
-a|--addr addr-spec Walk a range of pages
-b|--bits bits-spec Walk pages with specified bits
addr-spec:
N one page at offset N (unit: pages)
N+M pages range from N to N+M-1
N,M pages range from N to M-1
N, pages range from N to end
,M pages range from 0 to M
bits-spec:
bit1,bit2 (flags & (bit1|bit2)) != 0
bit1,bit2=bit1 (flags & (bit1|bit2)) == bit1
bit1,~bit2 (flags & (bit1|bit2)) == bit1
=bit1,bit2 flags == (bit1|bit2)
bit-names:
locked error referenced uptodate
dirty lru active slab
writeback reclaim buddy mmap
anonymous swapcache swapbacked compound_head
compound_tail huge unevictable hwpoison
nopage reserved(r) mlocked(r) mappedtodisk(r)
private(r) private_2(r) owner_private(r) arch(r)
uncached(r) readahead(o) slob_free(o) slub_frozen(o)
slub_debug(o)
(r) raw mode bits (o) overloaded bits# ./page-types
flags page-count MB symbolic-flags long-symbolic-flags
0x0000000000000000 487369 1903 _________________________________
0x0000000000000014 5 0 __R_D____________________________ referenced,dirty
0x0000000000000020 1 0 _____l___________________________ lru
0x0000000000000024 34 0 __R__l___________________________ referenced,lru
0x0000000000000028 3838 14 ___U_l___________________________ uptodate,lru
0x0001000000000028 48 0 ___U_l_______________________I___ uptodate,lru,readahead
0x000000000000002c 6478 25 __RU_l___________________________ referenced,uptodate,lru
0x000100000000002c 47 0 __RU_l_______________________I___ referenced,uptodate,lru,readahead
0x0000000000000040 8344 32 ______A__________________________ active
0x0000000000000060 1 0 _____lA__________________________ lru,active
0x0000000000000068 348 1 ___U_lA__________________________ uptodate,lru,active
0x0001000000000068 12 0 ___U_lA______________________I___ uptodate,lru,active,readahead
0x000000000000006c 988 3 __RU_lA__________________________ referenced,uptodate,lru,active
0x000100000000006c 48 0 __RU_lA______________________I___ referenced,uptodate,lru,active,readahead
0x0000000000004078 1 0 ___UDlA_______b__________________ uptodate,dirty,lru,active,swapbacked
0x000000000000407c 34 0 __RUDlA_______b__________________ referenced,uptodate,dirty,lru,active,swapbacked
0x0000000000000400 503 1 __________B______________________ buddy
0x0000000000000804 1 0 __R________M_____________________ referenced,mmap
0x0000000000000828 1029 4 ___U_l_____M_____________________ uptodate,lru,mmap
0x0001000000000828 43 0 ___U_l_____M_________________I___ uptodate,lru,mmap,readahead
0x000000000000082c 382 1 __RU_l_____M_____________________ referenced,uptodate,lru,mmap
0x000100000000082c 12 0 __RU_l_____M_________________I___ referenced,uptodate,lru,mmap,readahead
0x0000000000000868 192 0 ___U_lA____M_____________________ uptodate,lru,active,mmap
0x0001000000000868 12 0 ___U_lA____M_________________I___ uptodate,lru,active,mmap,readahead
0x000000000000086c 800 3 __RU_lA____M_____________________ referenced,uptodate,lru,active,mmap
0x000100000000086c 31 0 __RU_lA____M_________________I___ referenced,uptodate,lru,active,mmap,readahead
0x0000000000004878 2 0 ___UDlA____M__b__________________ uptodate,dirty,lru,active,mmap,swapbacked
0x0000000000001000 492 1 ____________a____________________ anonymous
0x0000000000005808 4 0 ___U_______Ma_b__________________ uptodate,mmap,anonymous,swapbacked
0x0000000000005868 2839 11 ___U_lA____Ma_b__________________ uptodate,lru,active,mmap,anonymous,swapbacked
0x000000000000586c 30 0 __RU_lA____Ma_b__________________ referenced,uptodate,lru,active,mmap,anonymous,swapbacked
total 513968 2007# ./page-types -r
flags page-count MB symbolic-flags long-symbolic-flags
0x0000000000000000 468002 1828 _________________________________
0x0000000100000000 19102 74 _____________________r___________ reserved
0x0000000000008000 41 0 _______________H_________________ compound_head
0x0000000000010000 188 0 ________________T________________ compound_tail
0x0000000000008014 1 0 __R_D__________H_________________ referenced,dirty,compound_head
0x0000000000010014 4 0 __R_D___________T________________ referenced,dirty,compound_tail
0x0000000000000020 1 0 _____l___________________________ lru
0x0000000800000024 34 0 __R__l__________________P________ referenced,lru,private
0x0000000000000028 3794 14 ___U_l___________________________ uptodate,lru
0x0001000000000028 46 0 ___U_l_______________________I___ uptodate,lru,readahead
0x0000000400000028 44 0 ___U_l_________________d_________ uptodate,lru,mappedtodisk
0x0001000400000028 2 0 ___U_l_________________d_____I___ uptodate,lru,mappedtodisk,readahead
0x000000000000002c 6434 25 __RU_l___________________________ referenced,uptodate,lru
0x000100000000002c 47 0 __RU_l_______________________I___ referenced,uptodate,lru,readahead
0x000000040000002c 14 0 __RU_l_________________d_________ referenced,uptodate,lru,mappedtodisk
0x000000080000002c 30 0 __RU_l__________________P________ referenced,uptodate,lru,private
0x0000000800000040 8124 31 ______A_________________P________ active,private
0x0000000000000040 219 0 ______A__________________________ active
0x0000000800000060 1 0 _____lA_________________P________ lru,active,private
0x0000000000000068 322 1 ___U_lA__________________________ uptodate,lru,active
0x0001000000000068 12 0 ___U_lA______________________I___ uptodate,lru,active,readahead
0x0000000400000068 13 0 ___U_lA________________d_________ uptodate,lru,active,mappedtodisk
0x0000000800000068 12 0 ___U_lA_________________P________ uptodate,lru,active,private
0x000000000000006c 977 3 __RU_lA__________________________ referenced,uptodate,lru,active
0x000100000000006c 48 0 __RU_lA______________________I___ referenced,uptodate,lru,active,readahead
0x000000040000006c 5 0 __RU_lA________________d_________ referenced,uptodate,lru,active,mappedtodisk
0x000000080000006c 3 0 __RU_lA_________________P________ referenced,uptodate,lru,active,private
0x0000000c0000006c 3 0 __RU_lA________________dP________ referenced,uptodate,lru,active,mappedtodisk,private
0x0000000c00000068 1 0 ___U_lA________________dP________ uptodate,lru,active,mappedtodisk,private
0x0000000000004078 1 0 ___UDlA_______b__________________ uptodate,dirty,lru,active,swapbacked
0x000000000000407c 34 0 __RUDlA_______b__________________ referenced,uptodate,dirty,lru,active,swapbacked
0x0000000000000400 538 2 __________B______________________ buddy
0x0000000000000804 1 0 __R________M_____________________ referenced,mmap
0x0000000000000828 1029 4 ___U_l_____M_____________________ uptodate,lru,mmap
0x0001000000000828 43 0 ___U_l_____M_________________I___ uptodate,lru,mmap,readahead
0x000000000000082c 382 1 __RU_l_____M_____________________ referenced,uptodate,lru,mmap
0x000100000000082c 12 0 __RU_l_____M_________________I___ referenced,uptodate,lru,mmap,readahead
0x0000000000000868 192 0 ___U_lA____M_____________________ uptodate,lru,active,mmap
0x0001000000000868 12 0 ___U_lA____M_________________I___ uptodate,lru,active,mmap,readahead
0x000000000000086c 800 3 __RU_lA____M_____________________ referenced,uptodate,lru,active,mmap
0x000100000000086c 31 0 __RU_lA____M_________________I___ referenced,uptodate,lru,active,mmap,readahead
0x0000000000004878 2 0 ___UDlA____M__b__________________ uptodate,dirty,lru,active,mmap,swapbacked
0x0000000000001000 492 1 ____________a____________________ anonymous
0x0000000000005008 2 0 ___U________a_b__________________ uptodate,anonymous,swapbacked
0x0000000000005808 4 0 ___U_______Ma_b__________________ uptodate,mmap,anonymous,swapbacked
0x000000000000580c 1 0 __RU_______Ma_b__________________ referenced,uptodate,mmap,anonymous,swapbacked
0x0000000000005868 2839 11 ___U_lA____Ma_b__________________ uptodate,lru,active,mmap,anonymous,swapbacked
0x000000000000586c 29 0 __RU_lA____Ma_b__________________ referenced,uptodate,lru,active,mmap,anonymous,swapbacked
total 513968 2007# ./page-types --raw --list --no-summary --bits reserved offset count flags 0 15 _____________________r___________ 31 4 _____________________r___________ 159 97 _____________________r___________ 4096 2067 _____________________r___________ 6752 2390 _____________________r___________ 9355 3 _____________________r___________ 9728 14526 _____________________r___________
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 1/7 mm: introduce PageHuge() for testing huge/gigantic pages
Introduce PageHuge(), which identifies huge/gigantic pages by their dedicated compound destructor functions.
--- include/linux/mm.h | 24 ++++++++++++++++++++++++ mm/hugetlb.c | 2 +- mm/page_alloc.c | 11 ++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-)
mm/page_alloc.c +10 -1
@@ -299,13 +299,22 @@ void prep_compound_page(struct page *pag }#ifdef CONFIG_HUGETLBFS +/* +* This (duplicated) destructor function distinguishes gigantic pages from +* normal compound pages. +*/ +void free_gigantic_page (struct page *page) +{ +__free_pages_ok (page,compound_order (page)); +} +void prep_compound_gigantic_page (struct page *page,unsigned long order) {int i;int nr_pages =1 << order;struct page *p = page +1 ; -set_compound_page_dtor (page, free_compound_page); +set_compound_page_dtor (page, free_gigantic_page);set_compound_order (page, order);__SetPageHead (page);for (i =1 ; i < nr_pages; i++, p =mem_map_next (p, page, i)) {
mm/hugetlb.c +1 -1
@@ -550,7 +550,7 @@ struct hstate *size_to_hstate(unsigned lreturn NULL ; } -static void free_huge_page (struct page *page) +void free_huge_page (struct page *page) {/* * Can't pass hstate in here because it is called from the
include/linux/mm.h +24 -0
@@ -355,6 +355,30 @@ static inline void set_compound_order(st page[1 ].lru.prev = (void *)order; } +#ifdef CONFIG_HUGETLBFS +void free_huge_page (struct page *page); +void free_gigantic_page (struct page *page); + +static inline int PageHuge (struct page *page) +{ +compound_page_dtor *dtor; + +if (!PageCompound (page)) +return 0 ; + + page =compound_head (page); + dtor =get_compound_page_dtor (page); + +return dtor == free_huge_page || + dtor == free_gigantic_page; +} +#else +static inline int PageHuge (struct page *page) +{ +return 0 ; +} +#endif +/* * Multiple processes may "see" the same page. E.g. for untouched * mappings of /dev/null, all processes see the same page full of
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 2/7 slob: use PG_slab for identifying SLOB pages
In reply to Wu FengguangFor the sake of consistency.
--- include/linux/page-flags.h | 2 -- mm/slob.c | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-)
include/linux/page-flags.h +0 -2
@@ -120,7 +120,6 @@ enum pageflags { PG_savepinned = PG_dirty,/* SLOB */ - PG_slob_page = PG_active, PG_slob_free = PG_private,/* SLUB */
@@ -203,7 +202,6 @@ PAGEFLAG(SavePinned, savepinned); /* X PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved) PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked) -__PAGEFLAG(SlobPage, slob_page) __PAGEFLAG(SlobFree, slob_free)__PAGEFLAG (SlubFrozen, slub_frozen)
mm/slob.c +3 -3
@@ -132,17 +132,17 @@ static LIST_HEAD(free_slob_large);*/ static inline int is_slob_page (struct slob_page *sp) { -return PageSlobPage ((struct page *)sp); +return PageSlab ((struct page *)sp); }static inline void set_slob_page (struct slob_page *sp) { -__SetPageSlobPage ((struct page *)sp); +__SetPageSlab ((struct page *)sp); }static inline void clear_slob_page (struct slob_page *sp) { -__ClearPageSlobPage ((struct page *)sp); +__ClearPageSlab ((struct page *)sp); }static inline struct slob_page *slob_page (const void *addr)
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 2/7] slob: use PG_slab for identifying SLOB pages
Quoted 4 lines · Wu Fengguang
For the sake of consistency.
Cc Matt Mackall <[email protected]>Signed-off-by Wu Fengguang <[email protected]>
Pekka, please take this one directly.
Quoted 48 lines
--- include/linux/page-flags.h | 2 -- mm/slob.c | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-)include/linux/page-flags.h +0
-2@@ -120,7 +120,6 @@ enum pageflags { PG_savepinned = PG_dirty,/* SLOB */ - PG_slob_page = PG_active, PG_slob_free = PG_private,/* SLUB */ @@ -203,7 +202,6 @@ PAGEFLAG(SavePinned, savepinned); /* X PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved) PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked) -__PAGEFLAG(SlobPage, slob_page) __PAGEFLAG(SlobFree, slob_free)__PAGEFLAG (SlubFrozen, slub_frozen)mm/slob.c +3
-3@@ -132,17 +132,17 @@ static LIST_HEAD(free_slob_large);*/ static inline int is_slob_page (struct slob_page *sp) { -return PageSlobPage ((struct page *)sp); +return PageSlab ((struct page *)sp); }static inline void set_slob_page (struct slob_page *sp) { -__SetPageSlobPage ((struct page *)sp); +__SetPageSlab ((struct page *)sp); }static inline void clear_slob_page (struct slob_page *sp) { -__ClearPageSlobPage ((struct page *)sp); +__ClearPageSlab ((struct page *)sp); }static inline struct slob_page *slob_page (const void *addr)Signature · 1 line
--
Signature · 7 lines
Mathematics is the supreme nostalgia of our time. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 3/7 proc: kpagecount/kpageflags code cleanup
In reply to Wu FengguangMove increments of pfn/out to bottom of the loop.
--- fs/proc/page.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
fs/proc/page.c +11 -6
@@ -11,6 +11,7 @@#define KPMSIZE sizeof(u64)#define KPMMASK (KPMSIZE - 1) +/* /proc/kpagecount - an array exposing page counts * * Each entry is a u64 representing the corresponding
@@ -32,20 +33,22 @@ static ssize_t kpagecount_read(struct fireturn -EINVAL ;while (count >0 ) { - ppage =NULL ;if (pfn_valid (pfn)) ppage =pfn_to_page (pfn); - pfn++; +else + ppage =NULL ;if (!ppage) pcount =0 ;else pcount =page_mapcount (ppage); -if (put_user (pcount, out++)) { +if (put_user (pcount, out)) { ret = -EFAULT ;break ; } + pfn++; + out++; count -=KPMSIZE ; }
@@ -98,10 +101,10 @@ static ssize_t kpageflags_read(struct fireturn -EINVAL ;while (count >0 ) { - ppage =NULL ;if (pfn_valid (pfn)) ppage =pfn_to_page (pfn); - pfn++; +else + ppage =NULL ;if (!ppage) kflags =0 ;else
@@ -119,11 +122,13 @@ static ssize_t kpageflags_read(struct fikpf_copy_bit (kflags,KPF_RECLAIM , PG_reclaim) |kpf_copy_bit (kflags,KPF_BUDDY , PG_buddy); -if (put_user (uflags, out++)) { +if (put_user (uflags, out)) { ret = -EFAULT ;break ; } + pfn++; + out++; count -=KPMSIZE ; }
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 3/7] proc: kpagecount/kpageflags code cleanup
Quoted 3 lines · Wu Fengguang
Move increments of pfn/out to bottom of the loop.
Signed-off-by Wu Fengguang <[email protected]>
Quoted 70 lines
--- fs/proc/page.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)fs/proc/page.c +11
-6@@ -11,6 +11,7 @@#define KPMSIZE sizeof(u64)#define KPMMASK (KPMSIZE - 1) +/* /proc/kpagecount - an array exposing page counts * * Each entry is a u64 representing the corresponding @@ -32,20 +33,22 @@ static ssize_t kpagecount_read(struct fireturn -EINVAL ;while (count >0 ) { - ppage =NULL ;if (pfn_valid (pfn)) ppage =pfn_to_page (pfn); - pfn++; +else + ppage =NULL ;if (!ppage) pcount =0 ;else pcount =page_mapcount (ppage); -if (put_user (pcount, out++)) { +if (put_user (pcount, out)) { ret = -EFAULT ;break ; } + pfn++; + out++; count -=KPMSIZE ; }@@ -98,10 +101,10 @@ static ssize_t kpageflags_read(struct fireturn -EINVAL ;while (count >0 ) { - ppage =NULL ;if (pfn_valid (pfn)) ppage =pfn_to_page (pfn); - pfn++; +else + ppage =NULL ;if (!ppage) kflags =0 ;else @@ -119,11 +122,13 @@ static ssize_t kpageflags_read(struct fikpf_copy_bit (kflags,KPF_RECLAIM , PG_reclaim) |kpf_copy_bit (kflags,KPF_BUDDY , PG_buddy); -if (put_user (uflags, out++)) { +if (put_user (uflags, out)) { ret = -EFAULT ;break ; } + pfn++; + out++; count -=KPMSIZE ; }Signature · 1 line
--
Signature · 7 lines
Mathematics is the supreme nostalgia of our time. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 4/7 proc: export more page flags in /proc/kpageflags
In reply to Wu FengguangExport all page flags faithfully in /proc/kpageflags.
11. KPF_MMAP (pseudo flag) memory mapped page
12. KPF_ANON (pseudo flag) memory mapped page (anonymous)
13. KPF_SWAPCACHE page is in swap cache
14. KPF_SWAPBACKED page is swap/RAM backed
15. KPF_COMPOUND_HEAD (*)
16. KPF_COMPOUND_TAIL (*)
17. KPF_HUGE hugeTLB pages
18. KPF_UNEVICTABLE page is in the unevictable LRU list
19. KPF_HWPOISON hardware detected corruption
20. KPF_NOPAGE (pseudo flag) no page frame at the address
32-39. more obscure flags for kernel developers
(*) For compound pages, exporting _both_ head/tail info enables
users to tell where a compound page starts/ends, and its order.
The acompanied page-types tool will handle the details like decoupling overloaded flags and hiding obscure flags to normal users.
Thanks to KOSAKI and Andi for their valuable recommendations!
--- fs/proc/page.c | 150 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 120 insertions(+), 30 deletions(-)
fs/proc/page.c +120 -30
@@ -71,19 +71,126 @@ static const struct file_operations proc/* These macros are used to decouple internal flags from exported ones */ -#define KPF_LOCKED 0 -#define KPF_ERROR 1 -#define KPF_REFERENCED 2 -#define KPF_UPTODATE 3 -#define KPF_DIRTY 4 -#define KPF_LRU 5 -#define KPF_ACTIVE 6 -#define KPF_SLAB 7 -#define KPF_WRITEBACK 8 -#define KPF_RECLAIM 9 -#define KPF_BUDDY 10 +#define KPF_LOCKED 0 +#define KPF_ERROR 1 +#define KPF_REFERENCED 2 +#define KPF_UPTODATE 3 +#define KPF_DIRTY 4 +#define KPF_LRU 5 +#define KPF_ACTIVE 6 +#define KPF_SLAB 7 +#define KPF_WRITEBACK 8 +#define KPF_RECLAIM 9 +#define KPF_BUDDY 10 + +/* 11-20: new additions in 2.6.31 */ +#define KPF_MMAP 11 +#define KPF_ANON 12 +#define KPF_SWAPCACHE 13 +#define KPF_SWAPBACKED 14 +#define KPF_COMPOUND_HEAD 15 +#define KPF_COMPOUND_TAIL 16 +#define KPF_HUGE 17 +#define KPF_UNEVICTABLE 18 +#define KPF_HWPOISON 19 +#define KPF_NOPAGE 20 + +/* kernel hacking assistances +* WARNING: subject to change, never rely on them! +*/ +#define KPF_RESERVED 32 +#define KPF_MLOCKED 33 +#define KPF_MAPPEDTODISK 34 +#define KPF_PRIVATE 35 +#define KPF_PRIVATE_2 36 +#define KPF_OWNER_PRIVATE 37 +#define KPF_ARCH 38 +#define KPF_UNCACHED 39 -#define kpf_copy_bit (flags, dstpos, srcpos) (((flags >> srcpos) & 1) << dstpos) +static inline u64 kpf_copy_bit (u64 kflags,int ubit,int kbit) +{ +return ((kflags >> kbit) &1 ) << ubit; +} + +static u64 get_uflags (struct page *page) +{ +u64 k; +u64 u; + +/* +* pseudo flag: KPF_NOPAGE +* it differentiates a memory hole from a page with no flags +*/ +if (!page) +return 1 <<KPF_NOPAGE ; + + k = page->flags; + u =0 ; + +/* +* pseudo flags for the well known (anonymous) memory mapped pages +*/ +if (!PageSlab (page) &&page_mapped (page)) + u |=1 <<KPF_MMAP ; +if (PageAnon (page)) + u |=1 <<KPF_ANON ; + +/* +* compound pages: export both head/tail info +* they together define a compound page's start/end pos and order +*/ +if (PageHead (page)) + u |=1 <<KPF_COMPOUND_HEAD ; +if (PageTail (page)) + u |=1 <<KPF_COMPOUND_TAIL ; +if (PageHuge (page)) + u |=1 <<KPF_HUGE ; + + u |=kpf_copy_bit (k,KPF_LOCKED , PG_locked); + +/* +* Caveats on high order pages: +* PG_buddy will only be set on the head page; SLUB/SLQB do the same +* for PG_slab; SLOB won't set PG_slab at all on compound pages. +*/ + u |=kpf_copy_bit (k,KPF_SLAB , PG_slab); + u |=kpf_copy_bit (k,KPF_BUDDY , PG_buddy); + + u |=kpf_copy_bit (k,KPF_ERROR , PG_error); + u |=kpf_copy_bit (k,KPF_DIRTY , PG_dirty); + u |=kpf_copy_bit (k,KPF_UPTODATE , PG_uptodate); + u |=kpf_copy_bit (k,KPF_WRITEBACK , PG_writeback); + + u |=kpf_copy_bit (k,KPF_LRU , PG_lru); + u |=kpf_copy_bit (k,KPF_REFERENCED , PG_referenced); + u |=kpf_copy_bit (k,KPF_ACTIVE , PG_active); + u |=kpf_copy_bit (k,KPF_RECLAIM , PG_reclaim); + + u |=kpf_copy_bit (k,KPF_SWAPCACHE , PG_swapcache); + u |=kpf_copy_bit (k,KPF_SWAPBACKED , PG_swapbacked); + +#ifdef CONFIG_MEMORY_FAILURE + u |=kpf_copy_bit (k,KPF_HWPOISON , PG_hwpoison); +#endif + +#ifdef CONFIG_UNEVICTABLE_LRU + u |=kpf_copy_bit (k,KPF_UNEVICTABLE , PG_unevictable); + u |=kpf_copy_bit (k,KPF_MLOCKED , PG_mlocked); +#endif + +#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR + u |=kpf_copy_bit (k,KPF_UNCACHED , PG_uncached); +#endif + + u |=kpf_copy_bit (k,KPF_RESERVED , PG_reserved); + u |=kpf_copy_bit (k,KPF_MAPPEDTODISK , PG_mappedtodisk); + u |=kpf_copy_bit (k,KPF_PRIVATE , PG_private); + u |=kpf_copy_bit (k,KPF_PRIVATE_2 , PG_private_2); + u |=kpf_copy_bit (k,KPF_OWNER_PRIVATE , PG_owner_priv_1); + u |=kpf_copy_bit (k,KPF_ARCH , PG_arch_1); + +return u; +};static ssize_t kpageflags_read (struct file *file,char __user *buf,size_t count,loff_t *ppos)
@@ -93,7 +200,6 @@ static ssize_t kpageflags_read(struct fiunsigned long src = *ppos;unsigned long pfn;ssize_t ret =0 ; -u64 kflags, uflags; pfn = src /KPMSIZE ; count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
@@ -105,24 +211,8 @@ static ssize_t kpageflags_read(struct fi ppage =pfn_to_page (pfn); else ppage =NULL ; -if (!ppage) - kflags =0 ; -else - kflags = ppage->flags; - - uflags =kpf_copy_bit (kflags,KPF_LOCKED , PG_locked) | -kpf_copy_bit (kflags,KPF_ERROR , PG_error) | -kpf_copy_bit (kflags,KPF_REFERENCED , PG_referenced) | -kpf_copy_bit (kflags,KPF_UPTODATE , PG_uptodate) | -kpf_copy_bit (kflags,KPF_DIRTY , PG_dirty) | -kpf_copy_bit (kflags,KPF_LRU , PG_lru) | -kpf_copy_bit (kflags,KPF_ACTIVE , PG_active) | -kpf_copy_bit (kflags,KPF_SLAB , PG_slab) | -kpf_copy_bit (kflags,KPF_WRITEBACK , PG_writeback) | -kpf_copy_bit (kflags,KPF_RECLAIM , PG_reclaim) | -kpf_copy_bit (kflags,KPF_BUDDY , PG_buddy); -if (put_user (uflags, out)) { +if (put_user (get_uflags (ppage), out)) { ret = -EFAULT ;break ; }
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/7] proc: export more page flags in /proc/kpageflags
Hi,
fs/proc/page.c static const struct file_operations proc · line 174
Quoted 3 lines
fs/proc/page.c +3
-0+#ifdef CONFIG_MEMORY_FAILURE + u |=kpf_copy_bit (k,KPF_HWPOISON , PG_hwpoison); +#endif
Did mmtom merge memory failure feature?
Signature · 8 lines
Kinds Regards Minchan Kim -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/7] proc: export more page flags in /proc/kpageflags
Quoted 8 lines · Minchan Kim
Hi,
fs/proc/page.c static const struct file_operations proc · line 174
Quoted 3 lines
fs/proc/page.c +3
-0+#ifdef CONFIG_MEMORY_FAILURE + u |=kpf_copy_bit (k,KPF_HWPOISON , PG_hwpoison); +#endif Did mmtom merge memory failure feature?
Maybe not yet.. but the #ifdef makes it safe :-)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/7] proc: export more page flags in /proc/kpageflags
Quoted 11 lines · Minchan Kim
Quoted 8 lines
Hi,
fs/proc/page.c static const struct file_operations proc · line 174
Quoted 3 lines
fs/proc/page.c +3
-0+#ifdef CONFIG_MEMORY_FAILURE + u |=kpf_copy_bit (k,KPF_HWPOISON , PG_hwpoison); +#endif Did mmtom merge memory failure feature?
Maybe not yet.. but the #ifdef makes it safe :-)
Please don't do that.
dependency of the out of tree code mean "please don't merge me".
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/7] proc: export more page flags in /proc/kpageflags
Quoted 10 lines · KOSAKI Motohiro
Quoted 10 lines · Minchan Kim
Quoted 8 lines
Hi,
fs/proc/page.c static const struct file_operations proc · line 174
Quoted 3 lines
fs/proc/page.c +3
-0+#ifdef CONFIG_MEMORY_FAILURE + u |=kpf_copy_bit (k,KPF_HWPOISON , PG_hwpoison); +#endif Did mmtom merge memory failure feature?
Quoted 4 lines
Quoted 1 line
Maybe not yet.. but the #ifdef makes it safe :-)
Please don't do that.
dependency of the out of tree code mean "please don't merge me".
OK. I'll keep that in mind for the next take.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/7] proc: export more page flags in /proc/kpageflags
In reply to Wu Fengguangfs/proc/page.c static const struct file_operations proc · line 136
Quoted 6 lines · On Thu, 07 May 2009 09:21:21 +0800 Wu Fengguang <[email protected]> wrote:
fs/proc/page.c +6
-0+* pseudo flags for the well known (anonymous) memory mapped pages +*/ +if (!PageSlab (page) &&page_mapped (page)) + u |=1 <<KPF_MMAP ; +if (PageAnon (page)) + u |=1 <<KPF_ANON ;
Why do you check PageSlab on user pages ?
Is there any case that PageSlab == true && page_mapped == true ?
Signature · 8 lines
Kinds Regards Minchan Kim -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/7] proc: export more page flags in /proc/kpageflags
Quoted 12 lines · Minchan Kim
fs/proc/page.c static const struct file_operations proc · line 136
Quoted 6 lines · On Thu, 07 May 2009 09:21:21 +0800 Wu Fengguang <[email protected]> wrote:
fs/proc/page.c +6
-0+* pseudo flags for the well known (anonymous) memory mapped pages +*/ +if (!PageSlab (page) &&page_mapped (page)) + u |=1 <<KPF_MMAP ; +if (PageAnon (page)) + u |=1 <<KPF_ANON ;Why do you check PageSlab on user pages ?
Is there any case that PageSlab == true &&page_mapped== true ?
Yes at least for SLUB: it reuses page->_mapcount, so page_mapped() is meaningless for slab pages.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/7] proc: export more page flags in /proc/kpageflags
Quoted 14 lines · Minchan Kim
Quoted 12 lines
fs/proc/page.c static const struct file_operations proc · line 136
Quoted 6 lines · On Thu, 07 May 2009 09:21:21 +0800 Wu Fengguang <[email protected]> wrote:
fs/proc/page.c +6
-0+* pseudo flags for the well known (anonymous) memory mapped pages +*/ +if (!PageSlab (page) &&page_mapped (page)) + u |=1 <<KPF_MMAP ; +if (PageAnon (page)) + u |=1 <<KPF_ANON ;Why do you check PageSlab on user pages ?
Is there any case that PageSlab == true &&page_mapped== true ?
Quoted 2 lines
Yes at least for SLUB: it reuses
page->_mapcount, sopage_mapped()is meaningless for slab pages.
this question and answer implies more comment required...
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 4/7] proc: export more page flags in /proc/kpageflags
Quoted 14 lines · KOSAKI Motohiro
Quoted 14 lines · Minchan Kim
Quoted 12 lines
fs/proc/page.c static const struct file_operations proc · line 136
Quoted 6 lines · On Thu, 07 May 2009 09:21:21 +0800 Wu Fengguang <[email protected]> wrote:
fs/proc/page.c +6
-0+* pseudo flags for the well known (anonymous) memory mapped pages +*/ +if (!PageSlab (page) &&page_mapped (page)) + u |=1 <<KPF_MMAP ; +if (PageAnon (page)) + u |=1 <<KPF_ANON ;Why do you check PageSlab on user pages ?
Is there any case that PageSlab == true &&page_mapped== true ?
Quoted 4 lines
Quoted 2 lines
Yes at least for SLUB: it reuses
page->_mapcount, sopage_mapped()is meaningless for slab pages.this question and answer implies more comment required...
Good point. Updated comment to:
/*
* pseudo flags for the well known (anonymous) memory mapped pages
*
* Note that page->_mapcount is overloaded in SLOB/SLUB/SLQB, so the
* simple test in page_mapped() is not enough.
*/
if (!PageSlab(page) && page_mapped(page))
u |= 1 << KPF_MMAP;Thanks,
Fengguang
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 5/7 pagemap: document clarifications
In reply to Wu FengguangSome bit ranges were inclusive and some not.
Fix them to be consistently inclusive.
--- Documentation/vm/pagemap.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Documentation/vm/pagemap.txt +3 -3
@@ -12,9 +12,9 @@ There are three components to pagemap: value for each virtual page, containing the following data (from fs/proc/task_mmu.c, above pagemap_read): - * Bits 0-55 page frame number (PFN) if present + * Bits 0-54 page frame number (PFN) if present * Bits 0-4 swap type if swapped - * Bits 5-55 swap offset if swapped + * Bits 5-54 swap offset if swapped * Bits 55-60 page shift (page size = 1<<page shift) * Bit 61 reserved for future use * Bit 62 page swapped
@@ -36,7 +36,7 @@ There are three components to pagemap: * /proc/kpageflags. This file contains a 64-bit set of flags for each page, indexed by PFN. - The flags are (from fs/proc/proc_misc, above kpageflags_read): + The flags are (from fs/proc/page.c, above kpageflags_read): 0. LOCKED 1. ERROR
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 6/7 pagemap: document 9 more exported page flags
In reply to Wu FengguangAlso add short descriptions for all of the 20 exported page flags.
--- Documentation/vm/pagemap.txt | 66 +++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+)
Documentation/vm/pagemap.txt +66 -0
@@ -49,6 +49,72 @@ There are three components to pagemap: 8. WRITEBACK 9. RECLAIM 10. BUDDY + 11. MMAP + 12. ANON + 13. SWAPCACHE + 14. SWAPBACKED + 15. COMPOUND_HEAD + 16. COMPOUND_TAIL + 16. HUGE + 18. UNEVICTABLE + 19. HWPOISON + 20. NOPAGE + +Short descriptions to the page flags: + + 0. LOCKED + page is being locked for exclusive access, eg. by undergoing read/write IO + + 7. SLAB + page is managed by the SLAB/SLOB/SLUB/SLQB kernel memory allocator + When compound page is used, SLUB/SLQB will only set this flag on the head + page; SLOB will not flag it at all. + +10. BUDDY + a free memory block managed by the buddy system allocator + The buddy system organizes free memory in blocks of various orders. + An order N block has 2^N physically contiguous pages, with the BUDDY flag + set for and _only_ for the first page. + +15. COMPOUND_HEAD +16. COMPOUND_TAIL + A compound page with order N consists of 2^N physically contiguous pages. + A compound page with order 2 takes the form of "HTTT", where H donates its + head page and T donates its tail page(s). The major consumers of compound + pages are hugeTLB pages (Documentation/vm/hugetlbpage.txt), the SLUB etc. + memory allocators and various device drivers. However in this interface, + only huge/giga pages are made visible to end users. +17. HUGE + this is an integral part of a HugeTLB page + +19. HWPOISON + hardware detected memory corruption on this page: don't touch the data! + +20. NOPAGE + no page frame exists at the requested address + + [IO related page flags] + 1. ERROR IO error occurred + 3. UPTODATE page has up-to-date data + ie. for file backed page: (in-memory data revision >= on-disk one) + 4. DIRTY page has been written to, hence contains new data + ie. for file backed page: (in-memory data revision > on-disk one) + 8. WRITEBACK page is being synced to disk + + [LRU related page flags] + 5. LRU page is in one of the LRU lists + 6. ACTIVE page is in the active LRU list +18. UNEVICTABLE page is in the unevictable (non-)LRU list + It is somehow pinned and not a candidate for LRU page reclaims, + eg. ramfs pages, shmctl(SHM_LOCK) and mlock() memory segments + 2. REFERENCED page has been referenced since last LRU list enqueue/requeue + 9. RECLAIM page will be reclaimed soon after its pageout IO completed +11. MMAP a memory mapped page +12. ANON a memory mapped page that is not part of a file +13. SWAPCACHE page is mapped to swap space, ie. has an associated swap entry +14. SWAPBACKED page is backed by swap/RAM + +The page-types tool in this directory can be used to query the above flags. Using pagemap to do something useful:
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 7/7 pagemap: add page-types tool
In reply to Wu FengguangAdd page-types, a handy tool for querying page flags.
It will expand some of the overloaded flags:
PG_slob_free = PG_private
PG_slub_frozen = PG_active
PG_slub_debug = PG_error
PG_readahead = PG_reclaim
and mask out obscure flags except in -raw mode:
PG_reserved PG_mlocked PG_mappedtodisk PG_private PG_private_2 PG_owner_priv_1 PG_arch_1 PG_uncached PG_compound* for non hugeTLB pages
--- Documentation/vm/Makefile | 2 Documentation/vm/page-types.c | 696 ++++++++++++++++++++++++++++++++ 2 files changed, 697 insertions(+), 1 deletion(-)
Documentation/vm/page-types.c new file +696 -0
@@ -0,0 +1,696 @@ +/* +* page-types: Tool for querying page flags +* +* Copyright (C) 2009 Intel corporation +* Copyright (C) 2009 Wu Fengguang <[email protected]> +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <stdarg.h> +#include <string.h> +#include <getopt.h> +#include <limits.h> +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/fcntl.h> + + +/* +* kernel page flags +*/ + +#define KPF_BYTES 8 +#define PROC_KPAGEFLAGS "/proc/kpageflags" + +/* copied from kpageflags_read() */ +#define KPF_LOCKED 0 +#define KPF_ERROR 1 +#define KPF_REFERENCED 2 +#define KPF_UPTODATE 3 +#define KPF_DIRTY 4 +#define KPF_LRU 5 +#define KPF_ACTIVE 6 +#define KPF_SLAB 7 +#define KPF_WRITEBACK 8 +#define KPF_RECLAIM 9 +#define KPF_BUDDY 10 + +/* [11-20] new additions in 2.6.31 */ +#define KPF_MMAP 11 +#define KPF_ANON 12 +#define KPF_SWAPCACHE 13 +#define KPF_SWAPBACKED 14 +#define KPF_COMPOUND_HEAD 15 +#define KPF_COMPOUND_TAIL 16 +#define KPF_HUGE 17 +#define KPF_UNEVICTABLE 18 +#define KPF_HWPOISON 19 +#define KPF_NOPAGE 20 + +/* [32-] kernel hacking assistances */ +#define KPF_RESERVED 32 +#define KPF_MLOCKED 33 +#define KPF_MAPPEDTODISK 34 +#define KPF_PRIVATE 35 +#define KPF_PRIVATE_2 36 +#define KPF_OWNER_PRIVATE 37 +#define KPF_ARCH 38 +#define KPF_UNCACHED 39 + +/* [48-] take some arbitrary free slots for expanding overloaded flags +* not part of kernel API +*/ +#define KPF_READAHEAD 48 +#define KPF_SLOB_FREE 49 +#define KPF_SLUB_FROZEN 50 +#define KPF_SLUB_DEBUG 51 + +#define KPF_ALL_BITS ((uint64_t)~0ULL) +#define KPF_HACKERS_BITS (0xffffULL << 32) +#define KPF_OVERLOADED_BITS (0xffffULL << 48) +#define BIT (name) (1ULL << KPF_##name) +#define BITS_COMPOUND (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL)) + +static char *page_flag_names[] = { + [KPF_LOCKED ] ="L:locked" , + [KPF_ERROR ] ="E:error" , + [KPF_REFERENCED ] ="R:referenced" , + [KPF_UPTODATE ] ="U:uptodate" , + [KPF_DIRTY ] ="D:dirty" , + [KPF_LRU ] ="l:lru" , + [KPF_ACTIVE ] ="A:active" , + [KPF_SLAB ] ="S:slab" , + [KPF_WRITEBACK ] ="W:writeback" , + [KPF_RECLAIM ] ="I:reclaim" , + [KPF_BUDDY ] ="B:buddy" , + + [KPF_MMAP ] ="M:mmap" , + [KPF_ANON ] ="a:anonymous" , + [KPF_SWAPCACHE ] ="s:swapcache" , + [KPF_SWAPBACKED ] ="b:swapbacked" , + [KPF_COMPOUND_HEAD ] ="H:compound_head" , + [KPF_COMPOUND_TAIL ] ="T:compound_tail" , + [KPF_HUGE ] ="G:huge" , + [KPF_UNEVICTABLE ] ="u:unevictable" , + [KPF_HWPOISON ] ="X:hwpoison" , + [KPF_NOPAGE ] ="n:nopage" , + + [KPF_RESERVED ] ="r:reserved" , + [KPF_MLOCKED ] ="m:mlocked" , + [KPF_MAPPEDTODISK ] ="d:mappedtodisk" , + [KPF_PRIVATE ] ="P:private" , + [KPF_PRIVATE_2 ] ="p:private_2" , + [KPF_OWNER_PRIVATE ] ="O:owner_private" , + [KPF_ARCH ] ="h:arch" , + [KPF_UNCACHED ] ="c:uncached" , + + [KPF_READAHEAD ] ="I:readahead" , + [KPF_SLOB_FREE ] ="P:slob_free" , + [KPF_SLUB_FROZEN ] ="A:slub_frozen" , + [KPF_SLUB_DEBUG ] ="E:slub_debug" , +}; + + +/* +* data structures +*/ + +static int opt_raw;/* for kernel developers */ +static int opt_list;/* list pages (in ranges) */ +static int opt_no_summary;/* don't show summary */ +static pid_t opt_pid;/* process to walk */ + +#define MAX_ADDR_RANGES 1024 +static int nr_addr_ranges; +static unsigned long opt_offset[MAX_ADDR_RANGES ]; +static unsigned long opt_size[MAX_ADDR_RANGES ]; + +#define MAX_BIT_FILTERS 64 +static int nr_bit_filters; +static uint64_t opt_mask[MAX_BIT_FILTERS ]; +static uint64_t opt_bits[MAX_BIT_FILTERS ]; + +static int page_size; + +#define PAGES_BATCH (64 << 10)/* 64k pages */ +static int kpageflags_fd; +static uint64_t kpageflags_buf[KPF_BYTES *PAGES_BATCH ]; + +#define HASH_SHIFT 13 +#define HASH_SIZE (1 << HASH_SHIFT) +#define HASH_MASK (HASH_SIZE - 1) +#define HASH_KEY (flags) (flags & HASH_MASK) + +static unsigned long total_pages; +static unsigned long nr_pages[HASH_SIZE ]; +static uint64_t page_flags[HASH_SIZE ]; + + +/* +* helper functions +*/ + +#define ARRAY_SIZE (x) (sizeof(x) / sizeof((x)[0])) + +#define min_t (type, x, y) ({ \ + type __min1 = (x); \ + type __min2 = (y); \ + __min1 < __min2 ? __min1 : __min2; }) + +unsigned long pages2mb (unsigned long pages) +{ +return (pages * page_size) >>20 ; +} + +void fatal (const char *x, ...) +{ +va_list ap; + +va_start (ap, x); +vfprintf (stderr, x, ap); +va_end (ap); +exit (EXIT_FAILURE ); +} + + +/* +* page flag names +*/ + +char *page_flag_name (uint64_t flags) +{ +static char buf[65 ]; +int present; +int i, j; + +for (i =0 , j =0 ; i <ARRAY_SIZE (page_flag_names); i++) { + present = (flags >> i) &1 ; +if (!page_flag_names[i]) { +if (present) +fatal ("unkown flag bit %d\n" , i); +continue ; + } + buf[j++] = present ? page_flag_names[i][0 ] :'_' ; + } + +return buf; +} + +char *page_flag_longname (uint64_t flags) +{ +static char buf[1024 ]; +int i, n; + +for (i =0 , n =0 ; i <ARRAY_SIZE (page_flag_names); i++) { +if (!page_flag_names[i]) +continue ; +if ((flags >> i) &1 ) + n +=snprintf (buf + n,sizeof (buf) - n,"%s," , + page_flag_names[i] +2 ); + } +if (n) + n--; + buf[n] ='\0' ; + +return buf; +} + + +/* +* page list and summary +*/ + +void show_page_range (unsigned long offset,uint64_t flags) +{ +static uint64_t flags0; +static unsigned long index; +static unsigned long count; + +if (flags == flags0 && offset == index + count) { + count++; +return ; + } + +if (count) +printf ("%lu\t%lu\t%s\n" , + index, count,page_flag_name (flags0)); + + flags0 = flags; + index = offset; + count =1 ; +} + +void show_page (unsigned long offset,uint64_t flags) +{ +printf ("%lu\t%s\n" , offset,page_flag_name (flags)); +} + +void show_summary () +{ +int i; + +printf (" flags\tpage-count MB" +" symbolic-flags\t\t\tlong-symbolic-flags\n" ); + +for (i =0 ; i <ARRAY_SIZE (nr_pages); i++) { +if (nr_pages[i]) +printf ("0x%016llx\t%10lu %8lu %s\t%s\n" , + (unsigned long long )page_flags[i], + nr_pages[i], +pages2mb (nr_pages[i]), +page_flag_name (page_flags[i]), +page_flag_longname (page_flags[i])); + } + +printf (" total\t%10lu %8lu\n" , + total_pages,pages2mb (total_pages)); +} + + +/* +* page flag filters +*/ + +int bit_mask_ok (uint64_t flags) +{ +int i; + +for (i =0 ; i < nr_bit_filters; i++) { +if (opt_bits[i] ==KPF_ALL_BITS ) { +if ((flags & opt_mask[i]) ==0 ) +return 0 ; + }else { +if ((flags & opt_mask[i]) != opt_bits[i]) +return 0 ; + } + } + +return 1 ; +} + +uint64_t expand_overloaded_flags (uint64_t flags) +{ +/* SLOB/SLUB overload several page flags */ +if (flags &BIT (SLAB )) { +if (flags &BIT (PRIVATE )) + flags ^=BIT (PRIVATE ) |BIT (SLOB_FREE ); +if (flags &BIT (ACTIVE )) + flags ^=BIT (ACTIVE ) |BIT (SLUB_FROZEN ); +if (flags &BIT (ERROR )) + flags ^=BIT (ERROR ) |BIT (SLUB_DEBUG ); + } + +/* PG_reclaim is overloaded as PG_readahead in the read path */ +if ((flags & (BIT (RECLAIM ) |BIT (WRITEBACK ))) ==BIT (RECLAIM )) + flags ^=BIT (RECLAIM ) |BIT (READAHEAD ); + +return flags; +} + +uint64_t well_known_flags (uint64_t flags) +{ +/* hide flags intended only for kernel hacker */ + flags &= ~KPF_HACKERS_BITS ; + +/* hide non-hugeTLB compound pages */ +if ((flags &BITS_COMPOUND ) && !(flags &BIT (HUGE ))) + flags &= ~BITS_COMPOUND ; + +return flags; +} + + +/* +* page frame walker +*/ + +int hash_slot (uint64_t flags) +{ +int k =HASH_KEY (flags); +int i; + +/* Explicitly reserve slot 0 for flags 0: the following logic +* cannot distinguish an unoccupied slot from slot (flags==0). +*/ +if (flags ==0 ) +return 0 ; + +/* search through the remaining (HASH_SIZE-1) slots */ +for (i =1 ; i <ARRAY_SIZE (page_flags); i++, k++) { +if (!k || k >=ARRAY_SIZE (page_flags)) + k =1 ; +if (page_flags[k] ==0 ) { + page_flags[k] = flags; +return k; + } +if (page_flags[k] == flags) +return k; + } + +fatal ("hash table full: bump up HASH_SHIFT?\n" ); +exit (EXIT_FAILURE ); +} + +void add_page (unsigned long offset,uint64_t flags) +{ + flags =expand_overloaded_flags (flags); + +if (!opt_raw) + flags =well_known_flags (flags); + +if (!bit_mask_ok (flags)) +return ; + +if (opt_list ==1 ) +show_page_range (offset, flags); +else if (opt_list ==2 ) +show_page (offset, flags); + + nr_pages[hash_slot (flags)]++; + total_pages++; +} + +void walk_pfn (unsigned long index,unsigned long count) +{ +unsigned long batch; +unsigned long n; +unsigned long i; + +if (index >ULONG_MAX /KPF_BYTES ) +fatal ("index overflow: %lu\n" , index); + +lseek (kpageflags_fd, index *KPF_BYTES ,SEEK_SET ); + +while (count) { + batch = min_t(unsigned long, count, PAGES_BATCH); + n =read (kpageflags_fd, kpageflags_buf, batch *KPF_BYTES ); +if (n ==0 ) +break ; +if (n <0 ) { +perror (PROC_KPAGEFLAGS ); +exit (EXIT_FAILURE ); + } + +if (n %KPF_BYTES !=0 ) +fatal ("partial read: %lu bytes\n" , n); + n = n /KPF_BYTES ; + +for (i =0 ; i < n; i++) +add_page (index + i, kpageflags_buf[i]); + + index += batch; + count -= batch; + } +} + +void walk_addr_ranges (void ) +{ +int i; + + kpageflags_fd =open (PROC_KPAGEFLAGS ,O_RDONLY ); +if (kpageflags_fd <0 ) { +perror (PROC_KPAGEFLAGS ); +exit (EXIT_FAILURE ); + } + +if (!nr_addr_ranges) +walk_pfn (0 ,ULONG_MAX ); + +for (i =0 ; i < nr_addr_ranges; i++) +walk_pfn (opt_offset[i], opt_size[i]); + +close (kpageflags_fd); +} + + +/* +* user interface +*/ + +const char *page_flag_type (uint64_t flag) +{ +if (flag &KPF_HACKERS_BITS ) +return "(r)" ; +if (flag &KPF_OVERLOADED_BITS ) +return "(o)" ; +return " " ; +} + +void usage (void ) +{ +int i, j; + +printf ( +"page-types [options]\n" +" -r|--raw Raw mode, for kernel developers\n" +" -a|--addr addr-spec Walk a range of pages\n" +" -b|--bits bits-spec Walk pages with specified bits\n" +#if 0 /* planned features */ +" -p|--pid pid Walk process address space\n" +" -f|--file filename Walk file address space\n" +#endif +"addr-spec:\n" +" N one page at offset N (unit: pages)\n" +" N+M pages range from N to N+M-1\n" +" N,M pages range from N to M-1\n" +" N, pages range from N to end\n" +" ,M pages range from 0 to M\n" +"bits-spec:\n" +" bit1,bit2 (flags & (bit1|bit2)) != 0\n" +" bit1,bit2=bit1 (flags & (bit1|bit2)) == bit1\n" +" bit1,~bit2 (flags & (bit1|bit2)) == bit1\n" +" =bit1,bit2 flags == (bit1|bit2)\n" +"bit-names:\n" + ); + +for (i =0 , j =0 ; i <ARRAY_SIZE (page_flag_names); i++) { +if (!page_flag_names[i]) +continue ; +printf ("%16s%s" , page_flag_names[i] +2 , +page_flag_type (1ULL << i)); +if (++j >3 ) { + j =0 ; +putchar ('\n' ); + } + } +printf ("\n " +"(r) raw mode bits (o) overloaded bits\n" ); +} + +unsigned long long parse_number (const char *str) +{ +unsigned long long n; + + n =strtoll (str,NULL ,0 ); + +if (n ==0 && str[0 ] !='0' ) +fatal ("invalid name or number: %s\n" , str); + +return n; +} + +void parse_pid (const char *str) +{ + opt_pid =parse_number (str); +} + +void parse_file (const char *name) +{ +} + +void add_addr_range (unsigned long offset,unsigned long size) +{ +if (nr_addr_ranges >=MAX_ADDR_RANGES ) +fatal ("too much addr ranges\n" ); + + opt_offset[nr_addr_ranges] = offset; + opt_size[nr_addr_ranges] = size; + nr_addr_ranges++; +} + +void parse_addr_range (const char *optarg) +{ +unsigned long offset; +unsigned long size; +char *p; + + p =strchr (optarg,',' ); +if (!p) + p =strchr (optarg,'+' ); + +if (p == optarg) { + offset =0 ; + size =parse_number (p +1 ); + }else if (p) { + offset =parse_number (optarg); +if (p[1 ] =='\0' ) + size =ULONG_MAX ; +else { + size =parse_number (p +1 ); +if (*p ==',' ) { +if (size < offset) +fatal ("invalid range: %lu,%lu\n" , + offset, size); + size -= offset; + } + } + }else { + offset =parse_number (optarg); + size =1 ; + } + +add_addr_range (offset, size); +} + +void add_bits_filter (uint64_t mask,uint64_t bits) +{ +if (nr_bit_filters >=MAX_BIT_FILTERS ) +fatal ("too much bit filters\n" ); + + opt_mask[nr_bit_filters] = mask; + opt_bits[nr_bit_filters] = bits; + nr_bit_filters++; +} + +uint64_t parse_flag_name (const char *str,int len) +{ +int i; + +if (!*str || !len) +return 0 ; + +if (len <=8 && !strncmp (str,"compound" , len)) +return BITS_COMPOUND ; + +for (i =0 ; i <ARRAY_SIZE (page_flag_names); i++) { +if (!page_flag_names[i]) +continue ; +if (!strncmp (str, page_flag_names[i] +2 , len)) +return 1ULL << i; + } + +return parse_number (str); +} + +uint64_t parse_flag_names (const char *str,int all) +{ +const char *p = str; +uint64_t flags =0 ; + +while (1 ) { +if (*p ==',' || *p =='=' || *p =='\0' ) { +if ((*str !='~' ) || (*str =='~' && all && *++str)) + flags |=parse_flag_name (str, p - str); +if (*p !=',' ) +break ; + str = p +1 ; + } + p++; + } + +return flags; +} + +void parse_bits_mask (const char *optarg) +{ +uint64_t mask; +uint64_t bits; +const char *p; + + p =strchr (optarg,'=' ); +if (p == optarg) { + mask =KPF_ALL_BITS ; + bits =parse_flag_names (p +1 ,0 ); + }else if (p) { + mask =parse_flag_names (optarg,0 ); + bits =parse_flag_names (p +1 ,0 ); + }else if (strchr (optarg,'~' )) { + mask =parse_flag_names (optarg,1 ); + bits =parse_flag_names (optarg,0 ); + }else { + mask =parse_flag_names (optarg,0 ); + bits =KPF_ALL_BITS ; + } + +add_bits_filter (mask, bits); +} + + +struct option opts[] = { + {"raw" ,0 ,NULL ,'r' }, + {"pid" ,1 ,NULL ,'p' }, + {"file" ,1 ,NULL ,'f' }, + {"addr" ,1 ,NULL ,'a' }, + {"bits" ,1 ,NULL ,'b' }, + {"list" ,0 ,NULL ,'l' }, + {"list-each" ,0 ,NULL ,'L' }, + {"no-summary" ,0 ,NULL ,'N' }, + {"help" ,0 ,NULL ,'h' }, + {NULL ,0 ,NULL ,0 } +}; + +int main (int argc,char *argv[]) +{ +int c; + + page_size =getpagesize (); + +while ((c =getopt_long (argc, argv, +"rp:f:a:b:lLNh" , opts,NULL )) !=-1 ) { +switch (c) { +case 'r' : + opt_raw =1 ; +break ; +case 'p' : +parse_pid (optarg); +break ; +case 'f' : +parse_file (optarg); +break ; +case 'a' : +parse_addr_range (optarg); +break ; +case 'b' : +parse_bits_mask (optarg); +break ; +case 'l' : + opt_list =1 ; +break ; +case 'L' : + opt_list =2 ; +break ; +case 'N' : + opt_no_summary =1 ; +break ; +case 'h' : +usage (); +exit (0 ); +default : +usage (); +exit (1 ); + } + } + +if (opt_list ==1 ) +printf ("offset\tcount\tflags\n" ); +if (opt_list ==2 ) +printf ("offset\tflags\n" ); + +walk_addr_ranges (); + +if (opt_list ==1 ) +show_page_range (0 ,0 );/* drain the buffer */ + +if (opt_no_summary) +return 0 ; + +if (opt_list) +printf ("\n\n" ); + +show_summary (); + +return 0 ; +}
Documentation/vm/Makefile +1 -1
@@ -2,7 +2,7 @@ obj- := dummy.o # List of programs to build -hostprogs-y := slabinfo +hostprogs-y := slabinfo slqbinfo page-types # Tell kbuild to always build the programs always := $(hostprogs-y)
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>