Commit 13524ab3 authored by David Howells's avatar David Howells

afs: Trace page dirty/clean

Add a trace event that logs the dirtying and cleaning of pages attached to
AFS inodes.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 1cf7a151
...@@ -583,6 +583,9 @@ static int afs_readpages(struct file *file, struct address_space *mapping, ...@@ -583,6 +583,9 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
static void afs_invalidatepage(struct page *page, unsigned int offset, static void afs_invalidatepage(struct page *page, unsigned int offset,
unsigned int length) unsigned int length)
{ {
struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
unsigned long priv;
_enter("{%lu},%u,%u", page->index, offset, length); _enter("{%lu},%u,%u", page->index, offset, length);
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
...@@ -598,6 +601,9 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, ...@@ -598,6 +601,9 @@ static void afs_invalidatepage(struct page *page, unsigned int offset,
#endif #endif
if (PagePrivate(page)) { if (PagePrivate(page)) {
priv = page_private(page);
trace_afs_page_dirty(vnode, tracepoint_string("inval"),
page->index, priv);
set_page_private(page, 0); set_page_private(page, 0);
ClearPagePrivate(page); ClearPagePrivate(page);
} }
...@@ -613,6 +619,7 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, ...@@ -613,6 +619,7 @@ static void afs_invalidatepage(struct page *page, unsigned int offset,
static int afs_releasepage(struct page *page, gfp_t gfp_flags) static int afs_releasepage(struct page *page, gfp_t gfp_flags)
{ {
struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
unsigned long priv;
_enter("{{%x:%u}[%lu],%lx},%x", _enter("{{%x:%u}[%lu],%lx},%x",
vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, vnode->fid.vid, vnode->fid.vnode, page->index, page->flags,
...@@ -628,6 +635,9 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags) ...@@ -628,6 +635,9 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags)
#endif #endif
if (PagePrivate(page)) { if (PagePrivate(page)) {
priv = page_private(page);
trace_afs_page_dirty(vnode, tracepoint_string("rel"),
page->index, priv);
set_page_private(page, 0); set_page_private(page, 0);
ClearPagePrivate(page); ClearPagePrivate(page);
} }
......
...@@ -17,19 +17,6 @@ ...@@ -17,19 +17,6 @@
#include <linux/pagevec.h> #include <linux/pagevec.h>
#include "internal.h" #include "internal.h"
/*
* We use page->private to hold the amount of the page that we've written to,
* splitting the field into two parts. However, we need to represent a range
* 0...PAGE_SIZE inclusive, so we can't support 64K pages on a 32-bit system.
*/
#if PAGE_SIZE > 32768
#define AFS_PRIV_MAX 0xffffffff
#define AFS_PRIV_SHIFT 32
#else
#define AFS_PRIV_MAX 0xffff
#define AFS_PRIV_SHIFT 16
#endif
/* /*
* mark a page as having been made dirty and thus needing writeback * mark a page as having been made dirty and thus needing writeback
*/ */
...@@ -145,6 +132,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping, ...@@ -145,6 +132,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
priv = (unsigned long)t << AFS_PRIV_SHIFT; priv = (unsigned long)t << AFS_PRIV_SHIFT;
priv |= f; priv |= f;
trace_afs_page_dirty(vnode, tracepoint_string("begin"),
page->index, priv);
SetPagePrivate(page); SetPagePrivate(page);
set_page_private(page, priv); set_page_private(page, priv);
_leave(" = 0"); _leave(" = 0");
...@@ -386,6 +375,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, ...@@ -386,6 +375,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
struct page *primary_page, struct page *primary_page,
pgoff_t final_page) pgoff_t final_page)
{ {
struct afs_vnode *vnode = AFS_FS_I(mapping->host);
struct page *pages[8], *page; struct page *pages[8], *page;
unsigned long count, priv; unsigned long count, priv;
unsigned n, offset, to, f, t; unsigned n, offset, to, f, t;
...@@ -407,8 +397,13 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, ...@@ -407,8 +397,13 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
priv = page_private(primary_page); priv = page_private(primary_page);
offset = priv & AFS_PRIV_MAX; offset = priv & AFS_PRIV_MAX;
to = priv >> AFS_PRIV_SHIFT; to = priv >> AFS_PRIV_SHIFT;
trace_afs_page_dirty(vnode, tracepoint_string("store"),
primary_page->index, priv);
WARN_ON(offset == to); WARN_ON(offset == to);
if (offset == to)
trace_afs_page_dirty(vnode, tracepoint_string("WARN"),
primary_page->index, priv);
if (start >= final_page || to < PAGE_SIZE) if (start >= final_page || to < PAGE_SIZE)
goto no_more; goto no_more;
...@@ -452,6 +447,9 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, ...@@ -452,6 +447,9 @@ static int afs_write_back_from_locked_page(struct address_space *mapping,
} }
to = t; to = t;
trace_afs_page_dirty(vnode, tracepoint_string("store+"),
page->index, priv);
if (!clear_page_dirty_for_io(page)) if (!clear_page_dirty_for_io(page))
BUG(); BUG();
if (test_set_page_writeback(page)) if (test_set_page_writeback(page))
...@@ -657,6 +655,7 @@ int afs_writepages(struct address_space *mapping, ...@@ -657,6 +655,7 @@ int afs_writepages(struct address_space *mapping,
void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call) void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call)
{ {
struct pagevec pv; struct pagevec pv;
unsigned long priv;
unsigned count, loop; unsigned count, loop;
pgoff_t first = call->first, last = call->last; pgoff_t first = call->first, last = call->last;
...@@ -676,6 +675,9 @@ void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call) ...@@ -676,6 +675,9 @@ void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call)
ASSERTCMP(pv.nr, ==, count); ASSERTCMP(pv.nr, ==, count);
for (loop = 0; loop < count; loop++) { for (loop = 0; loop < count; loop++) {
priv = page_private(pv.pages[loop]);
trace_afs_page_dirty(vnode, tracepoint_string("clear"),
pv.pages[loop]->index, priv);
set_page_private(pv.pages[loop], 0); set_page_private(pv.pages[loop], 0);
end_page_writeback(pv.pages[loop]); end_page_writeback(pv.pages[loop]);
} }
...@@ -783,6 +785,8 @@ int afs_page_mkwrite(struct vm_fault *vmf) ...@@ -783,6 +785,8 @@ int afs_page_mkwrite(struct vm_fault *vmf)
priv = (unsigned long)PAGE_SIZE << AFS_PRIV_SHIFT; /* To */ priv = (unsigned long)PAGE_SIZE << AFS_PRIV_SHIFT; /* To */
priv |= 0; /* From */ priv |= 0; /* From */
trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"),
vmf->page->index, priv);
SetPagePrivate(vmf->page); SetPagePrivate(vmf->page);
set_page_private(vmf->page, priv); set_page_private(vmf->page, priv);
...@@ -840,9 +844,13 @@ int afs_launder_page(struct page *page) ...@@ -840,9 +844,13 @@ int afs_launder_page(struct page *page)
t = priv >> AFS_PRIV_SHIFT; t = priv >> AFS_PRIV_SHIFT;
} }
trace_afs_page_dirty(vnode, tracepoint_string("launder"),
page->index, priv);
ret = afs_store_data(mapping, page->index, page->index, t, f); ret = afs_store_data(mapping, page->index, page->index, t, f);
} }
trace_afs_page_dirty(vnode, tracepoint_string("laundered"),
page->index, priv);
set_page_private(page, 0); set_page_private(page, 0);
ClearPagePrivate(page); ClearPagePrivate(page);
......
...@@ -402,6 +402,45 @@ TRACE_EVENT(afs_dir_check_failed, ...@@ -402,6 +402,45 @@ TRACE_EVENT(afs_dir_check_failed,
__entry->vnode, __entry->off, __entry->i_size) __entry->vnode, __entry->off, __entry->i_size)
); );
/*
* We use page->private to hold the amount of the page that we've written to,
* splitting the field into two parts. However, we need to represent a range
* 0...PAGE_SIZE inclusive, so we can't support 64K pages on a 32-bit system.
*/
#if PAGE_SIZE > 32768
#define AFS_PRIV_MAX 0xffffffff
#define AFS_PRIV_SHIFT 32
#else
#define AFS_PRIV_MAX 0xffff
#define AFS_PRIV_SHIFT 16
#endif
TRACE_EVENT(afs_page_dirty,
TP_PROTO(struct afs_vnode *vnode, const char *where,
pgoff_t page, unsigned long priv),
TP_ARGS(vnode, where, page, priv),
TP_STRUCT__entry(
__field(struct afs_vnode *, vnode )
__field(const char *, where )
__field(pgoff_t, page )
__field(unsigned long, priv )
),
TP_fast_assign(
__entry->vnode = vnode;
__entry->where = where;
__entry->page = page;
__entry->priv = priv;
),
TP_printk("vn=%p %lx %s %lu-%lu",
__entry->vnode, __entry->page, __entry->where,
__entry->priv & AFS_PRIV_MAX,
__entry->priv >> AFS_PRIV_SHIFT)
);
#endif /* _TRACE_AFS_H */ #endif /* _TRACE_AFS_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment