All of lore.kernel.org
 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 ` [Bug 12832] New: kernel leaks a lot of memory 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 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.