[PATCH RFC] vz extension: vzlist, ctid, vzps commands
by Vasily Averin
vz extension contains OpenVZ specific commands:
vzlist shows list of OpenVZ containers,
vzps shows all tasks executed inside of specified container,
ctid shows ContainerID of given task.
Signed-off-by: Vasily Averin <vvs(a)parallels.com>
---
extensions/vz.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 345 insertions(+)
create mode 100644 extensions/vz.c
diff --git a/extensions/vz.c b/extensions/vz.c
new file mode 100644
index 0000000..f48d428
--- /dev/null
+++ b/extensions/vz.c
@@ -0,0 +1,345 @@
+/* vz.c - crash extension for OpenVZ containers
+ *
+ * Copyright (C) 2015 Vasily Averin
+ * Copyright (C) 2015 Parallels IP Holdings GmbH.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "defs.h"
+
+#define VZ_MEMBER_OFFSET_INIT(X,Y,Z) (vz_offset_table.X=MEMBER_OFFSET(Y,Z))
+#define VZ_OFFSET(X) (OFFSET_verify(vz_offset_table.X, (char *)__FUNCTION__, __FILE__, __LINE__, #X))
+#define VZ_INIT 0x1
+
+struct vz_offset_table {
+ long task_veinfo;
+ long veinfo_ve;
+ long ve_veid;
+ long ve_nsproxy;
+ long nsproxy_pidns;
+ long pidns_init;
+};
+
+static struct vz_offset_table vz_offset_table = { 0 };
+static int init_flags = 0;
+static int id_size;
+
+void vz_init(void);
+void vz_fini(void);
+
+static ulong
+ve_to_task(ulong ve)
+{
+ ulong ns, pidns, task;
+
+ readmem(ve + VZ_OFFSET(ve_nsproxy), KVADDR, &ns,
+ sizeof(ulong), "ve_struct.ve_ns", FAULT_ON_ERROR);
+ readmem(ns + VZ_OFFSET(nsproxy_pidns), KVADDR, &pidns,
+ sizeof(ulong), "nsproxy.ve_pidns", FAULT_ON_ERROR);
+ readmem(pidns + VZ_OFFSET(pidns_init), KVADDR, &task,
+ sizeof(ulong), "pid_namespace.child_reaper", FAULT_ON_ERROR);
+
+ return task;
+}
+
+#define VZLIST_HEADER \
+" CTID VE_STRUCT TASK PID COMM\n"
+
+static void
+show_container(ulong ve, ulong ctid, ulong flag)
+{
+ ulong task;
+ struct task_context *tc;
+
+ task = ve_to_task(ve);
+ tc = task_to_context(task);
+
+ if (!(flag & PS_NO_HEADER))
+ fprintf(fp, VZLIST_HEADER);
+
+ fprintf(fp, "%9ld %16lx %16lx %6ld %s\n",
+ ctid, ve, tc->task, tc->pid, tc->comm);
+ return;
+}
+
+static void
+show_containers(ulong ctid)
+{
+ struct list_data list_data, *ld;
+ ulong ve, id, flag = 0;
+ int i, cnt;
+
+ ld = &list_data;
+ BZERO(ld, sizeof(struct list_data));
+ ld->flags |= LIST_ALLOCATE;
+
+ ld->start = ld->end = symbol_value("ve_list_head");
+ ld->list_head_offset = 0;
+
+ cnt = do_list(ld);
+
+ for (i = 1; i < cnt; i++) {
+ id = 0;
+ ve = ld->list_ptr[i];
+ readmem(ve + VZ_OFFSET(ve_veid), KVADDR, &id,
+ id_size, "ve_struct.veid", FAULT_ON_ERROR);
+ if ((ctid == -1) || ctid == id) {
+ show_container(ve, id, flag);
+ flag = PS_NO_HEADER;
+ }
+ }
+ return;
+}
+
+void
+cmd_vzlist(void)
+{
+ int c;
+ ulong ctid = -1;
+
+ while ((c = getopt(argcnt, args, "E:")) != EOF) {
+ switch(c)
+ {
+ case 'E':
+ ctid = stol(optarg, FAULT_ON_ERROR, NULL);
+ break;
+ default:
+ argerrs++;
+ break;
+ }
+ }
+ if (argerrs) {
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ return;
+ }
+
+ show_containers(ctid);
+ return;
+}
+
+char *help_vzlist[] = {
+"vzlist",
+"shows list of runnig OpenVZ containers",
+"[-E CTID]",
+"If no argument is entered, command shows IDs of all running containers\n",
+" -E Container ID",
+"\nEXAMPLES",
+"%s> vzlist",
+" CTID VE_STRUCT TASK PID COMM",
+" 121 ffff8801491e7000 ffff8801493d0ff0 95990 init",
+" 123 ffff880135a37000 ffff8803fb0a3470 95924 init",
+" 321 ffff88045a778000 ffff880400616300 95923 init",
+" 700 ffff88019ddae000 ffff88019ddd4fb0 95882 init",
+" 503 ffff88045a84e800 ffff8803c3c782c0 95902 init",
+" 122 ffff8804004ea000 ffff88045612afb0 95886 init",
+" 600 ffff88016e467000 ffff880459d653f0 95885 init",
+" 0 ffffffff81aaa220 ffff88045e530b30 1 init",
+NULL
+};
+
+static ulong
+task_to_ctid(ulong task)
+{
+ ulong veinfo, ve, ctid = 0;
+
+ veinfo = task + VZ_OFFSET(task_veinfo);
+ readmem(veinfo + VZ_OFFSET(veinfo_ve), KVADDR, &ve,
+ sizeof(ulong), "ve_task_info.exec_env", FAULT_ON_ERROR);
+ readmem(ve + VZ_OFFSET(ve_veid), KVADDR, &ctid,
+ id_size, "ve_struct.veid", FAULT_ON_ERROR);
+
+ return ctid;
+}
+
+static void
+show_ctid(struct task_context *tc, ulong flag)
+{
+ ulong ctid;
+
+ ctid = task_to_ctid(tc->task);
+ if (!(flag & PS_NO_HEADER))
+ fprintf(fp, " CTID PID TASK COMM\n");
+
+ fprintf(fp, "%9ld %6ld %16lx %s\n",
+ ctid, tc->pid, tc->task, tc->comm);
+ return;
+}
+
+void
+cmd_ctid(void)
+{
+ ulong value, flag = 0;
+ struct task_context *tc;
+ int c;
+
+ while ((c = getopt(argcnt, args, "")) != EOF) {
+ switch(c)
+ {
+ default:
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ return;
+ }
+ }
+
+ if (!args[optind]) {
+ tc = task_to_context(CURRENT_TASK());
+ show_ctid(tc, flag);
+ }
+ while (args[optind]) {
+ switch (str_to_context(args[optind], &value, &tc))
+ {
+ case STR_PID:
+ case STR_TASK:
+ break;
+ case STR_INVALID:
+ error(INFO, "invalid task or pid value: %s\n",
+ args[optind]);
+ default:
+ argerrs++;
+ break;
+ }
+ if (argerrs)
+ break;
+ show_ctid(tc, flag);
+ flag = PS_NO_HEADER;
+ optind++;
+ }
+ if (argerrs)
+ cmd_usage(pc->curcmd, SYNOPSIS);
+
+ return;
+}
+
+char *help_ctid[] = {
+"ctid",
+"shows Container ID of given tasks",
+"[task|pid]",
+" If no argument is entered, command shows CTID of current task",
+"\nEXAMPLES",
+"%s> ctid 99583",
+" CTID PID TASK COMM",
+" 121 99583 ffff880203e56f30 httpd",
+NULL
+};
+
+static void
+show_vzps(ulong ctid)
+{
+ struct task_context *tc;
+ ulong flag;
+ int i;
+
+ tc = FIRST_CONTEXT();
+ for (i = 0; i < RUNNING_TASKS(); i++, tc++) {
+ ulong id = task_to_ctid(tc->task);
+ if ((ctid == -1) || (ctid == id)) {
+ show_ctid(tc, flag);
+ flag = PS_NO_HEADER;
+ }
+ }
+ return;
+}
+
+void
+cmd_vzps(void)
+{
+ ulong ctid = -1;
+ int c;
+
+ while ((c = getopt(argcnt, args, "E:")) != EOF) {
+ switch(c)
+ {
+ case 'E':
+ ctid = stol(optarg, FAULT_ON_ERROR, NULL);
+ break;
+ default:
+ argerrs++;
+ break;
+ }
+ }
+ if (argerrs)
+ cmd_usage(pc->curcmd, SYNOPSIS);
+
+ show_vzps(ctid);
+ return;
+}
+
+char *help_vzps[] = {
+"vzps",
+"shows list of tasks related to specified CTID",
+" [ -E CTID]",
+" If no argument is entered, command shows CTID for all processes\n",
+"\nEXAMPLES",
+"%s> vzps -E 121",
+" CTID PID TASK COMM",
+" 121 95990 ffff8801493d0ff0 init",
+" 121 95996 ffff8803c3e3b0f0 kthreadd/121",
+" 121 95997 ffff8803cd3aacb0 khelper/121",
+" 121 97267 ffff880405e4b2f0 udevd",
+" 121 99341 ffff8803c3fd2440 syslogd",
+" 121 99404 ffff880405e0c2c0 klogd",
+" 121 99424 ffff8803fb0f68c0 sshd",
+" 121 99445 ffff8801493d0500 xinetd",
+" 121 99557 ffff8804599f9230 sendmail",
+" 121 99568 ffff8804591b00c0 sendmail",
+" 121 99583 ffff880203e56f30 httpd",
+" 121 99594 ffff88016e4e01c0 crond",
+" 121 99614 ffff8803fb26cf70 xfs",
+" 121 99624 ffff88045a6ce2c0 saslauthd",
+" 121 99625 ffff8801ce134ff0 saslauthd",
+" 121 248691 ffff88040e2ee9c0 httpd",
+NULL
+};
+
+static struct command_table_entry command_table[] = {
+ { "vzlist", cmd_vzlist, help_vzlist, 0},
+ { "ctid", cmd_ctid, help_ctid, 0},
+ { "vzps", cmd_vzps, help_vzps, 0},
+ { NULL },
+};
+
+void __attribute__((constructor))
+vz_init(void)
+{
+ if (init_flags & VZ_INIT)
+ return;
+
+ if (!symbol_exists("ve_list_head")) {
+ fprintf(fp, "vz commands only work on OpenVZ kernels\n");
+ return;
+ }
+ init_flags |= VZ_INIT;
+
+ BNEG(&vz_offset_table, sizeof(vz_offset_table));
+
+ if (STRUCT_EXISTS("ve_task_info")) {
+ VZ_MEMBER_OFFSET_INIT(task_veinfo,
+ "task_struct", "ve_task_info");
+ VZ_MEMBER_OFFSET_INIT(veinfo_ve, "ve_task_info", "exec_env");
+ }
+ if (STRUCT_EXISTS("ve_struct")) {
+ VZ_MEMBER_OFFSET_INIT(ve_veid, "ve_struct", "veid");
+ VZ_MEMBER_OFFSET_INIT(ve_nsproxy, "ve_struct", "ve_ns");
+ id_size = MEMBER_SIZE("ve_struct", "veid");
+ }
+ if (STRUCT_EXISTS("nsproxy")) {
+ VZ_MEMBER_OFFSET_INIT(nsproxy_pidns, "nsproxy", "pid_ns");
+ }
+ if (STRUCT_EXISTS("pid_namespace"))
+ VZ_MEMBER_OFFSET_INIT(pidns_init,
+ "pid_namespace", "child_reaper");
+
+ register_extension(command_table);
+}
+
+void __attribute__((destructor))
+vz_fini(void) { }
--
1.7.12.4
9 years, 7 months
Re: [Crash-utility] [PATCH] cmd_ps message cleanup
by Dave Anderson
----- Original Message -----
> ps -L no longer exists
>
> Signed-off-by: Vasily Averin <vvs(a)parallels.com>
> ---
> task.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/task.c b/task.c
> index c875bb9..bc7911b 100644
> --- a/task.c
> +++ b/task.c
> @@ -2843,7 +2843,7 @@ task_struct_member(struct task_context *tc, unsigned
> int radix, struct reference
> }
>
> static char *ps_exclusive =
> - "-a, -t, -c, -p, -g, -l, -m, -L, -S and -r flags are all mutually-exclusive\n";
> + "-a, -t, -c, -p, -g, -l, -m, -S and -r flags are all mutually-exclusive\n";
>
> static void
> check_ps_exclusive(ulong flag, ulong thisflag)
> --
> 1.7.12.4
Done -- queued for crash-7.1.1:
https://github.com/crash-utility/crash/commit/f1dbe49fa87682c2deee79a96e2...
Thanks,
Dave
9 years, 7 months
Value of
by Karlsson, Jan
Hi Dave
I was looking in the file arm64.c at function arm64_translate_pte and saw the line:
if (!page_present && (pte & PTE_FILE)) {
I also saw that there are two versions of the value PTE_FILE (see also defs.h) and the following code is included in arm64.c in arm64_init:
if (THIS_KERNEL_VERSION >= LINUX(3,10,0)) {
machdep->machspec->pte_protnone = PTE_PROT_NONE_3_10;
machdep->machspec->pte_file = PTE_FILE_3_10;
} else {
machdep->machspec->pte_protnone = PTE_PROT_NONE;
machdep->machspec->pte_file = PTE_FILE;
}
So should not the first mentioned line be changed to:
if (!page_present && (pte & machdep->machspec->pte_file)) {
Jan
Jan Karlsson
Senior Software Engineer
System Assurance
Sony Mobile Communications
Tel: +46 703 062 174
jan.karlsson(a)sonymobile.com<mailto:Firstname.Lastname@sonymobile.com>
sonymobile.com<http://sonymobile.com/>
[cid:image001.gif@01D08325.5A5F0670]
9 years, 7 months
[PATCH] Speed up usage of a flat makedumpfile vmcore.
by Don Slutz
Using a bubble sort is slow, switch to an insertion sort.
bubble sort: real 3m45.168s
insertion sort: real 0m3.164s
Signed-off-by: Don Slutz <dslutz(a)verizon.com>
---
I do have a big (32G sized file, that gzipped is 357M).
let me know if you want it.
It is the same as the xen rename of dom0
makedumpfile.c | 56 +++++++++++++++++++++++++-------------------------------
1 file changed, 25 insertions(+), 31 deletions(-)
diff --git a/makedumpfile.c b/makedumpfile.c
index f6834b9..c76e22c 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -56,8 +56,10 @@ store_flat_data_array(char *file, struct flat_data **fda)
{
int result = FALSE, fd;
int64_t offset_fdh;
+ int64_t offset_report = 0;
unsigned long long num_allocated = 0;
unsigned long long num_stored = 0;
+ unsigned long long sort_idx;
unsigned long long size_allocated;
struct flat_data *ptr = NULL, *cur, *new;
struct makedumpfile_data_header fdh;
@@ -100,11 +102,34 @@ store_flat_data_array(char *file, struct flat_data **fda)
break;
}
cur = ptr + num_stored;
+ sort_idx = num_stored;
+ while (sort_idx) {
+ new = ptr + --sort_idx;
+ if (new->off_rearranged >= fdh.offset) {
+ cur->off_flattened = new->off_flattened;
+ cur->off_rearranged = new->off_rearranged;
+ cur->buf_size = new->buf_size;
+ cur = new;
+ } else {
+ if (CRASHDEBUG(1) && sort_idx + 1 != num_stored) {
+ fprintf(fp,
+ "makedumpfile: Moved from %lld to %lld\n",
+ num_stored, sort_idx + 1);
+ }
+ break;
+ }
+ }
cur->off_flattened = offset_fdh + sizeof(fdh);
cur->off_rearranged = fdh.offset;
cur->buf_size = fdh.buf_size;
num_stored++;
+ if (CRASHDEBUG(1) && (fdh.offset >> 30) > (offset_report >> 30)) {
+ fprintf(fp, "makedumpfile: At %lld GiB\n",
+ fdh.offset >> 30);
+ offset_report = fdh.offset;
+ }
+
/* seek for next makedumpfile_data_header. */
if (lseek(fd, fdh.buf_size, SEEK_CUR) < 0) {
error(INFO, "%s: seek error (flat format)\n", file);
@@ -121,35 +146,6 @@ store_flat_data_array(char *file, struct flat_data **fda)
return num_stored;
}
-static void
-sort_flat_data_array(struct flat_data **fda, unsigned long long num_fda)
-{
- unsigned long long i, j;
- struct flat_data tmp, *cur_i, *cur_j;
-
- for (i = 0; i < num_fda - 1; i++) {
- for (j = i + 1; j < num_fda; j++) {
- cur_i = *fda + i;
- cur_j = *fda + j;
-
- if (cur_i->off_rearranged < cur_j->off_rearranged)
- continue;
-
- tmp.off_flattened = cur_i->off_flattened;
- tmp.off_rearranged = cur_i->off_rearranged;
- tmp.buf_size = cur_i->buf_size;
-
- cur_i->off_flattened = cur_j->off_flattened;
- cur_i->off_rearranged = cur_j->off_rearranged;
- cur_i->buf_size = cur_j->buf_size;
-
- cur_j->off_flattened = tmp.off_flattened;
- cur_j->off_rearranged = tmp.off_rearranged;
- cur_j->buf_size = tmp.buf_size;
- }
- }
-}
-
static int
read_all_makedumpfile_data_header(char *file)
{
@@ -161,8 +157,6 @@ read_all_makedumpfile_data_header(char *file)
if (retval < 0)
return FALSE;
- sort_flat_data_array(&fda, num);
-
afd.num_array = num;
afd.array = fda;
--
1.8.4
9 years, 7 months
[PATCH 1/1] CLI list command, print deep structure members
by Alexandr Terekhov
Hi Dave,
I found it useful to be able listing structure's fields which are resided deeper than the first level:
crash> list super_block.s_list -s super_block.s_id,s_dquot.info[1].dqi_dirty_list,s_dquot.dqonoff_mutex.count.counter -H 0xc0a9c800
de805c00
s_id = "sysfs\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
s_dquot.info[1].dqi_dirty_list = {
next = 0x0,
prev = 0x0
},
s_dquot.dqonoff_mutex.count.counter = 1
de805800
s_id = "rootfs\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
s_dquot.info[1].dqi_dirty_list = {
next = 0x0,
prev = 0x0
},
s_dquot.dqonoff_mutex.count.counter = 1
Here is a draft patch which contains corresponding logic.
I will appreciate your comments and suggestions.
Best regards,
Alexandr
--- crash-7.1.0.orig/tools.c 2015-02-06 21:44:11.000000000 +0300
+++ crash-7.1.0/tools.c 2015-04-28 14:09:40.764966266 +0300
@@ -3526,13 +3526,9 @@
dump_struct(ld->structname[i],
next - ld->list_head_offset, radix);
break;
- case 1:
+ default:
dump_struct_members(ld, i, next);
break;
- default:
- error(FATAL,
- "invalid structure reference: %s\n",
- ld->structname[i]);
}
}
}
--- crash-7.1.0.orig/symbols.c 2015-02-06 21:44:11.000000000 +0300
+++ crash-7.1.0/symbols.c 2015-04-28 13:46:12.760992540 +0300
@@ -93,6 +93,7 @@
#define PARSE_FOR_DATA (1)
#define PARSE_FOR_DECLARATION (2)
static void parse_for_member(struct datatype_member *, ulong);
+static void parse_for_member_new(struct datatype_member *, ulong);
static int show_member_offset(FILE *, struct datatype_member *, char *);
@@ -5576,17 +5577,19 @@
FREEBUF(buf);
error(FATAL, "invalid structure name: %s\n", dm->name);
}
+/*
if (!MEMBER_EXISTS(dm->name, dm->member)) {
FREEBUF(buf);
error(FATAL, "invalid structure member name: %s\n",
dm->member);
}
-
+*/
set_temporary_radix(radix, &restore_radix);
open_tmpfile();
print_struct(dm->name, addr);
- parse_for_member(dm, PARSE_FOR_DATA);
+/* parse_for_member(dm, PARSE_FOR_DATA); */
+ parse_for_member_new(dm, PARSE_FOR_DATA);
close_tmpfile();
restore_current_radix(restore_radix);
@@ -7251,6 +7254,206 @@
fprintf(ofp, ")\n");
}
+struct struct_elem {
+ char field_name[BUFSIZE];
+ char value[BUFSIZE];
+ unsigned char is_array;
+
+
+ struct struct_elem *parent;
+ struct struct_elem *inner;
+ struct struct_elem *next;
+ struct struct_elem *prev;
+};
+
+#define ALLOC_XXX_ELEMENT(xxx, clone_parent, is_array_root) \
+{ \
+ if (NULL == current) { \
+ return; \
+ } \
+ current->xxx = calloc(1, sizeof(struct struct_elem)); \
+ if (NULL == current->xxx) \
+ error(FATAL, "cannot allocate any more memory!\n"); \
+ if (clone_parent) current->xxx->parent = current->parent; \
+ else current->xxx->parent = current; \
+ current = current->xxx; \
+ current->is_array = is_array_root; \
+}
+
+#define ALLOC_INNER_ELEMENT ALLOC_XXX_ELEMENT(inner, 0, 0)
+#define ALLOC_NEXT_ELEMENT ALLOC_XXX_ELEMENT(next, 1, 0)
+#define ALLOC_ARRAY_ELEMENT ALLOC_XXX_ELEMENT(inner, 0, 1)
+
+unsigned char is_right_brace(const char *b) {
+ unsigned char r = 0;
+ for (; *b == ' '; b++);
+ if (*b == '}') {
+ b++;
+ r = 1;
+ if (*b == '}')
+ b++;
+ }
+
+ if (*b == ',')
+ b++;
+
+ if (*b == '\0')
+ return r;
+ else
+ return 0;
+}
+
+struct struct_elem *find_node(struct struct_elem *s, char *n) {
+ char *p, *b, *e;
+ struct struct_elem *f;
+ unsigned i;
+ do {
+ f = NULL;
+ /* [n .. p] - struct member with index*/
+ if (NULL == (p = strstr(n, ".")))
+ p = n + strlen(n);
+
+ /* [n .. b] - struct member without index*/
+ for (b = n; (b < p) && (*b != '['); b++);
+
+ while (s) {
+
+ if (0 == memcmp(s->field_name, n, b - n)) {
+ f = s; // Keep found node
+ s = s->inner;
+ if (*b == '[') {
+ i = strtol(b + 1, &e, 10);
+ if (!(s->is_array && *e == ']'&& (e != b + 1)))
+ return NULL;
+
+ while (i && s) {
+ s = s->next;
+ if (s)
+ i -= !!s->is_array;
+ }
+
+ }
+ break;
+ }
+ if (NULL == s)
+ return NULL;
+ s = s->next;
+ if (s && s->is_array)
+ break; // That is we encounter the next array item
+ }
+ if (*p == '.') n = p + 1; else n = p;
+ } while (*n);
+
+ return f;
+}
+
+
+
+void dump_node(struct struct_elem *p, char *f, unsigned char level, unsigned char is_array) {
+ unsigned int i;
+ if (p == NULL)
+ return;
+ do {
+#define PUT_INDENTED_STRING(m, ...) { \
+ for (i = 0; i++ < 2 * (m * is_array + level); printf(" ")); \
+ printf(__VA_ARGS__); }
+
+ if (p->inner) {
+ PUT_INDENTED_STRING(1, "%s = %s\n", f ? f : p->field_name, p->inner->is_array ? "{{" : "{");
+ dump_node(p->inner, NULL, is_array + level + 1, p->inner->is_array);
+ PUT_INDENTED_STRING(1, "%s%s\n", p->inner->is_array ? "}}" : "}", p->next ? "," : "");
+ } else {
+ PUT_INDENTED_STRING(1, "%s = %s%s\n", f ? f : p->field_name, p->value, p->next && !p->next->is_array ? "," : "");
+ }
+ if (level) {
+ p = p->next;
+ if (p && p->is_array)
+ PUT_INDENTED_STRING(0, "}, {\n");
+ }
+ } while (p && level);
+}
+
+void free_structure(struct struct_elem *p) {
+ if (p == NULL)
+ return;
+ free_structure(p->inner);
+ free_structure(p->next);
+ free(p);
+}
+
+static void
+parse_for_member_new(struct datatype_member *dm, ulong flag)
+{
+ struct struct_elem *current = NULL, *root = NULL;
+
+ char buf[BUFSIZE];
+ char *p, *p1;
+ unsigned int len;
+ unsigned char trailing_comma;
+
+ rewind(pc->tmpfile);
+
+ while (fgets(buf, BUFSIZE, pc->tmpfile)) {
+ len = strlen(buf) - 1;
+ for (; buf[len] <= ' '; buf[len--] = '\0');
+ if ((trailing_comma = (buf[len] == ',')))
+ buf[len--] = '\0';
+
+ if (is_right_brace(buf)) {
+ current = current->parent;
+ if (trailing_comma)
+ ALLOC_NEXT_ELEMENT;
+ continue;
+ }
+
+ for (p1 = buf; *p1 == ' '; p1++);
+
+ if (
+ (p = strstr(buf, " = ")) &&
+ ((*(p + 3) != '{') || (*(p + 3) == '{' && buf[len] == '}'))
+ ) /* next = 0x0 or files = {0x0, 0x0} */
+ {
+ strncpy(current->field_name, p1, p - p1);
+ strcpy(current->value, p + 3);
+ if (trailing_comma)
+ ALLOC_NEXT_ELEMENT;
+ }
+ else
+ if (p = strstr(buf, " = {")) {
+ strncpy(current->field_name, p1, p - p1);
+ if (*(p + 4) == '\0') {
+ ALLOC_INNER_ELEMENT;
+ } else if (*(p + 4) == '{' && *(p + 5) == '\0') {
+ ALLOC_ARRAY_ELEMENT;
+ }
+ }
+ else
+ if (strstr(buf, "}, {")) { /* Next array element */
+ ALLOC_NEXT_ELEMENT;
+ current->is_array = 1;
+ }
+ else
+ if (buf == (p = strstr(buf, "struct "))) { // The least likely branch
+ /* Our parent */
+ current = calloc(1, sizeof(struct struct_elem));
+ p += 7; /* strlen "struct " */
+ p1 = strstr(buf, " {");
+ strncpy(current->field_name, p, p1 - p);
+ root = current;
+ ALLOC_INNER_ELEMENT;
+ }
+ }
+
+ current = find_node(root->inner, dm->member);
+ if (NULL == current)
+ error(FATAL, "invalid structure reference: %s\n", dm->member);
+
+ dump_node(current, dm->member, 0, 0);
+ free_structure(root);
+
+ return;
+}
+
/*
* When a request is made to print just a member of a structure or union,
* the whole datatype is dumped to a temporary file, and this routine
9 years, 7 months
[PATCH] GET_TIMESTAMP is pc->flags2 not kt->flags2
by Don Slutz
Without this change REMOTE_DAEMON and GET_TIMESTAMP shared
one bit.
---
defs.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index d2a8215..3f4b648 100644
--- a/defs.h
+++ b/defs.h
@@ -518,6 +518,7 @@ struct program_context {
#define INCOMPLETE_DUMP (0x8000ULL)
#define is_incomplete_dump() (pc->flags2 & INCOMPLETE_DUMP)
#define QEMU_MEM_DUMP_COMPRESSED (0x10000ULL)
+#define GET_TIMESTAMP (0x20000ULL)
char *cleanup;
char *namelist_orig;
char *namelist_debug_orig;
@@ -617,11 +618,10 @@ struct new_utsname {
#define GCC_VERSION_DEPRECATED (GCC_3_2|GCC_3_2_3|GCC_2_96|GCC_3_3_2|GCC_3_3_3)
-/* flags2 */
+/* kt flags2 */
#define RELOC_AUTO (0x1ULL)
#define KASLR (0x2ULL)
#define KASLR_CHECK (0x4ULL)
-#define GET_TIMESTAMP (0x8ULL)
#define XEN() (kt->flags & ARCH_XEN)
#define OPENVZ() (kt->flags & ARCH_OPENVZ)
--
1.8.4
9 years, 7 months
[PATCH] xen: Handle rename of dom0 symbol in Xen 4.5.0
by Don Slutz
Has been replaced by hardware_domain.
Xen tracking:
commit c86ccbf0b7976ac0093bef4e4e43005771c0f829
Author: Daniel De Graaf <dgdegra(a)tycho.nsa.gov>
Date: Fri Apr 11 11:20:55 2014 +0200
rename dom0 to hardware_domain
Signed-off-by: Don Slutz <dslutz(a)verizon.com>
---
I do have a big (32G sized file, that gzipped is 357M).
let me know if you want it.
xen_hyper.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/xen_hyper.c b/xen_hyper.c
index db297ff..c02842b 100644
--- a/xen_hyper.c
+++ b/xen_hyper.c
@@ -1036,7 +1036,9 @@ xen_hyper_get_domains(void)
long domain_next_in_list;
int i, j;
- get_symbol_data("dom0", sizeof(void *), &domain);
+ i = try_get_symbol_data("dom0", sizeof(void *), &domain);
+ if (!i)
+ get_symbol_data("hardware_domain", sizeof(void *), &domain);
domain_next_in_list = MEMBER_OFFSET("domain", "next_in_list");
i = 0;
while (domain != 0) {
@@ -1077,7 +1079,9 @@ xen_hyper_get_domain_next(int mod, ulong *next)
if (xhdt->dom0) {
*next = xhdt->dom0->domain;
} else {
- get_symbol_data("dom0", sizeof(void *), next);
+ int ok = try_get_symbol_data("dom0", sizeof(void *), next);
+ if (!ok)
+ get_symbol_data("hardware_domain", sizeof(void *), next);
}
return xhdt->domain_struct;
break;
--
1.8.4
9 years, 7 months
[PATCH v2] kmem: Introduce -m option
by Aaron Tomlin
Hi Dave,
Hopefully this is satisfactory:
The dump_mem_map() function displays basic data about each entry in the
mem_map[] array, or if an address is specified, just the mem_map[] entry
for that address.
This patch introduces the -m option to be used with 'kmem -p' exclusively.
When used with -p, a comma-separated list of one or more struct page
members may be specified to generate a custom, formatted display. For
example:
crash> kmem -p -m mapping,index,_mapcount.counter,_count.counter
ffffea0000000000 0x0 0 0 0
ffffea0000000040 0x0 0 -1 1
ffffea0000000080 0x0 0 -1 1
ffffea00000000c0 0x0 0 -1 1
ffffea0000000100 0x0 0 -1 1
ffffea0000000140 0x0 0 -1 1
ffffea0000000180 0x0 0 -1 1
ffffea00000001c0 0x0 0 -1 1
ffffea0000000200 0x0 0 -1 1
ffffea0000000240 0x0 0 -1 1
...
Signed-off-by: Aaron Tomlin <atomlin(a)redhat.com>
---
help.c | 19 +++-
memory.c | 357 ++++++++++++++++++++++++++++++++++++++++++---------------------
2 files changed, 257 insertions(+), 119 deletions(-)
diff --git a/help.c b/help.c
index b2f4d21..76b640a 100644
--- a/help.c
+++ b/help.c
@@ -5530,7 +5530,7 @@ char *help_kmem[] = {
"kmem",
"kernel memory",
"[-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-z|-o|-h] [slab] [[-P] address]\n"
-" [-g [flags]] [-I slab[,slab]]",
+" [-g [flags]] [-I slab[,slab]] [-m member[,member]]",
" This command displays information about the use of kernel memory.\n",
" -f displays the contents of the system free memory headers.",
" also verifies that the page count equals nr_free_pages.",
@@ -5565,6 +5565,9 @@ char *help_kmem[] = {
" all slab cache names and addresses are listed.",
" -I slab when used with -s or -S, one or more slab cache names in a",
" comma-separated list may be specified as slab caches to ignore.",
+" -m member when used with -p, a comma-separated list of one or more",
+" struct page members may be specified to generate a custom",
+" formatted display.",
" -P declares that the following address argument is a physical address.",
" address when used without any flag, the address can be a kernel virtual,",
" or physical address; a search is made through the symbol table,",
@@ -5717,6 +5720,20 @@ char *help_kmem[] = {
" f5c51440 22000 0 0 1 80 slab",
" ...",
" ",
+" Dump the mem_map[] array but select desired fields:\n",
+" %s> kmem -p -m mapping,index,_mapcount.counter",
+" ffffea0000000000 0x0 0 0",
+" ffffea0000000040 0x0 0 -1",
+" ffffea0000000080 0x0 0 -1",
+" ffffea00000000c0 0x0 0 -1",
+" ffffea0000000100 0x0 0 -1",
+" ffffea0000000140 0x0 0 -1",
+" ffffea0000000180 0x0 0 -1",
+" ffffea00000001c0 0x0 0 -1",
+" ffffea0000000200 0x0 0 -1",
+" ffffea0000000240 0x0 0 -1",
+" ...",
+" ",
" Use the commands above with a page pointer or a physical address argument:\n",
" %s> kmem -f c40425b0",
" NODE ",
diff --git a/memory.c b/memory.c
index aacf929..0ec5f5a 100644
--- a/memory.c
+++ b/memory.c
@@ -54,6 +54,8 @@ struct meminfo { /* general purpose memory information structure */
int current_cache_index;
ulong found;
ulong retval;
+ ulong nr_members;
+ struct struct_member_data *page_member_cache;
char *ignore;
int errors;
int calls;
@@ -4214,6 +4216,101 @@ tgid_quick_search(ulong tgid)
return NULL;
}
+static void
+collect_page_member_data(char *optlist, struct meminfo *mi)
+{
+ int i;
+ int members;
+ char *opt_string;
+ char *memberlist[MAXARGS];
+ struct struct_member_data *page_member_cache, *pmd;
+
+ if ((count_chars(optlist, ',')+1) > MAXARGS)
+ error(FATAL, "too many members in comma-separated list\n");
+
+ if ((LASTCHAR(optlist) == ',') || (LASTCHAR(optlist) == '.'))
+ error(FATAL, "invalid format: %s\n", optlist);
+
+ opt_string = STRDUPBUF(optlist);
+ replace_string(opt_string, ",", ' ');
+
+ if (!(members = parse_line(opt_string, memberlist)))
+ error(FATAL, "invalid page struct member list format: %s\n",
+ optlist);
+
+ page_member_cache = (struct struct_member_data *)
+ GETBUF(sizeof(struct struct_member_data) * members);
+
+ for (i = 0, pmd = page_member_cache; i < members; i++, pmd++) {
+ pmd->structure = "page";
+ pmd->member = memberlist[i];
+
+ if (!fill_struct_member_data(pmd))
+ error(FATAL, "invalid %s struct member: %s\n",
+ pmd->structure, pmd->member);
+
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, " structure: %s\n", pmd->structure);
+ fprintf(fp, " member: %s\n", pmd->member);
+ fprintf(fp, " type: %ld\n", pmd->type);
+ fprintf(fp, " unsigned_type: %ld\n", pmd->unsigned_type);
+ fprintf(fp, " length: %ld\n", pmd->length);
+ fprintf(fp, " offset: %ld\n", pmd->offset);
+ fprintf(fp, " bitpos: %ld\n", pmd->bitpos);
+ fprintf(fp, " bitsize: %ld\n", pmd->bitsize);
+ }
+ }
+
+ mi->nr_members = members;
+ mi->page_member_cache = page_member_cache;
+
+ FREEBUF(page_member_cache);
+}
+
+static int
+show_page_member_data(ulong *pp, struct meminfo *mi, char *outputbuffer)
+{
+ int bufferindex, i;
+ ulong buf;
+ struct struct_member_data *pmd;
+
+ bufferindex = 0;
+ pmd = mi->page_member_cache;
+
+ bufferindex += sprintf(outputbuffer + bufferindex,
+ "%lx\t", *pp);
+
+ for (i = 0; i < mi->nr_members; pmd++, i++) {
+
+ switch (pmd->type)
+ {
+ case TYPE_CODE_PTR:
+ readmem(*pp + pmd->offset, KVADDR, &buf,
+ pmd->length, "page_member_cache offset", FAULT_ON_ERROR);
+ bufferindex += sprintf(outputbuffer + bufferindex, "0x%lx\t",
+ buf);
+ break;
+ case TYPE_CODE_INT:
+ readmem(*pp + pmd->offset, KVADDR, &buf,
+ pmd->length, "page_member_cache offset", FAULT_ON_ERROR);
+ if (pmd->unsigned_type ||
+ pmd->length == sizeof(ulonglong))
+ bufferindex += sprintf(outputbuffer + bufferindex,
+ "%lu\t", buf);
+ else
+ bufferindex += sprintf(outputbuffer + bufferindex,
+ "%d\t", (int)buf);
+ break;
+ default:
+ error(FATAL, "invalid data structure reference: %s.%s\n",
+ pmd->structure, pmd->member);
+ break;
+ }
+ }
+
+ return bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+}
+
/*
* Fill in the task_mem_usage structure with the RSS, virtual memory size,
* percent of physical memory being used, and the mm_struct address.
@@ -4425,7 +4522,7 @@ cmd_kmem(void)
BZERO(&meminfo, sizeof(struct meminfo));
BZERO(&value[0], sizeof(ulonglong)*MAXARGS);
- while ((c = getopt(argcnt, args, "gI:sSFfpvczCinl:L:PVoh")) != EOF) {
+ while ((c = getopt(argcnt, args, "gI:sSFfm:pvczCinl:L:PVoh")) != EOF) {
switch(c)
{
case 'V':
@@ -4480,6 +4577,10 @@ cmd_kmem(void)
pflag = 1;
break;
+ case 'm':
+ collect_page_member_data(optarg, &meminfo);
+ break;
+
case 'I':
meminfo.ignore = optarg;
break;
@@ -4980,62 +5081,64 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
char style3[100];
char style4[100];
- sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- VADDR_PRLEN,
- space(MINSPACE),
- space(MINSPACE));
- sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, " "),
- " ");
- sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, "-----"));
- sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- VADDR_PRLEN,
- space(MINSPACE));
-
v22 = VALID_MEMBER(page_inode); /* page.inode vs. page.mapping */
- if (v22) {
- sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
- mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
- space(MINSPACE),
- mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- RJUST, "PHYSICAL"),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
- space(MINSPACE-1));
- } else {
- sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
- mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
- space(MINSPACE),
- mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- RJUST, "PHYSICAL"),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
- }
+ if (!mi->nr_members) {
+ sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ VADDR_PRLEN,
+ space(MINSPACE),
+ space(MINSPACE));
+ sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, " "),
+ " ");
+ sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, "-----"));
+ sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ VADDR_PRLEN,
+ space(MINSPACE));
+
+ if (v22) {
+ sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
+ space(MINSPACE),
+ mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ RJUST, "PHYSICAL"),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
+ space(MINSPACE-1));
+ } else {
+ sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
+ space(MINSPACE),
+ mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ RJUST, "PHYSICAL"),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
+ }
+ }
mapping = index = 0;
reserved = shared = slabs = buffers = inode = offset = 0;
@@ -5065,7 +5168,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
error(FATAL, "dump_mem_map: no memtype specified\n");
break;
}
- print_hdr = TRUE;
+ if (!mi->nr_members)
+ print_hdr = TRUE;
break;
case GET_ALL:
@@ -5092,7 +5196,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
break;
default:
- print_hdr = TRUE;
+ if (!mi->nr_members)
+ print_hdr = TRUE;
break;
}
@@ -5188,6 +5293,11 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
if (!done && (pg_spec || phys_spec))
continue;
+
+ if (mi->nr_members) {
+ bufferindex += show_page_member_data(&pp, mi, outputbuffer+bufferindex);
+ goto display_members;
+ }
flags = ULONG(pcache + OFFSET(page_flags));
if (SIZE(page_flags) == 4)
@@ -5364,6 +5474,7 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
bufferindex += sprintf(outputbuffer+bufferindex, "\n");
}
+display_members:
if (bufferindex > buffersize) {
fprintf(fp, "%s", outputbuffer);
bufferindex = 0;
@@ -5443,6 +5554,11 @@ dump_mem_map(struct meminfo *mi)
char *outputbuffer;
int bufferindex;
+ if (IS_SPARSEMEM()) {
+ dump_mem_map_SPARSEMEM(mi);
+ return;
+ }
+
buffersize = 1024 * 1024;
outputbuffer = GETBUF(buffersize + 512);
@@ -5451,67 +5567,64 @@ dump_mem_map(struct meminfo *mi)
char style3[100];
char style4[100];
- if (IS_SPARSEMEM()) {
- dump_mem_map_SPARSEMEM(mi);
- return;
- }
-
- sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- VADDR_PRLEN,
- space(MINSPACE),
- space(MINSPACE));
- sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, " "),
- " ");
- sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, "-----"));
- sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- VADDR_PRLEN,
- space(MINSPACE));
-
v22 = VALID_MEMBER(page_inode); /* page.inode vs. page.mapping */
- if (v22) {
- sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
- mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
- space(MINSPACE),
- mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- RJUST, "PHYSICAL"),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
- space(MINSPACE-1));
- } else {
- sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
- mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
- space(MINSPACE),
- mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- RJUST, "PHYSICAL"),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
- }
+ if (!mi->nr_members) {
+ sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ VADDR_PRLEN,
+ space(MINSPACE),
+ space(MINSPACE));
+ sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, " "),
+ " ");
+ sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, "-----"));
+ sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ VADDR_PRLEN,
+ space(MINSPACE));
+
+ if (v22) {
+ sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
+ space(MINSPACE),
+ mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ RJUST, "PHYSICAL"),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
+ space(MINSPACE-1));
+ } else {
+ sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
+ space(MINSPACE),
+ mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ RJUST, "PHYSICAL"),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
+ }
+ }
mapping = index = 0;
reserved = shared = slabs = buffers = inode = offset = 0;
@@ -5541,7 +5654,8 @@ dump_mem_map(struct meminfo *mi)
error(FATAL, "dump_mem_map: no memtype specified\n");
break;
}
- print_hdr = TRUE;
+ if (!mi->nr_members)
+ print_hdr = TRUE;
break;
case GET_ALL:
@@ -5568,7 +5682,8 @@ dump_mem_map(struct meminfo *mi)
break;
default:
- print_hdr = TRUE;
+ if (!mi->nr_members)
+ print_hdr = TRUE;
break;
}
@@ -5626,6 +5741,11 @@ dump_mem_map(struct meminfo *mi)
if (!done && (pg_spec || phys_spec))
continue;
+ if (mi->nr_members) {
+ bufferindex += show_page_member_data(&pp, mi, outputbuffer+bufferindex);
+ goto display_members;
+ }
+
flags = ULONG(pcache + OFFSET(page_flags));
if (SIZE(page_flags) == 4)
flags &= 0xffffffff;
@@ -5802,6 +5922,7 @@ dump_mem_map(struct meminfo *mi)
bufferindex += sprintf(outputbuffer+bufferindex, "\n");
}
+display_members:
if (bufferindex > buffersize) {
fprintf(fp, "%s", outputbuffer);
bufferindex = 0;
--
1.9.3
9 years, 7 months
[PATCH 1/2] Fix typo and delete doubled words in manual
by Wei,Jiangang
* s/repetetively/repetitively/g
Signed-off-by: Wei,Jiangang <weijg.fnst(a)cn.fujitsu.com>
---
README | 4 ++--
help.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/README b/README
index bc83ae6..a55fc4a 100644
--- a/README
+++ b/README
@@ -79,7 +79,7 @@
$ make
The initial build will take several minutes because the embedded gdb module
- must be configured and and built. Alternatively, the crash source RPM file
+ must be configured and built. Alternatively, the crash source RPM file
may be installed and built, and the resultant crash binary RPM file installed.
The crash binary can only be used on systems of the same architecture as
@@ -342,7 +342,7 @@
Alternatively, you can create shared object library files consisting of
crash command extensions, that can be dynamically linked into the crash
- executable during runtime or during initialization. This will allow the
+ executable during runtime or during initialization. This will allow
the same shared object to be used with subsequent crash releases without
having to re-merge the command's code into each new set of crash sources.
The dynamically linked-in commands will automatically show up in the crash
diff --git a/help.c b/help.c
index d7c3ae2..128b4da 100755
--- a/help.c
+++ b/help.c
@@ -784,7 +784,7 @@ char *help_foreach[] = {
"display command data for multiple tasks in the system",
"[[pid | taskp | name | state | [kernel | user]] ...]\n"
" command [flag] [argument]",
-" This command allows for a an examination of various kernel data associated",
+" This command allows for an examination of various kernel data associated",
" with any, or all, tasks in the system, without having to set the context",
" to each targeted task.\n",
" pid perform the command(s) on this PID.",
@@ -6776,7 +6776,7 @@ char *input_info[] = {
"",
"Alternatively, an input file containing command arguments may be created.",
"The arguments in the input file will be passed to the command specified,",
-"which will be executed repetetively for each line of arguments in the file:",
+"which will be executed repetitively for each line of arguments in the file:",
"",
" %s> ps -p < inputfile",
"",
--
1.9.3
9 years, 7 months
[PATCH] kmem: introduce -m option
by Aaron Tomlin
The dump_mem_map() function displays basic data about each entry in the
mem_map[] array, or if an address is specified, just the mem_map[] entry
for that address. This patch introduces the -m option to be used with
'kmem -p' exclusively. When used with -p, a comma-separated list of one or
more struct page members may be specified to generate a custom, formatted
display. For example:
crash> kmem -p -m mapping,index,_mapcount.counter,_count.counter
ffffea0000000000 0x0 0 0 0
ffffea0000000040 0x0 0 -1 1
ffffea0000000080 0x0 0 -1 1
ffffea00000000c0 0x0 0 -1 1
ffffea0000000100 0x0 0 -1 1
ffffea0000000140 0x0 0 -1 1
ffffea0000000180 0x0 0 -1 1
ffffea00000001c0 0x0 0 -1 1
ffffea0000000200 0x0 0 -1 1
ffffea0000000240 0x0 0 -1 1
...
Signed-off-by: Aaron Tomlin <atomlin(a)redhat.com>
---
help.c | 19 +-
memory.c | 1074 ++++++++++++++++++++++++++++++++++++--------------------------
2 files changed, 649 insertions(+), 444 deletions(-)
diff --git a/help.c b/help.c
index b2f4d21..76b640a 100644
--- a/help.c
+++ b/help.c
@@ -5530,7 +5530,7 @@ char *help_kmem[] = {
"kmem",
"kernel memory",
"[-f|-F|-p|-c|-C|-i|-s|-S|-v|-V|-n|-z|-o|-h] [slab] [[-P] address]\n"
-" [-g [flags]] [-I slab[,slab]]",
+" [-g [flags]] [-I slab[,slab]] [-m member[,member]]",
" This command displays information about the use of kernel memory.\n",
" -f displays the contents of the system free memory headers.",
" also verifies that the page count equals nr_free_pages.",
@@ -5565,6 +5565,9 @@ char *help_kmem[] = {
" all slab cache names and addresses are listed.",
" -I slab when used with -s or -S, one or more slab cache names in a",
" comma-separated list may be specified as slab caches to ignore.",
+" -m member when used with -p, a comma-separated list of one or more",
+" struct page members may be specified to generate a custom",
+" formatted display.",
" -P declares that the following address argument is a physical address.",
" address when used without any flag, the address can be a kernel virtual,",
" or physical address; a search is made through the symbol table,",
@@ -5717,6 +5720,20 @@ char *help_kmem[] = {
" f5c51440 22000 0 0 1 80 slab",
" ...",
" ",
+" Dump the mem_map[] array but select desired fields:\n",
+" %s> kmem -p -m mapping,index,_mapcount.counter",
+" ffffea0000000000 0x0 0 0",
+" ffffea0000000040 0x0 0 -1",
+" ffffea0000000080 0x0 0 -1",
+" ffffea00000000c0 0x0 0 -1",
+" ffffea0000000100 0x0 0 -1",
+" ffffea0000000140 0x0 0 -1",
+" ffffea0000000180 0x0 0 -1",
+" ffffea00000001c0 0x0 0 -1",
+" ffffea0000000200 0x0 0 -1",
+" ffffea0000000240 0x0 0 -1",
+" ...",
+" ",
" Use the commands above with a page pointer or a physical address argument:\n",
" %s> kmem -f c40425b0",
" NODE ",
diff --git a/memory.c b/memory.c
index aacf929..d4114c2 100644
--- a/memory.c
+++ b/memory.c
@@ -55,6 +55,7 @@ struct meminfo { /* general purpose memory information structure */
ulong found;
ulong retval;
char *ignore;
+ char *include;
int errors;
int calls;
int cpu;
@@ -4425,7 +4426,7 @@ cmd_kmem(void)
BZERO(&meminfo, sizeof(struct meminfo));
BZERO(&value[0], sizeof(ulonglong)*MAXARGS);
- while ((c = getopt(argcnt, args, "gI:sSFfpvczCinl:L:PVoh")) != EOF) {
+ while ((c = getopt(argcnt, args, "gI:sSFfm:pvczCinl:L:PVoh")) != EOF) {
switch(c)
{
case 'V':
@@ -4480,6 +4481,10 @@ cmd_kmem(void)
pflag = 1;
break;
+ case 'm':
+ meminfo.include = optarg;
+ break;
+
case 'I':
meminfo.ignore = optarg;
break;
@@ -4948,7 +4953,7 @@ PG_slab_flag_init(void)
static void
dump_mem_map_SPARSEMEM(struct meminfo *mi)
{
- ulong i;
+ ulong i, j;
long total_pages;
int others, page_not_mapped, phys_not_mapped, page_mapping;
ulong pp, ppend;
@@ -4967,7 +4972,11 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
char buf4[BUFSIZE];
char *page_cache;
char *pcache;
- ulong section, section_nr, nr_mem_sections, section_size;
+ char *members = NULL;
+ char *memberlist[MAXARGS];
+ struct struct_member_data *member_data[MAXARGS];
+ int nr_members, populated;
+ ulong tmpvalue, section, section_nr, nr_mem_sections, section_size;
long buffersize;
char *outputbuffer;
int bufferindex;
@@ -4980,66 +4989,81 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
char style3[100];
char style4[100];
- sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- VADDR_PRLEN,
- space(MINSPACE),
- space(MINSPACE));
- sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, " "),
- " ");
- sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, "-----"));
- sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- VADDR_PRLEN,
- space(MINSPACE));
+ nr_members = mapping = index = 0;
+ reserved = shared = slabs = buffers = inode = offset = 0;
+ pg_spec = phys_spec = print_hdr = FALSE;
v22 = VALID_MEMBER(page_inode); /* page.inode vs. page.mapping */
- if (v22) {
- sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
- mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
- space(MINSPACE),
- mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- RJUST, "PHYSICAL"),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
- space(MINSPACE-1));
- } else {
- sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
- mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
- space(MINSPACE),
- mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- RJUST, "PHYSICAL"),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
- }
+ if (!mi->include) {
+ sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ VADDR_PRLEN,
+ space(MINSPACE),
+ space(MINSPACE));
+ sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, " "),
+ " ");
+ sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, "-----"));
+ sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ VADDR_PRLEN,
+ space(MINSPACE));
+
+ if (v22) {
+ sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
+ space(MINSPACE),
+ mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ RJUST, "PHYSICAL"),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
+ space(MINSPACE-1));
+ } else {
+ sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
+ space(MINSPACE),
+ mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ RJUST, "PHYSICAL"),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
+ }
+ } else {
+ if (count_chars(mi->include, ',') > MAXARGS)
+ error(FATAL, "too many members in comma-separated list!\n");
- mapping = index = 0;
- reserved = shared = slabs = buffers = inode = offset = 0;
- pg_spec = phys_spec = print_hdr = FALSE;
+ if ((LASTCHAR(mi->include) == ',') || (LASTCHAR(mi->include) == '.'))
+ error(FATAL, "invalid format: %s\n", mi->include);
+
+ members = GETBUF(strlen(mi->include)+1);
+ strcpy(members, mi->include);
+ replace_string(members, ",", ' ');
+ nr_members = parse_line(members, memberlist);
+ populated = FALSE;
+
+ }
switch (mi->flags)
{
@@ -5065,7 +5089,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
error(FATAL, "dump_mem_map: no memtype specified\n");
break;
}
- print_hdr = TRUE;
+ if (!mi->include)
+ print_hdr = TRUE;
break;
case GET_ALL:
@@ -5092,7 +5117,8 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
break;
default:
- print_hdr = TRUE;
+ if (!mi->include)
+ print_hdr = TRUE;
break;
}
@@ -5188,187 +5214,251 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
if (!done && (pg_spec || phys_spec))
continue;
-
- flags = ULONG(pcache + OFFSET(page_flags));
- if (SIZE(page_flags) == 4)
- flags &= 0xffffffff;
- count = UINT(pcache + OFFSET(page_count));
- switch (mi->flags)
- {
- case GET_ALL:
- case GET_BUFFERS_PAGES:
- if (VALID_MEMBER(page_buffers)) {
- tmp = ULONG(pcache +
- OFFSET(page_buffers));
- if (tmp)
- buffers++;
- } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) {
- if ((flags >> v26_PG_private) & 1)
- buffers++;
- } else
- error(FATAL,
- "cannot determine whether pages have buffers\n");
+ if (mi->include) {
+ if (!populated) {
- if (mi->flags != GET_ALL)
- continue;
+ j = 0;
+ do {
+ if (!(member_data[j] = malloc(sizeof(struct struct_member_data)))) {
+ error(WARNING, "cannot malloc member_data space.\n");
+ nr_members = j += 1;
+ goto failed_member_data;
+ }
- /* FALLTHROUGH */
+ member_data[j]->structure = "page";
+ member_data[j]->member = memberlist[j];
+ if (!(fill_struct_member_data(member_data[j]))) {
+ error(WARNING, "Failed to populate member_data: "
+ "%s.%s does not exist.\n",
+ member_data[j]->structure, member_data[j]->member);
+ nr_members = j += 1;
+ goto failed_member_data;
+ }
- case GET_SLAB_PAGES:
- if (v22) {
- if ((flags >> v22_PG_Slab) & 1)
- slabs++;
- } else if (vt->PG_slab) {
- if ((flags >> vt->PG_slab) & 1)
- slabs++;
- } else {
- if ((flags >> v24_PG_slab) & 1)
- slabs++;
+ } while (++j < nr_members);
+ populated = TRUE;
}
- if (mi->flags != GET_ALL)
- continue;
- /* FALLTHROUGH */
- case GET_SHARED_PAGES:
- case GET_TOTALRAM_PAGES:
- if (vt->PG_reserved)
- PG_reserved_flag = vt->PG_reserved;
- else
- PG_reserved_flag = v22 ?
- 1 << v22_PG_reserved :
- 1 << v24_PG_reserved;
+ bufferindex += sprintf(outputbuffer + bufferindex,
+ "%lx\t", pp);
- if (flags & PG_reserved_flag) {
- reserved++;
- } else {
- if ((int)count >
- (vt->flags & PGCNT_ADJ ? 0 : 1))
- shared++;
- }
- continue;
- }
- page_mapping = VALID_MEMBER(page_mapping);
-
- if (v22) {
- inode = ULONG(pcache + OFFSET(page_inode));
- offset = ULONG(pcache + OFFSET(page_offset));
- } else if (page_mapping) {
- mapping = ULONG(pcache +
- OFFSET(page_mapping));
- index = ULONG(pcache + OFFSET(page_index));
- }
-
- page_not_mapped = phys_not_mapped = FALSE;
+ j = 0;
+ do {
+ switch (member_data[j]->type)
+ {
+ case TYPE_CODE_PTR:
+ readmem(pp + member_data[j]->offset, KVADDR, &tmpvalue,
+ member_data[j]->length, "tmpvalue", FAULT_ON_ERROR);
+ bufferindex += sprintf(outputbuffer + bufferindex, "0x%lx\t",
+ tmpvalue);
+ break;
+ case TYPE_CODE_INT:
+ readmem(pp + member_data[j]->offset, KVADDR, &tmpvalue,
+ member_data[j]->length, "tmpvalue", FAULT_ON_ERROR);
+ if (member_data[j]->unsigned_type ||
+ member_data[j]->length == sizeof(ulonglong))
+ bufferindex += sprintf(outputbuffer + bufferindex,
+ "%lu\t", tmpvalue);
+ else
+ bufferindex += sprintf(outputbuffer + bufferindex,
+ "%d\t", (int)tmpvalue);
+ break;
+ default:
+ error(WARNING, "invalid data structure reference %s.%s\n",
+ member_data[j]->structure, member_data[j]->member);
+ nr_members = j += 1;
+ goto failed_member_data;
+ break;
+ }
+ } while (++j < nr_members);
+
+ bufferindex += sprintf(outputbuffer+bufferindex, "\n");
- if (v22) {
- bufferindex += sprintf(outputbuffer+bufferindex,
- (char *)&style1, pp, phys, inode,
- offset, count);
} else {
- if ((vt->flags & V_MEM_MAP)) {
- if (!machdep->verify_paddr(phys))
- phys_not_mapped = TRUE;
- if (!kvtop(NULL, pp, NULL, 0))
- page_not_mapped = TRUE;
+
+ flags = ULONG(pcache + OFFSET(page_flags));
+ if (SIZE(page_flags) == 4)
+ flags &= 0xffffffff;
+ count = UINT(pcache + OFFSET(page_count));
+
+ switch (mi->flags)
+ {
+ case GET_ALL:
+ case GET_BUFFERS_PAGES:
+ if (VALID_MEMBER(page_buffers)) {
+ tmp = ULONG(pcache +
+ OFFSET(page_buffers));
+ if (tmp)
+ buffers++;
+ } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) {
+ if ((flags >> v26_PG_private) & 1)
+ buffers++;
+ } else
+ error(FATAL,
+ "cannot determine whether pages have buffers\n");
+
+ if (mi->flags != GET_ALL)
+ continue;
+
+ /* FALLTHROUGH */
+
+ case GET_SLAB_PAGES:
+ if (v22) {
+ if ((flags >> v22_PG_Slab) & 1)
+ slabs++;
+ } else if (vt->PG_slab) {
+ if ((flags >> vt->PG_slab) & 1)
+ slabs++;
+ } else {
+ if ((flags >> v24_PG_slab) & 1)
+ slabs++;
+ }
+ if (mi->flags != GET_ALL)
+ continue;
+
+ /* FALLTHROUGH */
+
+ case GET_SHARED_PAGES:
+ case GET_TOTALRAM_PAGES:
+ if (vt->PG_reserved)
+ PG_reserved_flag = vt->PG_reserved;
+ else
+ PG_reserved_flag = v22 ?
+ 1 << v22_PG_reserved :
+ 1 << v24_PG_reserved;
+
+ if (flags & PG_reserved_flag) {
+ reserved++;
+ } else {
+ if ((int)count >
+ (vt->flags & PGCNT_ADJ ? 0 : 1))
+ shared++;
+ }
+ continue;
}
- if (page_not_mapped)
- bufferindex += sprintf(outputbuffer+bufferindex,
- (char *)&style2, pp, phys);
- else if (!page_mapping)
- bufferindex += sprintf(outputbuffer+bufferindex,
- (char *)&style3, pp, phys, count);
- else
+ page_mapping = VALID_MEMBER(page_mapping);
+
+ if (v22) {
+ inode = ULONG(pcache + OFFSET(page_inode));
+ offset = ULONG(pcache + OFFSET(page_offset));
+ } else if (page_mapping) {
+ mapping = ULONG(pcache +
+ OFFSET(page_mapping));
+ index = ULONG(pcache + OFFSET(page_index));
+ }
+
+ page_not_mapped = phys_not_mapped = FALSE;
+
+ if (v22) {
bufferindex += sprintf(outputbuffer+bufferindex,
- (char *)&style4, pp, phys,
- mapping, index, count);
- }
-
- others = 0;
-
+ (char *)&style1, pp, phys, inode,
+ offset, count);
+ } else {
+ if ((vt->flags & V_MEM_MAP)) {
+ if (!machdep->verify_paddr(phys))
+ phys_not_mapped = TRUE;
+ if (!kvtop(NULL, pp, NULL, 0))
+ page_not_mapped = TRUE;
+ }
+ if (page_not_mapped)
+ bufferindex += sprintf(outputbuffer+bufferindex,
+ (char *)&style2, pp, phys);
+ else if (!page_mapping)
+ bufferindex += sprintf(outputbuffer+bufferindex,
+ (char *)&style3, pp, phys, count);
+ else
+ bufferindex += sprintf(outputbuffer+bufferindex,
+ (char *)&style4, pp, phys,
+ mapping, index, count);
+ }
+
+ others = 0;
+
#define sprintflag(X) sprintf(outputbuffer + bufferindex, X, others++ ? "," : "")
- if (v22) {
- if ((flags >> v22_PG_DMA) & 1)
- bufferindex += sprintflag("%sDMA");
- if ((flags >> v22_PG_locked) & 1)
- bufferindex += sprintflag("%slocked");
- if ((flags >> v22_PG_error) & 1)
- bufferindex += sprintflag("%serror");
- if ((flags >> v22_PG_referenced) & 1)
- bufferindex += sprintflag("%sreferenced");
- if ((flags >> v22_PG_dirty) & 1)
- bufferindex += sprintflag("%sdirty");
- if ((flags >> v22_PG_uptodate) & 1)
- bufferindex += sprintflag("%suptodate");
- if ((flags >> v22_PG_free_after) & 1)
- bufferindex += sprintflag("%sfree_after");
- if ((flags >> v22_PG_decr_after) & 1)
- bufferindex += sprintflag("%sdecr_after");
- if ((flags >> v22_PG_swap_unlock_after) & 1)
- bufferindex += sprintflag("%sswap_unlock_after");
- if ((flags >> v22_PG_Slab) & 1)
- bufferindex += sprintflag("%sslab");
- if ((flags >> v22_PG_swap_cache) & 1)
- bufferindex += sprintflag("%sswap_cache");
- if ((flags >> v22_PG_skip) & 1)
- bufferindex += sprintflag("%sskip");
- if ((flags >> v22_PG_reserved) & 1)
- bufferindex += sprintflag("%sreserved");
- bufferindex += sprintf(outputbuffer+bufferindex, "\n");
- } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
- if (vt->flags & PAGEFLAGS)
- bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
- else
- bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
- } else {
-
- if ((flags >> v24_PG_locked) & 1)
- bufferindex += sprintflag("%slocked");
- if ((flags >> v24_PG_error) & 1)
- bufferindex += sprintflag("%serror");
- if ((flags >> v24_PG_referenced) & 1)
- bufferindex += sprintflag("%sreferenced");
- if ((flags >> v24_PG_uptodate) & 1)
- bufferindex += sprintflag("%suptodate");
- if ((flags >> v24_PG_dirty) & 1)
- bufferindex += sprintflag("%sdirty");
- if ((flags >> v24_PG_decr_after) & 1)
- bufferindex += sprintflag("%sdecr_after");
- if ((flags >> v24_PG_active) & 1)
- bufferindex += sprintflag("%sactive");
- if ((flags >> v24_PG_inactive_dirty) & 1)
- bufferindex += sprintflag("%sinactive_dirty");
- if ((flags >> v24_PG_slab) & 1)
- bufferindex += sprintflag("%sslab");
- if ((flags >> v24_PG_swap_cache) & 1)
- bufferindex += sprintflag("%sswap_cache");
- if ((flags >> v24_PG_skip) & 1)
- bufferindex += sprintflag("%sskip");
- if ((flags >> v24_PG_inactive_clean) & 1)
- bufferindex += sprintflag("%sinactive_clean");
- if ((flags >> v24_PG_highmem) & 1)
- bufferindex += sprintflag("%shighmem");
- if ((flags >> v24_PG_checked) & 1)
- bufferindex += sprintflag("%schecked");
- if ((flags >> v24_PG_bigpage) & 1)
- bufferindex += sprintflag("%sbigpage");
- if ((flags >> v24_PG_arch_1) & 1)
- bufferindex += sprintflag("%sarch_1");
- if ((flags >> v24_PG_reserved) & 1)
- bufferindex += sprintflag("%sreserved");
- if (phys_not_mapped)
- bufferindex += sprintflag("%s[NOT MAPPED]");
-
- bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+ if (v22) {
+ if ((flags >> v22_PG_DMA) & 1)
+ bufferindex += sprintflag("%sDMA");
+ if ((flags >> v22_PG_locked) & 1)
+ bufferindex += sprintflag("%slocked");
+ if ((flags >> v22_PG_error) & 1)
+ bufferindex += sprintflag("%serror");
+ if ((flags >> v22_PG_referenced) & 1)
+ bufferindex += sprintflag("%sreferenced");
+ if ((flags >> v22_PG_dirty) & 1)
+ bufferindex += sprintflag("%sdirty");
+ if ((flags >> v22_PG_uptodate) & 1)
+ bufferindex += sprintflag("%suptodate");
+ if ((flags >> v22_PG_free_after) & 1)
+ bufferindex += sprintflag("%sfree_after");
+ if ((flags >> v22_PG_decr_after) & 1)
+ bufferindex += sprintflag("%sdecr_after");
+ if ((flags >> v22_PG_swap_unlock_after) & 1)
+ bufferindex += sprintflag("%sswap_unlock_after");
+ if ((flags >> v22_PG_Slab) & 1)
+ bufferindex += sprintflag("%sslab");
+ if ((flags >> v22_PG_swap_cache) & 1)
+ bufferindex += sprintflag("%sswap_cache");
+ if ((flags >> v22_PG_skip) & 1)
+ bufferindex += sprintflag("%sskip");
+ if ((flags >> v22_PG_reserved) & 1)
+ bufferindex += sprintflag("%sreserved");
+ bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+ } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
+ if (vt->flags & PAGEFLAGS)
+ bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
+ else
+ bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
+ } else {
+
+ if ((flags >> v24_PG_locked) & 1)
+ bufferindex += sprintflag("%slocked");
+ if ((flags >> v24_PG_error) & 1)
+ bufferindex += sprintflag("%serror");
+ if ((flags >> v24_PG_referenced) & 1)
+ bufferindex += sprintflag("%sreferenced");
+ if ((flags >> v24_PG_uptodate) & 1)
+ bufferindex += sprintflag("%suptodate");
+ if ((flags >> v24_PG_dirty) & 1)
+ bufferindex += sprintflag("%sdirty");
+ if ((flags >> v24_PG_decr_after) & 1)
+ bufferindex += sprintflag("%sdecr_after");
+ if ((flags >> v24_PG_active) & 1)
+ bufferindex += sprintflag("%sactive");
+ if ((flags >> v24_PG_inactive_dirty) & 1)
+ bufferindex += sprintflag("%sinactive_dirty");
+ if ((flags >> v24_PG_slab) & 1)
+ bufferindex += sprintflag("%sslab");
+ if ((flags >> v24_PG_swap_cache) & 1)
+ bufferindex += sprintflag("%sswap_cache");
+ if ((flags >> v24_PG_skip) & 1)
+ bufferindex += sprintflag("%sskip");
+ if ((flags >> v24_PG_inactive_clean) & 1)
+ bufferindex += sprintflag("%sinactive_clean");
+ if ((flags >> v24_PG_highmem) & 1)
+ bufferindex += sprintflag("%shighmem");
+ if ((flags >> v24_PG_checked) & 1)
+ bufferindex += sprintflag("%schecked");
+ if ((flags >> v24_PG_bigpage) & 1)
+ bufferindex += sprintflag("%sbigpage");
+ if ((flags >> v24_PG_arch_1) & 1)
+ bufferindex += sprintflag("%sarch_1");
+ if ((flags >> v24_PG_reserved) & 1)
+ bufferindex += sprintflag("%sreserved");
+ if (phys_not_mapped)
+ bufferindex += sprintflag("%s[NOT MAPPED]");
+
+ bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+ }
}
if (bufferindex > buffersize) {
fprintf(fp, "%s", outputbuffer);
bufferindex = 0;
}
-
+
if (done)
break;
}
@@ -5413,12 +5503,18 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi)
FREEBUF(outputbuffer);
FREEBUF(page_cache);
+failed_member_data:
+ if (mi->include) {
+ FREEBUF(members);
+ for (i = 0; i < nr_members; i++)
+ free(member_data[i]);
+ }
}
static void
dump_mem_map(struct meminfo *mi)
{
- long i, n;
+ ulong i, n, j;
long total_pages;
int others, page_not_mapped, phys_not_mapped, page_mapping;
ulong pp, ppend;
@@ -5439,6 +5535,11 @@ dump_mem_map(struct meminfo *mi)
char buf4[BUFSIZE];
char *page_cache;
char *pcache;
+ char *members = NULL;
+ char *memberlist[MAXARGS];
+ struct struct_member_data *member_data[MAXARGS];
+ int nr_members, populated;
+ ulong tmpvalue;
long buffersize;
char *outputbuffer;
int bufferindex;
@@ -5456,67 +5557,82 @@ dump_mem_map(struct meminfo *mi)
return;
}
- sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- VADDR_PRLEN,
- space(MINSPACE),
- space(MINSPACE));
- sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, " "),
- " ");
- sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, "-----"));
- sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
- VADDR_PRLEN,
- space(MINSPACE),
- (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- space(MINSPACE),
- VADDR_PRLEN,
- space(MINSPACE));
+ nr_members = mapping = index = 0;
+ reserved = shared = slabs = buffers = inode = offset = 0;
+ pg_spec = phys_spec = print_hdr = FALSE;
v22 = VALID_MEMBER(page_inode); /* page.inode vs. page.mapping */
- if (v22) {
- sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
- mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
- space(MINSPACE),
- mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- RJUST, "PHYSICAL"),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
- space(MINSPACE-1));
- } else {
- sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
- mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
- space(MINSPACE),
- mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
- RJUST, "PHYSICAL"),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
- space(MINSPACE),
- mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
- }
+ if (!mi->include) {
+ sprintf((char *)&style1, "%%lx%s%%%dllx%s%%%dlx%s%%8lx %%2d%s",
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ VADDR_PRLEN,
+ space(MINSPACE),
+ space(MINSPACE));
+ sprintf((char *)&style2, "%%-%dlx%s%%%dllx%s%s%s%s %2s ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, " "),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, " "),
+ " ");
+ sprintf((char *)&style3, "%%-%dlx%s%%%dllx%s%s%s%s %%2d ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "-------"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, "-----"));
+ sprintf((char *)&style4, "%%-%dlx%s%%%dllx%s%%%dlx%s%%8lx %%2d ",
+ VADDR_PRLEN,
+ space(MINSPACE),
+ (int)MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ space(MINSPACE),
+ VADDR_PRLEN,
+ space(MINSPACE));
+
+ if (v22) {
+ sprintf(hdr, "%s%s%s%s%s%s%s%sCNT FLAGS\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
+ space(MINSPACE),
+ mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ RJUST, "PHYSICAL"),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "INODE"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|LJUST, "OFFSET"),
+ space(MINSPACE-1));
+ } else {
+ sprintf(hdr, "%s%s%s%s%s%s%sCNT FLAGS\n",
+ mkstring(buf1, VADDR_PRLEN, CENTER, "PAGE"),
+ space(MINSPACE),
+ mkstring(buf2, MAX(PADDR_PRLEN, strlen("PHYSICAL")),
+ RJUST, "PHYSICAL"),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN, CENTER|RJUST, "MAPPING"),
+ space(MINSPACE),
+ mkstring(buf4, 8, CENTER|RJUST, "INDEX"));
+ }
+ } else {
+ if (count_chars(mi->include, ',') > MAXARGS)
+ error(FATAL, "too many members in comma-separated list!\n");
+
+ if ((LASTCHAR(mi->include) == ',') || (LASTCHAR(mi->include) == '.'))
+ error(FATAL, "invalid format: %s\n", mi->include);
+
+ members = GETBUF(strlen(mi->include)+1);
+ strcpy(members, mi->include);
+ replace_string(members, ",", ' ');
+ nr_members = parse_line(members, memberlist);
+ populated = FALSE;
+
+ }
- mapping = index = 0;
- reserved = shared = slabs = buffers = inode = offset = 0;
- pg_spec = phys_spec = print_hdr = FALSE;
-
switch (mi->flags)
{
case ADDRESS_SPECIFIED:
@@ -5541,7 +5657,8 @@ dump_mem_map(struct meminfo *mi)
error(FATAL, "dump_mem_map: no memtype specified\n");
break;
}
- print_hdr = TRUE;
+ if (!mi->include)
+ print_hdr = TRUE;
break;
case GET_ALL:
@@ -5568,7 +5685,8 @@ dump_mem_map(struct meminfo *mi)
break;
default:
- print_hdr = TRUE;
+ if (!mi->include)
+ print_hdr = TRUE;
break;
}
@@ -5625,181 +5743,245 @@ dump_mem_map(struct meminfo *mi)
if (!done && (pg_spec || phys_spec))
continue;
-
- flags = ULONG(pcache + OFFSET(page_flags));
- if (SIZE(page_flags) == 4)
- flags &= 0xffffffff;
- count = UINT(pcache + OFFSET(page_count));
- switch (mi->flags)
- {
- case GET_ALL:
- case GET_BUFFERS_PAGES:
- if (VALID_MEMBER(page_buffers)) {
- tmp = ULONG(pcache +
- OFFSET(page_buffers));
- if (tmp)
- buffers++;
- } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) {
- if ((flags >> v26_PG_private) & 1)
- buffers++;
- } else
- error(FATAL,
- "cannot determine whether pages have buffers\n");
+ if (mi->include) {
+ if (!populated) {
- if (mi->flags != GET_ALL)
- continue;
+ j = 0;
+ do {
+ if (!(member_data[j] = malloc(sizeof(struct struct_member_data)))) {
+ error(WARNING, "cannot malloc member_data space.\n");
+ nr_members = j += 1;
+ goto failed_member_data;
+ }
- /* FALLTHROUGH */
+ member_data[j]->structure = "page";
+ member_data[j]->member = memberlist[j];
+ if (!(fill_struct_member_data(member_data[j]))) {
+ error(WARNING, "Failed to populate member_data: "
+ "%s.%s does not exist.\n",
+ member_data[j]->structure, member_data[j]->member);
+ nr_members = j += 1;
+ goto failed_member_data;
+ }
- case GET_SLAB_PAGES:
- if (v22) {
- if ((flags >> v22_PG_Slab) & 1)
- slabs++;
- } else if (vt->PG_slab) {
- if ((flags >> vt->PG_slab) & 1)
- slabs++;
- } else {
- if ((flags >> v24_PG_slab) & 1)
- slabs++;
+ } while (++j < nr_members);
+ populated = TRUE;
}
- if (mi->flags != GET_ALL)
- continue;
- /* FALLTHROUGH */
- case GET_SHARED_PAGES:
- case GET_TOTALRAM_PAGES:
- if (vt->PG_reserved)
- PG_reserved_flag = vt->PG_reserved;
- else
- PG_reserved_flag = v22 ?
- 1 << v22_PG_reserved :
- 1 << v24_PG_reserved;
+ bufferindex += sprintf(outputbuffer + bufferindex,
+ "%lx\t", pp);
- if (flags & PG_reserved_flag) {
- reserved++;
- } else {
- if ((int)count >
- (vt->flags & PGCNT_ADJ ? 0 : 1))
- shared++;
- }
- continue;
- }
-
- page_mapping = VALID_MEMBER(page_mapping);
-
- if (v22) {
- inode = ULONG(pcache + OFFSET(page_inode));
- offset = ULONG(pcache + OFFSET(page_offset));
- } else if (page_mapping) {
- mapping = ULONG(pcache +
- OFFSET(page_mapping));
- index = ULONG(pcache + OFFSET(page_index));
- }
-
- page_not_mapped = phys_not_mapped = FALSE;
+ j = 0;
+ do {
+ switch (member_data[j]->type)
+ {
+ case TYPE_CODE_PTR:
+ readmem(pp + member_data[j]->offset, KVADDR, &tmpvalue,
+ member_data[j]->length, "tmpvalue", FAULT_ON_ERROR);
+ bufferindex += sprintf(outputbuffer + bufferindex, "0x%lx\t",
+ tmpvalue);
+ break;
+ case TYPE_CODE_INT:
+ readmem(pp + member_data[j]->offset, KVADDR, &tmpvalue,
+ member_data[j]->length, "tmpvalue", FAULT_ON_ERROR);
+ if (member_data[j]->unsigned_type ||
+ member_data[j]->length == sizeof(ulonglong))
+ bufferindex += sprintf(outputbuffer + bufferindex,
+ "%lu\t", tmpvalue);
+ else
+ bufferindex += sprintf(outputbuffer + bufferindex,
+ "%d\t", (int)tmpvalue);
+ break;
+ default:
+ error(WARNING, "invalid data structure reference %s.%s\n",
+ member_data[j]->structure, member_data[j]->member);
+ nr_members = j += 1;
+ goto failed_member_data;
+ break;
+ }
+ } while (++j < nr_members);
+
+ bufferindex += sprintf(outputbuffer+bufferindex, "\n");
- if (v22) {
- bufferindex += sprintf(outputbuffer+bufferindex,
- (char *)&style1, pp, phys, inode,
- offset, count);
} else {
- if ((vt->flags & V_MEM_MAP)) {
- if (!machdep->verify_paddr(phys))
- phys_not_mapped = TRUE;
- if (!kvtop(NULL, pp, NULL, 0))
- page_not_mapped = TRUE;
+
+ flags = ULONG(pcache + OFFSET(page_flags));
+ if (SIZE(page_flags) == 4)
+ flags &= 0xffffffff;
+ count = UINT(pcache + OFFSET(page_count));
+
+ switch (mi->flags)
+ {
+ case GET_ALL:
+ case GET_BUFFERS_PAGES:
+ if (VALID_MEMBER(page_buffers)) {
+ tmp = ULONG(pcache +
+ OFFSET(page_buffers));
+ if (tmp)
+ buffers++;
+ } else if (THIS_KERNEL_VERSION >= LINUX(2,6,0)) {
+ if ((flags >> v26_PG_private) & 1)
+ buffers++;
+ } else
+ error(FATAL,
+ "cannot determine whether pages have buffers\n");
+
+ if (mi->flags != GET_ALL)
+ continue;
+
+ /* FALLTHROUGH */
+
+ case GET_SLAB_PAGES:
+ if (v22) {
+ if ((flags >> v22_PG_Slab) & 1)
+ slabs++;
+ } else if (vt->PG_slab) {
+ if ((flags >> vt->PG_slab) & 1)
+ slabs++;
+ } else {
+ if ((flags >> v24_PG_slab) & 1)
+ slabs++;
+ }
+ if (mi->flags != GET_ALL)
+ continue;
+
+ /* FALLTHROUGH */
+
+ case GET_SHARED_PAGES:
+ case GET_TOTALRAM_PAGES:
+ if (vt->PG_reserved)
+ PG_reserved_flag = vt->PG_reserved;
+ else
+ PG_reserved_flag = v22 ?
+ 1 << v22_PG_reserved :
+ 1 << v24_PG_reserved;
+
+ if (flags & PG_reserved_flag) {
+ reserved++;
+ } else {
+ if ((int)count >
+ (vt->flags & PGCNT_ADJ ? 0 : 1))
+ shared++;
+ }
+ continue;
}
- if (page_not_mapped)
- bufferindex += sprintf(outputbuffer+bufferindex,
- (char *)&style2, pp, phys);
- else if (!page_mapping)
- bufferindex += sprintf(outputbuffer+bufferindex,
- (char *)&style3, pp, phys, count);
- else
+
+ page_mapping = VALID_MEMBER(page_mapping);
+
+ if (v22) {
+ inode = ULONG(pcache + OFFSET(page_inode));
+ offset = ULONG(pcache + OFFSET(page_offset));
+ } else if (page_mapping) {
+ mapping = ULONG(pcache +
+ OFFSET(page_mapping));
+ index = ULONG(pcache + OFFSET(page_index));
+ }
+
+ page_not_mapped = phys_not_mapped = FALSE;
+
+ if (v22) {
bufferindex += sprintf(outputbuffer+bufferindex,
- (char *)&style4, pp, phys,
- mapping, index, count);
- }
-
- others = 0;
-
+ (char *)&style1, pp, phys, inode,
+ offset, count);
+ } else {
+ if ((vt->flags & V_MEM_MAP)) {
+ if (!machdep->verify_paddr(phys))
+ phys_not_mapped = TRUE;
+ if (!kvtop(NULL, pp, NULL, 0))
+ page_not_mapped = TRUE;
+ }
+ if (page_not_mapped)
+ bufferindex += sprintf(outputbuffer+bufferindex,
+ (char *)&style2, pp, phys);
+ else if (!page_mapping)
+ bufferindex += sprintf(outputbuffer+bufferindex,
+ (char *)&style3, pp, phys, count);
+ else
+ bufferindex += sprintf(outputbuffer+bufferindex,
+ (char *)&style4, pp, phys,
+ mapping, index, count);
+ }
+
+ others = 0;
+
#define sprintflag(X) sprintf(outputbuffer + bufferindex, X, others++ ? "," : "")
- if (v22) {
- if ((flags >> v22_PG_DMA) & 1)
- bufferindex += sprintflag("%sDMA");
- if ((flags >> v22_PG_locked) & 1)
- bufferindex += sprintflag("%slocked");
- if ((flags >> v22_PG_error) & 1)
- bufferindex += sprintflag("%serror");
- if ((flags >> v22_PG_referenced) & 1)
- bufferindex += sprintflag("%sreferenced");
- if ((flags >> v22_PG_dirty) & 1)
- bufferindex += sprintflag("%sdirty");
- if ((flags >> v22_PG_uptodate) & 1)
- bufferindex += sprintflag("%suptodate");
- if ((flags >> v22_PG_free_after) & 1)
- bufferindex += sprintflag("%sfree_after");
- if ((flags >> v22_PG_decr_after) & 1)
- bufferindex += sprintflag("%sdecr_after");
- if ((flags >> v22_PG_swap_unlock_after) & 1)
- bufferindex += sprintflag("%sswap_unlock_after");
- if ((flags >> v22_PG_Slab) & 1)
- bufferindex += sprintflag("%sslab");
- if ((flags >> v22_PG_swap_cache) & 1)
- bufferindex += sprintflag("%sswap_cache");
- if ((flags >> v22_PG_skip) & 1)
- bufferindex += sprintflag("%sskip");
- if ((flags >> v22_PG_reserved) & 1)
- bufferindex += sprintflag("%sreserved");
- bufferindex += sprintf(outputbuffer+bufferindex, "\n");
- } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
- if (vt->flags & PAGEFLAGS)
- bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
- else
- bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
- } else {
-
- if ((flags >> v24_PG_locked) & 1)
- bufferindex += sprintflag("%slocked");
- if ((flags >> v24_PG_error) & 1)
- bufferindex += sprintflag("%serror");
- if ((flags >> v24_PG_referenced) & 1)
- bufferindex += sprintflag("%sreferenced");
- if ((flags >> v24_PG_uptodate) & 1)
- bufferindex += sprintflag("%suptodate");
- if ((flags >> v24_PG_dirty) & 1)
- bufferindex += sprintflag("%sdirty");
- if ((flags >> v24_PG_decr_after) & 1)
- bufferindex += sprintflag("%sdecr_after");
- if ((flags >> v24_PG_active) & 1)
- bufferindex += sprintflag("%sactive");
- if ((flags >> v24_PG_inactive_dirty) & 1)
- bufferindex += sprintflag("%sinactive_dirty");
- if ((flags >> v24_PG_slab) & 1)
- bufferindex += sprintflag("%sslab");
- if ((flags >> v24_PG_swap_cache) & 1)
- bufferindex += sprintflag("%sswap_cache");
- if ((flags >> v24_PG_skip) & 1)
- bufferindex += sprintflag("%sskip");
- if ((flags >> v24_PG_inactive_clean) & 1)
- bufferindex += sprintflag("%sinactive_clean");
- if ((flags >> v24_PG_highmem) & 1)
- bufferindex += sprintflag("%shighmem");
- if ((flags >> v24_PG_checked) & 1)
- bufferindex += sprintflag("%schecked");
- if ((flags >> v24_PG_bigpage) & 1)
- bufferindex += sprintflag("%sbigpage");
- if ((flags >> v24_PG_arch_1) & 1)
- bufferindex += sprintflag("%sarch_1");
- if ((flags >> v24_PG_reserved) & 1)
- bufferindex += sprintflag("%sreserved");
- if (phys_not_mapped)
- bufferindex += sprintflag("%s[NOT MAPPED]");
-
- bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+ if (v22) {
+ if ((flags >> v22_PG_DMA) & 1)
+ bufferindex += sprintflag("%sDMA");
+ if ((flags >> v22_PG_locked) & 1)
+ bufferindex += sprintflag("%slocked");
+ if ((flags >> v22_PG_error) & 1)
+ bufferindex += sprintflag("%serror");
+ if ((flags >> v22_PG_referenced) & 1)
+ bufferindex += sprintflag("%sreferenced");
+ if ((flags >> v22_PG_dirty) & 1)
+ bufferindex += sprintflag("%sdirty");
+ if ((flags >> v22_PG_uptodate) & 1)
+ bufferindex += sprintflag("%suptodate");
+ if ((flags >> v22_PG_free_after) & 1)
+ bufferindex += sprintflag("%sfree_after");
+ if ((flags >> v22_PG_decr_after) & 1)
+ bufferindex += sprintflag("%sdecr_after");
+ if ((flags >> v22_PG_swap_unlock_after) & 1)
+ bufferindex += sprintflag("%sswap_unlock_after");
+ if ((flags >> v22_PG_Slab) & 1)
+ bufferindex += sprintflag("%sslab");
+ if ((flags >> v22_PG_swap_cache) & 1)
+ bufferindex += sprintflag("%sswap_cache");
+ if ((flags >> v22_PG_skip) & 1)
+ bufferindex += sprintflag("%sskip");
+ if ((flags >> v22_PG_reserved) & 1)
+ bufferindex += sprintflag("%sreserved");
+ bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+ } else if (THIS_KERNEL_VERSION > LINUX(2,4,9)) {
+ if (vt->flags & PAGEFLAGS)
+ bufferindex += translate_page_flags(outputbuffer+bufferindex, flags);
+ else
+ bufferindex += sprintf(outputbuffer+bufferindex, "%lx\n", flags);
+ } else {
+
+ if ((flags >> v24_PG_locked) & 1)
+ bufferindex += sprintflag("%slocked");
+ if ((flags >> v24_PG_error) & 1)
+ bufferindex += sprintflag("%serror");
+ if ((flags >> v24_PG_referenced) & 1)
+ bufferindex += sprintflag("%sreferenced");
+ if ((flags >> v24_PG_uptodate) & 1)
+ bufferindex += sprintflag("%suptodate");
+ if ((flags >> v24_PG_dirty) & 1)
+ bufferindex += sprintflag("%sdirty");
+ if ((flags >> v24_PG_decr_after) & 1)
+ bufferindex += sprintflag("%sdecr_after");
+ if ((flags >> v24_PG_active) & 1)
+ bufferindex += sprintflag("%sactive");
+ if ((flags >> v24_PG_inactive_dirty) & 1)
+ bufferindex += sprintflag("%sinactive_dirty");
+ if ((flags >> v24_PG_slab) & 1)
+ bufferindex += sprintflag("%sslab");
+ if ((flags >> v24_PG_swap_cache) & 1)
+ bufferindex += sprintflag("%sswap_cache");
+ if ((flags >> v24_PG_skip) & 1)
+ bufferindex += sprintflag("%sskip");
+ if ((flags >> v24_PG_inactive_clean) & 1)
+ bufferindex += sprintflag("%sinactive_clean");
+ if ((flags >> v24_PG_highmem) & 1)
+ bufferindex += sprintflag("%shighmem");
+ if ((flags >> v24_PG_checked) & 1)
+ bufferindex += sprintflag("%schecked");
+ if ((flags >> v24_PG_bigpage) & 1)
+ bufferindex += sprintflag("%sbigpage");
+ if ((flags >> v24_PG_arch_1) & 1)
+ bufferindex += sprintflag("%sarch_1");
+ if ((flags >> v24_PG_reserved) & 1)
+ bufferindex += sprintflag("%sreserved");
+ if (phys_not_mapped)
+ bufferindex += sprintflag("%s[NOT MAPPED]");
+
+ bufferindex += sprintf(outputbuffer+bufferindex, "\n");
+ }
}
if (bufferindex > buffersize) {
@@ -5851,6 +6033,12 @@ dump_mem_map(struct meminfo *mi)
FREEBUF(outputbuffer);
FREEBUF(page_cache);
+failed_member_data:
+ if (mi->include) {
+ FREEBUF(members);
+ for (i = 0; i < nr_members; i++)
+ free(member_data[i]);
+ }
}
/*
--
1.9.3
9 years, 7 months