From 823a5bed3429401ab73bee9187317451332a81cb Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Wed, 21 Jun 2017 16:15:53 -0700 Subject: [PATCH] scoutfs: add some segment cache life cycle tracing Signed-off-by: Zach Brown --- kmod/src/counters.h | 4 +++- kmod/src/scoutfs_trace.h | 42 ++++++++++++++++++++++++++++++++++++++++ kmod/src/seg.c | 27 ++++++++++++-------------- kmod/src/seg.h | 13 ++++++++++++- 4 files changed, 69 insertions(+), 17 deletions(-) diff --git a/kmod/src/counters.h b/kmod/src/counters.h index a41340e2..9fe291c0 100644 --- a/kmod/src/counters.h +++ b/kmod/src/counters.h @@ -14,7 +14,9 @@ #define EXPAND_EACH_COUNTER \ EXPAND_COUNTER(alloc_alloc) \ EXPAND_COUNTER(alloc_free) \ - EXPAND_COUNTER(seg_lru_shrink) \ + EXPAND_COUNTER(seg_alloc) \ + EXPAND_COUNTER(seg_shrink) \ + EXPAND_COUNTER(seg_free) \ EXPAND_COUNTER(trans_level0_seg_write) \ EXPAND_COUNTER(manifest_compact_migrate) \ EXPAND_COUNTER(compact_operations) \ diff --git a/kmod/src/scoutfs_trace.h b/kmod/src/scoutfs_trace.h index e03c2c6d..175fe3e6 100644 --- a/kmod/src/scoutfs_trace.h +++ b/kmod/src/scoutfs_trace.h @@ -29,6 +29,7 @@ #include "format.h" #include "kvec.h" #include "lock.h" +#include "seg.h" struct scoutfs_sb_info; @@ -357,6 +358,47 @@ TRACE_EVENT(scoutfs_lock_invalidate_sb, __get_str(start), __get_str(end)) ); +DECLARE_EVENT_CLASS(scoutfs_seg_class, + TP_PROTO(struct scoutfs_segment *seg), + TP_ARGS(seg), + TP_STRUCT__entry( + __field(unsigned int, major) + __field(unsigned int, minor) + __field(struct scoutfs_segment *, seg) + __field(int, refcount) + __field(u64, segno) + __field(unsigned long, flags) + __field(int, err) + ), + TP_fast_assign( + __entry->major = MAJOR(seg->sb->s_bdev->bd_dev); + __entry->minor = MINOR(seg->sb->s_bdev->bd_dev); + __entry->seg = seg; + __entry->refcount = atomic_read(&seg->refcount); + __entry->segno = seg->segno; + __entry->flags = seg->flags; + __entry->err = seg->err; + ), + TP_printk("dev %u:%u seg %p refcount %d segno %llu flags %lx err %d", + __entry->major, __entry->minor, __entry->seg, __entry->refcount, + __entry->segno, __entry->flags, __entry->err) +); + +DEFINE_EVENT(scoutfs_seg_class, scoutfs_seg_alloc, + TP_PROTO(struct scoutfs_segment *seg), + TP_ARGS(seg) +); + +DEFINE_EVENT(scoutfs_seg_class, scoutfs_seg_shrink, + TP_PROTO(struct scoutfs_segment *seg), + TP_ARGS(seg) +); + +DEFINE_EVENT(scoutfs_seg_class, scoutfs_seg_free, + TP_PROTO(struct scoutfs_segment *seg), + TP_ARGS(seg) +); + #endif /* _TRACE_SCOUTFS_H */ /* This part must be outside protection */ diff --git a/kmod/src/seg.c b/kmod/src/seg.c index 8437d98b..fffbbf34 100644 --- a/kmod/src/seg.c +++ b/kmod/src/seg.c @@ -26,6 +26,7 @@ #include "alloc.h" #include "key.h" #include "counters.h" +#include "scoutfs_trace.h" /* * seg.c should just be about the cache and io, and maybe @@ -49,21 +50,12 @@ struct segment_cache { unsigned long lru_nr; }; -struct scoutfs_segment { - struct rb_node node; - struct list_head lru_entry; - atomic_t refcount; - u64 segno; - unsigned long flags; - int err; - struct page *pages[SCOUTFS_SEGMENT_PAGES]; -}; enum { SF_END_IO = 0, }; -static struct scoutfs_segment *alloc_seg(u64 segno) +static struct scoutfs_segment *alloc_seg(struct super_block *sb, u64 segno) { struct scoutfs_segment *seg; struct page *page; @@ -76,6 +68,7 @@ static struct scoutfs_segment *alloc_seg(u64 segno) if (!seg) return seg; + seg->sb = sb; RB_CLEAR_NODE(&seg->node); INIT_LIST_HEAD(&seg->lru_entry); atomic_set(&seg->refcount, 1); @@ -83,8 +76,6 @@ static struct scoutfs_segment *alloc_seg(u64 segno) for (i = 0; i < SCOUTFS_SEGMENT_PAGES; i++) { page = alloc_page(GFP_NOFS); - trace_printk("seg %p segno %llu page %u %p\n", - seg, segno, i, page); if (!page) { scoutfs_seg_put(seg); return ERR_PTR(-ENOMEM); @@ -93,6 +84,9 @@ static struct scoutfs_segment *alloc_seg(u64 segno) seg->pages[i] = page; } + trace_scoutfs_seg_alloc(seg); + scoutfs_inc_counter(sb, seg_alloc); + return seg; } @@ -106,6 +100,8 @@ void scoutfs_seg_put(struct scoutfs_segment *seg) int i; if (!IS_ERR_OR_NULL(seg) && atomic_dec_and_test(&seg->refcount)) { + trace_scoutfs_seg_free(seg); + scoutfs_inc_counter(seg->sb, seg_free); WARN_ON_ONCE(!RB_EMPTY_NODE(&seg->node)); WARN_ON_ONCE(!list_empty(&seg->lru_entry)); for (i = 0; i < SCOUTFS_SEGMENT_PAGES; i++) @@ -256,7 +252,7 @@ int scoutfs_seg_alloc(struct super_block *sb, u64 segno, unsigned long flags; int ret; - seg = alloc_seg(segno); + seg = alloc_seg(sb, segno); if (!seg) { ret = -ENOMEM; goto out; @@ -321,7 +317,7 @@ struct scoutfs_segment *scoutfs_seg_submit_read(struct super_block *sb, if (seg) return seg; - seg = alloc_seg(segno); + seg = alloc_seg(sb, segno); if (IS_ERR(seg)) return seg; @@ -776,7 +772,8 @@ static int seg_lru_shrink(struct shrinker *shrink, struct shrink_control *sc) spin_unlock_irqrestore(&cac->lock, flags); list_for_each_entry_safe(seg, tmp, &list, lru_entry) { - scoutfs_inc_counter(sb, seg_lru_shrink); + trace_scoutfs_seg_shrink(seg); + scoutfs_inc_counter(sb, seg_shrink); list_del_init(&seg->lru_entry); scoutfs_seg_put(seg); } diff --git a/kmod/src/seg.h b/kmod/src/seg.h index fbe11d88..9d1cd4c9 100644 --- a/kmod/src/seg.h +++ b/kmod/src/seg.h @@ -2,10 +2,21 @@ #define _SCOUTFS_SEG_H_ struct scoutfs_bio_completion; -struct scoutfs_segment; struct scoutfs_key_buf; struct kvec; +/* this is only visible for trace events */ +struct scoutfs_segment { + struct super_block *sb; + struct rb_node node; + struct list_head lru_entry; + atomic_t refcount; + u64 segno; + unsigned long flags; + int err; + struct page *pages[SCOUTFS_SEGMENT_PAGES]; +}; + struct scoutfs_segment *scoutfs_seg_submit_read(struct super_block *sb, u64 segno); int scoutfs_seg_wait(struct super_block *sb, struct scoutfs_segment *seg);