linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Wu Fengguang <fengguang.wu@intel.com>
To: Pierre Ossman <drzeus@drzeus.cx>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	"bugme-daemon@bugzilla.kernel.org"
	<bugme-daemon@bugzilla.kernel.org>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>
Subject: Re: [Bug 12832] New: kernel leaks a lot of memory
Date: Tue, 10 Mar 2009 20:22:10 +0800	[thread overview]
Message-ID: <20090310122210.GA8415@localhost> (raw)
In-Reply-To: <20090310105523.3dfd4873@mjolnir.ossman.eu>

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

On Tue, Mar 10, 2009 at 11:55:23AM +0200, Pierre Ossman wrote:
> On Tue, 10 Mar 2009 16:19:17 +0800
> Wu Fengguang <fengguang.wu@intel.com> wrote:
> 
> > 
> > Here is the initial patch and tool for finding the missing pages.
> > 
> > In the following example, the pages with no flags set is kind of too
> > many (1816MB), but hopefully your missing pages will have PG_reserved
> > or other flags set ;-)
> > 
> > # ./page-types
> > L:locked E:error R:referenced U:uptodate D:dirty L:lru A:active S:slab W:writeback x:reclaim B:buddy r:reserved c:swapcache b:swapbacked
> >  
> 
> Thanks. I'll have a look in a bit. Right now I'm very close to a
> complete bisect. It is just ftrace commits left though, so I'm somewhat
> sceptical that it is correct. ftrace isn't even turned on in the
> kernels I've been testing.
> 
> The remaining commits are ec1bb60bb..6712e299.

And here's my progress, some more page flags are introduced:

# ./page-types
  flags page-count       MB    symbolic-flags    long-symbolic-flags
0x00000       3978       15  __________________  
0x00004          1        0  __R_______________  referenced
0x00014          5        0  __R_D_____________  referenced,dirty
0x00020          2        0  _____l____________  lru
0x00028       8835       34  ___U_l____________  uptodate,lru
0x0002c       9588       37  __RU_l____________  referenced,uptodate,lru
0x00068       1031        4  ___U_lA___________  uptodate,lru,active
0x0006c       3032       11  __RU_lA___________  referenced,uptodate,lru,active
0x00080      11001       42  _______S__________  slab
0x00228        140        0  ___U_l___x________  uptodate,lru,reclaim
0x0022c         79        0  __RU_l___x________  referenced,uptodate,lru,reclaim
0x00268         43        0  ___U_lA__x________  uptodate,lru,active,reclaim
0x0026c        110        0  __RU_lA__x________  referenced,uptodate,lru,active,reclaim
0x00400       1102        4  __________B_______  buddy
0x00800      18735       73  ___________r______  reserved
0x02008         13        0  ___U_________b____  uptodate,swapbacked
0x02068       9371       36  ___U_lA______b____  uptodate,lru,active,swapbacked
0x0206c       1339        5  __RU_lA______b____  referenced,uptodate,lru,active,swapbacked
0x02078         21        0  ___UDlA______b____  uptodate,dirty,lru,active,swapbacked
0x0207c         17        0  __RUDlA______b____  referenced,uptodate,dirty,lru,active,swapbacked
0x20000     445525     1740  _________________n  noflags
  total     513968     2007

Thanks,
Fengguang


[-- Attachment #2: page-types.c --]
[-- Type: text/x-csrc, Size: 3487 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>

/* copied from kpageflags_read() */
enum {
	KPF_LOCKED,	/*  0 */
	KPF_ERROR,	/*  1 */
	KPF_REFERENCED,	/*  2 */
	KPF_UPTODATE,	/*  3 */
	KPF_DIRTY,	/*  4 */
	KPF_LRU,	/*  5 */
	KPF_ACTIVE,	/*  6 */
	KPF_SLAB,	/*  7 */
	KPF_WRITEBACK,	/*  8 */
	KPF_RECLAIM,	/*  9 */
	KPF_BUDDY,	/* 10 */
	KPF_RESERVED,	/* 11 */
	KPF_SWAPCACHE,	/* 12 */
	KPF_SWAPBACKED,	/* 13 */
        KPF_PRIVATE,    /* 14 */
        KPF_PRIVATE2,   /* 15 */
        KPF_NOPAGE,     /* 16 */
        KPF_NOFLAGS,    /* 17 */
	KPF_NUM
};
#define KPF_BYTES	8

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

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]		= "x:reclaim",
	[KPF_BUDDY]		= "B:buddy",
	[KPF_RESERVED]		= "r:reserved",
	[KPF_SWAPBACKED]	= "b:swapbacked",
	[KPF_SWAPCACHE]		= "c:swapcache",
	[KPF_PRIVATE]		= "P:private",
	[KPF_PRIVATE2]		= "p:private_2",
	[KPF_NOPAGE]		= "N:nopage",
	[KPF_NOFLAGS]		= "n:noflags",
};

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

char *page_flag_name(uint64_t flags)
{
	int i;
	static char buf[64];

	for (i = 0; i < ARRAY_SIZE(page_flag_names); i++)
		buf[i] = (flags & (1 << i)) ? 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 (flags & (1<<i))
		       n += snprintf(buf + n, sizeof(buf) - n, "%s,",
				       page_flag_names[i] + 2);
	if (n)
		n--;
	buf[n] = '\0';

	return buf;
}

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

int main(int argc, char *argv[])
{
	static char kpageflags_name[] = "/proc/kpageflags";
	unsigned long i;
	uint64_t flags;
	int fd;

	fd = open(kpageflags_name, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "%s: cannot open `%s': %s\n",
				argv[0], kpageflags_name, strerror(errno));
		exit(1);
	}

	nr_pages = read(fd, kpageflags, sizeof(kpageflags));
	if (nr_pages <= 0) {
		fprintf(stderr, "%s: cannot read `%s': %s\n",
				argv[0], kpageflags_name, strerror(errno));
		exit(2);
	}
	if (nr_pages % KPF_BYTES != 0) {
		fprintf(stderr, "%s: partial read: %lu bytes\n",
				argv[0], nr_pages);
		exit(3);
	}
	nr_pages = nr_pages / KPF_BYTES;

	for (i = 0; i < nr_pages; i++) {
		flags = kpageflags[i];
		if (flags == 0x40000)
			flags = ARRAY_SIZE(page_count) - 1;
		if (flags >= ARRAY_SIZE(page_count)) {
			fprintf(stderr, "%s: flags overflow: 0x%lx > 0x%lx\n",
					argv[0], flags, ARRAY_SIZE(page_count));
			exit(4);
		}
		page_count[flags]++;
	}

#if 0
	for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) {
		printf("%s ", page_flag_names[i]);
	}
#endif

	printf("  flags\tpage-count       MB    symbolic-flags    long-symbolic-flags\n");
	for (i = 0; i < ARRAY_SIZE(page_count); i++) {
		if (page_count[i])
			printf("0x%05lx\t%10lu %8lu  %s  %s\n",
				i,
				page_count[i],
				pages2mb(page_count[i]),
				page_flag_name(i),
				page_flag_longname(i));
	}

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

	return 0;
}

[-- Attachment #3: kpageflags-improvements.patch --]
[-- Type: text/x-diff, Size: 3800 bytes --]

---
 fs/proc/page.c |   88 +++++++++++++++++++++++++++++------------------
 1 file changed, 56 insertions(+), 32 deletions(-)

--- mm.orig/fs/proc/page.c
+++ mm/fs/proc/page.c
@@ -68,19 +68,60 @@ 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
+enum {
+	KPF_LOCKED,	/*  0 */
+	KPF_ERROR,	/*  1 */
+	KPF_REFERENCED,	/*  2 */
+	KPF_UPTODATE,	/*  3 */
+	KPF_DIRTY,	/*  4 */
+	KPF_LRU,	/*  5 */
+	KPF_ACTIVE,	/*  6 */
+	KPF_SLAB,	/*  7 */
+	KPF_WRITEBACK,	/*  8 */
+	KPF_RECLAIM,	/*  9 */
+	KPF_BUDDY,	/* 10 */
+	KPF_RESERVED,	/* 11 */
+	KPF_SWAPCACHE,	/* 12 */
+	KPF_SWAPBACKED,	/* 13 */
+	KPF_PRIVATE,	/* 14 */
+	KPF_PRIVATE2,	/* 15 */
+	KPF_NOPAGE,	/* 16 */
+	KPF_NOFLAGS,	/* 17 */
+	KPF_NUM
+};
+
+#define PAGE_FLAGS_MASK	((1 << __NR_PAGEFLAGS) - 1)
+
+#define kpf_copy_bit(flags, dstpos, srcpos) (((flags >> srcpos) & 1) << dstpos)
 
-#define kpf_copy_bit(flags, srcpos, dstpos) (((flags >> srcpos) & 1) << dstpos)
+u64 get_uflags(struct page *page)
+{
+	unsigned long kflags;
+
+	if (!page)
+		return (1 << KPF_NOPAGE);
+
+	kflags = page->flags;
+	if ((kflags & PAGE_FLAGS_MASK) == 0)
+		return (1 << KPF_NOFLAGS);
+
+	return 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)	   |
+	       kpf_copy_bit(kflags, KPF_SWAPCACHE,  PG_swapcache)  |
+	       kpf_copy_bit(kflags, KPF_SWAPBACKED, PG_swapbacked) |
+	       kpf_copy_bit(kflags, KPF_PRIVATE,    PG_private)    |
+	       kpf_copy_bit(kflags, KPF_PRIVATE2,   PG_private_2)  |
+	       kpf_copy_bit(kflags, KPF_RESERVED,   PG_reserved);
+};
 
 static ssize_t kpageflags_read(struct file *file, char __user *buf,
 			     size_t count, loff_t *ppos)
@@ -90,7 +131,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 +138,16 @@ 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;
+		pfn++;
 
-		if (put_user(uflags, out++)) {
+		if (put_user(get_uflags(ppage), out++)) {
 			ret = -EFAULT;
 			break;
 		}
-
 		count -= KPMSIZE;
 	}
 

  reply	other threads:[~2009-03-10 12:23 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <bug-12832-27@http.bugzilla.kernel.org/>
2009-03-07 20:24 ` Andrew Morton
2009-03-07 21:00   ` Pierre Ossman
2009-03-07 22:13     ` Andrew Morton
2009-03-07 22:53       ` Pierre Ossman
2009-03-08 10:00       ` Pierre Ossman
2009-03-08 10:36         ` Pierre Ossman
2009-03-08 12:38           ` Wu Fengguang
2009-03-08 14:26             ` Pierre Ossman
2009-03-08 15:54             ` Pierre Ossman
2009-03-08 19:11               ` Andrew Morton
2009-03-08 19:23                 ` Pierre Ossman
2009-03-07 22:16     ` Andrew Morton
2009-03-09  1:37     ` Wu Fengguang
     [not found]       ` <20090309020701.GA381@localhost>
2009-03-09  7:40         ` Pierre Ossman
2009-03-09 14:22           ` Wu Fengguang
2009-03-09 15:02             ` Pierre Ossman
2009-03-10  2:41               ` Wu Fengguang
2009-03-10  6:56                 ` Pierre Ossman
2009-03-10  8:19                 ` Wu Fengguang
2009-03-10  9:55                   ` Pierre Ossman
2009-03-10 12:22                     ` Wu Fengguang [this message]
2009-03-10 13:11                       ` Wu Fengguang
2009-03-10 15:52                         ` Pierre Ossman
2009-03-10 20:21                         ` Pierre Ossman
2009-03-11  1:37                           ` Wu Fengguang
     [not found]                             ` <20090311075703.35de2488@mjolnir.ossman.eu>
2009-03-11  7:14                               ` Wu Fengguang
2009-03-11  7:26                                 ` Pierre Ossman
2009-03-11  7:36                                   ` Wu Fengguang
2009-03-11  7:57                                     ` Pierre Ossman
2009-03-11  8:20                                       ` Wu Fengguang
2009-03-11 13:05                                         ` Pierre Ossman
2009-03-11 13:00                                       ` Wu Fengguang
2009-03-11 15:02                                         ` Pierre Ossman
2009-03-11 15:47                                           ` Steven Rostedt
2009-03-11 16:46                                             ` Pierre Ossman
2009-03-11 21:43                                               ` Pierre Ossman
2009-03-12  6:50                                                 ` Pierre Ossman
2009-03-12  1:08                                           ` Wu Fengguang
2009-03-12  6:55                                             ` Pierre Ossman
2009-03-12  7:29                                               ` Wu Fengguang
2009-03-11 14:25                                     ` Steven Rostedt
2009-03-11 14:35                                       ` Pierre Ossman
2009-03-11 16:55                                       ` Pierre Ossman
2009-03-11 17:28                                         ` Steven Rostedt
2009-03-11 18:33                                           ` Pierre Ossman
2009-03-11 18:48                                             ` Steven Rostedt
2009-03-11 18:56                                               ` Pierre Ossman
2009-03-11 19:03                                                 ` Steven Rostedt
2009-03-12  2:46                                                   ` KOSAKI Motohiro
2009-03-12  6:53                                                     ` Pierre Ossman
2009-03-10 19:58                       ` Pierre Ossman
2009-03-11  0:19                     ` KOSAKI Motohiro
2009-03-11  7:22                       ` Pierre Ossman

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=20090310122210.GA8415@localhost \
    --to=fengguang.wu@intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=bugme-daemon@bugzilla.kernel.org \
    --cc=drzeus@drzeus.cx \
    --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