summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2017-11-02 15:27:53 +0000
committerDavid Howells <dhowells@redhat.com>2017-11-13 15:38:21 +0000
commit13524ab3c6f41bcd257d28644414297bea8282b7 (patch)
tree9ac5ab8bfd44026bb13783cf540f4fdb57d72d44
parent1cf7a1518aefa69ac6ba0c3f9206073e4221e3c8 (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.c10
-rw-r--r--fs/afs/write.c34
-rw-r--r--include/trace/events/afs.h39
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 */