Hello,
I have a few enhancement suggestions to kdb mainly for adding in some
additional support for NUMA_K8 kernels. These changes seem to working
fine for us, and we hoped that you might be interested in making use of
some or all of the changes shown below.
Thank you for your time and considerations.
John Blackwood [EMAIL PROTECTED]
Consulting Software Engineer
Concurrent Computer Corporation
-----------------------------------------------------------------------------
The diffs below are based off of the kdb-v4.4-2.6.9-common-1 version
of these files.
The following changes are:
1. kdb/modules/kdbm_pg.c
- Changed the existing kdbm_memmap() i386 version to handle -1
page._count.counter values. The page_counts[] array was increased
in size by 1 to hold the -1 page count values.
- Added memmap/kdbm_memmap() support for x86_64 with discontigmem
(numa) enabled. This version will output either just one numa nodes
statistics if the options node id is specified "memmap node_id".
If the node id is not specified, then a total of all the numa nodes
is output.
2. kdb/modules/kdbm_task.c
Just added output of the 'mempolicy' and 'il_next' task structure
fields in the 'task' command if CONFIG_NUMA is enabled.
3. kdb/modules/kdbm_vm.c
- The kdbm_print_vm() routine now outputs (when the -v option is
specified) the vm_ops 'populate' field and the 'set_policy' and
'set_policy' fields if CONFIG_NUMA is enabled. The 'vm_policy' field
of the vm_area structure is also output if CONFIG_NUMA is enabled.
- Added a new 'mempolicy' command, which is support with the
kdbm_mpol() routine. This command dumps out the mempolicy
structure information. Only present when CONFIG_NUMA is enabled.
You must supply the address of the mempolicy structure for this
command.
- Added a new pgdat command. On non-NUMA systems, this
outputs information for the one pglist_data structure.
On NUMA systems, you can specify a numa node id and
get the pglist_data structure information for any numa node.
Defaults to numa node 0.
-----------------------------------------------------------------------------
diff -ru old/kdb/modules/kdbm_pg.c new/kdb/modules/kdbm_pg.c
--- old/kdb/modules/kdbm_pg.c 2005-05-03 15:51:07.589573107 -0400
+++ new/kdb/modules/kdbm_pg.c 2005-05-03 15:48:24.000000000 -0400
@@ -460,7 +460,7 @@
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
+#ifdef CONFIG_X86
/* According to Steve Lord, this code is ix86 specific. Patches to
extend it to
* other architectures will be greatefully accepted.
*/
@@ -473,19 +473,45 @@
int slab_count = 0;
int dirty_count = 0;
int locked_count = 0;
- int page_counts[9];
+ int page_counts[10]; /* [8] = large counts, [9] = -1 counts */
int buffered_count = 0;
#ifdef buffer_delay
int delay_count = 0;
#endif
int diag;
unsigned long addr;
+#ifdef CONFIG_DISCONTIGMEM
+ int node_id = -1, found_node = 0;
+ int tot_page_count = 0;
+ unsigned long unode_id;
+ pg_data_t *pgdat;
+
+ if (argc == 1) { /* node_id was specified */
+ diag = kdbgetularg(argv[argc], &unode_id);
+ if (diag)
+ return diag;
+ node_id = (int)unode_id;
+ }
+ else if (argc)
+ return KDB_ARGCOUNT;
- addr = (unsigned long)mem_map;
- page_count = max_mapnr;
+ tot_page_count = 0;
memset(page_counts, 0, sizeof(page_counts));
- for (i = 0; i < page_count; i++) {
+ for_each_pgdat(pgdat) {
+ if ((node_id != -1) && (pgdat->node_id != node_id))
+ continue;
+ found_node = 1;
+ addr = (unsigned long)pgdat->node_mem_map;
+ page_count = pgdat->node_spanned_pages;
+ tot_page_count += page_count;
+#else
+ addr = (unsigned long)mem_map;
+ page_count = max_mapnr;
+ memset(page_counts, 0, sizeof(page_counts));
+#endif
+
+ for (i = 0; i < page_count; i++) {
if ((diag = kdb_getarea(page, addr)))
return(diag);
addr += sizeof(page);
@@ -496,7 +522,9 @@
dirty_count++;
if (PageLocked(&page))
locked_count++;
- if (page._count.counter < 8)
+ if (page._count.counter == -1)
+ page_counts[9]++;
+ else if (page._count.counter < 8)
page_counts[page._count.counter]++;
else
page_counts[8]++;
@@ -507,9 +535,18 @@
delay_count++;
#endif
}
-
+ }
+#ifdef CONFIG_DISCONTIGMEM
}
-
+ page_count = tot_page_count;
+ if (node_id != -1) {
+ if (!found_node) {
+ kdb_printf("Node %d does not exist.\n", node_id);
+ return 0;
+ }
+ kdb_printf("Node %d pages:\n", node_id);
+ }
+#endif
kdb_printf(" Total pages: %6d\n", page_count);
kdb_printf(" Slab pages: %6d\n", slab_count);
kdb_printf(" Dirty pages: %6d\n", dirty_count);
@@ -518,6 +555,7 @@
#ifdef buffer_delay
kdb_printf(" Delalloc pages: %6d\n", delay_count);
#endif
+ kdb_printf(" -1 page count: %6d\n", page_counts[9]);
for (i = 0; i < 8; i++) {
kdb_printf(" %d page count: %6d\n",
i, page_counts[i]);
@@ -525,7 +563,7 @@
kdb_printf(" high page count: %6d\n", page_counts[8]);
return 0;
}
-#endif /* CONFIG_X86 && !CONFIG_X86_64 */
+#endif /* CONFIG_X86 */
static int __init kdbm_pg_init(void)
{
@@ -538,8 +576,12 @@
kdb_register("inode_pages", kdbm_inode_pages, "<inode *>", "Display
pages in an inode", 0);
kdb_register("req", kdbm_request, "<vaddr>", "dump request struct", 0);
kdb_register("rqueue", kdbm_rqueue, "<vaddr>", "dump request queue", 0);
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
+#ifdef CONFIG_X86
+#ifndef CONFIG_DISCONTIGMEM
kdb_register("memmap", kdbm_memmap, "", "page table summary", 0);
+#else
+ kdb_register("memmap", kdbm_memmap, "<nodeid>", "page table summary",
0);
+#endif
#endif
return 0;
@@ -557,7 +599,7 @@
kdb_unregister("inode_pages");
kdb_unregister("req");
kdb_unregister("rqueue");
-#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
+#ifdef CONFIG_X86
kdb_unregister("memmap");
#endif
}
diff -ru old/kdb/modules/kdbm_task.c new/kdb/modules/kdbm_task.c
--- old/kdb/modules/kdbm_task.c 2005-05-03 15:51:10.420414385 -0400
+++ new/kdb/modules/kdbm_task.c 2005-05-03 15:48:24.000000000 -0400
@@ -102,6 +102,12 @@
" utime=%ld stime=%ld cutime=%ld cstime=%ld\n",
tp->utime, tp->stime, tp->signal->cutime, tp->signal->cstime);
+#ifdef CONFIG_NUMA
+ kdb_printf(
+ " mempolicy=0x%p il_next=%d\n",
+ tp->mempolicy, tp->il_next);
+#endif
+
out:
if (tp)
kfree(tp);
diff -ru old/kdb/modules/kdbm_vm.c new/kdb/modules/kdbm_vm.c
--- old/kdb/modules/kdbm_vm.c 2005-05-03 15:51:13.790225372 -0400
+++ new/kdb/modules/kdbm_vm.c 2005-05-03 16:46:00.465394659 -0400
@@ -83,13 +83,21 @@
kdb_printf("vm_ops->open = 0x%p\n", vp->vm_ops->open);
kdb_printf("vm_ops->close = 0x%p\n", vp->vm_ops->close);
kdb_printf("vm_ops->nopage = 0x%p\n", vp->vm_ops->nopage);
+ kdb_printf("vm_ops->populate = 0x%p\n", vp->vm_ops->populate);
#ifdef HAVE_VMOP_MPROTECT
kdb_printf("vm_ops->mprotect = 0x%p\n", vp->vm_ops->mprotect);
#endif
+#ifdef CONFIG_NUMA
+ kdb_printf("vm_ops->set_policy = 0x%p\n",
vp->vm_ops->set_policy);
+ kdb_printf("vm_ops->get_policy = 0x%p\n",
vp->vm_ops->get_policy);
+#endif
}
kdb_printf("vm_pgoff = 0x%lx\n", vp->vm_pgoff);
kdb_printf("vm_file = 0x%p\n", (void *) vp->vm_file);
kdb_printf("vm_private_data = 0x%p\n", vp->vm_private_data);
+#ifdef CONFIG_NUMA
+ kdb_printf("vm_policy = 0x%p\n", vp->vm_policy);
+#endif
return 0;
}
@@ -115,6 +123,203 @@
return 0;
}
+
+#ifdef CONFIG_NUMA
+#include <linux/mempolicy.h>
+
+/*
+ * kdbm_mpol
+ *
+ * This function implements the 'mempolicy' command.
+ * Print a struct mempolicy.
+ *
+ * mempolicy <address> Print struct mempolicy at <address>
+ */
+static int
+kdbm_mpol(int argc, const char **argv, const char **envp, struct
pt_regs *regs)
+{
+ unsigned long addr;
+ long offset = 0;
+ int nextarg;
+ int err = 0;
+ struct mempolicy *mp = NULL;
+
+ if (argc != 1)
+ return KDB_ARGCOUNT;
+
+ nextarg = 1;
+ if ((err = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset,
+ NULL, regs)) != 0)
+ return(err);
+
+ if (!(mp = kmalloc(sizeof(*mp), GFP_ATOMIC))) {
+ kdb_printf("%s: cannot kmalloc mp\n", __FUNCTION__);
+ goto out;
+ }
+
+ if ((err = kdb_getarea(*mp, addr))) {
+ kdb_printf("%s: invalid mempolicy address\n", __FUNCTION__);
+ goto out;
+ }
+
+ kdb_printf("struct mempolicy at 0x%p\n", (struct mempolicy *)addr);
+ kdb_printf(" refcnt %d\n", atomic_read(&mp->refcnt));
+
+ switch (mp->policy) {
+ case MPOL_DEFAULT:
+ kdb_printf(" policy %d (MPOL_DEFAULT)\n", mp->policy);
+ break;
+
+ case MPOL_PREFERRED:
+ kdb_printf(" policy %d (MPOL_PREFERRED)\n", mp->policy);
+ kdb_printf(" preferred_node %d\n", mp->v.preferred_node);
+ break;
+
+ case MPOL_BIND:
+ {
+ int i, z;
+ struct zone *zonep;
+ pg_data_t *pgdatp;
+
+ kdb_printf(" policy %d (MPOL_BIND)\n", mp->policy);
+ kdb_printf(" zonelist 0x%p\n", mp->v.zonelist);
+
+ for (i = 0; mp->v.zonelist; i++) {
+ zonep = mp->v.zonelist->zones[i];
+ if (!zonep) {
+ break;
+ }
+ kdb_printf(" 0x%p", zonep);
+ for_each_pgdat(pgdatp) {
+ for (z = 0; z < MAX_NR_ZONES; z++) {
+ if (zonep == &pgdatp->node_zones[z]) {
+ kdb_printf(" (node %d node_zones[%d])",
+ pgdatp->node_id, z);
+ break;
+ }
+ }
+ if (z != MAX_NR_ZONES)
+ break; /* found it */
+ }
+ kdb_printf("\n");
+ }
+ break;
+ }
+
+ case MPOL_INTERLEAVE:
+ {
+ int i, nlongs;
+ unsigned long *longp;
+
+ kdb_printf(" policy %d (MPOL_INTERLEAVE)\n", mp->policy);
+ nlongs = (int)BITS_TO_LONGS(MAX_NUMNODES);
+ kdb_printf(" nodes:");
+ longp = mp->v.nodes;
+ for (i = 0; i < nlongs; i++, longp++)
+ kdb_printf(" 0x%lx ", *longp);
+ kdb_printf("\n");
+ break;
+ }
+
+ default:
+ kdb_printf(" policy %d (unknown)\n", mp->policy);
+ break;
+ }
+out:
+ if (mp)
+ kfree(mp);
+ return err;
+}
+
+#endif /* CONFIG_NUMA */
+
+/*
+ * kdbm_pgdat
+ *
+ * This function implements the 'pgdat' command.
+ * Print a struct pglist_data (pg_data_t).
+ *
+ * pgdat <node_id> Print struct pglist_data for node <node_id>.
+ *
+ * Print pglist_data for node 0 if node_id not specified,
+ * or print the one pglist_data structure if !CONFIG_NUMA.
+ */
+static int
+kdbm_pgdat(int argc, const char **argv, const char **envp, struct
pt_regs *regs)
+{
+ int i, err = 0, node_id = 0;
+ pg_data_t *pgdatp = NULL;
+
+#ifdef CONFIG_NUMA
+ if (argc > 1)
+ return KDB_ARGCOUNT;
+ if (argc == 1) {
+ int nextarg;
+ long offset = 0;
+ unsigned long node_id_ul;
+
+ nextarg = 1;
+ if ((err = kdbgetaddrarg(argc, argv, &nextarg, &node_id_ul,
+ &offset, NULL, regs)) != 0) {
+ return(err);
+ }
+ node_id = (int)node_id_ul;
+ }
+#endif
+ for_each_pgdat(pgdatp) {
+ if (pgdatp->node_id == node_id)
+ break;
+ }
+ if (!pgdatp) {
+ kdb_printf("%s: specified node not found\n", __FUNCTION__);
+ return 0;
+ }
+ kdb_printf("struct pglist_data at 0x%p node_id = %d\n",
+ pgdatp, pgdatp->node_id);
+
+ for (i = 0; i < GFP_ZONETYPES; i++) {
+ struct zone **zonep;
+
+ zonep = pgdatp->node_zonelists[i].zones;
+ kdb_printf(" node_zonelists[%d] at 0x%p\n", i, zonep);
+
+ while (1) {
+ int z;
+ pg_data_t *tmp_pgdatp;
+
+ if (*zonep == NULL)
+ break;
+ kdb_printf(" 0x%p", *zonep);
+ for_each_pgdat(tmp_pgdatp) {
+ for (z = 0; z < MAX_NR_ZONES; z++) {
+ if (*zonep == &tmp_pgdatp->node_zones[z]) {
+ kdb_printf(" (node %d node_zones[%d])",
+ tmp_pgdatp->node_id, z);
+ break;
+ }
+ }
+ if (z != MAX_NR_ZONES)
+ break; /* found it */
+ }
+ kdb_printf("\n");
+ zonep++;
+ }
+ }
+ kdb_printf(" nr_zones = %d", pgdatp->nr_zones);
+ kdb_printf(" node_mem_map = 0x%p\n", pgdatp->node_mem_map);
+ kdb_printf(" bdata = 0x%p", pgdatp->bdata);
+ kdb_printf(" node_start_pfn = 0x%lx\n", pgdatp->node_start_pfn);
+ kdb_printf(" node_present_pages = %ld (0x%lx)\n",
+ pgdatp->node_present_pages, pgdatp->node_present_pages);
+ kdb_printf(" node_spanned_pages = %ld (0x%lx)\n",
+ pgdatp->node_spanned_pages, pgdatp->node_spanned_pages);
+ kdb_printf(" kswapd = 0x%p\n", pgdatp->kswapd);
+ kdb_printf(" pgdat_next = 0x%p\n", pgdatp->pgdat_next);
+
+ return err;
+}
+
+
/*
* kdbm_vm
*
@@ -648,6 +853,12 @@
{
kdb_register("vm", kdbm_vm, "[-v] <vaddr>", "Display vm_area_struct",
0);
kdb_register("vmp", kdbm_vm, "[-v] <pid>", "Display all
vm_area_struct for <pid>", 0);
+#ifdef CONFIG_NUMA
+ kdb_register("mempolicy", kdbm_mpol, "<vaddr>", "Display mempolicy
structure", 0);
+ kdb_register("pgdat", kdbm_pgdat, "<node_id>", "Display pglist_data
node structure", 0);
+#else
+ kdb_register("pgdat", kdbm_pgdat, "", "Display pglist_data node
structure", 0);
+#endif
kdb_register("pte", kdbm_pte, "( -m <mm> | -p <pid> ) <vaddr>
[<nbytes>]", "Display pte_t for mm_struct or pid", 0);
kdb_register("dentry", kdbm_dentry, "<dentry>", "Display interesting
dentry stuff", 0);
kdb_register("filp", kdbm_fp, "<filp>", "Display interesting filp
stuff", 0);
@@ -663,6 +874,10 @@
{
kdb_unregister("vm");
kdb_unregister("vmp");
+#ifdef CONFIG_NUMA
+ kdb_unregister("mempolicy");
+#endif
+ kdb_unregister("pgdat");
kdb_unregister("pte");
kdb_unregister("dentry");
kdb_unregister("filp");
---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.