This patch introduces new fields to per-mount and global stats, and export them to user space. @page_alloc -- number of pages allocated from buddy to buffer cache @page_free -- number of pages freed to buddy from buffer cache @kbb_alloc -- number of BBs allocated from kmalloc slab to buffer cache @kbb_free -- number of BBs freed to kmalloc slab from buffer cache @vbb_alloc -- number of BBs allocated from vmalloc system to buffer cache @vbb_free -- number of BBs freed to vmalloc system from buffer cache By looking at above stats fields, user space can easily know the buffer cache usage. Signed-off-by: Wengang Wang <wen.gang.wang@xxxxxxxxxx> --- fs/xfs/xfs_buf.c | 15 +++++++++++---- fs/xfs/xfs_stats.c | 16 ++++++++++++++++ fs/xfs/xfs_stats.h | 8 ++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 1a2b3f06fa71..db3cb94eabee 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -113,12 +113,17 @@ xfs_buf_free( if (!xfs_buftarg_is_mem(bp->b_target) && size >= PAGE_SIZE) mm_account_reclaimed_pages(howmany(size, PAGE_SHIFT)); - if (is_vmalloc_addr(bp->b_addr)) + if (is_vmalloc_addr(bp->b_addr)) { vfree(bp->b_addr); - else if (bp->b_flags & _XBF_KMEM) + XFS_STATS_ADD(bp->b_mount, xs_buf_vbb_free, bp->b_length); + } else if (bp->b_flags & _XBF_KMEM) { kfree(bp->b_addr); - else + XFS_STATS_ADD(bp->b_mount, xs_buf_kbb_free, bp->b_length); + } else { folio_put(virt_to_folio(bp->b_addr)); + XFS_STATS_ADD(bp->b_mount, xs_buf_page_free, + BBTOB(bp->b_length) >> PAGE_SHIFT); + } call_rcu(&bp->b_rcu, xfs_buf_free_callback); } @@ -147,6 +152,7 @@ xfs_buf_alloc_kmem( return -ENOMEM; } bp->b_flags |= _XBF_KMEM; + XFS_STATS_ADD(bp->b_mount, xs_buf_kbb_alloc, bp->b_length); trace_xfs_buf_backing_kmem(bp, _RET_IP_); return 0; } @@ -232,6 +238,7 @@ xfs_buf_alloc_backing_mem( } bp->b_addr = folio_address(folio); trace_xfs_buf_backing_folio(bp, _RET_IP_); + XFS_STATS_ADD(bp->b_mount, xs_buf_page_alloc, size >> PAGE_SHIFT); return 0; fallback: @@ -244,7 +251,7 @@ xfs_buf_alloc_backing_mem( XFS_STATS_INC(bp->b_mount, xb_page_retries); memalloc_retry_wait(gfp_mask); } - + XFS_STATS_ADD(bp->b_mount, xs_buf_vbb_alloc, bp->b_length); trace_xfs_buf_backing_vmalloc(bp, _RET_IP_); return 0; } diff --git a/fs/xfs/xfs_stats.c b/fs/xfs/xfs_stats.c index 35c7fb3ba324..a0f6813dc782 100644 --- a/fs/xfs/xfs_stats.c +++ b/fs/xfs/xfs_stats.c @@ -24,6 +24,12 @@ int xfs_stats_format(struct xfsstats __percpu *stats, char *buf) uint64_t xs_write_bytes = 0; uint64_t xs_read_bytes = 0; uint64_t defer_relog = 0; + uint64_t pg_alloc = 0; + uint64_t pg_free = 0; + uint64_t kbb_alloc = 0; + uint64_t kbb_free = 0; + uint64_t vbb_alloc = 0; + uint64_t vbb_free = 0; static const struct xstats_entry { char *desc; @@ -77,6 +83,12 @@ int xfs_stats_format(struct xfsstats __percpu *stats, char *buf) xs_write_bytes += per_cpu_ptr(stats, i)->s.xs_write_bytes; xs_read_bytes += per_cpu_ptr(stats, i)->s.xs_read_bytes; defer_relog += per_cpu_ptr(stats, i)->s.defer_relog; + pg_alloc += per_cpu_ptr(stats, i)->s.xs_buf_page_alloc; + pg_free += per_cpu_ptr(stats, i)->s.xs_buf_page_free; + kbb_alloc += per_cpu_ptr(stats, i)->s.xs_buf_kbb_alloc; + kbb_free += per_cpu_ptr(stats, i)->s.xs_buf_kbb_free; + vbb_alloc += per_cpu_ptr(stats, i)->s.xs_buf_vbb_alloc; + vbb_free += per_cpu_ptr(stats, i)->s.xs_buf_vbb_free; } len += scnprintf(buf + len, PATH_MAX-len, "xpc %llu %llu %llu\n", @@ -89,6 +101,10 @@ int xfs_stats_format(struct xfsstats __percpu *stats, char *buf) #else 0); #endif + len += scnprintf(buf + len, PATH_MAX-len, + "cache %llu %llu %llu %llu %llu %llu\n", + pg_alloc, pg_free, kbb_alloc, kbb_free, + vbb_alloc, vbb_free); return len; } diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h index 15ba1abcf253..5e186880d8d0 100644 --- a/fs/xfs/xfs_stats.h +++ b/fs/xfs/xfs_stats.h @@ -143,6 +143,14 @@ struct __xfsstats { uint64_t xs_write_bytes; uint64_t xs_read_bytes; uint64_t defer_relog; + + /* number of pages/bbs allocated/freed in buffer cache */ + uint64_t xs_buf_page_alloc; + uint64_t xs_buf_page_free; + uint64_t xs_buf_kbb_alloc; + uint64_t xs_buf_kbb_free; + uint64_t xs_buf_vbb_alloc; + uint64_t xs_buf_vbb_free; }; #define xfsstats_offset(f) (offsetof(struct __xfsstats, f)/sizeof(uint32_t)) -- 2.39.5 (Apple Git-154)