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.

Reply via email to