diff --git a/include/sys/arc.h b/include/sys/arc.h index 90a4adb108ee..158cbe633d66 100644 --- a/include/sys/arc.h +++ b/include/sys/arc.h @@ -90,6 +90,8 @@ typedef enum arc_space_type { ARC_SPACE_META, ARC_SPACE_HDRS, ARC_SPACE_L2HDRS, + ARC_SPACE_ABD_DATA, + ARC_SPACE_ABD_HDRS, ARC_SPACE_OTHER, ARC_SPACE_NUMTYPES } arc_space_type_t; diff --git a/module/zfs/abd.c b/module/zfs/abd.c index 58dc71ebd781..1ddef8c0c0e4 100644 --- a/module/zfs/abd.c +++ b/module/zfs/abd.c @@ -24,6 +24,7 @@ */ #include +#include #ifdef _KERNEL #include #include @@ -819,9 +820,9 @@ abd_alloc(size_t size) arc_buf_data_t *abd; struct page *page; int i, n = DIV_ROUND_UP(size, PAGE_SIZE); - - abd = kmem_alloc(sizeof (arc_buf_data_t) + - n * sizeof (struct scatterlist), KM_PUSHPAGE); + const int headersize = sizeof(arc_buf_data_t) + + n * sizeof(struct scatterlist); + abd = kmem_alloc(headersize, KM_PUSHPAGE); ASSERT(abd); ASSERT_ABD_LINEAR(abd); @@ -842,7 +843,8 @@ abd_alloc(size_t size) } sg_set_page(&abd->abd_sgl[i], page, PAGE_SIZE, 0); } - + arc_space_consume(headersize, ARC_SPACE_ABD_HDRS); + arc_space_consume(PAGE_SIZE * n, ARC_SPACE_ABD_DATA); return (abd_t *)(((unsigned long)abd)|0x1); } @@ -856,6 +858,8 @@ abd_free(abd_t *__abd, size_t size) ASSERT(abd->abd_sgl == &abd->__abd_sgl[0]); ASSERT(abd->abd_size == size); n = DIV_ROUND_UP(abd->abd_size, PAGE_SIZE); + const int headersize = sizeof(arc_buf_data_t) + + n * sizeof(struct scatterlist); abd->abd_magic = 0; for (i = 0; i < n; i++) { @@ -863,6 +867,8 @@ abd_free(abd_t *__abd, size_t size) if (page) __free_page(page); } - kmem_free(abd, sizeof (arc_buf_data_t) + - n * sizeof (struct scatterlist)); + kmem_free(abd, headersize); + arc_space_return(headersize, ARC_SPACE_ABD_HDRS); + arc_space_return(PAGE_SIZE * n, ARC_SPACE_ABD_DATA); } + diff --git a/module/zfs/arc.c b/module/zfs/arc.c index e8059f5b58b0..1ce156b52178 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -364,6 +364,8 @@ typedef struct arc_stats { kstat_named_t arcstat_meta_used; kstat_named_t arcstat_meta_limit; kstat_named_t arcstat_meta_max; + kstat_named_t arcstat_abd_data_size; + kstat_named_t arcstat_abd_hdr_size; } arc_stats_t; static arc_stats_t arc_stats = { @@ -452,6 +454,8 @@ static arc_stats_t arc_stats = { { "arc_meta_used", KSTAT_DATA_UINT64 }, { "arc_meta_limit", KSTAT_DATA_UINT64 }, { "arc_meta_max", KSTAT_DATA_UINT64 }, + { "abd_data_size", KSTAT_DATA_UINT64 }, + { "abd_hdr_size", KSTAT_DATA_UINT64 }, }; #define ARCSTAT(stat) (arc_stats.stat.value.ui64) @@ -1401,9 +1405,16 @@ arc_space_consume(uint64_t space, arc_space_type_t type) case ARC_SPACE_L2HDRS: ARCSTAT_INCR(arcstat_l2_hdr_size, space); break; + case ARC_SPACE_ABD_DATA: + ARCSTAT_INCR(arcstat_abd_data_size, space); + /* Return because otherwise we double-count data space */ + return; + case ARC_SPACE_ABD_HDRS: + ARCSTAT_INCR(arcstat_abd_hdr_size, space); + break; } - if (type != ARC_SPACE_DATA) + if (type != ARC_SPACE_DATA && type != ARC_SPACE_ABD_DATA) ARCSTAT_INCR(arcstat_meta_used, space); atomic_add_64(&arc_size, space); @@ -1432,9 +1443,16 @@ arc_space_return(uint64_t space, arc_space_type_t type) case ARC_SPACE_L2HDRS: ARCSTAT_INCR(arcstat_l2_hdr_size, -space); break; + case ARC_SPACE_ABD_DATA: + ARCSTAT_INCR(arcstat_abd_data_size, -space); + /* Return because otherwise we double-count data space */ + return; + case ARC_SPACE_ABD_HDRS: + ARCSTAT_INCR(arcstat_abd_hdr_size, -space); + break; } - if (type != ARC_SPACE_DATA) { + if (type != ARC_SPACE_DATA && type != ARC_SPACE_ABD_DATA) { ASSERT(arc_meta_used >= space); if (arc_meta_max < arc_meta_used) arc_meta_max = arc_meta_used;