Re: [PATCH] add a new command: ipcs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Dave,

The patch has been changed into an extension module. And the option and its related output is changed as well. Please check.


--
--
Regards
Qiao Nuohan


/* ipcs.c - provide information on ipc facilities
 *
 * Copyright (C) 2012 FUJITSU LIMITED
 * Auther: Qiao Nuohan <qiaonuohan@xxxxxxxxxxxxxx>
 *
 * 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"    /* From the crash source top-level directory */

#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)

#define SHM_DEST   01000
#define SHM_LOCKED 02000

#define IPCS_MEMBER_OFFSET_INIT(X, Y, Z) (ipcs_offset_table.X = MEMBER_OFFSET(Y, Z))
#define IPCS_ANON_MEMBER_OFFSET_INIT(X, Y, Z) (ipcs_offset_table.X = ANON_MEMBER_OFFSET(Y, Z))
#define IPCS_STRUCT_SIZE_INIT(X, Y) (ipcs_size_table.X = STRUCT_SIZE(Y))

#define IPCS_OFFSET(X)	   (OFFSET_verify(ipcs_offset_table.X, (char *)__FUNCTION__, __FILE__, __LINE__, #X))
#define IPCS_SIZE(X)            (SIZE_verify(ipcs_size_table.X, (char *)__FUNCTION__, __FILE__, __LINE__, #X))

#define IPCS_INVALID_MEMBER(X)  (ipcs_offset_table.X == INVALID_OFFSET)
#define IPCS_INVALID_SIZE(X)    (ipcs_size_table.X == -1)
#define IPCS_VALID_SIZE(X)      (ipcs_size_table.X >= 0)
#define IPCS_VALID_STRUCT(X)    (ipcs_size_table.X >= 0)
#define IPCS_VALID_MEMBER(X)    (ipcs_offset_table.X >= 0)

/*
 * struct declaration
 */
struct ipcs_offset_table {
	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 ipc_namespace_used_sems;
	long ipc_namespace_msg_hdrs;
	long ipc_namespace_msg_bytes;
	long kern_ipc_perm_deleted;
	long kern_ipc_perm_key;
	long kern_ipc_perm_mode;
	long kern_ipc_perm_uid;
	long kern_ipc_perm_id;
	long kern_ipc_perm_seq;
	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 sem_array_sem_perm;
	long sem_array_sem_id;
	long sem_array_sem_nsems;
	long msg_queue_q_perm;
	long msg_queue_q_id;
	long msg_queue_q_cbytes;
	long msg_queue_q_qnum;
	long super_block_s_fs_info;
};

struct ipcs_size_table {
	long hstate;
	long ipc_ids;
	long shmid_kernel;
	long sem_array;
	long msg_queue;
};

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 sem_info {
	ulong sem_array;
	int key;
	int semid;
	unsigned int uid;
	unsigned int perms;
	ulong nsems;
	int deleted;
};

struct msg_info {
	ulong msg_queue;
	int key;
	int msgid;
	unsigned int uid;
	unsigned int perms;
	ulong bytes;
	ulong messages;
	int deleted;
};

struct total_shm_info {
	int used_ids;
	ulong shm_tot;
	ulong shm_rss;
	ulong shm_swp;
	ulong swap_attempts;
	ulong swap_successes;
};

struct total_sem_info {
	int semusz;
	int semaem;
};

struct total_msg_info {
	int msgpool;
	int msgmap;
	int msgtql;
};

struct ipcs_table {
	int idr_bits;
	ulong init_flags;
	ulong hugetlbfs_f_op_addr;
	ulong shm_f_op_addr;
	ulong shm_f_op_huge_addr;
	int use_shm_f_op;
	int seq_multiplier;
};

/*
 * function declaration
 */
int _init(void);
int _fini(void);

void cmd_ipcs(void);     /* Declare the commands and their help data. */
char *help_ipcs[];

static void ipcs_init(void);
static void dump_shared_memory(int, int);
static void dump_semaphore_arrays(int, int);
static void dump_message_queues(int, int);
static void ipc_search_idr(ulong, int, int, int (*)(ulong, int, int));
static void ipc_search_array(ulong, int, int, int (*)(ulong, int, int));
static ulong idr_find(ulong, int);
static int dump_single_shm(ulong, int, int);
static int dump_specified_shm(ulong, int, int);
static int dump_single_sem(ulong, int, int);
static int dump_specified_sem(ulong, int, int);
static int dump_single_msg(ulong, int, int);
static int dump_specified_msg(ulong, int, int);
static void get_shm_info(struct shm_info *, ulong, int);
static void get_sem_info(struct sem_info *, ulong, int);
static void get_msg_info(struct msg_info *, ulong, int);
static void add_rss_swap(ulong, int, ulong *, ulong *);
static int is_file_hugepages(ulong);
static void display_shm_summary(void);
static void display_sem_summary(void);
static void display_msg_summary(void);

static struct command_table_entry command_table[] = {
	{ "ipcs", cmd_ipcs, help_ipcs, 0 },    /* One or more commands, */
	{ NULL }                               /* terminated by NULL, */
};

/*
 * global data
 */
static struct ipcs_offset_table ipcs_offset_table = { 0 };
static struct ipcs_size_table ipcs_size_table = { 0 };
static struct total_shm_info total_shm_info = { 0 };
static struct total_sem_info total_sem_info = { 0 };
static struct total_msg_info total_msg_info = { 0 };
static struct ipcs_table ipcs_table = { 0 };

int 
_init(void) /* Register the command set. */
{ 
        register_extension(command_table);
	return 1;
}
 
/* 
 *  The _fini() function is called if the shared object is unloaded. 
 *  If desired, perform any cleanups here. 
 */
int 
_fini(void) 
{ 
	return 1;
}

static void
ipcs_init(void)
{
	if (ipcs_table.init_flags & IPCS_INIT) {
		return;
	}

	ipcs_table.init_flags |= IPCS_INIT;

	IPCS_MEMBER_OFFSET_INIT(file_f_op, "file", "f_op");
	IPCS_MEMBER_OFFSET_INIT(file_private_data, "file", "private_data");
	IPCS_MEMBER_OFFSET_INIT(hstate_order, "hstate", "order");
	IPCS_MEMBER_OFFSET_INIT(hugetlbfs_sb_info_hstate, "hugetlbfs_sb_info",
			"hstate");
	IPCS_MEMBER_OFFSET_INIT(idr_layers, "idr", "layers");
	IPCS_MEMBER_OFFSET_INIT(idr_layer_layer, "idr_layer", "layer");
	IPCS_MEMBER_OFFSET_INIT(idr_layer_ary, "idr_layer", "ary");
	IPCS_MEMBER_OFFSET_INIT(idr_top, "idr", "top");
	IPCS_MEMBER_OFFSET_INIT(ipc_id_ary_p, "ipc_id_ary", "p");
	IPCS_MEMBER_OFFSET_INIT(ipc_ids_entries, "ipc_ids", "entries");
	IPCS_MEMBER_OFFSET_INIT(ipc_ids_max_id, "ipc_ids", "max_id");
	IPCS_MEMBER_OFFSET_INIT(ipc_ids_in_use, "ipc_ids", "in_use");
	IPCS_MEMBER_OFFSET_INIT(ipc_ids_ipcs_idr, "ipc_ids", "ipcs_idr");
	IPCS_MEMBER_OFFSET_INIT(ipc_namespace_ids, "ipc_namespace", "ids");
	IPCS_MEMBER_OFFSET_INIT(ipc_namespace_shm_tot, "ipc_namespace",
			"shm_tot");
	IPCS_MEMBER_OFFSET_INIT(ipc_namespace_used_sems, "ipc_namespace",
			"used_sems");
	IPCS_MEMBER_OFFSET_INIT(ipc_namespace_msg_hdrs, "ipc_namespace",
			"msg_hdrs");
	IPCS_MEMBER_OFFSET_INIT(ipc_namespace_msg_bytes, "ipc_namespace",
			"msg_bytes");
	IPCS_MEMBER_OFFSET_INIT(kern_ipc_perm_key, "kern_ipc_perm", "key");
	IPCS_MEMBER_OFFSET_INIT(kern_ipc_perm_id, "kern_ipc_perm", "id");
	IPCS_MEMBER_OFFSET_INIT(kern_ipc_perm_uid, "kern_ipc_perm", "uid");
	IPCS_MEMBER_OFFSET_INIT(kern_ipc_perm_mode, "kern_ipc_perm", "mode");
	IPCS_MEMBER_OFFSET_INIT(kern_ipc_perm_deleted, "kern_ipc_perm",
			"deleted");
	IPCS_MEMBER_OFFSET_INIT(kern_ipc_perm_seq, "kern_ipc_perm", "seq");
	IPCS_MEMBER_OFFSET_INIT(nsproxy_ipc_ns, "nsproxy", "ipc_ns");
	IPCS_MEMBER_OFFSET_INIT(shmem_inode_info_vfs_inode, "shmem_inode_info",
			"vfs_inode");
	IPCS_MEMBER_OFFSET_INIT(shmem_inode_info_swapped, "shmem_inode_info",
			"swapped");
	if (IPCS_INVALID_MEMBER(shmem_inode_info_swapped))
		IPCS_ANON_MEMBER_OFFSET_INIT(shmem_inode_info_swapped,
				"shmem_inode_info", "swapped");
	IPCS_MEMBER_OFFSET_INIT(shm_file_data_file, "shm_file_data", "file");
	IPCS_MEMBER_OFFSET_INIT(shmid_kernel_shm_perm, "shmid_kernel",
			"shm_perm");
	IPCS_MEMBER_OFFSET_INIT(shmid_kernel_shm_segsz, "shmid_kernel",
			"shm_segsz");
	IPCS_MEMBER_OFFSET_INIT(shmid_kernel_shm_nattch, "shmid_kernel",
			"shm_nattch");
	IPCS_MEMBER_OFFSET_INIT(shmid_kernel_shm_file, "shmid_kernel",
			"shm_file");
	IPCS_MEMBER_OFFSET_INIT(shmid_kernel_id, "shmid_kernel", "id");
	IPCS_MEMBER_OFFSET_INIT(sem_array_sem_perm, "sem_array", "sem_perm");
	IPCS_MEMBER_OFFSET_INIT(sem_array_sem_id, "sem_array", "sem_id");
	IPCS_MEMBER_OFFSET_INIT(sem_array_sem_nsems, "sem_array", "sem_nsems");
	IPCS_MEMBER_OFFSET_INIT(msg_queue_q_perm, "msg_queue", "q_perm");
	IPCS_MEMBER_OFFSET_INIT(msg_queue_q_id, "msg_queue", "q_id");
	IPCS_MEMBER_OFFSET_INIT(msg_queue_q_cbytes, "msg_queue", "q_cbytes");
	IPCS_MEMBER_OFFSET_INIT(msg_queue_q_qnum, "msg_queue", "q_qnum");
	IPCS_MEMBER_OFFSET_INIT(super_block_s_fs_info, "super_block",
			"s_fs_info");

	/*
	 * struct size
	 */
	IPCS_STRUCT_SIZE_INIT(ipc_ids, "ipc_ids");
	IPCS_STRUCT_SIZE_INIT(shmid_kernel, "shmid_kernel");
	IPCS_STRUCT_SIZE_INIT(sem_array, "sem_array");
	IPCS_STRUCT_SIZE_INIT(msg_queue, "msg_queue");
	IPCS_STRUCT_SIZE_INIT(hstate, "hstate");

	if (symbol_exists("hugetlbfs_file_operations"))
		ipcs_table.hugetlbfs_f_op_addr =
			symbol_value("hugetlbfs_file_operations");
	if (symbol_exists("is_file_shm_hugepages")) {
		ipcs_table.use_shm_f_op = TRUE;
		ipcs_table.shm_f_op_addr =
			symbol_value("shm_file_operations");
		if (symbol_exists("shm_file_operations_huge")) {
			ipcs_table.shm_f_op_huge_addr =
				symbol_value("shm_file_operations_huge");
		} else {
			ipcs_table.shm_f_op_huge_addr = -1;
		}
	} else {
		ipcs_table.use_shm_f_op = FALSE;
		ipcs_table.shm_f_op_addr = -1;
		ipcs_table.shm_f_op_huge_addr = -1;
	}

	if (BITS32())
		ipcs_table.idr_bits = 5;
	else if (BITS64())
		ipcs_table.idr_bits = 6;
	else
		error(FATAL, "machdep->bits is not 32 or 64");

	ipcs_table.seq_multiplier = 32768;
}

/* 
 *  Arguments are passed to the command functions in the global args[argcnt]
 *  array.  See getopt(3) for info on dash arguments.  Check out defs.h and
 *  other crash commands for usage of the myriad of utility routines available
 *  to accomplish what your task.
 */
void
cmd_ipcs(void)
{
	int show_summary, specified;
	int specified_id;
	int c;
	int shm, sem, msg;

	specified_id = 0;
	show_summary = 0;
	specified = 0;
	shm = 0;
	sem = 0;
	msg = 0;
	
	while ((c = getopt(argcnt, args, "ui:smq")) != EOF) {
		switch(c) {
			case 'u':
				show_summary = 1;
				break;
			case 'i':
				specified_id =
					dtoi(optarg, FAULT_ON_ERROR, NULL);
				specified = 1;
				break;
			case 's':
				sem = 1;
				break;
			case 'm':
				shm = 1;
				break;
			case 'q':
				msg = 1;
				break;
			default:
				cmd_usage(pc->curcmd, SYNOPSIS);;
				return;
		}
	}

	if (specified && (shm + sem + msg) != 1) {
		error(INFO,
			"specified one of -s -m -q together with -i option\n");
		cmd_usage(pc->curcmd, SYNOPSIS);
	}

	if (THIS_KERNEL_VERSION < LINUX(2,6,0))
		command_not_supported();

	ipcs_init();

	if (!shm && !sem && !msg)
		shm = sem = msg = 1;

	if (show_summary && !specified)
		open_tmpfile();

	if (shm)
		dump_shared_memory(specified, specified_id);
	if (sem)
		dump_semaphore_arrays(specified, specified_id);
	if (msg)
		dump_message_queues(specified, specified_id);

	if (show_summary && !specified) {
		close_tmpfile();
		if (shm)
			display_shm_summary();
		if (sem)
			display_sem_summary();
		if (msg)
			display_msg_summary();
	}
}

char *help_ipcs[] = {
	"ipcs",                                   /* command name */
	"provide information on ipc facilities",  /* short description */
	"[[-u] [-smq]] | [-i id [-smq]]",         /* argument synopsis, or " " if none */
 
	"  This command provides information on the ipc facilities. Without",
	"  specified one of -s -m -q, the command will show all of three",
	"  facilities.",
	"  ",
	"       -u  shows summary information",
	"       -s  shows semaphore arrays",
	"       -m  shows shared memory segments",
	"       -M  shows shared memory segments' other information",
	"       -q  shows message queue",
	"    -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      UID   PERMS BYTES      NATTCH STATUS",
	"    ffff88046925d5d0 0x00000000 786432     0     600   393216     2      dest ",
	"    ffff880868747c10 0x00000000 819201     0     600   393216     2      dest ",
	"    ffff880859e63cd0 0x00000000 851970     0     600   393216     2      dest ",
	"    ffff880859e63790 0x00000000 884739     0     600   393216     2      dest ",
	"    ffff880859e63610 0x00000000 917508     0     600   393216     2      dest ",
	"    ffff88085902fed0 0x00000000 950277     0     600   393216     2      dest ",
	"    ffff880868041990 0x00000000 983046     0     600   393216     2      dest ",
	"    ffff880859e633d0 0x00000000 1015815    0     600   393216     2      dest ",
	"    ffff8808687479d0 0x00000000 1048584    0     600   393216     2      dest ",
	"    ffff880868041510 0x00000000 1081353    0     600   393216     2      dest ",
	"    ffff880859e63550 0x00000000 1114122    0     600   393216     2      dest ",
	"    ffff880859e63850 0x00000000 1146891    0     600   393216     2      dest ",
	"    ffff880859ecaf10 0x00000000 1179660    0     600   393216     2      dest ",
	"    ffff880868041d50 0x00000000 1212429    0     600   393216     2      dest ",
	"    ffff880408727450 0x00000000 3637262    0     600   1920000    2      dest ",
	"    ffff88085902f810 0x00000000 1409039    0     600   393216     2      dest ",
	"    ffff88085f4720d0 0x00000000 1441808    0     600   393216     2      dest ",
	"    ffff880868041450 0x00000000 1474577    0     600   393216     2      dest ",
	"    ffff880859eca850 0x00000000 3014674    0     600   393216     2      dest ",
	"    ffff880859eca9d0 0x00000000 3440659    0     600   393216     2      dest ",
	"    ffff880859ecac10 0x00000000 3473428    0     600   393216     2      dest ",
	"    ffff880864adea90 0x00000000 3506197    0     600   393216     2      dest ",
	"    ",
	"    ------ Semaphore Arrays --------",
	"    SEM_ARRAY        KEY        SEMID      UID   PERMS NSEMS     ",
	"    ffff88046a337f10 0x00000000 0          0     600   1         ",
	"    ffff880869d8ed90 0x00000000 32769      0     600   1         ",
	"    ",
	"    ------ Message Queues --------",
	"    MSG_QUEUE        KEY        MSQID      UID   PERMS USED-BYTES   MESSAGES    ",
	"    ffff88085902f5d0 0x00000000 0          0     666   0            0           ",
	"    ffff88085902f150 0x00000001 32769      0     666   0            0           ",
	"    ffff88085902f750 0x00000002 65538      0     666   0            0           ",
	"    ffff88085902fd50 0x00000003 98307      0     666   0            0           ",
	"    ffff88085902f690 0x00000004 131076     0     666   0            0           ",
	"    ffff88086811b990 0x00000005 163845     0     666   0            0           ",
	"    ffff880864ab4310 0x00000006 196614     0     666   0            0           ",
	"    ffff880864ab4190 0x00000007 229383     0     666   0            0           ",
	"    ffff880864ab4250 0x00000008 262152     0     666   0            0           ",
	"    ffff880864ab40d0 0x00000009 294921     0     666   0            0           ",
	"    ",
	"  display summary:\n",
	"    %s> ipcs -u",
	"    ------ Shared Memroy Status --------",
	"    segments allocated 22",
	"    pages allocatd 2485",
	"    pages resident 4872",
	"    pages swapped  0",
	"    swap performance attemts   0",
	"    swap performance successes 0",
	"    ",
	"    ------ Semaphore Status --------",
	"    used arrays = 2",
	"    allocated semaphores = 2",
	"    ",
	"    ------ Messages Status --------",
	"    allocated queues = 10",
	"    used headers = 0",
	"    used space = 0 bytes",
	"    ",
	"  display a specified resource:\n",
	"    %s> ipcs -u -i 458766",
	"    SHMID: 1048584",
	"    ------ Shared Memroy Status --------",
	"    segments allocated 22",
	"    pages allocatd 96",
	"    pages resident 72",
	"    pages swapped  0",
	"    swap performance attemts   0",
	"    swap performance successes 0",
	"    vfs_inode 0xffff880868092a98",
	NULL
};

static void
dump_shared_memory(int specified, int specified_id)
{
	ulong cur_task = CURRENT_TASK();
	ulong nsproxy_p, ipc_ns_p;
	ulong ipc_ids_p;
	void (*ipc_search)(ulong, int, int, int (*)(ulong, int, int));
	int (*dump_shm)(ulong, int, 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];

	if (!specified) {
		fprintf(fp, "------ Shared Memory Segments ------\n");
		fprintf(fp, "%s %s %s %s %s %s %s %s\n",
			mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN,
				LJUST, "SHM_KERNEL"),
			mkstring(buf1, 10, LJUST, "KEY"),
			mkstring(buf2, 10, LJUST, "SHMID"),
			mkstring(buf3, 5, LJUST, "UID"),
			mkstring(buf4, 5, LJUST, "PERMS"),
			mkstring(buf5, 10, LJUST, "BYTES"),
			mkstring(buf6, 6, LJUST, "NATTCH"),
			mkstring(buf7, 6, LJUST, "STATUS"));
		dump_shm = dump_single_shm;
	} else
		dump_shm = dump_specified_shm;

	if (IPCS_VALID_MEMBER(kern_ipc_perm_id)) {
		ipc_search = ipc_search_idr;
	} else {
		ipc_search = ipc_search_array;
	}

	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);
		if (!readmem(nsproxy_p + IPCS_OFFSET(nsproxy_ipc_ns), KVADDR,
			&ipc_ns_p, sizeof(ulong), "nsproxy.ipc_ns",
			RETURN_ON_ERROR|QUIET))
			error(FATAL,
				"cannot determine ipc_namespace location!\n");
		int shm_tot;
		readmem(ipc_ns_p + IPCS_OFFSET(ipc_namespace_shm_tot), KVADDR,
			&shm_tot, sizeof(int), "ipc_namespace.shm_tot",
			FAULT_ON_ERROR);
		total_shm_info.shm_tot = shm_tot;

		if (MEMBER_SIZE("ipc_namespace","ids") == sizeof(ulong) * 3)
			readmem(ipc_ns_p + IPCS_OFFSET(ipc_namespace_ids) +
				sizeof(ulong) * 2, KVADDR, &ipc_ids_p,
				sizeof(ulong), "ipc_namespace.ids[2]",
				FAULT_ON_ERROR);
		else
			ipc_ids_p = ipc_ns_p + IPCS_OFFSET(ipc_namespace_ids) +
				2 * IPCS_SIZE(ipc_ids);
	}

	int in_use;
	readmem(ipc_ids_p + IPCS_OFFSET(ipc_ids_in_use), KVADDR, &in_use,
		sizeof(int), "ipc_ids.in_use", FAULT_ON_ERROR);
	total_shm_info.used_ids = in_use;

	ipc_search(ipc_ids_p, specified, specified_id, dump_shm);

	fprintf(fp, "\n");
}

static void
dump_semaphore_arrays(int specified, int specified_id)
{
	ulong cur_task = CURRENT_TASK();
	ulong nsproxy_p, ipc_ns_p;
	ulong ipc_ids_p;
	void (*ipc_search)(ulong, int, int, int (*)(ulong, int, int));
	int (*dump_sem)(ulong, int, int);
	char buf0[BUFSIZE];
	char buf1[BUFSIZE];
	char buf2[BUFSIZE];
	char buf3[BUFSIZE];
	char buf4[BUFSIZE];
	char buf5[BUFSIZE];

	if(!specified) {
		fprintf(fp, "------ Semaphore Arrays --------\n");
		fprintf(fp, "%s %s %s %s %s %s\n",
			mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN,
					LJUST, "SEM_ARRAY"),
			mkstring(buf1, 10, LJUST, "KEY"),
			mkstring(buf2, 10, LJUST, "SEMID"),
			mkstring(buf3, 5, LJUST, "UID"),
			mkstring(buf4, 5, LJUST, "PERMS"),
			mkstring(buf5, 10, LJUST, "NSEMS"));
		dump_sem = dump_single_sem;;
	} else
		dump_sem = dump_specified_sem;
	
	if (IPCS_VALID_MEMBER(kern_ipc_perm_id)) {
		ipc_search = ipc_search_idr;
	} else {
		ipc_search = ipc_search_array;
	}

	if (symbol_exists("sem_ids")) {
		ipc_ids_p = symbol_value("sem_ids");
		int semaem;
		readmem(symbol_value("used_sems"), KVADDR, &semaem,
			sizeof(int), "used_sems", FAULT_ON_ERROR);
		total_sem_info.semaem = semaem;
	} else {
		readmem(cur_task + OFFSET(task_struct_nsproxy), KVADDR,
			&nsproxy_p, sizeof(ulong), "task_struct.nsproxy",
			FAULT_ON_ERROR);
		
		readmem(nsproxy_p + IPCS_OFFSET(nsproxy_ipc_ns), KVADDR,
			&ipc_ns_p, sizeof(ulong), "nsproxy.ipc_ns",
			FAULT_ON_ERROR);

		int semaem;
		readmem(ipc_ns_p + IPCS_OFFSET(ipc_namespace_used_sems),
			KVADDR,	&semaem, sizeof(int),
			"ipc_namespace.used_sems", FAULT_ON_ERROR);
		total_sem_info.semaem = semaem;

		if (MEMBER_SIZE("ipc_namespace","ids") == sizeof(ulong) * 3)
			readmem(ipc_ns_p + IPCS_OFFSET(ipc_namespace_ids),
				KVADDR,	&ipc_ids_p, sizeof(ulong),
				"ipc_namespace.ids[2]",	FAULT_ON_ERROR);
		else
			ipc_ids_p = ipc_ns_p + IPCS_OFFSET(ipc_namespace_ids);
	}

	int semusz;
	readmem(ipc_ids_p + IPCS_OFFSET(ipc_ids_in_use), KVADDR, &semusz,
			sizeof(int), "ipc_ids.in_use", FAULT_ON_ERROR);
	total_sem_info.semusz = semusz;

	ipc_search(ipc_ids_p, specified, specified_id, dump_sem);

	fprintf(fp, "\n");
}

static void
dump_message_queues(int specified, int specified_id)
{
	ulong cur_task = CURRENT_TASK();
	ulong nsproxy_p, ipc_ns_p;
	ulong ipc_ids_p;
	void (*ipc_search)(ulong, int, int, int (*)(ulong, int, int));
	int (*dump_msg)(ulong, int, int);
	char buf0[BUFSIZE];
	char buf1[BUFSIZE];
	char buf2[BUFSIZE];
	char buf3[BUFSIZE];
	char buf4[BUFSIZE];
	char buf5[BUFSIZE];
	char buf6[BUFSIZE];

	if(!specified) {
		fprintf(fp, "------ Message Queues --------\n");
		fprintf(fp, "%s %s %s %s %s %s %s\n",
			mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN,
					LJUST, "MSG_QUEUE"),
			mkstring(buf1, 10, LJUST, "KEY"),
			mkstring(buf2, 10, LJUST, "MSQID"),
			mkstring(buf3, 5, LJUST, "UID"),
			mkstring(buf4, 5, LJUST, "PERMS"),
			mkstring(buf5, 12, LJUST, "USED-BYTES"),
			mkstring(buf6, 12, LJUST, "MESSAGES"));
		dump_msg = dump_single_msg;
	} else
		dump_msg = dump_specified_msg;
	
	if (IPCS_VALID_MEMBER(kern_ipc_perm_id)) {
		ipc_search = ipc_search_idr;
	} else {
		ipc_search = ipc_search_array;
	}

	if (symbol_exists("msg_ids")) {
		ipc_ids_p = symbol_value("msg_ids");
	} else {
		readmem(cur_task + OFFSET(task_struct_nsproxy), KVADDR,
			&nsproxy_p, sizeof(ulong), "task_struct.nsproxy",
			FAULT_ON_ERROR);
		readmem(nsproxy_p + IPCS_OFFSET(nsproxy_ipc_ns), KVADDR,
			&ipc_ns_p, sizeof(ulong), "nsproxy.ipc_ns",
			FAULT_ON_ERROR);

		if (MEMBER_SIZE("ipc_namespace","ids") == sizeof(ulong) * 3)
			readmem(ipc_ns_p + IPCS_OFFSET(ipc_namespace_ids) +
				sizeof(ulong), KVADDR, &ipc_ids_p,
				sizeof(ulong), "ipc_namespace.ids[2]",
				FAULT_ON_ERROR);
		else
			ipc_ids_p = ipc_ns_p + IPCS_OFFSET(ipc_namespace_ids) +
				IPCS_SIZE(ipc_ids);
	}

	int msgmap;
	int msgtql;

	if (IPCS_VALID_MEMBER(ipc_namespace_msg_hdrs)) {
		readmem(ipc_ns_p + IPCS_OFFSET(ipc_namespace_msg_hdrs), KVADDR,
			&msgmap, sizeof(int), "ipc_namespace.msg_hdrs",
			FAULT_ON_ERROR);
		readmem(ipc_ns_p + IPCS_OFFSET(ipc_namespace_msg_bytes),
			KVADDR,	&msgtql, sizeof(int),
			"ipc_namespace.msg_bytes", FAULT_ON_ERROR);
	} else {
		readmem(symbol_value("msg_hdrs"), KVADDR, &msgmap, sizeof(int),
			"msg_hdrs", FAULT_ON_ERROR);
		readmem(symbol_value("msg_bytes"), KVADDR, &msgtql,
			sizeof(int), "msg_bytes", FAULT_ON_ERROR);
	}

	total_msg_info.msgmap = msgmap;
	total_msg_info.msgtql = msgtql;

	int msgpool;
	readmem(ipc_ids_p + IPCS_OFFSET(ipc_ids_in_use), KVADDR, &msgpool,
		sizeof(int), "ipc_ids.in_use", FAULT_ON_ERROR);
	total_msg_info.msgpool = msgpool;

	ipc_search(ipc_ids_p, specified, specified_id, dump_msg);

	fprintf(fp, "\n");
}

/*
 * if shared memory information is stored in an array, use this function.
 */
static void
ipc_search_array(ulong ipc_ids_p, int specified, int specified_id, int (*fn)(ulong, int, int))
{
	ulong entries_p;
	int max_id, i;
	ulong *array;
	int found = 0;

	readmem(ipc_ids_p + IPCS_OFFSET(ipc_ids_entries), KVADDR, &entries_p,
		sizeof(ulong), "ipc_ids.entries", FAULT_ON_ERROR);
	readmem(ipc_ids_p + IPCS_OFFSET(ipc_ids_max_id), KVADDR, &max_id,
		sizeof(int), "ipc_ids.max_id", FAULT_ON_ERROR);

	if (!specified && max_id < 0) {
		fprintf(fp, "(none allocated)");
		return;
	}

	array = (ulong *)GETBUF(sizeof(ulong *) * (max_id + 1));
	if (IPCS_VALID_MEMBER(ipc_id_ary_p))
		readmem(entries_p + IPCS_OFFSET(ipc_id_ary_p), KVADDR, array,
			sizeof(ulong *) * (max_id + 1), "ipc_id_ary.p",
			FAULT_ON_ERROR);
	else
		readmem(entries_p, KVADDR, array, sizeof(ulong *)*(max_id+1),
				"ipc_id array", FAULT_ON_ERROR);

	for (i=0; i<=max_id; i++) {
		if (array[i] == 0)
			continue;
		if (fn(array[i], specified_id, i)) {
			found = 1;
			break;
		}
	}

	if (specified && !found)
		fprintf(fp, "(none found)\n");

	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 specified, int specified_id, int (*fn)(ulong, int, int))
{
	int in_use;
	ulong ipcs_idr_p;
	ulong ipc;
	int next_id, total;
	int found = 0;

	readmem(ipc_ids_p + IPCS_OFFSET(ipc_ids_in_use), KVADDR, &in_use, 
		sizeof(int), "ipc_ids.in_use", FAULT_ON_ERROR);

	ipcs_idr_p = ipc_ids_p + IPCS_OFFSET(ipc_ids_ipcs_idr);

	if (!specified && !in_use)
		fprintf(fp, "(none allocated)\n");

	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, specified_id, next_id)) {
			found = 1;
			break;
		}
	}
	
	if (specified && !found)
		fprintf(fp, "(none found)\n");
}

/*
 * search every idr_layer
 */
static ulong
idr_find(ulong idp, int id)
{
	ulong idr_layer_p;
	int layer;
	int idr_layers;
	int n;
	int index;

	readmem(idp + IPCS_OFFSET(idr_top), KVADDR, &idr_layer_p,
		sizeof(ulong), "idr.top", FAULT_ON_ERROR);

	if (!idr_layer_p)
		return 0;

	if (IPCS_VALID_MEMBER(idr_layer_layer)) {
		readmem(idr_layer_p + IPCS_OFFSET(idr_layer_layer), KVADDR,
			&layer,	sizeof(int), "idr_layer.layer",
			FAULT_ON_ERROR);
		n = (layer + 1) * ipcs_table.idr_bits;
	} else {
		readmem(idp + IPCS_OFFSET(idr_layers), KVADDR, &idr_layers,
			sizeof(int), "idr.layers", FAULT_ON_ERROR);
		n = idr_layers * ipcs_table.idr_bits;
	}
	id &= MAX_ID_MASK;

	if (id >= (1 << n))
		return 0;

	while (n > 0 && idr_layer_p) {
		n -= ipcs_table.idr_bits;
		index = (id >> n) & ((1 << ipcs_table.idr_bits) - 1);
		readmem(idr_layer_p + IPCS_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 specified_id, int id)
{
	struct shm_info shm_info;
	char buf0[BUFSIZE];

	get_shm_info(&shm_info, shp, id);
	
	if (shm_info.deleted)
		return 0;

	fprintf(fp, "%s 0x%08x %-10d %-5d %-5o %-10ld %-6ld %-s %-s\n",
		mkstring(buf0, VADDR_PRLEN <= 10 ? 10 : VADDR_PRLEN,
			LJUST|LONG_HEX,	(char *)shm_info.shm_kernel),
		shm_info.key,
		shm_info.shmid,
		shm_info.uid,
		shm_info.perms & 0777,
		shm_info.bytes,
		shm_info.nattch,
		shm_info.perms & SHM_DEST ? "dest" : "",
		shm_info.perms & SHM_LOCKED ? "locked" : "");

	return 0;
}

/*
 * if the resource is specified, use this function to output information
 */
static int
dump_specified_shm(ulong shp, int specified_id, int id)
{
	struct shm_info shm_info;

	get_shm_info(&shm_info, shp, id);

	if(shm_info.shmid == specified_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 + PAGESIZE() - 1) >> PAGESHIFT());
		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\n",
			total_shm_info.swap_successes);
		fprintf(fp, "vfs_inode 0x%lx", shm_info.shm_inode);
		return 1;
	}

	return 0;
}

static int
dump_single_sem(ulong shp, int specified_id, int id)
{
	struct sem_info sem_info;
	char buf0[BUFSIZE];

	get_sem_info(&sem_info, shp, id);

	if (sem_info.deleted)
		return 0;

	fprintf(fp, "%s 0x%08x %-10d %-5d %-5o %-10ld\n",
		mkstring(buf0, VADDR_PRLEN <= 10 ? 10 : VADDR_PRLEN,
			LJUST|LONG_HEX,	(char *)sem_info.sem_array),
		sem_info.key,
		sem_info.semid,
		sem_info.uid,
		sem_info.perms & 0777,
		sem_info.nsems);

	return 0;
}

static int
dump_specified_sem(ulong shp, int specified_id, int id)
{
	struct sem_info sem_info;

	get_sem_info(&sem_info, shp, id);

	if (sem_info.semid == specified_id) {
		fprintf(fp, "SEMID: %d\n", sem_info.semid);
		fprintf(fp ,"------ Semaphore Status --------\n");
		fprintf(fp, "used arrays          %d\n",
			total_sem_info.semusz);
		fprintf(fp, "allocated semaphores %ld\n", sem_info.nsems);
		return 1;
	}

	return 0;
}

static int
dump_single_msg(ulong shp, int specified_id, int id)
{
	struct msg_info msg_info;
	char buf0[BUFSIZE];

	get_msg_info(&msg_info, shp, id);

	if (msg_info.deleted)
		return 0;

	fprintf(fp, "%s 0x%08x %-10d %-5d %-5o %-12ld %-12ld\n",
		mkstring(buf0, VADDR_PRLEN <= 10 ? 10 : VADDR_PRLEN,
			LJUST|LONG_HEX,	(char *)msg_info.msg_queue),
		msg_info.key,
		msg_info.msgid,
		msg_info.uid,
		msg_info.perms & 0777,
		msg_info.bytes,
		msg_info.messages);

	return 0;
}

static int
dump_specified_msg(ulong shp, int specified_id, int id)
{
	struct msg_info msg_info;

	get_msg_info(&msg_info, shp, id);

	if (msg_info.msgid == specified_id) {
		fprintf(fp, "MSGID: %d\n", msg_info.msgid);
		fprintf(fp ,"------ Message Status --------\n");
		fprintf(fp, "allocated queues %d\n", total_msg_info.msgpool);
		fprintf(fp, "used headers     %ld\n", msg_info.messages);
		fprintf(fp, "used space       %ld\n", msg_info.bytes);
		return 1;
	}

	return 0;
}

static void
get_shm_info(struct shm_info *shm_info, ulong shp, int id)
{
	char buf[BUFSIZE];
	ulong filep, dentryp, inodep;

	shm_info->shm_kernel = shp - IPCS_OFFSET(shmid_kernel_shm_perm);

	//cache shmid_kernel
	readmem(shm_info->shm_kernel, KVADDR, buf, IPCS_SIZE(shmid_kernel),
		"shmid_kernel", FAULT_ON_ERROR);

	shm_info->key = INT(buf + IPCS_OFFSET(shmid_kernel_shm_perm) +
			IPCS_OFFSET(kern_ipc_perm_key));
	if (IPCS_VALID_MEMBER(shmid_kernel_id))
		shm_info->shmid = INT(buf + IPCS_OFFSET(shmid_kernel_id));
	else
		shm_info->shmid = INT(buf +
				IPCS_OFFSET(shmid_kernel_shm_perm) +
				IPCS_OFFSET(kern_ipc_perm_id));

	shm_info->uid = UINT(buf + IPCS_OFFSET(shmid_kernel_shm_perm) +
			IPCS_OFFSET(kern_ipc_perm_uid));

	if (BITS32())
		shm_info->perms = USHORT(buf +
				IPCS_OFFSET(shmid_kernel_shm_perm) +
				IPCS_OFFSET(kern_ipc_perm_mode));
	else
		shm_info->perms = UINT(buf +
				IPCS_OFFSET(shmid_kernel_shm_perm) +
				IPCS_OFFSET(kern_ipc_perm_mode));

	shm_info->bytes = ULONG(buf + IPCS_OFFSET(shmid_kernel_shm_segsz));

	shm_info->nattch = ULONG(buf + IPCS_OFFSET(shmid_kernel_shm_nattch));

	filep = ULONG(buf + IPCS_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 + IPCS_OFFSET(shmid_kernel_shm_perm) +
				IPCS_OFFSET(kern_ipc_perm_deleted));
}

static void
get_sem_info(struct sem_info *sem_info, ulong shp, int id)
{
	char buf[BUFSIZE];
	
	sem_info->sem_array = shp - IPCS_OFFSET(sem_array_sem_perm);

	//cache sem_array
	readmem(sem_info->sem_array, KVADDR, buf, IPCS_SIZE(sem_array),
		"sem_array", FAULT_ON_ERROR);

	sem_info->key = INT(buf + IPCS_OFFSET(sem_array_sem_perm) +
			IPCS_OFFSET(kern_ipc_perm_key));

	if (IPCS_VALID_MEMBER(sem_array_sem_id))
		sem_info->semid = INT(buf + IPCS_OFFSET(sem_array_sem_id));
	else if (IPCS_VALID_MEMBER(kern_ipc_perm_id))
		sem_info->semid = INT(buf + IPCS_OFFSET(sem_array_sem_perm) +
				IPCS_OFFSET(kern_ipc_perm_id));
	else {
		ulong seq;
		seq = ULONG(buf + IPCS_OFFSET(sem_array_sem_perm) +
				IPCS_OFFSET(kern_ipc_perm_seq));
		sem_info->semid = ipcs_table.seq_multiplier * seq + id;
	}

	sem_info->uid = UINT(buf + IPCS_OFFSET(sem_array_sem_perm) +
			IPCS_OFFSET(kern_ipc_perm_uid));

	if (BITS32())
		sem_info->perms = USHORT(buf +
				IPCS_OFFSET(sem_array_sem_perm) +
				IPCS_OFFSET(kern_ipc_perm_mode));
	else
		sem_info->perms = UINT(buf + IPCS_OFFSET(sem_array_sem_perm) +
				IPCS_OFFSET(kern_ipc_perm_mode));

	sem_info->nsems = ULONG(buf + IPCS_OFFSET(sem_array_sem_nsems));

	sem_info->deleted = UINT(buf + IPCS_OFFSET(sem_array_sem_perm) +
				IPCS_OFFSET(kern_ipc_perm_deleted));
}

static void
get_msg_info(struct msg_info *msg_info, ulong shp, int id)
{
	char buf[BUFSIZE];

	msg_info->msg_queue = shp - IPCS_OFFSET(msg_queue_q_perm);

	//cache msg_queue;
	readmem(msg_info->msg_queue, KVADDR, buf, IPCS_SIZE(msg_queue),
		"msg_queue", FAULT_ON_ERROR);

	msg_info->key = INT(buf + IPCS_OFFSET(msg_queue_q_perm) +
			IPCS_OFFSET(kern_ipc_perm_key));

	if (IPCS_VALID_MEMBER(msg_queue_q_id))
		msg_info->msgid = INT(buf + IPCS_OFFSET(msg_queue_q_id));
	else if (IPCS_VALID_MEMBER(kern_ipc_perm_id))
		msg_info->msgid = INT(buf + IPCS_OFFSET(msg_queue_q_perm) +
				IPCS_OFFSET(kern_ipc_perm_id));
	else {
		ulong seq;
		seq = ULONG(buf + IPCS_OFFSET(msg_queue_q_perm) +
				IPCS_OFFSET(kern_ipc_perm_seq));
		msg_info->msgid = ipcs_table.seq_multiplier * seq + id;
	}

	msg_info->uid = UINT(buf + IPCS_OFFSET(msg_queue_q_perm) +
			IPCS_OFFSET(kern_ipc_perm_uid));

	if (BITS32())
		msg_info->perms = USHORT(buf + IPCS_OFFSET(msg_queue_q_perm) +
				IPCS_OFFSET(kern_ipc_perm_mode));
	else
		msg_info->perms = UINT(buf + IPCS_OFFSET(msg_queue_q_perm) +
				IPCS_OFFSET(kern_ipc_perm_mode));

	msg_info->bytes = ULONG(buf + IPCS_OFFSET(msg_queue_q_cbytes));

	msg_info->messages = ULONG(buf + IPCS_OFFSET(msg_queue_q_qnum));
	
	msg_info->deleted = UINT(buf + IPCS_OFFSET(msg_queue_q_perm) +
				IPCS_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 (IPCS_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 + IPCS_OFFSET(super_block_s_fs_info),
				KVADDR,	&hsb_p, sizeof(ulong),
				"super_block.s_fs_info", FAULT_ON_ERROR);
			readmem(hsb_p + IPCS_OFFSET(hugetlbfs_sb_info_hstate),
				KVADDR,	&hstate_p, sizeof(ulong),
				"hugetlbfs_sb_info.hstate", FAULT_ON_ERROR);
			readmem(hstate_p + IPCS_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) / PAGESIZE();
		}
		*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 - IPCS_OFFSET(shmem_inode_info_vfs_inode) +
			IPCS_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 + IPCS_OFFSET(file_f_op), KVADDR, &f_op, sizeof(ulong),
		"file.f_op", FAULT_ON_ERROR);
	if (f_op == ipcs_table.hugetlbfs_f_op_addr)
		return 1;

	if (ipcs_table.use_shm_f_op) {
		if (ipcs_table.shm_f_op_huge_addr != -1) {
			if (f_op == ipcs_table.shm_f_op_huge_addr)
				return 1;
		} else {
			if (f_op == ipcs_table.shm_f_op_addr) {
				readmem(file_p +
					IPCS_OFFSET(file_private_data),
					KVADDR,	&sfd_p, sizeof(ulong),
					"file.private_data", FAULT_ON_ERROR);
				readmem(sfd_p +
					IPCS_OFFSET(shm_file_data_file),
					KVADDR,	&file_p, sizeof(ulong),
					"shm_file_data.file", FAULT_ON_ERROR);
				goto again;
			}
		}
	}

	return 0;
}

static void
display_shm_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\n",
			total_shm_info.swap_successes);
	fprintf(fp ,"\n");
}

static void
display_sem_summary()
{
	fprintf(fp, "------ Semaphore Status --------\n");
	fprintf(fp, "used arrays = %d\n", total_sem_info.semusz);
	fprintf(fp, "allocated semaphores = %d\n", total_sem_info.semaem);
	fprintf(fp, "\n");
}

static void
display_msg_summary()
{
	fprintf(fp, "------ Messages Status --------\n");
	fprintf(fp, "allocated queues = %d\n", total_msg_info.msgpool);
	fprintf(fp, "used headers = %d\n", total_msg_info.msgmap);
	fprintf(fp, "used space = %d bytes", total_msg_info.msgtql);
	fprintf(fp, "\n");
}
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux