Hello Dave, I am still locating problems of the SLES9. Until now, nothing was found, and I will continue checking the difference. Once I fix them, I will send the patch. The attachment only fixes the problem of output. -- -- 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 SPECIFIED_NOTHING 0x0 #define SPECIFIED_ID 0x1 #define SPECIFIED_ADDR 0x2 #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 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 shmid_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 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 int dump_shared_memory(int, ulong, int); static int dump_semaphore_arrays(int, ulong, int); static int dump_message_queues(int, ulong, int); static int ipc_search_idr(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int); static int ipc_search_array(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int); static ulong idr_find(ulong, int); static int dump_shm_info(ulong, int, ulong, int, int); static int dump_sem_info(ulong, int, ulong, int, int); static int dump_msg_info(ulong, int, 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 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 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(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; char *specified_value[MAXARGS]; int value_index; int c; int shm, sem, msg, verbose; int i; ulong value; int found; char buf[BUFSIZE]; value_index = 0; show_summary = 0; specified = SPECIFIED_NOTHING; shm = 0; sem = 0; msg = 0; verbose = 0; while ((c = getopt(argcnt, args, "smMq")) != EOF) { switch(c) { case 's': sem = 1; break; case 'm': shm = 1; break; case 'M': shm = 1; verbose = 1; break; case 'q': msg = 1; break; default: cmd_usage(pc->curcmd, SYNOPSIS);; return; } } while (args[optind]) { if (value_index >= MAXARGS) error(FATAL, "too many id/member specified\n"); specified |= SPECIFIED_ID | SPECIFIED_ADDR; specified_value[value_index] = args[optind]; stol(args[optind], FAULT_ON_ERROR, NULL); optind++; value_index++; } if (THIS_KERNEL_VERSION < LINUX(2,6,0)) command_not_supported(); ipcs_init(); if (!shm && !sem && !msg) shm = sem = msg = 1; if (!value_index) { if (shm) dump_shared_memory(specified, 0, verbose); if (sem) dump_semaphore_arrays(specified, 0, 0); if (msg) dump_message_queues(specified, 0, 0); } else { open_tmpfile(); i = 0; while (i < value_index) { found = 0; value = stol(specified_value[i], FAULT_ON_ERROR, NULL); if (shm) found += dump_shared_memory(specified, value, verbose); if (sem) found += dump_semaphore_arrays(specified, value, 0); if (msg) found += dump_message_queues(specified, value, 0); if (!found) fprintf(pc->saved_fp, "invalid id or address: %s\n\n", specified_value[i]); i++; } fflush(fp); rewind(fp); while (fgets(buf, BUFSIZE, fp)) fprintf(pc->saved_fp, "%s", buf); close_tmpfile(); } } char *help_ipcs[] = { "ipcs", /* command name */ "provide information on ipc facilities", /* short description */ "[-smMq] [id | addr]", /* argument synopsis, or " " if none */ " This command provides information on the ipc facilities. Without", " specified one of -s -m -q -M, the command will show all of three", " facilities.", " ", " -s shows semaphore arrays", " -m shows shared memory segments", " -M shows shared memory segments with some detailed", " information", " -q shows message queue", " id it allows a specific resource id to be specified, and the", " information on this id will be printed", " addr it allows a specific resource's address to be specified,", " the address is listed by ipcs command in the first column", "\nEXAMPLE", " display all ipc facilities:\n", " %s> ipcs", " SHMID_KERNEL KEY SHMID UID PERMS BYTES NATTCH STATUS", " ffff880473a28310 00000000 0 0 666 90000 1 ", " ffff880473a28490 00000001 32769 0 666 90000 1 ", " ffff880473a28250 00000002 65538 0 666 90000 1 ", " ", " SEM_ARRAY KEY SEMID UID PERMS NSEMS ", " ffff88047200f9d0 00000000 0 0 600 1 ", " ffff88046f826910 00000000 32769 0 600 1 ", " ", " MSG_QUEUE KEY MSQID UID PERMS USED-BYTES MESSAGES ", " (none allocated)", " ", " display shared memory with detailed information:\n", " %s> ipcs -M", " SHMID_KERNEL KEY SHMID UID PERMS BYTES NATTCH STATUS", " ffff880473a28310 00000000 0 0 666 90000 1 ", " PAGES ALLOCATED: 22 RESIDENT: 1 SWAPPED: 0", " SWAP PERFORMANCE ATTEMPTS: 0 SUCCESSES: 0", " VFS_INODE: ffff88047239cd98", " ", " SHMID_KERNEL KEY SHMID UID PERMS BYTES NATTCH STATUS", " ffff880473a28490 00000001 32769 0 666 90000 1 ", " PAGES ALLOCATED: 22 RESIDENT: 1 SWAPPED: 0", " SWAP PERFORMANCE ATTEMPTS: 0 SUCCESSES: 0", " VFS_INODE: ffff88047239c118", " ", " SHMID_KERNEL KEY SHMID UID PERMS BYTES NATTCH STATUS", " ffff880473a28250 00000002 65538 0 666 90000 1 ", " PAGES ALLOCATED: 22 RESIDENT: 1 SWAPPED: 0", " SWAP PERFORMANCE ATTEMPTS: 0 SUCCESSES: 0", " VFS_INODE: ffff880470503758", " ", " display specified resources in detail with an address\n", " %s> ipcs -M ffff880473a28250", " SHMID_KERNEL KEY SHMID UID PERMS BYTES NATTCH STATUS", " ffff880473a28250 00000002 65538 0 666 90000 1 ", " PAGES ALLOCATED: 96 RESIDENT: 22 SWAPPED: 0", " SWAP PERFORMANCE ATTEMPTS: 0 SUCCESSES: 0", " VFS_INODE: ffff880470503758", NULL }; static int dump_shared_memory(int specified, ulong specified_value, int verbose) { ulong cur_task = CURRENT_TASK(); ulong nsproxy_p, ipc_ns_p; ulong ipc_ids_p; int (*ipc_search)(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int); int (*dump_shm)(ulong, int, 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 (!verbose && specified == SPECIFIED_NOTHING) { fprintf(fp, "%s %s %s %s %s %s %s %s\n", mkstring(buf0, VADDR_PRLEN<=12?12:VADDR_PRLEN, LJUST, "SHMID_KERNEL"), mkstring(buf1, 8, 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_shm_info; 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"); } 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"); 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); } if (ipc_search(ipc_ids_p, specified, specified_value, dump_shm, verbose)) { return 1; } else { if (verbose && specified == SPECIFIED_NOTHING) { fprintf(fp, "%s %s %s %s %s %s %s %s\n", mkstring(buf0, VADDR_PRLEN<=12?12:VADDR_PRLEN, LJUST, "SHMID_KERNEL"), mkstring(buf1, 8, 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")); fprintf(fp, "(none allocated)\n\n"); } return 0; } } static int dump_semaphore_arrays(int specified, ulong specified_value, int verbose) { ulong cur_task = CURRENT_TASK(); ulong nsproxy_p, ipc_ns_p; ulong ipc_ids_p; int (*ipc_search)(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int); int (*dump_sem)(ulong, int, ulong, int, int); char buf0[BUFSIZE]; char buf1[BUFSIZE]; char buf2[BUFSIZE]; char buf3[BUFSIZE]; char buf4[BUFSIZE]; char buf5[BUFSIZE]; if (specified == SPECIFIED_NOTHING) { fprintf(fp, "%s %s %s %s %s %s\n", mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN, LJUST, "SEM_ARRAY"), mkstring(buf1, 8, 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_sem_info; 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"); } 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), 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); } return ipc_search(ipc_ids_p, specified, specified_value, dump_sem, verbose); } static int dump_message_queues(int specified, ulong specified_value, int verbose) { ulong cur_task = CURRENT_TASK(); ulong nsproxy_p, ipc_ns_p; ulong ipc_ids_p; int (*ipc_search)(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int); int (*dump_msg)(ulong, int, 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 == SPECIFIED_NOTHING) { fprintf(fp, "%s %s %s %s %s %s %s\n", mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN, LJUST, "MSG_QUEUE"), mkstring(buf1, 8, 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_msg_info; 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); } return ipc_search(ipc_ids_p, specified, specified_value, dump_msg, verbose); } /* * if shared memory information is stored in an array, use this function. */ static int ipc_search_array(ulong ipc_ids_p, int specified, ulong specified_value, int (*fn)(ulong, int, ulong, int, int), int verbose) { ulong entries_p; int max_id, i; ulong *array; int found = 0; int allocated = 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 (max_id < 0) { if (specified == SPECIFIED_NOTHING && !verbose) fprintf(fp, "(none allocated)\n\n"); return 0; } 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; allocated++; if (fn(array[i], specified, specified_value, i, verbose)) { found = 1; break; } } if (specified == SPECIFIED_NOTHING && !verbose) { if (!allocated) fprintf(fp, "(none allocated)\n"); fprintf(fp, "\n"); } FREEBUF(array); if (found || (specified == SPECIFIED_NOTHING && allocated)) return 1; else return 0; } /* * if shared memory information is stored by using idr, use this function to * get data. */ static int ipc_search_idr(ulong ipc_ids_p, int specified, ulong specified_value, int (*fn)(ulong, int, ulong, int, int), int verbose) { 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 (!in_use) { if (specified == SPECIFIED_NOTHING && !verbose) fprintf(fp, "(none allocated)\n\n"); return 0; } 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, specified_value, next_id, verbose)) { found = 1; break; } } if (!verbose && specified == SPECIFIED_NOTHING) fprintf(fp, "\n"); if (found || specified == SPECIFIED_NOTHING) return 1; else return 0; } /* * 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; } /* * only specified is not SPECIFIED_NOTHIND, and the specified_value is found, * then return 1 */ static int dump_shm_info(ulong shp, int specified, ulong specified_value, int id, int verbose) { struct shm_info shm_info; char buf[BUFSIZE]; char buf0[BUFSIZE]; char buf1[BUFSIZE]; char buf2[BUFSIZE]; char buf3[BUFSIZE]; char buf4[BUFSIZE]; char buf5[BUFSIZE]; char buf6[BUFSIZE]; char buf7[BUFSIZE]; get_shm_info(&shm_info, shp, id); if (shm_info.deleted) return 0; if (((specified & SPECIFIED_ID) && shm_info.shmid == specified_value) || ((specified & SPECIFIED_ADDR) && shm_info.shmid_kernel == specified_value) || specified == SPECIFIED_NOTHING) { if (verbose || specified != SPECIFIED_NOTHING) { fprintf(fp, "%s %s %s %s %s %s %s %s\n", mkstring(buf0, VADDR_PRLEN<=12?12:VADDR_PRLEN, LJUST, "SHMID_KERNEL"), mkstring(buf1, 8, 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")); } fprintf(fp, "%s %08x %-10d %-5d %-5o %-10ld %-6ld %-s %-s\n", mkstring(buf, VADDR_PRLEN <= 12 ? 12 : VADDR_PRLEN, LJUST|LONG_HEX, (char *)shm_info.shmid_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" : ""); if (verbose) { fprintf(fp, "PAGES ALLOCATED: %ld RESIDENT: %ld SWAPPED: %ld\n", (shm_info.bytes+PAGESIZE()-1) >> PAGESHIFT(), shm_info.rss, shm_info.swap); fprintf(fp, "SWAP PERFORMANCE ATTEMPTS: %ld SUCCESSES: %ld\n", 0L, 0L); fprintf(fp, "VFS_INODE: %lx\n", shm_info.shm_inode); } if (verbose || specified != SPECIFIED_NOTHING) fprintf(fp, "\n"); } if (((specified & SPECIFIED_ID) && shm_info.shmid == specified_value) || ((specified & SPECIFIED_ADDR) && shm_info.shmid_kernel == specified_value)) return 1; else return 0; } /* * only specified is not SPECIFIED_NOTHIND, and the specified_value is found, * then return 1 */ static int dump_sem_info(ulong shp, int specified, ulong specified_value, int id, int verbose) { struct sem_info sem_info; char buf[BUFSIZE]; char buf0[BUFSIZE]; char buf1[BUFSIZE]; char buf2[BUFSIZE]; char buf3[BUFSIZE]; char buf4[BUFSIZE]; char buf5[BUFSIZE]; get_sem_info(&sem_info, shp, id); if (sem_info.deleted) return 0; if (((specified & SPECIFIED_ID) && sem_info.semid == specified_value) || ((specified & SPECIFIED_ADDR) && sem_info.sem_array == specified_value) || specified == SPECIFIED_NOTHING) { if (specified != SPECIFIED_NOTHING) { fprintf(fp, "%s %s %s %s %s %s\n", mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN, LJUST, "SEM_ARRAY"), mkstring(buf1, 8, LJUST, "KEY"), mkstring(buf2, 10, LJUST, "SEMID"), mkstring(buf3, 5, LJUST, "UID"), mkstring(buf4, 5, LJUST, "PERMS"), mkstring(buf5, 10, LJUST, "NSEMS")); } fprintf(fp, "%s %08x %-10d %-5d %-5o %-10ld\n", mkstring(buf, 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); if (specified != SPECIFIED_NOTHING) fprintf(fp, "\n"); } if (((specified & SPECIFIED_ID) && sem_info.semid == specified_value) || ((specified & SPECIFIED_ADDR) && sem_info.sem_array == specified_value)) return 1; else return 0; } /* * only specified is not SPECIFIED_NOTHIND, and the specified_value is found, * then return 1 */ static int dump_msg_info(ulong shp, int specified, ulong specified_value, int id, int verbose) { struct msg_info msg_info; char buf[BUFSIZE]; char buf0[BUFSIZE]; char buf1[BUFSIZE]; char buf2[BUFSIZE]; char buf3[BUFSIZE]; char buf4[BUFSIZE]; char buf5[BUFSIZE]; char buf6[BUFSIZE]; get_msg_info(&msg_info, shp, id); if (msg_info.deleted) return 0; if (((specified & SPECIFIED_ID) && msg_info.msgid == specified_value) || ((specified & SPECIFIED_ADDR) && msg_info.msg_queue == specified_value) || specified == SPECIFIED_NOTHING) { if (specified != SPECIFIED_NOTHING) { fprintf(fp, "%s %s %s %s %s %s %s\n", mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN, LJUST, "MSG_QUEUE"), mkstring(buf1, 8, 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")); } fprintf(fp, "%s %08x %-10d %-5d %-5o %-12ld %-12ld\n", mkstring(buf, 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); if (specified != SPECIFIED_NOTHING) fprintf(fp, "\n"); } if (((specified & SPECIFIED_ID) && msg_info.msgid == specified_value) || ((specified & SPECIFIED_ADDR) && msg_info.msg_queue == specified_value)) return 1; else 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->shmid_kernel = shp - IPCS_OFFSET(shmid_kernel_shm_perm); /* * cache shmid_kernel */ readmem(shm_info->shmid_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; } else { unsigned long swapped; *rss += nr_pages; 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; } } 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; }
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility