Hello Dave,
I have been working on a new command to provide information of ipc
facilities. Recently, the function displaying shared memory segments has
been implemented.
The output is like below:
crash> ipcs
------ Shared Memory Segments ------
SHM_KERNEL KEY SHMID RSS SWAP UID PERMS BYTES
NATTCH SHM_INODE
ffff8804683b0310 0x00000000 0 7 15 0 600 393216 2
ffff880470512d98
ffff880470987910 0x00000000 32769 6 16 0 600 393216 2
ffff880470512758
ffff880471621190 0x00000000 65538 46 0 0 600 393216 2
ffff880474202d98
ffff8804747f1a50 0x00000000 98307 12 12 0 600 393216 2
ffff880471264758
ffff8804704ad510 0x00000000 131076 96 0 0 600 393216 2
ffff880474094d98
To see more details, please refer to the help information and the patch.
--
--
Regards
Qiao Nuohan
>From 25c19191bb42c690a17f1c2d2170ef3174c06705 Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@xxxxxxxxxxxxxx>
Date: Fri, 30 Mar 2012 10:15:15 +0800
Subject: [PATCH] add ipcs command
---
Makefile | 7 +-
defs.h | 37 ++++
global_data.c | 1 +
help.c | 69 +++++++
ipcs.c | 580 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 692 insertions(+), 2 deletions(-)
create mode 100644 ipcs.c
diff --git a/Makefile b/Makefile
index 5d88a44..b682128 100644
--- a/Makefile
+++ b/Makefile
@@ -68,7 +68,7 @@ CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \
netdump.c diskdump.c makedumpfile.c xendump.c unwind.c unwind_decoder.c \
unwind_x86_32_64.c unwind_arm.c \
xen_hyper.c xen_hyper_command.c xen_hyper_global_data.c \
- xen_hyper_dump_tables.c kvmdump.c qemu.c qemu-load.c sadump.c
+ xen_hyper_dump_tables.c kvmdump.c qemu.c qemu-load.c sadump.c ipcs.c
SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \
${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \
@@ -85,7 +85,7 @@ OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \
lkcd_x86_trace.o unwind_v1.o unwind_v2.o unwind_v3.o \
unwind_x86_32_64.o unwind_arm.o \
xen_hyper.o xen_hyper_command.o xen_hyper_global_data.o \
- xen_hyper_dump_tables.o kvmdump.o qemu.o qemu-load.o sadump.o
+ xen_hyper_dump_tables.o kvmdump.o qemu.o qemu-load.o sadump.o ipcs.o
MEMORY_DRIVER_FILES=memory_driver/Makefile memory_driver/crash.c memory_driver/README
@@ -485,6 +485,9 @@ xen_hyper_global_data.o: ${GENERIC_HFILES} xen_hyper_global_data.c
xen_hyper_dump_tables.o: ${GENERIC_HFILES} xen_hyper_dump_tables.c
cc -c ${CRASH_CFLAGS} xen_hyper_dump_tables.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+ipcs.o: ${GENERIC_HFILES} ipcs.c
+ cc -c ${CRASH_CFLAGS} ipcs.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+
${PROGRAM}: force
@make --no-print-directory all
diff --git a/defs.h b/defs.h
index a942dbb..e454911 100755
--- a/defs.h
+++ b/defs.h
@@ -1662,6 +1662,38 @@ struct offset_table { /* stash of commonly-used offsets */
long request_queue_rq;
long subsys_private_klist_devices;
long subsystem_kset;
+
+ long file_f_op;
+ long file_private_data;
+ long hstate_order;
+ long hugetlbfs_sb_info_hstate;
+ long idr_layer_ary;
+ long idr_layer_layer;
+ long idr_layers;
+ long idr_top;
+ long ipc_id_ary_p;
+ long ipc_ids_entries;
+ long ipc_ids_max_id;
+ long ipc_ids_ipcs_idr;
+ long ipc_ids_in_use;
+ long ipc_namespace_ids;
+ long ipc_namespace_shm_tot;
+ long kern_ipc_perm_deleted;
+ long kern_ipc_perm_key;
+ long kern_ipc_perm_mode;
+ long kern_ipc_perm_seq;
+ long kern_ipc_perm_uid;
+ long kern_ipc_perm_id;
+ long nsproxy_ipc_ns;
+ long shmem_inode_info_swapped;
+ long shmem_inode_info_vfs_inode;
+ long shm_file_data_file;
+ long shmid_kernel_shm_file;
+ long shmid_kernel_shm_nattch;
+ long shmid_kernel_shm_perm;
+ long shmid_kernel_shm_segsz;
+ long shmid_kernel_id;
+ long super_block_s_fs_info;
};
struct size_table { /* stash of commonly-used sizes */
@@ -1788,6 +1820,9 @@ struct size_table { /* stash of commonly-used sizes */
long class_private;
long rq_in_flight;
long class_private_devices;
+ long hstate;
+ long ipc_ids;
+ long shmid_kernel;
};
struct array_table {
@@ -3539,6 +3574,7 @@ void cmd_dev(void); /* dev.c */
void cmd_gdb(void); /* gdb_interface.c */
void cmd_net(void); /* net.c */
void cmd_extend(void); /* extensions.c */
+void cmd_ipcs(void); /* ipcs.c */
#if defined(S390) || defined(S390X)
void cmd_s390dbf(void);
#endif
@@ -4017,6 +4053,7 @@ extern char *help_vtop[];
extern char *help_waitq[];
extern char *help_whatis[];
extern char *help_wr[];
+extern char *help_ipcs[];
#if defined(S390) || defined(S390X)
extern char *help_s390dbf[];
#endif
diff --git a/global_data.c b/global_data.c
index 98a5a79..e697f8e 100755
--- a/global_data.c
+++ b/global_data.c
@@ -118,6 +118,7 @@ struct command_table_entry linux_command_table[] = {
{"waitq", cmd_waitq, help_waitq, REFRESH_TASK_TABLE},
{"whatis", cmd_whatis, help_whatis, 0},
{"wr", cmd_wr, help_wr, 0},
+ {"ipcs", cmd_ipcs, help_ipcs, REFRESH_TASK_TABLE},
#if defined(S390) || defined(S390X)
{"s390dbf", cmd_s390dbf, help_s390dbf, 0},
#endif
diff --git a/help.c b/help.c
index f752283..2ba0389 100755
--- a/help.c
+++ b/help.c
@@ -5491,6 +5491,75 @@ char *help_waitq[] = {
NULL
};
+char *help_ipcs[] = {
+"ipcs",
+"provide information on ipc facilities(shared memory)",
+" [-u] [-i id]",
+" This command provides information on the ipc facilities. SHM_KERNEL is the",
+" address of the structure shmid_kernel. The unit of RSS and SWAP is the",
+" number of pages, and the BYTES is allocated memory with the unit of byte.",
+" The SHM_INODE represents the address of vfs_inode member of",
+" shmem_inode_info objects. The command now only shows information on shared",
+" memory.",
+" ",
+" -u shows summary information",
+" -i id it allows a specific resource id to be specified, and the",
+" information on this id will be printed",
+"\nEXAMPLE",
+" display all ipc facilities:\n",
+" %s> ipcs",
+" ------ Shared Memory Segments ------",
+" SHM_KERNEL KEY SHMID RSS SWAP UID PERMS BYTES NATTCH SHM_INODE ",
+" ffff8804683b0310 0x00000000 0 7 15 0 600 393216 2 ffff880470512d98",
+" ffff880470987910 0x00000000 32769 6 16 0 600 393216 2 ffff880470512758",
+" ffff880471621190 0x00000000 65538 46 0 0 600 393216 2 ffff880474202d98",
+" ffff8804747f1a50 0x00000000 98307 12 12 0 600 393216 2 ffff880471264758",
+" ffff8804704ad510 0x00000000 131076 96 0 0 600 393216 2 ffff880474094d98",
+" ffff880872e42150 0x00000000 163845 44 0 0 600 393216 2 ffff880872e6f758",
+" ffff88049cf33e10 0x00000000 196614 33 15 0 600 393216 2 ffff880872f0a438",
+" ffff880872e428d0 0x00000000 229383 72 0 0 600 393216 2 ffff880872e6f118",
+" ffff8804704ad5d0 0x00000000 262152 72 13 0 600 393216 2 ffff880470408758",
+" ffff880872e42210 0x00000000 294921 10 12 0 600 393216 2 ffff880872df2438",
+" ffff880872e42510 0x00000000 327690 96 0 0 600 393216 2 ffff880872ece118",
+" ffff880872e42750 0x00000000 360459 96 0 0 600 393216 2 ffff880872ece438",
+" ffff88086e2c0090 0x00000000 393228 96 0 0 600 393216 2 ffff880872045438",
+" ffff880872e422d0 0x00000000 425997 11 11 0 600 393216 2 ffff880872e6c118",
+" ffff880872e42090 0x00000000 458766 26 22 0 600 393216 2 ffff880872ea8d98",
+" ffff88046803a090 0x00000000 491535 0 25 0 600 393216 2 ffff880474202a78",
+" ffff88046803ad50 0x00000000 524304 0 45 0 600 393216 2 ffff880474202758",
+" ffff8804716219d0 0x00000000 557073 9 87 0 600 393216 2 ffff8804707bc758",
+" ffff88046803ab10 0x00000000 589842 89 7 0 600 393216 2 ffff880474202118",
+" ffff880471621790 0x00000000 4423699 0 0 0 666 1024 0 ffff88046f49e438",
+" ffff880470988390 0x00000000 720916 96 0 0 600 393216 2 ffff880470408d98",
+" ffff8804747f1810 0x00000000 753685 24 0 0 600 393216 2 ffff88047467d758",
+" ffff880470987610 0x00000000 4390934 282 0 0 600 1152000 2 ffff880471470438",
+" ffff880471621850 0x00000001 4456471 0 0 0 666 1024 0 ffff88046f49e118",
+" ffff880471621550 0x00000002 4489240 0 0 0 666 1024 0 ffff8804704be758",
+" ffff880471621a90 0x00000003 4522009 0 0 0 666 1024 0 ffff88046f5f7758",
+" ffff880471621b50 0x00000004 4554778 0 0 0 666 1024 0 ffff8804683f9758",
+" ",
+" display summary:\n",
+" %s> ipcs -u",
+" ------ Shared Memroy Status --------",
+" segments allocated 27",
+" pages allocatd 2303",
+" pages resident 1223",
+" pages swapped 280",
+" swap performance attemts 0",
+" swap performance successes 0",
+" ",
+" display a specified resource:\n",
+" %s> ipcs -u -i 458766",
+" SHMID: 458766",
+" ------ Shared Memroy Status --------",
+" segments allocated 27",
+" pages allocatd 96",
+" pages resident 26",
+" pages swapped 22",
+" swap performance attemts 0",
+" swap performance successes 0",
+};
+
/*
* Find out what the help request is looking for, accepting aliases as well,
diff --git a/ipcs.c b/ipcs.c
new file mode 100644
index 0000000..8048b72
--- /dev/null
+++ b/ipcs.c
@@ -0,0 +1,580 @@
+/* ipcs.c - core analysis suite
+ *
+ * Copyright (C) 2012 FUJITSU LIMITED
+ *
+ * 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 IPCS_INIT 0x1
+#define MAX_ID_SHIFT (sizeof(int)*8 - 1)
+#define MAX_ID_BIT (1U << MAX_ID_SHIFT)
+#define MAX_ID_MASK (MAX_ID_BIT - 1)
+
+/*
+ * struct declaration
+ */
+struct shm_info {
+ ulong shm_kernel;
+ int key;
+ int shmid;
+ ulong rss;
+ ulong swap;
+ unsigned int uid;
+ unsigned int perms;
+ ulong bytes;
+ ulong nattch;
+ ulong shm_inode;
+ int deleted;
+};
+
+struct total_shm_info {
+ int used_ids;
+ ulong shm_tot;
+ ulong shm_rss;
+ ulong shm_swp;
+ ulong swap_attempts;
+ ulong swap_successes;
+};
+
+/*
+ * function declaration
+ */
+static void dump_shared_memory(int, int);
+static void ipc_search_idr(ulong, int, int (*)(ulong, int));
+static void ipc_search_array(ulong, int, int (*)(ulong, int));
+static ulong idr_find(ulong, int);
+static int dump_single_shm(ulong, int);
+static int dump_specified_shm(ulong, int);
+static void get_shm_info(struct shm_info *, ulong);
+static void add_rss_swap(ulong, int, ulong *, ulong *);
+static int is_file_hugepages(ulong);
+static void display_summary(void);
+
+/*
+ * global data
+ */
+static int idr_bits;
+static ulong init_flags;
+static ulong hugetlbfs_f_op_addr;
+static ulong shm_f_op_addr;
+static ulong shm_f_op_huge_addr;
+static int use_shm_f_op;
+static struct total_shm_info total_shm_info;
+static unsigned int page_size;
+static unsigned int page_shift;
+
+static void ipcs_init(void)
+{
+ total_shm_info.shm_rss = 0;
+ total_shm_info.shm_swp = 0;
+ total_shm_info.swap_attempts = 0;
+ total_shm_info.swap_successes = 0;
+
+ if (init_flags & IPCS_INIT) {
+ return;
+ }
+
+ init_flags |= IPCS_INIT;
+
+ MEMBER_OFFSET_INIT(nsproxy_ipc_ns, "nsproxy", "ipc_ns");
+ MEMBER_OFFSET_INIT(ipc_namespace_ids, "ipc_namespace", "ids");
+ MEMBER_OFFSET_INIT(ipc_namespace_shm_tot, "ipc_namespace", "shm_tot");
+ MEMBER_OFFSET_INIT(ipc_ids_entries, "ipc_ids", "entries");
+ MEMBER_OFFSET_INIT(ipc_ids_max_id, "ipc_ids", "max_id");
+ MEMBER_OFFSET_INIT(ipc_ids_in_use, "ipc_ids", "in_use");
+ MEMBER_OFFSET_INIT(ipc_ids_ipcs_idr, "ipc_ids", "ipcs_idr");
+ MEMBER_OFFSET_INIT(ipc_id_ary_p, "ipc_id_ary", "p");
+ MEMBER_OFFSET_INIT(idr_top, "idr", "top");
+ MEMBER_OFFSET_INIT(idr_layer_layer, "idr_layer", "layer");
+ MEMBER_OFFSET_INIT(idr_layer_ary, "idr_layer", "ary");
+ MEMBER_OFFSET_INIT(shmid_kernel_shm_perm, "shmid_kernel", "shm_perm");
+ MEMBER_OFFSET_INIT(shmid_kernel_shm_segsz, "shmid_kernel", "shm_segsz");
+ MEMBER_OFFSET_INIT(shmid_kernel_shm_nattch, "shmid_kernel", "shm_nattch");
+ MEMBER_OFFSET_INIT(shmid_kernel_shm_file, "shmid_kernel", "shm_file");
+ MEMBER_OFFSET_INIT(shmid_kernel_id, "shmid_kernel", "id");
+ MEMBER_OFFSET_INIT(kern_ipc_perm_key, "kern_ipc_perm", "key");
+ MEMBER_OFFSET_INIT(kern_ipc_perm_id, "kern_ipc_perm", "id");
+ MEMBER_OFFSET_INIT(kern_ipc_perm_uid, "kern_ipc_perm", "uid");
+ MEMBER_OFFSET_INIT(kern_ipc_perm_mode, "kern_ipc_perm", "mode");
+ MEMBER_OFFSET_INIT(kern_ipc_perm_deleted, "kern_ipc_perm", "deleted");
+ MEMBER_OFFSET_INIT(file_f_op, "file", "f_op");
+ MEMBER_OFFSET_INIT(file_private_data, "file", "private_data");
+ MEMBER_OFFSET_INIT(shm_file_data_file, "shm_file_data", "file");
+ MEMBER_OFFSET_INIT(super_block_s_fs_info, "super_block", "s_fs_info");
+ MEMBER_OFFSET_INIT(hstate_order, "hstate", "order");
+ MEMBER_OFFSET_INIT(shmem_inode_info_vfs_inode, "shmem_inode_info", "vfs_inode");
+ MEMBER_OFFSET_INIT(shmem_inode_info_swapped, "shmem_inode_info", "swapped");
+
+ /*
+ * struct size
+ */
+ STRUCT_SIZE_INIT(ipc_ids, "ipc_ids");
+ STRUCT_SIZE_INIT(shmid_kernel, "shmid_kernel");
+ STRUCT_SIZE_INIT(hstate, "hstate");
+
+ hugetlbfs_f_op_addr = symbol_value("hugetlbfs_file_operations");
+ if (symbol_exists("is_file_shm_hugepages")) {
+ use_shm_f_op = TRUE;
+ shm_f_op_addr = symbol_value("shm_file_operations");
+ if (symbol_exists("shm_file_operations_huge")) {
+ shm_f_op_huge_addr =
+ symbol_value("shm_file_operations_huge");
+ } else {
+ shm_f_op_huge_addr = -1;
+ }
+ } else {
+ use_shm_f_op = FALSE;
+ shm_f_op_addr = -1;
+ shm_f_op_huge_addr = -1;
+ }
+
+ if (BITS32())
+ idr_bits = 5;
+ else if (BITS64())
+ idr_bits = 6;
+ else
+ error(FATAL, "machdep->bits is not 32 or 64");
+
+ page_size = memory_page_size();
+ page_shift = ffs(page_size) - 1;
+}
+
+void cmd_ipcs(void)
+{
+ int show_summary, specified_id;
+ int id;
+ int c;
+
+ id = 0;
+ show_summary = 0;
+ specified_id = 0;
+ while ((c = getopt(argcnt, args, "ui:")) != EOF) {
+ switch(c) {
+ case 'u':
+ show_summary = 1;
+ break;
+ case 'i':
+ id = dtoi(optarg, FAULT_ON_ERROR, NULL);
+ specified_id = 1;
+ break;
+ default:
+ cmd_usage(pc->curcmd, SYNOPSIS);;
+ return;
+ }
+ }
+
+ ipcs_init();
+
+ if (show_summary && !specified_id)
+ open_tmpfile();
+
+ dump_shared_memory(specified_id, id);
+
+ if (show_summary && !specified_id) {
+ close_tmpfile();
+ display_summary();
+ }
+}
+
+static void dump_shared_memory(int specified_id, int id)
+{
+ ulong cur_task = CURRENT_TASK();
+ ulong nsproxy_p, ipc_ns_p;
+ ulong ipc_ids_p;
+ void (*ipc_search)(ulong, int, int (*)(ulong, int));
+ int (*dump_shm)(ulong, int);
+ char buf0[BUFSIZE];
+ char buf1[BUFSIZE];
+ char buf2[BUFSIZE];
+ char buf3[BUFSIZE];
+ char buf4[BUFSIZE];
+ char buf5[BUFSIZE];
+ char buf6[BUFSIZE];
+ char buf7[BUFSIZE];
+ char buf8[BUFSIZE];
+ char buf9[BUFSIZE];
+
+ if (!specified_id) {
+ fprintf(fp, "------ Shared Memory Segments ------\n");
+ fprintf(fp, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ mkstring(buf0, VADDR_PRLEN, LJUST, "SHM_KERNEL"),
+ space(MINSPACE),
+ mkstring(buf1, 10, LJUST, "KEY"),
+ space(MINSPACE),
+ mkstring(buf2, 8, LJUST, "SHMID"),
+ space(MINSPACE),
+ mkstring(buf3, 5, LJUST, "RSS"),
+ space(MINSPACE),
+ mkstring(buf4, 5, LJUST, "SWAP"),
+ space(MINSPACE),
+ mkstring(buf5, 5, LJUST, "UID"),
+ space(MINSPACE),
+ mkstring(buf6, 5, LJUST, "PERMS"),
+ space(MINSPACE),
+ mkstring(buf7, 7, LJUST, "BYTES"),
+ space(MINSPACE),
+ mkstring(buf8, 7, LJUST, "NATTCH"),
+ space(MINSPACE),
+ mkstring(buf9, VADDR_PRLEN, LJUST, "SHM_INODE"));
+ dump_shm = dump_single_shm;
+ } else
+ dump_shm = dump_specified_shm;
+
+ if (VALID_MEMBER(ipc_ids_max_id)) {
+ ipc_search = ipc_search_array;
+ } else {
+ ipc_search = ipc_search_idr;
+ }
+
+ if (symbol_exists("shm_ids")) {
+ ipc_ids_p = symbol_value("shm_ids");
+ int shm_tot;
+ readmem(symbol_value("shm_tot"), KVADDR, &shm_tot, sizeof(int),
+ "shm_tot", FAULT_ON_ERROR);
+ total_shm_info.shm_tot = shm_tot;
+ } else {
+ readmem(cur_task + OFFSET(task_struct_nsproxy), KVADDR,
+ &nsproxy_p, sizeof(ulong), "task_struct.nsproxy",
+ FAULT_ON_ERROR);
+ readmem(nsproxy_p + OFFSET(nsproxy_ipc_ns), KVADDR, &ipc_ns_p,
+ sizeof(ulong), "nsproxy.ipc_ns", FAULT_ON_ERROR);
+ int shm_tot;
+ readmem(ipc_ns_p + OFFSET(ipc_namespace_shm_tot), KVADDR,
+ &shm_tot, sizeof(int),
+ "ipc_namespace.shm_tot", FAULT_ON_ERROR);
+ total_shm_info.shm_tot = shm_tot;
+
+ ipc_ids_p = ipc_ns_p + OFFSET(ipc_namespace_ids) + 2 * SIZE(ipc_ids);
+ }
+ ipc_search(ipc_ids_p, id, dump_shm);
+}
+
+/*
+ * if shared memory information is stored in an array, use this function.
+ */
+static void ipc_search_array(ulong ipc_ids_p, int id, int (*fn)(ulong, int))
+{
+ ulong entries_p;
+ int max_id, i;
+ ulong *array;
+
+ readmem(ipc_ids_p + OFFSET(ipc_ids_entries), KVADDR, &entries_p,
+ sizeof(ulong), "ipc_ids.entries", FAULT_ON_ERROR);
+ readmem(ipc_ids_p + OFFSET(ipc_ids_max_id), KVADDR, &max_id, sizeof(int),
+ "ipc_ids.max_id", FAULT_ON_ERROR);
+ ulong in_use;
+ readmem(ipc_ids_p + OFFSET(ipc_ids_in_use), KVADDR, &in_use,
+ sizeof(int), "ipc_ids.in_use", FAULT_ON_ERROR);
+ total_shm_info.used_ids = in_use;
+
+ array = (ulong *)GETBUF(sizeof(ulong *) * (max_id + 1));
+ readmem(entries_p + OFFSET(ipc_id_ary_p), KVADDR, array,
+ sizeof(ulong *) * (max_id + 1), "ipc_id_ary.p", FAULT_ON_ERROR);
+
+ for (i=0; i<=max_id; i++) {
+ if (array[i] == 0)
+ continue;
+ if (fn(array[i], id))
+ break;
+ }
+
+ FREEBUF(array);
+}
+
+/*
+ * if shared memory information is stored by using idr, use this function to
+ * get data.
+ */
+static void ipc_search_idr(ulong ipc_ids_p, int id, int (*fn)(ulong, int))
+{
+ int in_use;
+ ulong ipcs_idr_p;
+ ulong ipc;
+ int next_id, total;
+
+ readmem(ipc_ids_p + OFFSET(ipc_ids_in_use), KVADDR, &in_use,
+ sizeof(int), "ipc_ids.in_use", FAULT_ON_ERROR);
+
+ total_shm_info.used_ids = in_use;
+ ipcs_idr_p = ipc_ids_p + OFFSET(ipc_ids_ipcs_idr);
+
+ for (total = 0, next_id = 0; total < in_use; next_id++) {
+ ipc = idr_find(ipcs_idr_p, next_id);
+ if (ipc == 0)
+ continue;
+
+ total++;
+ if (fn(ipc, id))
+ break;
+ }
+}
+
+/*
+ * search every idr_layer
+ */
+static ulong idr_find(ulong idp, int id)
+{
+ ulong idr_layer_p;
+ int layer;
+ int n;
+ int index;
+
+ readmem(idp + OFFSET(idr_top), KVADDR, &idr_layer_p, sizeof(ulong),
+ "idr.top", FAULT_ON_ERROR);
+
+ if (!idr_layer_p)
+ return 0;
+
+ readmem(idr_layer_p + OFFSET(idr_layer_layer), KVADDR, &layer,
+ sizeof(int), "idr_layer.layer", FAULT_ON_ERROR);
+
+ n = (layer + 1) * idr_bits;
+ id &= MAX_ID_MASK;
+
+ if (id >= (1 << n))
+ return 0;
+
+ while (n > 0 && idr_layer_p) {
+ n -= idr_bits;
+ index = (id >> n) & ((1 << idr_bits) - 1);
+ readmem(idr_layer_p + OFFSET(idr_layer_ary) + sizeof(ulong) * index,
+ KVADDR, &idr_layer_p, sizeof(ulong), "idr_layer.ary",
+ FAULT_ON_ERROR);
+ }
+
+ return idr_layer_p;
+}
+
+static int dump_single_shm(ulong shp, int id)
+{
+ struct shm_info shm_info;
+ char buf0[BUFSIZE];
+ char buf1[BUFSIZE];
+
+ get_shm_info(&shm_info, shp);
+
+ if (shm_info.deleted)
+ return 0;
+
+ fprintf(fp, "%s%s0x%08x%s%-8d%s%-5ld%s%-5ld%s%-5d%s%-5o%s%-7ld%s%-7ld%s%s\n",
+ mkstring(buf0, VADDR_PRLEN <= 10 ? 10 : VADDR_PRLEN,
+ LJUST|LONG_HEX, (char *)shm_info.shm_kernel),
+ space(MINSPACE),
+ shm_info.key,
+ space(MINSPACE),
+ shm_info.shmid,
+ space(MINSPACE),
+ shm_info.rss,
+ space(MINSPACE),
+ shm_info.swap,
+ space(MINSPACE),
+ shm_info.uid,
+ space(MINSPACE),
+ shm_info.perms & 0777,
+ space(MINSPACE),
+ shm_info.bytes,
+ space(MINSPACE),
+ shm_info.nattch,
+ space(MINSPACE),
+ mkstring(buf1, VADDR_PRLEN <= 9 ? 9 : VADDR_PRLEN, LJUST|LONG_HEX,
+ (char *)shm_info.shm_inode));
+
+ return 0;
+}
+
+/*
+ * if the resource is specified, use this function to output information
+ */
+static int dump_specified_shm(ulong shp, int id)
+{
+ struct shm_info shm_info;
+
+ get_shm_info(&shm_info, shp);
+
+ if(shm_info.shmid == id) {
+ fprintf(fp, "SHMID: %d\n", shm_info.shmid);
+ fprintf(fp, "------ Shared Memroy Status --------\n");
+ fprintf(fp, "segments allocated %d\n", total_shm_info.used_ids);
+ fprintf(fp, "pages allocatd %ld\n",
+ (shm_info.bytes + page_size - 1) >> page_shift);
+ fprintf(fp, "pages resident %ld\n", shm_info.rss);
+ fprintf(fp, "pages swapped %ld\n", shm_info.swap);
+ fprintf(fp, "swap performance attemts %ld\n",
+ total_shm_info.swap_attempts);
+ fprintf(fp, "swap performance successes %ld",
+ total_shm_info.swap_successes);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void get_shm_info(struct shm_info *shm_info, ulong shp)
+{
+ char buf[BUFSIZE];
+ ulong filep, dentryp, inodep;
+
+ shm_info->shm_kernel = shp - OFFSET(shmid_kernel_shm_perm);
+
+ //cache shmid_kernel
+ readmem(shm_info->shm_kernel, KVADDR, buf, SIZE(shmid_kernel),
+ "shmid_kernel", FAULT_ON_ERROR);
+
+ shm_info->key = INT(buf + OFFSET(shmid_kernel_shm_perm) +
+ OFFSET(kern_ipc_perm_key));
+ if (VALID_MEMBER(shmid_kernel_id))
+ shm_info->shmid = INT(buf + OFFSET(shmid_kernel_id));
+ else
+ shm_info->shmid = INT(buf + OFFSET(shmid_kernel_shm_perm) +
+ OFFSET(kern_ipc_perm_id));
+
+ shm_info->uid = UINT(buf + OFFSET(shmid_kernel_shm_perm) +
+ OFFSET(kern_ipc_perm_uid));
+
+ if (BITS32())
+ shm_info->perms = USHORT(buf + OFFSET(shmid_kernel_shm_perm) +
+ OFFSET(kern_ipc_perm_mode));
+ else
+ shm_info->perms = UINT(buf + OFFSET(shmid_kernel_shm_perm) +
+ OFFSET(kern_ipc_perm_mode));
+
+ shm_info->bytes = ULONG(buf + OFFSET(shmid_kernel_shm_segsz));
+
+ shm_info->nattch = ULONG(buf + OFFSET(shmid_kernel_shm_nattch));
+
+ filep = ULONG(buf + OFFSET(shmid_kernel_shm_file));
+ readmem(filep + OFFSET(file_f_dentry), KVADDR, &dentryp, sizeof(ulong),
+ "file.f_dentry", FAULT_ON_ERROR);
+ readmem(dentryp + OFFSET(dentry_d_inode), KVADDR, &inodep, sizeof(ulong),
+ "dentry.d_inode", FAULT_ON_ERROR);
+ // shm_inode here is the vfs_inode of struct shmem_inode_info
+ shm_info->shm_inode = inodep;
+
+ shm_info->rss = 0;
+ shm_info->swap = 0;
+
+ add_rss_swap(inodep, is_file_hugepages(filep), &shm_info->rss,
+ &shm_info->swap);
+
+ shm_info->deleted = UINT(buf + OFFSET(shmid_kernel_shm_perm) +
+ OFFSET(kern_ipc_perm_deleted));
+}
+
+/*
+ * get rss & swap related to every shared memory, and get the total number of rss
+ * & swap
+ */
+static void add_rss_swap(ulong inode_p, int hugepage, ulong *rss, ulong *swap)
+{
+ unsigned long mapping_p, nr_pages;
+
+ readmem(inode_p + OFFSET(inode_i_mapping), KVADDR, &mapping_p,
+ sizeof(ulong), "inode.i_mapping", FAULT_ON_ERROR);
+ readmem(mapping_p + OFFSET(address_space_nrpages), KVADDR, &nr_pages,
+ sizeof(ulong), "address_space.nrpages", FAULT_ON_ERROR);
+
+ if (hugepage) {
+ unsigned long pages_per_hugepage;
+ if (VALID_SIZE(hstate)) {
+ unsigned long i_sb_p, hsb_p, hstate_p;
+ unsigned int order;
+
+ readmem(inode_p + OFFSET(inode_i_sb), KVADDR, &i_sb_p,
+ sizeof(ulong), "inode.i_sb", FAULT_ON_ERROR);
+ readmem(i_sb_p + OFFSET(super_block_s_fs_info), KVADDR,
+ &hsb_p, sizeof(ulong), "super_block.s_fs_info",
+ FAULT_ON_ERROR);
+ readmem(hsb_p + OFFSET(hugetlbfs_sb_info_hstate), KVADDR,
+ &hstate_p, sizeof(ulong),
+ "hugetlbfs_sb_info.hstate", FAULT_ON_ERROR);
+ readmem(hstate_p + OFFSET(hstate_order), KVADDR, &order,
+ sizeof(uint), "hstate.order", FAULT_ON_ERROR);
+ pages_per_hugepage = 1 << order;
+ } else {
+ unsigned long hpage_shift;
+ /*
+ * HPAGE_SHIFT is 21 after commit 83a5101b(kernel > 2.6.24)
+ */
+ if (THIS_KERNEL_VERSION > LINUX(2, 6, 24)) {
+ hpage_shift = 21;
+ } else {
+ /*
+ * HPAGE_SHIFT:
+ * x86(PAE): 21
+ * x86(no PAE): 22
+ * x86_64: 21
+ */
+ if ((machine_type("X86") && !(machdep->flags & PAE)))
+ hpage_shift = 22;
+ else
+ hpage_shift = 21;
+ }
+ pages_per_hugepage = (1 << hpage_shift) / page_size;
+ }
+ *rss += pages_per_hugepage * nr_pages;
+ total_shm_info.shm_rss += *rss;
+ } else {
+ unsigned long swapped;
+
+ *rss += nr_pages;
+ total_shm_info.shm_rss += *rss;
+ readmem(inode_p - OFFSET(shmem_inode_info_vfs_inode) +
+ OFFSET(shmem_inode_info_swapped), KVADDR, &swapped,
+ sizeof(ulong), "shmem_inode_info.swapped", FAULT_ON_ERROR);
+ *swap += swapped;
+ total_shm_info.shm_swp += *swap;
+ }
+}
+
+static int is_file_hugepages(ulong file_p)
+{
+ unsigned long f_op, sfd_p;
+
+again:
+ readmem(file_p + OFFSET(file_f_op), KVADDR, &f_op, sizeof(ulong),
+ "file.f_op", FAULT_ON_ERROR);
+ if (f_op == hugetlbfs_f_op_addr)
+ return 1;
+
+ if (use_shm_f_op) {
+ if (shm_f_op_huge_addr != -1) {
+ if (f_op == shm_f_op_huge_addr)
+ return 1;
+ } else {
+ if (f_op == shm_f_op_addr) {
+ readmem(file_p + OFFSET(file_private_data), KVADDR,
+ &sfd_p, sizeof(ulong), "file.private_data",
+ FAULT_ON_ERROR);
+ readmem(sfd_p + OFFSET(shm_file_data_file), KVADDR,
+ &file_p, sizeof(ulong),
+ "shm_file_data.file", FAULT_ON_ERROR);
+ goto again;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void display_summary()
+{
+ fprintf(fp, "------ Shared Memroy Status --------\n");
+ fprintf(fp, "segments allocated %d\n", total_shm_info.used_ids);
+ fprintf(fp, "pages allocatd %ld\n", total_shm_info.shm_tot);
+ fprintf(fp, "pages resident %ld\n", total_shm_info.shm_rss);
+ fprintf(fp, "pages swapped %ld\n", total_shm_info.shm_swp);
+ fprintf(fp, "swap performance attemts %ld\n",
+ total_shm_info.swap_attempts);
+ fprintf(fp, "swap performance successes %ld",
+ total_shm_info.swap_successes);
+}
--
1.7.1
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility