linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Wu Fengguang <fengguang.wu@intel.com>
To: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Andi Kleen <andi@firstfloor.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	LKML <linux-kernel@vger.kernel.org>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>
Subject: Re: [RFC][PATCH] proc: export more page flags in /proc/kpageflags (take 3)
Date: Sat, 25 Apr 2009 09:59:11 +0800	[thread overview]
Message-ID: <20090425015911.GA18265@localhost> (raw)
In-Reply-To: <20090423022625.GA8822@localhost>

[-- Attachment #1: Type: text/plain, Size: 19254 bytes --]

Hi all,

For your convenience, I attached the uptodate code for page-types and
page-areas. Enjoy hacking~

Thanks,
Fengguang

On Thu, Apr 23, 2009 at 10:26:25AM +0800, Wu Fengguang wrote:
> Andi and KOSAKI: can we hopefully reach harmony of opinions on this version?
> 
> Export 9 page flags in /proc/kpageflags, and 8 more for kernel developers.
> 
> 1) for kernel hackers (on CONFIG_DEBUG_KERNEL)
>    - all available page flags are exported, and
>    - exported as is
> 2) for admins and end users
>    - only the more `well known' flags are exported:
> 	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_UNEVICTABLE	page is in the unevictable LRU list
> 	18. KPF_POISON		hardware detected corruption
> 	19. 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.
> 
>    - limit flags to their typical usage scenario, as indicated by KOSAKI:
> 	- LRU pages: only export relevant flags
> 		- PG_lru
> 		- PG_unevictable
> 		- PG_active
> 		- PG_referenced
> 		- page_mapped()
> 		- PageAnon()
> 		- PG_swapcache
> 		- PG_swapbacked
> 		- PG_reclaim
> 	- no-IO pages: mask out irrelevant flags
> 		- PG_dirty
> 		- PG_uptodate
> 		- PG_writeback
> 	- SLAB pages: mask out overloaded flags:
> 		- PG_error
> 		- PG_active
> 		- PG_private
> 	- PG_reclaim: filter out the overloaded PG_readahead
> 
> Note that compound page flags are exported faithfully to end user.  This risks
> exposing internal implementation details of the SLUB allocator, however hiding
> it risks larger impacts:
> 	- admins may wonder where all the compound pages gone - the use of
> 	  compound pages in SLUB might have some real world relevance, so that
> 	  end users want to be aware of this behavior
> 	- admins may be confused on inconsistent number of head/tail segments
> 	  This is because SLUB only marks PG_slab on the compound head page.
> 	  If we mask out PG_head|PG_tail for PG_slab pages, we are actually
> 	  only masking out PG_head flags. Therefore the PG_tail segments will
> 	  outnumber PG_head ones, which puzzled me for some time..
> 
> Here are the admin/linus views of all page flags on a newly booted nfs-root system:
> 
> # ./page-types # for admin
>          flags  page-count       MB  symbolic-flags                     long-symbolic-flags
> 0x000000000000      491449     1919  ____________________________
> 0x000000008000          15        0  _______________H____________       compound_head
> 0x000000010000        4280       16  ________________T___________       compound_tail
> 0x000000000008          17        0  ___U________________________       uptodate
> 0x000000008010           1        0  ____D__________H____________       dirty,compound_head
> 0x000000010010           4        0  ____D___________T___________       dirty,compound_tail
> 0x000000000020           1        0  _____l______________________       lru
> 0x000000000028        2678       10  ___U_l______________________       uptodate,lru
> 0x00000000002c        5244       20  __RU_l______________________       referenced,uptodate,lru
> 0x000000004060           1        0  _____lA_______b_____________       lru,active,swapbacked
> 0x000000004064          13        0  __R__lA_______b_____________       referenced,lru,active,swapbacked
> 0x000000000068         236        0  ___U_lA_____________________       uptodate,lru,active
> 0x00000000006c         927        3  __RU_lA_____________________       referenced,uptodate,lru,active
> 0x000000008080         968        3  _______S_______H____________       slab,compound_head
> 0x000000000080        1539        6  _______S____________________       slab
> 0x000000000400         516        2  __________B_________________       buddy
> 0x000000000828        1142        4  ___U_l_____M________________       uptodate,lru,mmap
> 0x00000000082c         280        1  __RU_l_____M________________       referenced,uptodate,lru,mmap
> 0x000000004860           2        0  _____lA____M__b_____________       lru,active,mmap,swapbacked
> 0x000000000868         366        1  ___U_lA____M________________       uptodate,lru,active,mmap
> 0x00000000086c         623        2  __RU_lA____M________________       referenced,uptodate,lru,active,mmap
> 0x000000005868        3639       14  ___U_lA____Ma_b_____________       uptodate,lru,active,mmap,anonymous,swapbacked
> 0x00000000586c          27        0  __RU_lA____Ma_b_____________       referenced,uptodate,lru,active,mmap,anonymous,swapbacked
>          total      513968     2007
> 
> # ./page-types # for linus, when CONFIG_DEBUG_KERNEL is turned on
>          flags  page-count       MB  symbolic-flags                     long-symbolic-flags
> 0x000000000000      471731     1842  ____________________________
> 0x000100000000       19258       75  ____________________r_______       reserved
> 0x000000008000          15        0  _______________H____________       compound_head
> 0x000000010000        4270       16  ________________T___________       compound_tail
> 0x000000000008           3        0  ___U________________________       uptodate
> 0x000000008014           1        0  __R_D__________H____________       referenced,dirty,compound_head
> 0x000000010014           4        0  __R_D___________T___________       referenced,dirty,compound_tail
> 0x000000000020           1        0  _____l______________________       lru
> 0x000000000028        2626       10  ___U_l______________________       uptodate,lru
> 0x00000000002c        5244       20  __RU_l______________________       referenced,uptodate,lru
> 0x000000000068         238        0  ___U_lA_____________________       uptodate,lru,active
> 0x00000000006c         925        3  __RU_lA_____________________       referenced,uptodate,lru,active
> 0x000000004078           1        0  ___UDlA_______b_____________       uptodate,dirty,lru,active,swapbacked
> 0x00000000407c          13        0  __RUDlA_______b_____________       referenced,uptodate,dirty,lru,active,swapbacked
> 0x000000000228          49        0  ___U_l___I__________________       uptodate,lru,reclaim
> 0x000000000400         523        2  __________B_________________       buddy
> 0x000000000804           1        0  __R________M________________       referenced,mmap
> 0x00000000080c           1        0  __RU_______M________________       referenced,uptodate,mmap
> 0x000000000828        1142        4  ___U_l_____M________________       uptodate,lru,mmap
> 0x00000000082c         280        1  __RU_l_____M________________       referenced,uptodate,lru,mmap
> 0x000000000868         366        1  ___U_lA____M________________       uptodate,lru,active,mmap
> 0x00000000086c         622        2  __RU_lA____M________________       referenced,uptodate,lru,active,mmap
> 0x000000004878           2        0  ___UDlA____M__b_____________       uptodate,dirty,lru,active,mmap,swapbacked
> 0x000000008880         907        3  _______S___M___H____________       slab,mmap,compound_head
> 0x000000000880        1488        5  _______S___M________________       slab,mmap
> 0x0000000088c0          59        0  ______AS___M___H____________       active,slab,mmap,compound_head
> 0x0000000008c0          49        0  ______AS___M________________       active,slab,mmap
> 0x000000001000         465        1  ____________a_______________       anonymous
> 0x000000005008           8        0  ___U________a_b_____________       uptodate,anonymous,swapbacked
> 0x000000005808           4        0  ___U_______Ma_b_____________       uptodate,mmap,anonymous,swapbacked
> 0x00000000580c           1        0  __RU_______Ma_b_____________       referenced,uptodate,mmap,anonymous,swapbacked
> 0x000000005868        3645       14  ___U_lA____Ma_b_____________       uptodate,lru,active,mmap,anonymous,swapbacked
> 0x00000000586c          26        0  __RU_lA____Ma_b_____________       referenced,uptodate,lru,active,mmap,anonymous,swapbacked
>          total      513968     2007
> 
> Kudos to KOSAKI and Andi for the extensive recommendations!
> 
> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
> Cc: Andi Kleen <andi@firstfloor.org>
> Cc: Matt Mackall <mpm@selenic.com>
> Cc: Alexey Dobriyan <adobriyan@gmail.com>
> Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
> ---
>  Documentation/vm/pagemap.txt |   65 ++++++++++
>  fs/proc/page.c               |  197 +++++++++++++++++++++++++++------
>  2 files changed, 227 insertions(+), 35 deletions(-)
> 
> --- mm.orig/fs/proc/page.c
> +++ mm/fs/proc/page.c
> @@ -6,6 +6,7 @@
>  #include <linux/mmzone.h>
>  #include <linux/proc_fs.h>
>  #include <linux/seq_file.h>
> +#include <linux/backing-dev.h>
>  #include <asm/uaccess.h>
>  #include "internal.h"
>  
> @@ -68,19 +69,167 @@ 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
> +
> +/* 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_UNEVICTABLE		17
> +#define KPF_POISON		18
> +#define KPF_NOPAGE		19
> +
> +/* kernel hacking assistances */
> +#define KPF_RESERVED		32
> +#define KPF_MLOCKED		33
> +#define KPF_MAPPEDTODISK	34
> +#define KPF_PRIVATE		35
> +#define KPF_PRIVATE2		36
> +#define KPF_OWNER_PRIVATE	37
> +#define KPF_ARCH		38
> +#define KPF_UNCACHED		39
> +
> +/*
> + * Kernel flags are exported faithfully to Linus and his fellow hackers.
> + * Otherwise some details are masked to avoid confusing the end user:
> + * - some kernel flags are completely invisible
> + * - some kernel flags are conditionally invisible on their odd usages
> + */
> +#ifdef CONFIG_DEBUG_KERNEL
> +static inline int genuine_linus(void) { return 1; }
> +#else
> +static inline int genuine_linus(void) { return 0; }
> +#endif
> +
> +#define kpf_copy_bit(uflags, kflags, visible, ubit, kbit)		\
> +	do {								\
> +		if (visible || genuine_linus())				\
> +			uflags |= ((kflags >> kbit) & 1) << ubit;	\
> +	} while (0);
> +
> +/* a helper function _not_ intended for more general uses */
> +static inline int page_cap_writeback_dirty(struct page *page)
> +{
> +	struct address_space *mapping = NULL;
> +
> +	if (!PageSlab(page))
> +		mapping = page_mapping(page);
> +
> +	return !mapping || mapping_cap_writeback_dirty(mapping);
> +}
>  
> -#define kpf_copy_bit(flags, dstpos, srcpos) (((flags >> srcpos) & 1) << dstpos)
> +static u64 get_uflags(struct page *page)
> +{
> +	u64 k;
> +	u64 u;
> +	int io;
> +	int lru;
> +	int slab;
> +
> +	/*
> +	 * 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;
> +
> +	io   = page_cap_writeback_dirty(page);
> +	lru  = k & (1 << PG_lru);
> +	slab = k & (1 << PG_slab);
> +
> +	/*
> +	 * pseudo flags for the well known (anonymous) memory mapped pages
> +	 */
> +	if (lru || genuine_linus()) {
> +		if (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;
> +
> +	kpf_copy_bit(u, k, 1,	  KPF_LOCKED,		PG_locked);
> +
> +	kpf_copy_bit(u, k, 1,     KPF_SLAB,		PG_slab);
> +	kpf_copy_bit(u, k, 1,     KPF_BUDDY,		PG_buddy);
> +
> +	kpf_copy_bit(u, k, io,    KPF_ERROR,		PG_error);
> +	kpf_copy_bit(u, k, io,    KPF_DIRTY,		PG_dirty);
> +	kpf_copy_bit(u, k, io,    KPF_UPTODATE,		PG_uptodate);
> +	kpf_copy_bit(u, k, io,    KPF_WRITEBACK,	PG_writeback);
> +
> +	kpf_copy_bit(u, k, 1,     KPF_LRU,		PG_lru);
> +	kpf_copy_bit(u, k, lru,	  KPF_REFERENCED,	PG_referenced);
> +	kpf_copy_bit(u, k, lru,   KPF_ACTIVE,		PG_active);
> +	kpf_copy_bit(u, k, lru,   KPF_RECLAIM,		PG_reclaim);
> +
> +	kpf_copy_bit(u, k, lru,   KPF_SWAPCACHE,	PG_swapcache);
> +	kpf_copy_bit(u, k, lru,   KPF_SWAPBACKED,	PG_swapbacked);
> +
> +#ifdef CONFIG_MEMORY_FAILURE
> +	kpf_copy_bit(u, k, 1,     KPF_POISON,		PG_poison);
> +#endif
> +
> +#ifdef CONFIG_UNEVICTABLE_LRU
> +	kpf_copy_bit(u, k, lru,   KPF_UNEVICTABLE,	PG_unevictable);
> +	kpf_copy_bit(u, k, 0,     KPF_MLOCKED,		PG_mlocked);
> +#endif
> +
> +	kpf_copy_bit(u, k, 0,     KPF_RESERVED,		PG_reserved);
> +	kpf_copy_bit(u, k, 0,     KPF_MAPPEDTODISK,	PG_mappedtodisk);
> +	kpf_copy_bit(u, k, 0,     KPF_PRIVATE,		PG_private);
> +	kpf_copy_bit(u, k, 0,     KPF_PRIVATE2,		PG_private_2);
> +	kpf_copy_bit(u, k, 0,     KPF_OWNER_PRIVATE,	PG_owner_priv_1);
> +	kpf_copy_bit(u, k, 0,     KPF_ARCH,		PG_arch_1);
> +
> +#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
> +	kpf_copy_bit(u, k, 0,     KPF_UNCACHED,		PG_uncached);
> +#endif
> +
> +	if (!genuine_linus()) {
> +		/*
> +		 * SLAB/SLOB/SLUB overload some page flags which may confuse end user
> +		 */
> +		if (slab) {
> +			u &= ~ ((1 << KPF_ACTIVE)	|
> +				(1 << KPF_ERROR)	|
> +				(1 << KPF_MMAP));
> +		}
> +		/*
> +		 * PG_reclaim could be overloaded as PG_readahead,
> +		 * and we only want to export the first one.
> +		 */
> +		if ((u & ((1 << KPF_RECLAIM) | (1 << KPF_WRITEBACK))) ==
> +			  (1 << KPF_RECLAIM))
> +			u &= ~ (1 << KPF_RECLAIM);
> +	}
> +
> +	return u;
> +};
>  
>  static ssize_t kpageflags_read(struct file *file, char __user *buf,
>  			     size_t count, loff_t *ppos)
> @@ -90,7 +239,6 @@ static ssize_t kpageflags_read(struct fi
>  	unsigned 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);
> @@ -98,32 +246,17 @@ static ssize_t kpageflags_read(struct fi
>  		return -EINVAL;
>  
>  	while (count > 0) {
> -		ppage = NULL;
>  		if (pfn_valid(pfn))
>  			ppage = pfn_to_page(pfn);
> -		pfn++;
> -		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);
> +			ppage = NULL;
>  
> -		if (put_user(uflags, out++)) {
> +		if (put_user(get_uflags(ppage), out)) {
>  			ret = -EFAULT;
>  			break;
>  		}
> -
> +		out++;
> +		pfn++;
>  		count -= KPMSIZE;
>  	}
>  
> --- mm.orig/Documentation/vm/pagemap.txt
> +++ mm/Documentation/vm/pagemap.txt
> @@ -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
> @@ -49,6 +49,65 @@ 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
> +    17. UNEVICTABLE
> +    18. POISON
> +    19. 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
> +
> +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.
> +
> +18. POISON
> +    hardware has detected memory corruption on this page
> +
> +19. 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
> +17. 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 who is not a file page
> +13. SWAPCACHE   page is mapped to swap space, ie. has an associated swap entry
> +14. SWAPBACKED  page is backed by swap/RAM
> +
>  
>  Using pagemap to do something useful:
>  

[-- Attachment #2: pagemap.h --]
[-- Type: text/x-chdr, Size: 2400 bytes --]

#ifndef _PAGEMAP_H_
#define _PAGEMAP_H_

#define KPF_BYTES		8
#define PROC_KPAGEFLAGS		"/proc/kpageflags"

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

/* 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

/* 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_UNEVICTABLE         17
#define KPF_POISON              18
#define KPF_NOPAGE              19

/* kernel hacking assistances */
#define KPF_RESERVED            32
#define KPF_MLOCKED             33
#define KPF_MAPPEDTODISK        34
#define KPF_PRIVATE             35
#define KPF_PRIVATE2            36
#define KPF_OWNER_PRIVATE       37
#define KPF_ARCH                38
#define KPF_UNCACHED            39

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_UNEVICTABLE]	= "u:unevictable",
	[KPF_POISON]		= "X:poison",
	[KPF_NOPAGE]		= "n:nopage",

	[KPF_RESERVED]		= "r:reserved",
	[KPF_MLOCKED]		= "m:mlocked",
	[KPF_MAPPEDTODISK]	= "d:mappedtodisk",
	[KPF_PRIVATE]		= "P:private",
	[KPF_PRIVATE2]		= "p:private_2",
	[KPF_OWNER_PRIVATE]	= "O:owner_private",
	[KPF_ARCH]		= "h:arch",
	[KPF_UNCACHED]		= "c:uncached",
};


static inline unsigned long pages2kb(unsigned long pages)
{
	return (pages * getpagesize()) >> 10;
}

static inline unsigned long pages2mb(unsigned long pages)
{
	return (pages * getpagesize()) >> 20;
}

#endif /* _PAGEMAP_H_ */

[-- Attachment #3: page-types.c --]
[-- Type: text/x-csrc, Size: 2656 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/fcntl.h>

#include "pagemap.h"

#define HASH_SHIFT	13
#define HASH_MASK	((1 << HASH_SHIFT) - 1)
#define HASH_KEY(flags)	(flags & HASH_MASK)

static unsigned long	page_count[1 << HASH_SHIFT];
static uint64_t 	page_flags[1 << HASH_SHIFT];

int hash_index(uint64_t flags)
{
	int i;
	int k = HASH_KEY(flags);

	if (!flags)
		return 0;

	for (i = 1; i < ARRAY_SIZE(page_count); i++, k++) {
		if (!k || k >= ARRAY_SIZE(page_count))
			k = 1;
		if (page_flags[k] == 0) {
			page_flags[k] = flags;
			return k;
		}
		if (page_flags[k] == flags)
			return k;
	}

	exit(1); /* die hard on full hash table */
}

char *page_flag_name(uint64_t flags)
{
	int i, j;
	int bit;
	static char buf[65];

	for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) {
		bit = (flags >> i) & 1;
		if (!page_flag_names[i]) {
			if (bit)
				fprintf(stderr, "unkown flag bit %d\n", i);
			continue;
		}
		buf[j++] = bit ? page_flag_names[i][0] : '_';
	}

	return buf;
}

char *page_flag_longname(uint64_t flags)
{
	int i, n;
	static char buf[1024];

	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;
}

static unsigned long nr_pages;
static uint64_t kpageflags[KPF_BYTES * (1<<20)];

unsigned long collect_page_count()
{
	unsigned long n;
	unsigned long i;
	uint64_t flags;
	int fd;

	fd = open(PROC_KPAGEFLAGS, O_RDONLY);
	if (fd < 0) {
		perror(PROC_KPAGEFLAGS);
		exit(1);
	}

	while (1) {
		n = read(fd, kpageflags, sizeof(kpageflags));
		if (n == 0)
			break;
		if (n < 0) {
			perror(PROC_KPAGEFLAGS);
			exit(2);
		}
		if (n % KPF_BYTES != 0) {
			fprintf(stderr, "partial read: %lu bytes\n", n);
			exit(3);
		}
		n = n / KPF_BYTES;

		for (i = 0; i < n; i++) {
			flags = kpageflags[i];
			page_count[hash_index(flags)]++;
		}
		nr_pages += n;
	}

	close(fd);
}

void show_page_count()
{
	int i;

	printf("         flags\tpage-count       MB"
		"  symbolic-flags\t\t\tlong-symbolic-flags\n");

	for (i = 0; i < ARRAY_SIZE(page_count); i++) {
		if (page_count[i])
			printf("0x%012lx\t%10lu %8lu  %s\t%s\n",
				page_flags[i],
				page_count[i],
				pages2mb(page_count[i]),
				page_flag_name(page_flags[i]),
				page_flag_longname(page_flags[i]));
	}

	printf("         total\t%10lu %8lu\n",
			nr_pages, pages2mb(nr_pages));
}

int main(int argc, char *argv[])
{
	collect_page_count();
	show_page_count();
	return 0;
}

[-- Attachment #4: page-areas.c --]
[-- Type: text/x-csrc, Size: 1495 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/fcntl.h>

#include "pagemap.h"

static void add_index(unsigned long index)
{
	static unsigned long offset, len;

	if (index == offset + len)
		len++;
	else {
		if (len)
			printf("%10lu %8lu %8luKB\n", offset, len, pages2kb(len));
		offset = index;
		len = 1;
	}
}

static void usage(const char *prog)
{
	printf("Usage: %s page_flags\n", prog);
}

static uint64_t kpageflags[KPF_BYTES * (1<<20)];

int main(int argc, char *argv[])
{
	uint64_t match_flags;
	int	 match_exact;
	unsigned long n;
	unsigned long i;
	char *p;
	int fd;

	if (argc < 2) {
		usage(argv[0]);
		exit(1);
	}

	match_exact = 0;
	p = argv[1];
	if (p[0] == '=') {
		match_exact = 1;
		p++;
	}
	match_flags = strtol(p, 0, 16);

	fd = open(PROC_KPAGEFLAGS, O_RDONLY);
	if (fd < 0) {
		perror(PROC_KPAGEFLAGS);
		exit(1);
	}

	while (1) {
		n = read(fd, kpageflags, sizeof(kpageflags));
		if (n == 0)
			break;
		if (n < 0) {
			perror(PROC_KPAGEFLAGS);
			exit(2);
		}
		if (n % KPF_BYTES != 0) {
			fprintf(stderr, "%s: partial read: %lu bytes\n",
					argv[0], n);
			exit(3);
		}
		n = n / KPF_BYTES;

		printf("    offset      len         KB\n");
		for (i = 0; i < n; i++) {
			if (!match_exact && ((kpageflags[i] & match_flags) == match_flags) ||
			    (match_exact && kpageflags[i] == match_flags))
				add_index(i);
		}
	}
	add_index(0); /* flush the stored range */

	return 0;
}

[-- Attachment #5: Makefile --]
[-- Type: text/plain, Size: 169 bytes --]

BINS = page-types page-areas

all: $(BINS)

page-types: page-types.c pagemap.h
	gcc -g -o $@ $<

page-areas: page-areas.c pagemap.h
	gcc -g -o $@ $<

clean:
	rm $(BINS)

  parent reply	other threads:[~2009-04-25  1:58 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-14  4:22 [RFC][PATCH] proc: export more page flags in /proc/kpageflags Wu Fengguang
2009-04-14  4:36 ` Wu Fengguang
2009-04-14  4:37 ` KOSAKI Motohiro
2009-04-14  6:41   ` Wu Fengguang
2009-04-14  6:54     ` KOSAKI Motohiro
2009-04-14  7:11       ` Andi Kleen
2009-04-14  7:17         ` KOSAKI Motohiro
2009-04-15 13:18         ` Wu Fengguang
2009-04-15 13:57           ` Andi Kleen
2009-04-16  2:41             ` Wu Fengguang
2009-04-16  3:54               ` Andi Kleen
2009-04-16  4:43                 ` Wu Fengguang
2009-04-16  2:26           ` KOSAKI Motohiro
2009-04-16  3:49             ` Wu Fengguang
2009-04-16  6:30               ` Wu Fengguang
2009-04-23  2:26             ` [RFC][PATCH] proc: export more page flags in /proc/kpageflags (take 3) Wu Fengguang
2009-04-23  7:48               ` Andi Kleen
2009-04-23  8:10                 ` Wu Fengguang
2009-04-23  8:54                   ` Andi Kleen
2009-04-23 11:21                     ` Wu Fengguang
2009-04-25  1:59               ` Wu Fengguang [this message]
2009-04-14  7:22       ` [RFC][PATCH] proc: export more page flags in /proc/kpageflags Wu Fengguang
2009-04-14  7:42         ` KOSAKI Motohiro

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090425015911.GA18265@localhost \
    --to=fengguang.wu@intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=andi@firstfloor.org \
    --cc=kosaki.motohiro@jp.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).