2008-06-27 12:12:18

by Johannes Weiner

[permalink] [raw]
Subject: [PATCH 02/20] mm: generic show_mem()

This implements a platform-independent version of show_mem().

Signed-off-by: Johannes Weiner <[email protected]>
---
mm/Kconfig | 3 +++
mm/page_alloc.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)

--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -45,6 +45,7 @@
#include <linux/fault-inject.h>
#include <linux/page-isolation.h>
#include <linux/memcontrol.h>
+#include <linux/nmi.h>
#include <linux/debugobjects.h>

#include <asm/tlbflush.h>
@@ -2042,6 +2043,60 @@ static void zoneref_set_zone(struct zone
zoneref->zone_idx = zone_idx(zone);
}

+#ifdef CONFIG_HAVE_GENERIC_SHOW_MEM
+void show_mem(void)
+{
+ pg_data_t *pgdat;
+ int total = 0, reserved = 0, shared = 0, nonshared = 0, highmem = 0;
+
+ printk(KERN_INFO "Mem-Info:\n");
+ show_free_areas();
+
+ for_each_online_pgdat(pgdat) {
+ unsigned long i, flags;
+
+ pgdat_resize_lock(pgdat, &flags);
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
+ struct page *page;
+ unsigned long pfn = pgdat->node_start_pfn + i;
+
+ if (unlikely((i % MAX_ORDER_NR_PAGES) == 0))
+ touch_nmi_watchdog();
+
+ if (!pfn_valid(pfn))
+ continue;
+
+ page = pfn_to_page(pfn);
+
+ if (PageHighMem(page))
+ highmem++;
+
+ if (PageReserved(page))
+ reserved++;
+ else if (page_count(page) == 1)
+ nonshared++;
+ else if (page_count(page) > 1)
+ shared += page_count(page) - 1;
+
+ total++;
+ }
+ pgdat_resize_unlock(pgdat, &flags);
+ }
+
+ printk(KERN_INFO "%d pages RAM\n", total);
+#ifdef CONFIG_HIGHMEM
+ printk(KERN_INFO "%d pages HighMem\n", highmem);
+#endif
+ printk(KERN_INFO "%d pages reserved\n", reserved);
+ printk(KERN_INFO "%d pages shared\n", shared);
+ printk(KERN_INFO "%d pages non-shared\n", nonshared);
+#ifdef CONFIG_QUICKLIST
+ printk(KERN_INFO "%d pages in pagetable cache\n",
+ quicklist_total_size());
+#endif
+}
+#endif /* CONFIG_HAVE_GENERIC_SHOW_MEM */
+
/*
* Builds allocation fallback zone lists.
*
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -213,6 +213,9 @@ config VIRT_TO_BUS
config PAGE_WALKER
def_bool n

+config HAVE_GENERIC_SHOW_MEM
+ def_bool n
+
config UNEVICTABLE_LRU
bool "Add LRU list to track non-evictable pages"
default y

--


2008-06-27 14:44:31

by Heiko Carstens

[permalink] [raw]
Subject: Re: [PATCH 02/20] mm: generic show_mem()

> +#ifdef CONFIG_HAVE_GENERIC_SHOW_MEM
> +void show_mem(void)
> +{
> + pg_data_t *pgdat;
> + int total = 0, reserved = 0, shared = 0, nonshared = 0, highmem = 0;

All of these should be unsigned long. Might overflow on very large
configurations otherwise.

2008-06-27 21:17:50

by Johannes Weiner

[permalink] [raw]
Subject: [PATCH 02/20 fixed] mm: generic show_mem()

This implements a platform-independent version of show_mem().

Signed-off-by: Johannes Weiner <[email protected]>
---
mm/Kconfig | 3 +++
mm/page_alloc.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+)

Heiko Carstens <[email protected]> writes:

>> +#ifdef CONFIG_HAVE_GENERIC_SHOW_MEM
>> +void show_mem(void)
>> +{
>> + pg_data_t *pgdat;
>> + int total = 0, reserved = 0, shared = 0, nonshared = 0, highmem = 0;
>
> All of these should be unsigned long. Might overflow on very large
> configurations otherwise.

Thanks Heiko for pointing it out. quicklist_total_size() also returns
UL so I fixed up the format character there as well.

--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -45,6 +45,7 @@
#include <linux/fault-inject.h>
#include <linux/page-isolation.h>
#include <linux/memcontrol.h>
+#include <linux/nmi.h>
#include <linux/debugobjects.h>

#include <asm/tlbflush.h>
@@ -2042,6 +2043,61 @@ static void zoneref_set_zone(struct zone
zoneref->zone_idx = zone_idx(zone);
}

+#ifdef CONFIG_HAVE_GENERIC_SHOW_MEM
+void show_mem(void)
+{
+ pg_data_t *pgdat;
+ unsigned long total = 0, reserved = 0, shared = 0,
+ nonshared = 0, highmem = 0;
+
+ printk(KERN_INFO "Mem-Info:\n");
+ show_free_areas();
+
+ for_each_online_pgdat(pgdat) {
+ unsigned long i, flags;
+
+ pgdat_resize_lock(pgdat, &flags);
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
+ struct page *page;
+ unsigned long pfn = pgdat->node_start_pfn + i;
+
+ if (unlikely((i % MAX_ORDER_NR_PAGES) == 0))
+ touch_nmi_watchdog();
+
+ if (!pfn_valid(pfn))
+ continue;
+
+ page = pfn_to_page(pfn);
+
+ if (PageHighMem(page))
+ highmem++;
+
+ if (PageReserved(page))
+ reserved++;
+ else if (page_count(page) == 1)
+ nonshared++;
+ else if (page_count(page) > 1)
+ shared += page_count(page) - 1;
+
+ total++;
+ }
+ pgdat_resize_unlock(pgdat, &flags);
+ }
+
+ printk(KERN_INFO "%lu pages RAM\n", total);
+#ifdef CONFIG_HIGHMEM
+ printk(KERN_INFO "%lu pages HighMem\n", highmem);
+#endif
+ printk(KERN_INFO "%lu pages reserved\n", reserved);
+ printk(KERN_INFO "%lu pages shared\n", shared);
+ printk(KERN_INFO "%lu pages non-shared\n", nonshared);
+#ifdef CONFIG_QUICKLIST
+ printk(KERN_INFO "%lu pages in pagetable cache\n",
+ quicklist_total_size());
+#endif
+}
+#endif /* CONFIG_HAVE_GENERIC_SHOW_MEM */
+
/*
* Builds allocation fallback zone lists.
*
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -213,6 +213,9 @@ config VIRT_TO_BUS
config PAGE_WALKER
def_bool n

+config HAVE_GENERIC_SHOW_MEM
+ def_bool n
+
config UNEVICTABLE_LRU
bool "Add LRU list to track non-evictable pages"
default y

2008-06-28 04:25:31

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH 02/20] mm: generic show_mem()

On Fri, Jun 27, 2008 at 01:53:51PM +0200, Johannes Weiner wrote:
> This implements a platform-independent version of show_mem().
>
> Signed-off-by: Johannes Weiner <[email protected]>

Looking at this again, does having this as a Kconfig option really make
sense? We have no tristate in-tree users of this that I can see, wouldn't
this be better off in lib/? It would be preferable not to let the
HAVE_foo stuff get out of hand if we can avoid it.

2008-06-28 10:26:44

by Johannes Weiner

[permalink] [raw]
Subject: Re: [PATCH 02/20] mm: generic show_mem()

Hi,

Paul Mundt <[email protected]> writes:

> On Fri, Jun 27, 2008 at 01:53:51PM +0200, Johannes Weiner wrote:
>> This implements a platform-independent version of show_mem().
>>
>> Signed-off-by: Johannes Weiner <[email protected]>
>
> Looking at this again, does having this as a Kconfig option really make
> sense? We have no tristate in-tree users of this that I can see, wouldn't
> this be better off in lib/? It would be preferable not to let the
> HAVE_foo stuff get out of hand if we can avoid it.

I hate the current Kconfig usage, too. But I figured, if I won't obey
on such decisions by people who maintain it, it won't have a chance to
get in.

So, what do you suggest? Moving it to lib/ and have one simple #define
if the arch wants to use it or not?

Hannes

2008-06-28 17:54:20

by Paul Mundt

[permalink] [raw]
Subject: Re: [PATCH 02/20] mm: generic show_mem()

On Sat, Jun 28, 2008 at 12:25:57PM +0200, Johannes Weiner wrote:
> Paul Mundt <[email protected]> writes:
> > On Fri, Jun 27, 2008 at 01:53:51PM +0200, Johannes Weiner wrote:
> >> This implements a platform-independent version of show_mem().
> >>
> >> Signed-off-by: Johannes Weiner <[email protected]>
> >
> > Looking at this again, does having this as a Kconfig option really make
> > sense? We have no tristate in-tree users of this that I can see, wouldn't
> > this be better off in lib/? It would be preferable not to let the
> > HAVE_foo stuff get out of hand if we can avoid it.
>
> I hate the current Kconfig usage, too. But I figured, if I won't obey
> on such decisions by people who maintain it, it won't have a chance to
> get in.
>
> So, what do you suggest? Moving it to lib/ and have one simple #define
> if the arch wants to use it or not?
>
There's no need for a define. If you move it to lib/ it will just be the
default implementation unless an architecture overloads it with their own
definition. With your current patch set, you should just be able to shove
it in to lib/, drop the Kconfig option, and be good to go.