All of lore.kernel.org
 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:59 UTC|newest]

Thread overview: 44+ 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:22 ` Wu Fengguang
2009-04-14  4:36 ` Wu Fengguang
2009-04-14  4:37 ` KOSAKI Motohiro
2009-04-14  4:37   ` KOSAKI Motohiro
2009-04-14  6:41   ` Wu Fengguang
2009-04-14  6:41     ` Wu Fengguang
2009-04-14  6:54     ` KOSAKI Motohiro
2009-04-14  6:54       ` KOSAKI Motohiro
2009-04-14  7:11       ` Andi Kleen
2009-04-14  7:11         ` Andi Kleen
2009-04-14  7:17         ` KOSAKI Motohiro
2009-04-14  7:17           ` KOSAKI Motohiro
2009-04-15 13:18         ` Wu Fengguang
2009-04-15 13:18           ` Wu Fengguang
2009-04-15 13:57           ` Andi Kleen
2009-04-15 13:57             ` Andi Kleen
2009-04-16  2:41             ` Wu Fengguang
2009-04-16  2:41               ` Wu Fengguang
2009-04-16  3:54               ` Andi Kleen
2009-04-16  3:54                 ` Andi Kleen
2009-04-16  4:43                 ` Wu Fengguang
2009-04-16  4:43                   ` Wu Fengguang
2009-04-16  2:26           ` KOSAKI Motohiro
2009-04-16  2:26             ` KOSAKI Motohiro
2009-04-16  3:49             ` Wu Fengguang
2009-04-16  3:49               ` Wu Fengguang
2009-04-16  6:30               ` 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  2:26               ` Wu Fengguang
2009-04-23  7:48               ` Andi Kleen
2009-04-23  7:48                 ` Andi Kleen
2009-04-23  8:10                 ` Wu Fengguang
2009-04-23  8:10                   ` Wu Fengguang
2009-04-23  8:54                   ` Andi Kleen
2009-04-23  8:54                     ` Andi Kleen
2009-04-23 11:21                     ` Wu Fengguang
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:22         ` Wu Fengguang
2009-04-14  7:42         ` KOSAKI Motohiro
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.