----- Original Message -----
----- Original Message -----
> At 2012-6-7 21:39, Dave Anderson wrote:
> > I think the -h description should state that the address is a pointer to
> > a "data structure containing a list_head". The "next"
sentence probably
> > doesn't belong there, because it's pretty much repeating the list_head
> > related discussion above in help page's number "2" section. And
> > there should probably be a caveat re: the fact that there may be
> > a bogus structure address shown in the case of an external LIST_HEAD()
> > or a starting list_head that's in a different data structure entirely.
> >
> > And most importantly, a simple but clear example should be shown.
>
> Hello Dave,
>
> I made some modification to help__list. Is it suitable to describe the
> function of "-h" option?
Not bad -- in fact it's pretty good English! ;-)
However, I will amplify your documentation to add a caveat for the display
of a bogus structure address (and -s <structure> contents) if:
(1) the list passes through a standalone external LIST_HEAD, or
(2) the list passes through a starting list_head that is contained within
a different structure type.
Queued for crash-6.0.8.
Thanks,
Dave
Qiao,
I ended up re-writing a signficant chunk of the help page. Your
patch inserted -h/-H usage information up at the top in the section
where it's describing the format of singly-linked and doubly-linked
lists in general. So I moved that stuff down to the "[-h|H] start"
argument description below. I also added a new WARNING section for
"-h start", and used a different "-h start" example. Here's what
it looks like:
$ crash -h list
NAME
list - linked list
SYNOPSIS
list [[-o] offset] [-e end] [-s struct[.member[,member]] -[xd]] [-h|-H] start
DESCRIPTION
This command dumps the contents of a linked list. The entries in a linked
list are typically data structures that are tied together in one of two
formats:
1. A starting address points to a data structure; that structure contains
a member that is a pointer to the next structure, and so on. This type
of a singly-linked list typically ends when a "next" pointer value
contains one of the following:
(a) a NULL pointer.
(b) a pointer to the start address.
(c) a pointer to the first item pointed to by the start address.
(d) a pointer to its containing structure.
2. Most Linux lists of data structures are doubly-linked using "list_head"
structures that are embedded members of the data structures in the list:
struct list_head {
struct list_head *next, *prev;
};
The linked list is typically headed by an external, standalone list_head,
which is simply initialized to point to itself, signifying that the list
is empty:
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
In the case of list_head-linked lists, the "list_head.next" pointer is
the address of a list_head structure that is embedded in the next data
structure in the list, and not the address of the next data structure
itself. The starting point of the list may be:
(a) an external, standalone, LIST_HEAD().
(b) a list_head that is embedded within a data structure of the same
type as the whole linked list.
(c) a list_head that is embedded within a data structure that is
different than the type of structures in the the linked list.
The list typically ends when the embedded "list_head.next" pointer of
a data structure in the linked list points back to the LIST_HEAD()
address. However, some list_head-linked lists have no defined starting
point, but just link back onto themselves in a circular manner.
This command can handle both types of linked list; in both cases the list
of addresses that are dumped are the addresses of the data structures
themselves.
The arguments are as follows:
[-o] offset The offset within the structure to the "next" pointer
(default is 0). If non-zero, the offset may be entered
in either of two manners:
1. In "structure.member" format; the "-o" is not
necessary.
2. A number of bytes; the "-o" is only necessary on processors
where the offset value could be misconstrued as a kernel
virtual address.
-e end If the list ends in a manner unlike the typical manners that
are described above, an explicit ending address value may be
entered.
-s struct For each address in list, format and print as this type of
structure; use the "struct.member" format in order to display
a particular member of the structure. To display multiple
members of a structure, use a comma-separated list of members.
-x Override the default output format with hexadecimal format.
-d Override the default output format with decimal format.
The meaning of the "start" argument, which can be expressed symbolically,
in hexadecimal format, or an expression evaluating to an address, depends
upon whether the -h or -H option is pre-pended:
start The address of the first data structure in the list.
-H start The address of a list_head structure, typically that of an
external, standalone LIST_HEAD(). The list typically ends
when the embedded "list_head.next" of a data structure in
the linked list points back to this "start" address.
-h start The address of a data structure which contains an embedded
list_head. The list typically ends when the embedded
"list_head.next" of a data structure in the linked list
points back to the embedded list_head contained in the data
structure whose address is this "start" argument.
WARNING
When the "-h start" option is used, it is possible that the list_head-linked
list will:
1. pass through an external standalone LIST_HEAD(), or
2. pass through a list_head that is the actual starting list_head, but is
contained within a data structure that is not the same type as all of
the other data structures in the list.
When that occurs, the data structure address displayed for that list_head
will be incorrect, because the "-h start" option presumes that all
list_head structures in the list are contained within the same type of
data structure. Furthermore, if the "-s struct[.member[,member]" option
is used, it will display bogus data for that particular list_head.
EXAMPLES
Note that each task_struct is linked to its parent's task_struct via the
p_pptr member:
crash> struct task_struct.p_pptr
struct task_struct {
[136] struct task_struct *p_pptr;
}
That being the case, given a task_struct pointer of c169a000, show its
parental hierarchy back to the "init_task" (the "swapper" task):
crash> list task_struct.p_pptr c169a000
c169a000
c0440000
c50d0000
c0562000
c0d28000
c7894000
c6a98000
c009a000
c0252000
Given that the "task_struct.p_pptr" offset is 136 bytes, the same
result could be accomplished like so:
crash> list 136 c169a000
c169a000
c0440000
c50d0000
c0562000
c0d28000
c7894000
c6a98000
c009a000
c0252000
The list of currently-registered file system types are headed up by a
struct file_system_type pointer named "file_systems", and linked by
the "next" field in each file_system_type structure. The following
sequence displays the structure address followed by the name and
fs_flags members of each registered file system type:
crash> p file_systems
file_systems = $1 = (struct file_system_type *) 0xc03adc90
crash> list file_system_type.next -s file_system_type.name,fs_flags c03adc90
c03adc90
name = 0xc02c05c8 "rootfs",
fs_flags = 0x30,
c03abf94
name = 0xc02c0319 "bdev",
fs_flags = 0x10,
c03acb40
name = 0xc02c07c4 "proc",
fs_flags = 0x8,
c03e9834
name = 0xc02cfc83 "sockfs",
fs_flags = 0x10,
c03ab8e4
name = 0xc02bf512 "tmpfs",
fs_flags = 0x20,
c03ab8c8
name = 0xc02c3d6b "shm",
fs_flags = 0x20,
c03ac394
name = 0xc02c03cf "pipefs",
fs_flags = 0x10,
c03ada74
name = 0xc02c0e6b "ext2",
fs_flags = 0x1,
c03adc74
name = 0xc02c0e70 "ramfs",
fs_flags = 0x20,
c03ade74
name = 0xc02c0e76 "hugetlbfs",
fs_flags = 0x20,
c03adf8c
name = 0xc02c0f84 "iso9660",
fs_flags = 0x1,
c03aec14
name = 0xc02c0ffd "devpts",
fs_flags = 0x8,
c03e93f4
name = 0xc02cf1b9 "pcihpfs",
fs_flags = 0x28,
e0831a14
name = 0xe082f89f "ext3",
fs_flags = 0x1,
e0846af4
name = 0xe0841ac6 "usbdevfs",
fs_flags = 0x8,
e0846b10
name = 0xe0841acf "usbfs",
fs_flags = 0x8,
e0992370
name = 0xe099176c "autofs",
fs_flags = 0x0,
e2dcc030
name = 0xe2dc8849 "nfs",
fs_flags = 0x48000,
In some kernels, the system run queue is a linked list headed up by the
"runqueue_head", which is defined like so:
static LIST_HEAD(runqueue_head);
The run queue linking is done with the "run_list" member of the task_struct:
crash> struct task_struct.run_list
struct task_struct {
[60] struct list_head run_list;
}
Therefore, to view the list of task_struct addresses in the run queue,
either of the following commands will work:
crash> list task_struct.run_list -H runqueue_head
f79ac000
f7254000
f7004000
crash> list 60 -H runqueue_head
f79ac000
f7254000
f7004000
In some kernel versions, the vfsmount structures of the mounted
filesystems are linked by the LIST_HEAD "vfsmntlist", which uses the
mnt_list list_head of each vfsmount structure in the list. To dump each
vfsmount structure in the list, append the -s option:
crash> list -H vfsmntlist vfsmount.mnt_list -s vfsmount
c3fc9e60
struct vfsmount {
mnt_hash = {
next = 0xc3fc9e60,
prev = 0xc3fc9e60
},
mnt_parent = 0xc3fc9e60,
mnt_mountpoint = 0xc3fc5dc0,
mnt_root = 0xc3fc5dc0,
mnt_instances = {
next = 0xc3f60a74,
prev = 0xc3f60a74
},
mnt_sb = 0xc3f60a00,
mnt_mounts = {
next = 0xf7445e08,
prev = 0xf7445f88
},
mnt_child = {
next = 0xc3fc9e88,
prev = 0xc3fc9e88
},
mnt_count = {
counter = 209
},
mnt_flags = 0,
mnt_devname = 0xc8465b20 "/dev/root",
mnt_list = {
next = 0xf7445f9c,
prev = 0xc02eb828
},
mnt_owner = 0
}
f7445f60
struct vfsmount {
...
The task_struct of every task in the system is linked into a circular list
by its embedded "tasks" list_head. Show the task_struct addresses and the
pids of all tasks in the system using "-h" option, starting with the
task_struct at ffff88012b98e040:
crash> list task_struct.tasks -s task_struct.pid -h ffff88012b98e040
ffff88012b98e040
pid = 14187
ffff8801277be0c0
pid = 14248
ffffffff81a2d020
pid = 0
ffff88012d7dd4c0
pid = 1
ffff88012d7dca80
pid = 2
ffff88012d7dc040
pid = 3
ffff88012d7e9500
pid = 4
...
ffff88012961a100
pid = 14101
ffff880129017580
pid = 14134
ffff8801269ed540
pid = 14135
ffff880128256080
pid = 14138
ffff88012b8f4100
pid = 14183