diff options
Diffstat (limited to 'fs/proc/page.c')
| -rw-r--r-- | fs/proc/page.c | 27 | 
1 files changed, 19 insertions, 8 deletions
diff --git a/fs/proc/page.c b/fs/proc/page.c index 3b8b4566033..e647c55275d 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c @@ -40,7 +40,7 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,  			ppage = pfn_to_page(pfn);  		else  			ppage = NULL; -		if (!ppage) +		if (!ppage || PageSlab(ppage))  			pcount = 0;  		else  			pcount = page_mapcount(ppage); @@ -115,16 +115,27 @@ u64 stable_page_flags(struct page *page)  		u |= 1 << KPF_COMPOUND_TAIL;  	if (PageHuge(page))  		u |= 1 << KPF_HUGE; - -	u |= kpf_copy_bit(k, KPF_LOCKED,	PG_locked); +	/* +	 * PageTransCompound can be true for non-huge compound pages (slab +	 * pages or pages allocated by drivers with __GFP_COMP) because it +	 * just checks PG_head/PG_tail, so we need to check PageLRU/PageAnon +	 * to make sure a given page is a thp, not a non-huge compound page. +	 */ +	else if (PageTransCompound(page) && (PageLRU(compound_head(page)) || +					     PageAnon(compound_head(page)))) +		u |= 1 << KPF_THP;  	/* -	 * 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. +	 * Caveats on high order pages: page->_count will only be set +	 * -1 on the head page; SLUB/SLQB do the same for PG_slab; +	 * SLOB won't set PG_slab at all on compound pages.  	 */ +	if (PageBuddy(page)) +		u |= 1 << KPF_BUDDY; + +	u |= kpf_copy_bit(k, KPF_LOCKED,	PG_locked); +  	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); @@ -207,4 +218,4 @@ static int __init proc_page_init(void)  	proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);  	return 0;  } -module_init(proc_page_init); +fs_initcall(proc_page_init);  | 
