This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Re: Page faults
- From: David Smith <dsmith at redhat dot com>
- To: "Paddie O'Brien" <paddieobrien at gmail dot com>
- Cc: systemtap at sourceware dot org
- Date: Mon, 09 Sep 2013 16:00:31 -0500
- Subject: Re: Page faults
- Authentication-results: sourceware.org; auth=none
- References: <CAOK12DZSCVBTZsi8iMAgjpJCU+8q-DWoK0KBUsuj0XUAz17azA at mail dot gmail dot com>
On 09/09/2013 03:36 PM, Paddie O'Brien wrote:
> Hi,
>
> I run the attached to print out the offsets of faulting pages. Both
> probes should (I think) print the same number but instead I get this:
>
> hello: filemap_fault
> Page: 1678263179
> hello: find_get_page
> Page: 15
>
> hello: filemap_fault
> Page: 1678263179
> hello: find_get_page
> Page: 1
>
> hello: filemap_fault
> Page: 1678263179
> hello: find_get_page
> Page: 10
>
> etc. etc.
>
> Both functions are from mm/filemap.c. filemap_fault does this:
>
> pgoff_t offset = vmf->offset;
> find_get_page(mapping, offset);
>
> Basically, printing the offset in find_get_page works but printing
> vmf->offset in filemap_fault doesn't.
>
> Why?
Here's your script:
====
probe kernel.function("filemap_fault")
{
if (execname() != "hello") next;
printf("%s: filemap_fault\n", execname());
printf("Page: %lu\n", $vmf->pgoff);
}
probe kernel.function("find_get_page")
{
if (execname() != "hello") next;
printf("%s: find_get_page\n", execname());
printf("Page: %lu\n", $offset);
}
=====
Here's filemap_fault() (at least my version of it):
====
int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
int error;
struct file *file = vma->vm_file;
struct address_space *mapping = file->f_mapping;
struct file_ra_state *ra = &file->f_ra;
struct inode *inode = mapping->host;
pgoff_t offset = vmf->pgoff;
struct page *page;
pgoff_t size;
int ret = 0;
size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (offset >= size)
return VM_FAULT_SIGBUS;
/*
* Do we have something in the page cache already?
*/
page = find_get_page(mapping, offset);
====
Based on that, filemap_fault() can return before calling
find_get_page(), so your calls may not be matching up like you think
they do.
You might try something like this (untested), and see what happens:
=====
global handled
probe kernel.function("filemap_fault")
{
if (execname() != "hello") next;
printf("%s: filemap_fault\n", execname());
printf("Page: %lu\n", $vmf->pgoff);
handled[tid()] = 1
}
probe kernel.function("filemap_fault").return
{
delete handled[tid()]
}
probe kernel.function("find_get_page")
{
if (handled[tid()] != 1) next;
printf("%s: find_get_page\n", execname());
printf("Page: %lu\n", $offset);
}
=====
--
David Smith
dsmith@redhat.com
Red Hat
http://www.redhat.com
256.217.0141 (direct)
256.837.0057 (fax)