Skip to content

Commit 84230c6

Browse files
committed
Add L2ARC arcstats for MFU/MRU buffers and buffer content type
Currently the initial ARC state (MFU/MRU) of cached L2ARC buffers at the time of their caching is unknown. The same applies for the buffer content type. This commit adds L2ARC arcstats that display the aligned size (in bytes) of L2ARC buffers according to their content type (data/metadata) and according to their ARC state (MRU/MFU) at the time of caching in L2ARC. This may prove beneficial in adjusting the L2ARC caching policy in the future. Signed-off-by: George Amanakis <[email protected]>
1 parent 772c69d commit 84230c6

File tree

3 files changed

+106
-16
lines changed

3 files changed

+106
-16
lines changed

cmd/zdb/zdb.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4101,6 +4101,8 @@ dump_l2arc_log_entries(uint64_t log_entries,
41014101
(u_longlong_t)L2BLK_GET_PREFETCH((&le[j])->le_prop));
41024102
(void) printf("|\t\t\t\taddress: %llu\n",
41034103
(u_longlong_t)le[j].le_daddr);
4104+
(void) printf("|\t\t\t\tstate: %llu\n",
4105+
(u_longlong_t)L2BLK_GET_STATE((&le[j])->le_prop));
41044106
(void) printf("|\n");
41054107
}
41064108
(void) printf("\n");

include/sys/arc_impl.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ typedef struct l2arc_lb_ptr_buf {
349349
#define L2BLK_SET_TYPE(field, x) BF64_SET((field), 48, 8, x)
350350
#define L2BLK_GET_PROTECTED(field) BF64_GET((field), 56, 1)
351351
#define L2BLK_SET_PROTECTED(field, x) BF64_SET((field), 56, 1, x)
352+
#define L2BLK_GET_STATE(field) BF64_GET((field), 57, 4)
353+
#define L2BLK_SET_STATE(field, x) BF64_SET((field), 57, 4, x)
352354

353355
#define PTR_SWAP(x, y) \
354356
do { \
@@ -445,6 +447,7 @@ typedef struct l2arc_buf_hdr {
445447
uint64_t b_daddr; /* disk address, offset byte */
446448
uint32_t b_hits;
447449
list_node_t b_l2node;
450+
arc_state_type_t b_arcs_state;
448451
} l2arc_buf_hdr_t;
449452

450453
typedef struct l2arc_write_callback {
@@ -733,6 +736,20 @@ typedef struct arc_stats {
733736
kstat_named_t arcstat_mfu_ghost_evictable_metadata;
734737
kstat_named_t arcstat_l2_hits;
735738
kstat_named_t arcstat_l2_misses;
739+
/*
740+
* Aligned size (in bytes) of L2ARC cached buffers according to their
741+
* ARC state at the time of caching in L2ARC.
742+
*/
743+
kstat_named_t arcstat_l2_mru_asize;
744+
kstat_named_t arcstat_l2_mru_ghost_asize;
745+
kstat_named_t arcstat_l2_mfu_asize;
746+
kstat_named_t arcstat_l2_mfu_ghost_asize;
747+
/*
748+
* Aligned size (in bytes) of L2ARC cached buffers by buffer content
749+
* type.
750+
*/
751+
kstat_named_t arcstat_l2_bufc_data_asize;
752+
kstat_named_t arcstat_l2_bufc_metadata_asize;
736753
kstat_named_t arcstat_l2_feeds;
737754
kstat_named_t arcstat_l2_rw_clash;
738755
kstat_named_t arcstat_l2_read_bytes;

module/zfs/arc.c

Lines changed: 87 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,12 @@ arc_stats_t arc_stats = {
527527
{ "mfu_ghost_evictable_metadata", KSTAT_DATA_UINT64 },
528528
{ "l2_hits", KSTAT_DATA_UINT64 },
529529
{ "l2_misses", KSTAT_DATA_UINT64 },
530+
{ "l2_mru_asize", KSTAT_DATA_UINT64 },
531+
{ "l2_mru_ghost_asize", KSTAT_DATA_UINT64 },
532+
{ "l2_mfu_asize", KSTAT_DATA_UINT64 },
533+
{ "l2_mfu_ghost_asize", KSTAT_DATA_UINT64 },
534+
{ "l2_bufc_data_asize", KSTAT_DATA_UINT64 },
535+
{ "l2_bufc_metadata_asize", KSTAT_DATA_UINT64 },
530536
{ "l2_feeds", KSTAT_DATA_UINT64 },
531537
{ "l2_rw_clash", KSTAT_DATA_UINT64 },
532538
{ "l2_read_bytes", KSTAT_DATA_UINT64 },
@@ -887,6 +893,7 @@ static inline void arc_hdr_clear_flags(arc_buf_hdr_t *hdr, arc_flags_t flags);
887893
static boolean_t l2arc_write_eligible(uint64_t, arc_buf_hdr_t *);
888894
static void l2arc_read_done(zio_t *);
889895
static void l2arc_do_free_on_write(void);
896+
static void l2arc_hdr_arcstats_update(arc_buf_hdr_t *hdr, boolean_t incr);
890897

891898
/*
892899
* L2ARC TRIM
@@ -1707,7 +1714,8 @@ arc_buf_try_copy_decompressed_data(arc_buf_t *buf)
17071714
static arc_buf_hdr_t *
17081715
arc_buf_alloc_l2only(size_t size, arc_buf_contents_t type, l2arc_dev_t *dev,
17091716
dva_t dva, uint64_t daddr, int32_t psize, uint64_t birth,
1710-
enum zio_compress compress, boolean_t protected, boolean_t prefetch)
1717+
enum zio_compress compress, boolean_t protected, boolean_t prefetch,
1718+
arc_state_type_t arcs_state)
17111719
{
17121720
arc_buf_hdr_t *hdr;
17131721

@@ -1730,6 +1738,7 @@ arc_buf_alloc_l2only(size_t size, arc_buf_contents_t type, l2arc_dev_t *dev,
17301738

17311739
hdr->b_l2hdr.b_dev = dev;
17321740
hdr->b_l2hdr.b_daddr = daddr;
1741+
hdr->b_l2hdr.b_arcs_state = arcs_state;
17331742

17341743
return (hdr);
17351744
}
@@ -3661,6 +3670,68 @@ arc_alloc_raw_buf(spa_t *spa, void *tag, uint64_t dsobj, boolean_t byteorder,
36613670
return (buf);
36623671
}
36633672

3673+
static void
3674+
l2arc_hdr_arcstats_update(arc_buf_hdr_t *hdr, boolean_t incr)
3675+
{
3676+
l2arc_buf_hdr_t *l2hdr = &hdr->b_l2hdr;
3677+
l2arc_dev_t *dev = l2hdr->b_dev;
3678+
uint64_t lsize = HDR_GET_LSIZE(hdr);
3679+
uint64_t psize = HDR_GET_PSIZE(hdr);
3680+
uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev, psize);
3681+
arc_buf_contents_t type = hdr->b_type;
3682+
int64_t lsize_s;
3683+
int64_t psize_s;
3684+
int64_t asize_s;
3685+
3686+
if (!incr) {
3687+
lsize_s = -lsize;
3688+
psize_s = -psize;
3689+
asize_s = -asize;
3690+
} else {
3691+
lsize_s = lsize;
3692+
psize_s = psize;
3693+
asize_s = asize;
3694+
}
3695+
3696+
ARCSTAT_INCR(arcstat_l2_psize, psize_s);
3697+
ARCSTAT_INCR(arcstat_l2_lsize, lsize_s);
3698+
3699+
/*
3700+
* We use the value stored in the L2 header upon initial caching in
3701+
* L2ARC. This is because we are interested in the state of the buffer
3702+
* in ARC when it was cached in L2ARC for the first time. This also
3703+
* solves the problem of a possibly absent L1 header.
3704+
*/
3705+
switch (hdr->b_l2hdr.b_arcs_state) {
3706+
case ARC_STATE_MRU:
3707+
ARCSTAT_INCR(arcstat_l2_mru_asize, asize_s);
3708+
break;
3709+
case ARC_STATE_MRU_GHOST:
3710+
ARCSTAT_INCR(arcstat_l2_mru_ghost_asize, asize_s);
3711+
break;
3712+
case ARC_STATE_MFU:
3713+
ARCSTAT_INCR(arcstat_l2_mfu_asize, asize_s);
3714+
break;
3715+
case ARC_STATE_MFU_GHOST:
3716+
ARCSTAT_INCR(arcstat_l2_mfu_ghost_asize, asize_s);
3717+
break;
3718+
default:
3719+
break;
3720+
}
3721+
3722+
switch (type) {
3723+
case ARC_BUFC_DATA:
3724+
ARCSTAT_INCR(arcstat_l2_bufc_data_asize, asize_s);
3725+
break;
3726+
case ARC_BUFC_METADATA:
3727+
ARCSTAT_INCR(arcstat_l2_bufc_metadata_asize, asize_s);
3728+
break;
3729+
default:
3730+
break;
3731+
}
3732+
}
3733+
3734+
36643735
static void
36653736
arc_hdr_l2hdr_destroy(arc_buf_hdr_t *hdr)
36663737
{
@@ -3674,9 +3745,7 @@ arc_hdr_l2hdr_destroy(arc_buf_hdr_t *hdr)
36743745

36753746
list_remove(&dev->l2ad_buflist, hdr);
36763747

3677-
ARCSTAT_INCR(arcstat_l2_psize, -psize);
3678-
ARCSTAT_INCR(arcstat_l2_lsize, -HDR_GET_LSIZE(hdr));
3679-
3748+
l2arc_hdr_arcstats_update(hdr, B_FALSE);
36803749
vdev_space_update(dev->l2ad_vdev, -asize, 0, 0);
36813750

36823751
(void) zfs_refcount_remove_many(&dev->l2ad_alloc, arc_hdr_size(hdr),
@@ -8025,9 +8094,6 @@ l2arc_write_done(zio_t *zio)
80258094
DTRACE_PROBE2(l2arc__iodone, zio_t *, zio,
80268095
l2arc_write_callback_t *, cb);
80278096

8028-
if (zio->io_error != 0)
8029-
ARCSTAT_BUMP(arcstat_l2_writes_error);
8030-
80318097
/*
80328098
* All writes completed, or an error was hit.
80338099
*/
@@ -8091,8 +8157,7 @@ l2arc_write_done(zio_t *zio)
80918157
arc_hdr_clear_flags(hdr, ARC_FLAG_HAS_L2HDR);
80928158

80938159
uint64_t psize = HDR_GET_PSIZE(hdr);
8094-
ARCSTAT_INCR(arcstat_l2_psize, -psize);
8095-
ARCSTAT_INCR(arcstat_l2_lsize, -HDR_GET_LSIZE(hdr));
8160+
l2arc_hdr_arcstats_update(hdr, B_FALSE);
80968161

80978162
bytes_dropped +=
80988163
vdev_psize_to_asize(dev->l2ad_vdev, psize);
@@ -8140,6 +8205,8 @@ l2arc_write_done(zio_t *zio)
81408205
list_destroy(&cb->l2wcb_abd_list);
81418206

81428207
if (zio->io_error != 0) {
8208+
ARCSTAT_BUMP(arcstat_l2_writes_error);
8209+
81438210
/*
81448211
* Restore the lbps array in the header to its previous state.
81458212
* If the list of log block pointers is empty, zero out the
@@ -9024,6 +9091,8 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
90249091
hdr->b_l2hdr.b_hits = 0;
90259092

90269093
hdr->b_l2hdr.b_daddr = dev->l2ad_hand;
9094+
hdr->b_l2hdr.b_arcs_state =
9095+
hdr->b_l1hdr.b_state->arcs_state;
90279096
arc_hdr_set_flags(hdr, ARC_FLAG_HAS_L2HDR);
90289097

90299098
mutex_enter(&dev->l2ad_mtx);
@@ -9046,6 +9115,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
90469115
write_psize += psize;
90479116
write_asize += asize;
90489117
dev->l2ad_hand += asize;
9118+
l2arc_hdr_arcstats_update(hdr, B_TRUE);
90499119
vdev_space_update(dev->l2ad_vdev, asize, 0, 0);
90509120

90519121
mutex_exit(hash_lock);
@@ -10023,19 +10093,18 @@ l2arc_hdr_restore(const l2arc_log_ent_phys_t *le, l2arc_dev_t *dev)
1002310093
L2BLK_GET_PSIZE((le)->le_prop), le->le_birth,
1002410094
L2BLK_GET_COMPRESS((le)->le_prop),
1002510095
L2BLK_GET_PROTECTED((le)->le_prop),
10026-
L2BLK_GET_PREFETCH((le)->le_prop));
10096+
L2BLK_GET_PREFETCH((le)->le_prop),
10097+
L2BLK_GET_STATE((le)->le_prop));
1002710098
asize = vdev_psize_to_asize(dev->l2ad_vdev,
1002810099
L2BLK_GET_PSIZE((le)->le_prop));
1002910100

1003010101
/*
1003110102
* vdev_space_update() has to be called before arc_hdr_destroy() to
10032-
* avoid underflow since the latter also calls the former.
10103+
* avoid underflow since the latter also calls vdev_space_update().
1003310104
*/
10105+
l2arc_hdr_arcstats_update(hdr, B_TRUE);
1003410106
vdev_space_update(dev->l2ad_vdev, asize, 0, 0);
1003510107

10036-
ARCSTAT_INCR(arcstat_l2_lsize, HDR_GET_LSIZE(hdr));
10037-
ARCSTAT_INCR(arcstat_l2_psize, HDR_GET_PSIZE(hdr));
10038-
1003910108
mutex_enter(&dev->l2ad_mtx);
1004010109
list_insert_tail(&dev->l2ad_buflist, hdr);
1004110110
(void) zfs_refcount_add_many(&dev->l2ad_alloc, arc_hdr_size(hdr), hdr);
@@ -10055,14 +10124,15 @@ l2arc_hdr_restore(const l2arc_log_ent_phys_t *le, l2arc_dev_t *dev)
1005510124
arc_hdr_set_flags(exists, ARC_FLAG_HAS_L2HDR);
1005610125
exists->b_l2hdr.b_dev = dev;
1005710126
exists->b_l2hdr.b_daddr = le->le_daddr;
10127+
exists->b_l2hdr.b_arcs_state =
10128+
L2BLK_GET_STATE((le)->le_prop);
1005810129
mutex_enter(&dev->l2ad_mtx);
1005910130
list_insert_tail(&dev->l2ad_buflist, exists);
1006010131
(void) zfs_refcount_add_many(&dev->l2ad_alloc,
1006110132
arc_hdr_size(exists), exists);
1006210133
mutex_exit(&dev->l2ad_mtx);
10134+
l2arc_hdr_arcstats_update(exists, B_TRUE);
1006310135
vdev_space_update(dev->l2ad_vdev, asize, 0, 0);
10064-
ARCSTAT_INCR(arcstat_l2_lsize, HDR_GET_LSIZE(exists));
10065-
ARCSTAT_INCR(arcstat_l2_psize, HDR_GET_PSIZE(exists));
1006610136
}
1006710137
ARCSTAT_BUMP(arcstat_l2_rebuild_bufs_precached);
1006810138
}
@@ -10357,6 +10427,7 @@ l2arc_log_blk_insert(l2arc_dev_t *dev, const arc_buf_hdr_t *hdr)
1035710427
L2BLK_SET_TYPE((le)->le_prop, hdr->b_type);
1035810428
L2BLK_SET_PROTECTED((le)->le_prop, !!(HDR_PROTECTED(hdr)));
1035910429
L2BLK_SET_PREFETCH((le)->le_prop, !!(HDR_PREFETCH(hdr)));
10430+
L2BLK_SET_STATE((le)->le_prop, hdr->b_l1hdr.b_state->arcs_state);
1036010431

1036110432
dev->l2ad_log_blk_payload_asize += vdev_psize_to_asize(dev->l2ad_vdev,
1036210433
HDR_GET_PSIZE(hdr));

0 commit comments

Comments
 (0)