diff options
author | David Howells <dhowells@redhat.com> | 2017-11-02 15:27:53 +0000 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2017-11-13 15:38:21 +0000 |
commit | 13524ab3c6f41bcd257d28644414297bea8282b7 (patch) | |
tree | 9ac5ab8bfd44026bb13783cf540f4fdb57d72d44 | |
parent | 1cf7a1518aefa69ac6ba0c3f9206073e4221e3c8 (diff) |
afs: Trace page dirty/clean
Add a trace event that logs the dirtying and cleaning of pages attached to
AFS inodes.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | fs/afs/file.c | 10 | ||||
-rw-r--r-- | fs/afs/write.c | 34 | ||||
-rw-r--r-- | include/trace/events/afs.h | 39 |
3 files changed, 70 insertions, 13 deletions
diff --git a/fs/afs/file.c b/fs/afs/file.c index 675c5c268a52..a39192ced99e 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -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, unsigned int length) { + struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); + unsigned long priv; + _enter("{%lu},%u,%u", page->index, offset, length); BUG_ON(!PageLocked(page)); @@ -598,6 +601,9 @@ static void afs_invalidatepage(struct page *page, unsigned int offset, #endif if (PagePrivate(page)) { + priv = page_private(page); + trace_afs_page_dirty(vnode, tracepoint_string("inval"), + page->index, priv); set_page_private(page, 0); ClearPagePrivate(page); } @@ -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) { struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); + unsigned long priv; _enter("{{%x:%u}[%lu],%lx},%x", 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) #endif if (PagePrivate(page)) { + priv = page_private(page); + trace_afs_page_dirty(vnode, tracepoint_string("rel"), + page->index, priv); set_page_private(page, 0); ClearPagePrivate(page); } diff --git a/fs/afs/write.c b/fs/afs/write.c index 6807277ef956..4472882f06df 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -18,19 +18,6 @@ #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 */ int afs_set_page_dirty(struct page *page) @@ -145,6 +132,8 @@ try_again: priv = (unsigned long)t << AFS_PRIV_SHIFT; priv |= f; + trace_afs_page_dirty(vnode, tracepoint_string("begin"), + page->index, priv); SetPagePrivate(page); set_page_private(page, priv); _leave(" = 0"); @@ -386,6 +375,7 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, struct page *primary_page, pgoff_t final_page) { + struct afs_vnode *vnode = AFS_FS_I(mapping->host); struct page *pages[8], *page; unsigned long count, priv; unsigned n, offset, to, f, t; @@ -407,8 +397,13 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, priv = page_private(primary_page); offset = priv & AFS_PRIV_MAX; to = priv >> AFS_PRIV_SHIFT; + trace_afs_page_dirty(vnode, tracepoint_string("store"), + primary_page->index, priv); 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) goto no_more; @@ -452,6 +447,9 @@ static int afs_write_back_from_locked_page(struct address_space *mapping, } to = t; + trace_afs_page_dirty(vnode, tracepoint_string("store+"), + page->index, priv); + if (!clear_page_dirty_for_io(page)) BUG(); if (test_set_page_writeback(page)) @@ -657,6 +655,7 @@ int afs_writepages(struct address_space *mapping, void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call) { struct pagevec pv; + unsigned long priv; unsigned count, loop; 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) ASSERTCMP(pv.nr, ==, count); 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); end_page_writeback(pv.pages[loop]); } @@ -783,6 +785,8 @@ int afs_page_mkwrite(struct vm_fault *vmf) priv = (unsigned long)PAGE_SIZE << AFS_PRIV_SHIFT; /* To */ priv |= 0; /* From */ + trace_afs_page_dirty(vnode, tracepoint_string("mkwrite"), + vmf->page->index, priv); SetPagePrivate(vmf->page); set_page_private(vmf->page, priv); @@ -840,9 +844,13 @@ int afs_launder_page(struct page *page) 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); } + trace_afs_page_dirty(vnode, tracepoint_string("laundered"), + page->index, priv); set_page_private(page, 0); ClearPagePrivate(page); diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index 9cfb7657b72c..5f4e8193932d 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -402,6 +402,45 @@ TRACE_EVENT(afs_dir_check_failed, __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 */ /* This part must be outside protection */ |