FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Crash Utility

 
 
LinkBack Thread Tools
 
Old 01-09-2012, 02:50 PM
Dave Anderson
 
Default display MCNT and PRIVATE when using kmem -p

----- Original Message -----
> Hello Dave,
>
> I think it is necessary to see what is hided in the union where
> _mapcount lies. However, as you said, it's hard to pick which fields are
> more important than others when adding new items to "kmem -p". So I
> think over using struct sub-command to show what I want.
>
> What if I change struct sub-command to this:
>
> 1. it can refer to anonymous members (e.g., page._mapcount)
> 2. it can refer to submembers(e.g., page._count.counter)
> 3. it can output easy-parsing format (using an option to specify), maybe
> like 'kmem -p'. For example,
> crash> struct page.flags,_count.counter -.. < PAGE_list.txt
> 1024 0
> 1024 1
> 1024 1
> 1024 1
>
> After adding these features to struct sub-command, I guess it is more
> easier to get information hiding in structs and parsing it. Before
> implementing, I feel the necessity to ask you for some advices. So what
> about these features?

That would certainly be useful. The problem in getting that to work
would be twofold:

(1) handling a "member" request that has a "." in it.

crash> struct page._count.counter ffffea0000000400
struct: invalid format: page._count.counter
crash>

(2) getting a successful return value from the call to arg_to_datatype()
in cmd_datatype_common().

crash> struct page.private ffffea0000000400
struct: invalid data structure reference: page.private
crash>

And both of the above would require getting the get_member_data()
function in gdb-7.3.1/gdb/symtab.c to dig out the information for
anonymous members, which it currently does not do.

In this part of get_member_data(), the requested member name string is
searched for:

for (i = 0; i < nfields; i++) {
if (STREQ(req->member, nextfield->name)) {
req->member_offset = nextfield->loc.bitpos;
req->member_length = TYPE_LENGTH(nextfield->type);
req->member_typecode = TYPE_CODE(nextfield->type);
if ((req->member_typecode == TYPE_CODE_TYPEDEF) &&
(typedef_type = check_typedef(nextfield->type)))
req->member_length = TYPE_LENGTH(typedef_type);
return;
}
nextfield++;
}

When get_member_data() walks through the page stucture, it does find the
anonymous members above, but nextfield->name points to a NULL name string.

That seems to be related to gdb's behavior when asking it to simply
print a page structure, which is requested with a "ptype struct page"
gdb command:

crash> struct page
struct page {
long unsigned int flags;
struct address_space *mapping;
struct {
union {...};
union {...};
};
struct list_head lru;
union {
long unsigned int private;
spinlock_t ptl;
struct kmem_cache *slab;
struct page *first_page;
};
}
SIZE: 64
crash>

I don't know how to get gdb to display the "full" structure declaration?

Anyway, when given an internal request to display a page structure
from memory, it does display them:

crash> page ffffea0000000400
struct page {
flags = 0,
mapping = 0x0,
{
{
index = 18446612132314288112,
freelist = 0xffff880000010ff0
},
{
counters = 4294967168,
{
{
_mapcount = {
counter = -128
},
{
inuse = 65408,
objects = 32767,
frozen = 1
}
},
_count = {
counter = 0
}
}
}
},
lru = {
next = 0xffffea00000042a0,
prev = 0xffffea00000005a0
},
{
private = 1,
ptl = {
{
rlock = {
raw_lock = {
slock = 1
}
}
}
},
slab = 0x1,
first_page = 0x1
}
}
crash>

And because that works OK, the ANON_MEMBER_OFFSET_REQUEST() macro
exists to handle cases for required offset_table entries.

Here, if I put a debug printf each time though the member loop
in get_member_data(), you'll see this:

crash> page.slab ffffea0000000400
page -> flags
page -> mapping
page ->
page -> lru
page ->
struct: invalid data structure reference: page.slab
crash>

which again, reflects what happens when a page struct is printed:

crash> struct page
struct page {
long unsigned int flags;
struct address_space *mapping;
struct {
union {...};
union {...};
};
struct list_head lru;
union {
long unsigned int private;
spinlock_t ptl;
struct kmem_cache *slab;
struct page *first_page;
};
}
SIZE: 64
crash>

So, anyway, I would presume that perhaps something could be applied to
get_member_data() to and check out the fields with NULL name strings, i.e.:

for (i = 0; i < nfields; i++) {
if (STREQ(req->member, nextfield->name)) {
req->member_offset = nextfield->loc.bitpos;
req->member_length = TYPE_LENGTH(nextfield->type);
req->member_typecode = TYPE_CODE(nextfield->type);
if ((req->member_typecode == TYPE_CODE_TYPEDEF) &&
(typedef_type = check_typedef(nextfield->type)))
req->member_length = TYPE_LENGTH(typedef_type);
return;
}
+ if (strlen(nextfield->name) == 0) {
+ ...
+ }
nextfield++;
}

And that section would have to somehow deal with members that are part
of anonymous struct members (like "private"), as well as with anonymous
members that are expressed with a "." in them (like "_mapcount.counter).

I don't expect it will be very easy to accomplish. But it would be a
desirable capability, so please be my guest!

Thanks,
Dave


> At 2012-1-6 3:37, Dave Anderson wrote:
> > I appreciate the effort, but I'm not sure whether it's worth changing
> > it at this point, or whether it could be accomplished in a different
> > manner.
> >
> > The primary purpose for "kmem -p" is to show the page structure
> > address associated with each physical address in the system -- along
> > with "basic information about each page". It's had those basic
> > fields in it forever -- which BTW, fit into 80 columns. I prefer not
> > to have command output exceed 80 columns unless it is impossible to
> > predict the size of an output field.
> >
> > Anyway, the page structure definition keeps changing over time, more
> > specifically the embedded anonymous structures contained within it, and
> > the fields within the anonymous structs have multiple meanings. With
> > your patch, the output becomes cluttered and hard to understand, especially
> > due to the strange values that can be seen in the MCNT column when it's
> > not a counter value, but rather a slab-page construct:
> >
> > union {
> > atomic_t _mapcount;
> >
> > struct {
> > unsigned inuse:16;
> > unsigned objects:15;
> > unsigned frozen:1;
> > };
> > };
> >
> > And so it's hard to pick which fields are more important than
> > others,
> > because it pretty much depends upon what's being debugged. You
> > have
> > picked the private field (which can have numerous meanings), but
> > for
> > example, there have been times in the past where I wanted to see
> > the
> > lru list_head contents.
> >
> > That all being said, your patch does have merit, but I wonder if
> > there
> > could be an alternate way of selecting or filtering what fields are
> > displayed?
>
>
> --
> --
> Regards
> Qiao Nuohan
>
> --
> Crash-utility mailing list
> Crash-utility@redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
>

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 01-10-2012, 01:53 AM
qiaonuohan
 
Default display MCNT and PRIVATE when using kmem -p

Hello Dave,

Glab to hear the capability is desirable. I will start to implement this
soon.


At 2012-1-9 23:50, Dave Anderson wrote:



----- Original Message -----

Hello Dave,

I think it is necessary to see what is hided in the union where
_mapcount lies. However, as you said, it's hard to pick which fields are
more important than others when adding new items to "kmem -p". So I
think over using struct sub-command to show what I want.

What if I change struct sub-command to this:

1. it can refer to anonymous members (e.g., page._mapcount)
2. it can refer to submembers(e.g., page._count.counter)
3. it can output easy-parsing format (using an option to specify), maybe
like 'kmem -p'. For example,
crash> struct page.flags,_count.counter -..< PAGE_list.txt
1024 0
1024 1
1024 1
1024 1

After adding these features to struct sub-command, I guess it is more
easier to get information hiding in structs and parsing it. Before
implementing, I feel the necessity to ask you for some advices. So what
about these features?


That would certainly be useful. The problem in getting that to work
would be twofold:

(1) handling a "member" request that has a "." in it.

crash> struct page._count.counter ffffea0000000400
struct: invalid format: page._count.counter
crash>

(2) getting a successful return value from the call to arg_to_datatype()
in cmd_datatype_common().

crash> struct page.private ffffea0000000400
struct: invalid data structure reference: page.private
crash>

And both of the above would require getting the get_member_data()
function in gdb-7.3.1/gdb/symtab.c to dig out the information for
anonymous members, which it currently does not do.

In this part of get_member_data(), the requested member name string is
searched for:

for (i = 0; i< nfields; i++) {
if (STREQ(req->member, nextfield->name)) {
req->member_offset = nextfield->loc.bitpos;
req->member_length = TYPE_LENGTH(nextfield->type);
req->member_typecode = TYPE_CODE(nextfield->type);
if ((req->member_typecode == TYPE_CODE_TYPEDEF)&&
(typedef_type = check_typedef(nextfield->type)))
req->member_length = TYPE_LENGTH(typedef_type);
return;
}
nextfield++;
}

When get_member_data() walks through the page stucture, it does find the
anonymous members above, but nextfield->name points to a NULL name string.

That seems to be related to gdb's behavior when asking it to simply
print a page structure, which is requested with a "ptype struct page"
gdb command:

crash> struct page
struct page {
long unsigned int flags;
struct address_space *mapping;
struct {
union {...};
union {...};
};
struct list_head lru;
union {
long unsigned int private;
spinlock_t ptl;
struct kmem_cache *slab;
struct page *first_page;
};
}
SIZE: 64
crash>

I don't know how to get gdb to display the "full" structure declaration?

Anyway, when given an internal request to display a page structure
from memory, it does display them:

crash> page ffffea0000000400
struct page {
flags = 0,
mapping = 0x0,
{
{
index = 18446612132314288112,
freelist = 0xffff880000010ff0
},
{
counters = 4294967168,
{
{
_mapcount = {
counter = -128
},
{
inuse = 65408,
objects = 32767,
frozen = 1
}
},
_count = {
counter = 0
}
}
}
},
lru = {
next = 0xffffea00000042a0,
prev = 0xffffea00000005a0
},
{
private = 1,
ptl = {
{
rlock = {
raw_lock = {
slock = 1
}
}
}
},
slab = 0x1,
first_page = 0x1
}
}
crash>

And because that works OK, the ANON_MEMBER_OFFSET_REQUEST() macro
exists to handle cases for required offset_table entries.

Here, if I put a debug printf each time though the member loop
in get_member_data(), you'll see this:

crash> page.slab ffffea0000000400
page -> flags
page -> mapping
page ->
page -> lru
page ->
struct: invalid data structure reference: page.slab
crash>

which again, reflects what happens when a page struct is printed:

crash> struct page
struct page {
long unsigned int flags;
struct address_space *mapping;
struct {
union {...};
union {...};
};
struct list_head lru;
union {
long unsigned int private;
spinlock_t ptl;
struct kmem_cache *slab;
struct page *first_page;
};
}
SIZE: 64
crash>

So, anyway, I would presume that perhaps something could be applied to
get_member_data() to and check out the fields with NULL name strings, i.e.:

for (i = 0; i< nfields; i++) {
if (STREQ(req->member, nextfield->name)) {
req->member_offset = nextfield->loc.bitpos;
req->member_length = TYPE_LENGTH(nextfield->type);
req->member_typecode = TYPE_CODE(nextfield->type);
if ((req->member_typecode == TYPE_CODE_TYPEDEF)&&
(typedef_type = check_typedef(nextfield->type)))
req->member_length = TYPE_LENGTH(typedef_type);
return;
}
+ if (strlen(nextfield->name) == 0) {
+ ...
+ }
nextfield++;
}

And that section would have to somehow deal with members that are part
of anonymous struct members (like "private"), as well as with anonymous
members that are expressed with a "." in them (like "_mapcount.counter).

I don't expect it will be very easy to accomplish. But it would be a
desirable capability, so please be my guest!

Thanks,
Dave



At 2012-1-6 3:37, Dave Anderson wrote:

I appreciate the effort, but I'm not sure whether it's worth changing
it at this point, or whether it could be accomplished in a different
manner.

The primary purpose for "kmem -p" is to show the page structure
address associated with each physical address in the system -- along
with "basic information about each page". It's had those basic
fields in it forever -- which BTW, fit into 80 columns. I prefer not
to have command output exceed 80 columns unless it is impossible to
predict the size of an output field.

Anyway, the page structure definition keeps changing over time, more
specifically the embedded anonymous structures contained within it, and
the fields within the anonymous structs have multiple meanings. With
your patch, the output becomes cluttered and hard to understand, especially
due to the strange values that can be seen in the MCNT column when it's
not a counter value, but rather a slab-page construct:

union {
atomic_t _mapcount;

struct {
unsigned inuse:16;
unsigned objects:15;
unsigned frozen:1;
};
};

And so it's hard to pick which fields are more important than
others,
because it pretty much depends upon what's being debugged. You
have
picked the private field (which can have numerous meanings), but
for
example, there have been times in the past where I wanted to see
the
lru list_head contents.

That all being said, your patch does have merit, but I wonder if
there
could be an alternate way of selecting or filtering what fields are
displayed?



--
--
Regards
Qiao Nuohan

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility



--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility





--
--
Regards
Qiao Nuohan

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-29-2012, 01:34 PM
Dave Anderson
 
Default display MCNT and PRIVATE when using kmem -p

----- Original Message -----
> At 2012-2-28 23:37, Dave Anderson wrote:
> >
> >
> > ----- Original Message -----
> >> At 2012-1-10 21:54, Dave Anderson wrote:
> >>>
> >>>
> >>> ----- Original Message -----
> >>>> Hello Dave,
> >>>>
> >>>> Glad to hear the capability is desirable. I will start to
> >>>> implement this
> >>>> soon.
> >>>>
> >>>
> >>>>>> What if I change struct sub-command to this:
> >>>>>>
> >>>>>> 1. it can refer to anonymous members (e.g., page._mapcount)
> >>>>>> 2. it can refer to submembers(e.g., page._count.counter)
> >>>
> >>> One other suggestion -- I believe it should not be necessary to
> >>> support the "page._count.counter" format, because you can get
> >>> the data by using the container name. Taking the "_count.counter"
> >>> example:
> >>>
> >>> crash> p ((struct page *)0xffffea0000000200)._count.counter
> >>> $10 = 0
> >>> crash> p ((struct page *)0xffffea0000000200)._count
> >>> $11 = {
> >>> counter = 0
> >>> }
> >>> crash>
> >>>
> >>> So using "page._count" should suffice.
> >>>
> >>> Thanks,
> >>> Dave
> >>>
> >>> --
> >>> Crash-utility mailing list
> >>> Crash-utility@redhat.com
> >>> https://www.redhat.com/mailman/listinfo/crash-utility
> >>>
> >>>
> >> Hello Dave,
> >>
> >> Sorry for reacting late. I have started to realize these item we talked
> >> before. But, considering your mail about "page._count.counter" format, I
> >> need to explain my opinion to you. Trying to support the
> >> "page._count.counter" format is used to help implementing the formatted
> >> output like:
> >>
> >> crash> struct page.flags,_count.counter -..< PAGE_list.txt
> >> 1024 0
> >> 1024 1
> >> 1024 1
> >> 1024 1
> >>
> >> Compared with "p ((struct page
> >> *)0xffffea0000000200)._count.counter",
> >> which can only display only one data each time, the former style can be
> >> more helpful when parsing the output.
> >>
> >> The reason why I want the "page._count.counter" format is I want to
> >> offer an efficient way to collect a lot of data. Then I'd like you to
> >> give some comments. Thanks.
> >
> > I'm not interested in completely changing the output format of the "struct"
> > command to display the raw data for multiple fields on a single line as
> > you've shown in your example above. It's completely redefining the output
> > format of the command. If you want to implement something like that, it
> > would have to be governed by a new output option, expressed something like:
> >
> > crash> struct -<raw-output-option> page.flags,_count.counter
> >
> > And if you were to do something like that, then I still maintain that the
> > "page._count.counter" format is unnecessary. You're going to be dumping
> > the whole structure behind the scenes, and then parsing for whatever fields
> > you're looking for.
>
> Do you mean you don't accept changing the output format or simplely the
> "page._count.counter" format?
>
> As we talk before, I want to get "_count.counter" of several pages. So
> the "page._count.counter" format comes up, which is not acceptable. If
> you can accept changing the output format by using a new output option,
> just like:
>
> flags = 0
> _count = {
> counter = 0
> }
> ...
>
> change to:
>
> "0 {0} ..." or "0 { counter = 0 } ..." or 0 "{ .counter = 0 } ..."
>
> Actually the original code is easy to read, but hard to parse. So please
> think about the above change.

Look, the original "struct.member" command format -- where both the member
name and its contents are pulled from the full structure output and displayed
individually is *not* going to change.

As I said before, if you would like to propose a new "struct -x" option
that displays the data in a single line or something to that effect,
post a patch and I'll consider it. But keep in mind, what you feel
is useful may be considered hard to use by others.

Also, given that this whole discussion has *completely* revolved around
picking out data from the kernel's page structures, I'm beginning
to think that you might want to consider writing a "page" extension module
that deals only with the kernel's page structures -- parsing them, pulling
out data, finding pages with particular data contents, etc., something that
goes well beyond "kmem -p" or "struct", and which can be easily enhanced.
And if the module gathers interest, we can then consider polishing it up for
inclusion as a regular command.

Dave





--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 

Thread Tools




All times are GMT. The time now is 06:44 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org