afs: Trace page dirty/clean
authorDavid Howells <dhowells@redhat.com>
Thu, 2 Nov 2017 15:27:53 +0000 (15:27 +0000)
committerDavid Howells <dhowells@redhat.com>
Mon, 13 Nov 2017 15:38:21 +0000 (15:38 +0000)
Add a trace event that logs the dirtying and cleaning of pages attached to
AFS inodes.

Signed-off-by: David Howells <dhowells@redhat.com>
fs/afs/file.c
fs/afs/write.c
include/trace/events/afs.h

index 675c5c2..a39192c 100644 (file)
@@ -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);
        }
index 6807277..4472882 100644 (file)
 #include <linux/pagevec.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
  */
@@ -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);
 
index 9cfb765..5f4e819 100644 (file)
@@ -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 */