Skip to content

Commit

Permalink
Add L2ARC arcstats for MFU/MRU buffers and buffer content type
Browse files Browse the repository at this point in the history
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 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 <gamanakis@gmail.com>
  • Loading branch information
gamanakis committed Aug 20, 2020
1 parent 772c69d commit dbb3afb
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 16 deletions.
2 changes: 2 additions & 0 deletions cmd/zdb/zdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -4101,6 +4101,8 @@ dump_l2arc_log_entries(uint64_t log_entries,
(u_longlong_t)L2BLK_GET_PREFETCH((&le[j])->le_prop));
(void) printf("|\t\t\t\taddress: %llu\n",
(u_longlong_t)le[j].le_daddr);
(void) printf("|\t\t\t\tstate: %llu\n",
(u_longlong_t)L2BLK_GET_STATE((&le[j])->le_prop));
(void) printf("|\n");
}
(void) printf("\n");
Expand Down
17 changes: 17 additions & 0 deletions include/sys/arc_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ typedef struct l2arc_lb_ptr_buf {
#define L2BLK_SET_TYPE(field, x) BF64_SET((field), 48, 8, x)
#define L2BLK_GET_PROTECTED(field) BF64_GET((field), 56, 1)
#define L2BLK_SET_PROTECTED(field, x) BF64_SET((field), 56, 1, x)
#define L2BLK_GET_STATE(field) BF64_GET((field), 57, 4)
#define L2BLK_SET_STATE(field, x) BF64_SET((field), 57, 4, x)

#define PTR_SWAP(x, y) \
do { \
Expand Down Expand Up @@ -445,6 +447,7 @@ typedef struct l2arc_buf_hdr {
uint64_t b_daddr; /* disk address, offset byte */
uint32_t b_hits;
list_node_t b_l2node;
arc_state_type_t b_arcs_state;
} l2arc_buf_hdr_t;

typedef struct l2arc_write_callback {
Expand Down Expand Up @@ -733,6 +736,20 @@ typedef struct arc_stats {
kstat_named_t arcstat_mfu_ghost_evictable_metadata;
kstat_named_t arcstat_l2_hits;
kstat_named_t arcstat_l2_misses;
/*
* Aligned size (in bytes) of L2ARC cached buffers according to their
* ARC state at the time of caching in L2ARC.
*/
kstat_named_t arcstat_l2_mru_asize;
kstat_named_t arcstat_l2_mru_ghost_asize;
kstat_named_t arcstat_l2_mfu_asize;
kstat_named_t arcstat_l2_mfu_ghost_asize;
/*
* Aligned size (in bytes) of L2ARC cached buffers by buffer content
* type.
*/
kstat_named_t arcstat_l2_bufc_data_asize;
kstat_named_t arcstat_l2_bufc_metadata_asize;
kstat_named_t arcstat_l2_feeds;
kstat_named_t arcstat_l2_rw_clash;
kstat_named_t arcstat_l2_read_bytes;
Expand Down
97 changes: 81 additions & 16 deletions module/zfs/arc.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,12 @@ arc_stats_t arc_stats = {
{ "mfu_ghost_evictable_metadata", KSTAT_DATA_UINT64 },
{ "l2_hits", KSTAT_DATA_UINT64 },
{ "l2_misses", KSTAT_DATA_UINT64 },
{ "l2_mru_asize", KSTAT_DATA_UINT64 },
{ "l2_mru_ghost_asize", KSTAT_DATA_UINT64 },
{ "l2_mfu_asize", KSTAT_DATA_UINT64 },
{ "l2_mfu_ghost_asize", KSTAT_DATA_UINT64 },
{ "l2_bufc_data_asize", KSTAT_DATA_UINT64 },
{ "l2_bufc_metadata_asize", KSTAT_DATA_UINT64 },
{ "l2_feeds", KSTAT_DATA_UINT64 },
{ "l2_rw_clash", KSTAT_DATA_UINT64 },
{ "l2_read_bytes", KSTAT_DATA_UINT64 },
Expand Down Expand Up @@ -887,6 +893,7 @@ static inline void arc_hdr_clear_flags(arc_buf_hdr_t *hdr, arc_flags_t flags);
static boolean_t l2arc_write_eligible(uint64_t, arc_buf_hdr_t *);
static void l2arc_read_done(zio_t *);
static void l2arc_do_free_on_write(void);
static void l2arc_hdr_arcstats_update(arc_buf_hdr_t *hdr, boolean_t incr);

/*
* L2ARC TRIM
Expand Down Expand Up @@ -1707,7 +1714,8 @@ arc_buf_try_copy_decompressed_data(arc_buf_t *buf)
static arc_buf_hdr_t *
arc_buf_alloc_l2only(size_t size, arc_buf_contents_t type, l2arc_dev_t *dev,
dva_t dva, uint64_t daddr, int32_t psize, uint64_t birth,
enum zio_compress compress, boolean_t protected, boolean_t prefetch)
enum zio_compress compress, boolean_t protected, boolean_t prefetch,
arc_state_type_t arcs_state)
{
arc_buf_hdr_t *hdr;

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

hdr->b_l2hdr.b_dev = dev;
hdr->b_l2hdr.b_daddr = daddr;
hdr->b_l2hdr.b_arcs_state = arcs_state;

return (hdr);
}
Expand Down Expand Up @@ -3661,6 +3670,62 @@ arc_alloc_raw_buf(spa_t *spa, void *tag, uint64_t dsobj, boolean_t byteorder,
return (buf);
}

static void
l2arc_hdr_arcstats_update(arc_buf_hdr_t *hdr, boolean_t incr)
{
l2arc_buf_hdr_t *l2hdr = &hdr->b_l2hdr;
l2arc_dev_t *dev = l2hdr->b_dev;
uint64_t lsize = HDR_GET_LSIZE(hdr);
uint64_t psize = HDR_GET_PSIZE(hdr);
uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev, psize);
arc_buf_contents_t type = hdr->b_type;
int64_t lsize_s;
int64_t psize_s;
int64_t asize_s;

if (!incr) {
lsize_s = -lsize;
psize_s = -psize;
asize_s = -asize;
} else {
lsize_s = lsize;
psize_s = psize;
asize_s = asize;
}

ARCSTAT_INCR(arcstat_l2_psize, psize_s);
ARCSTAT_INCR(arcstat_l2_lsize, lsize_s);

switch (hdr->b_l2hdr.b_arcs_state) {
case ARC_STATE_MRU:
ARCSTAT_INCR(arcstat_l2_mru_asize, asize_s);
break;
case ARC_STATE_MRU_GHOST:
ARCSTAT_INCR(arcstat_l2_mru_ghost_asize, asize_s);
break;
case ARC_STATE_MFU:
ARCSTAT_INCR(arcstat_l2_mfu_asize, asize_s);
break;
case ARC_STATE_MFU_GHOST:
ARCSTAT_INCR(arcstat_l2_mfu_ghost_asize, asize_s);
break;
default:
break;
}

switch (type) {
case ARC_BUFC_DATA:
ARCSTAT_INCR(arcstat_l2_bufc_data_asize, asize_s);
break;
case ARC_BUFC_METADATA:
ARCSTAT_INCR(arcstat_l2_bufc_metadata_asize, asize_s);
break;
default:
break;
}
}


static void
arc_hdr_l2hdr_destroy(arc_buf_hdr_t *hdr)
{
Expand All @@ -3674,9 +3739,7 @@ arc_hdr_l2hdr_destroy(arc_buf_hdr_t *hdr)

list_remove(&dev->l2ad_buflist, hdr);

ARCSTAT_INCR(arcstat_l2_psize, -psize);
ARCSTAT_INCR(arcstat_l2_lsize, -HDR_GET_LSIZE(hdr));

l2arc_hdr_arcstats_update(hdr, B_FALSE);
vdev_space_update(dev->l2ad_vdev, -asize, 0, 0);

(void) zfs_refcount_remove_many(&dev->l2ad_alloc, arc_hdr_size(hdr),
Expand Down Expand Up @@ -8025,9 +8088,6 @@ l2arc_write_done(zio_t *zio)
DTRACE_PROBE2(l2arc__iodone, zio_t *, zio,
l2arc_write_callback_t *, cb);

if (zio->io_error != 0)
ARCSTAT_BUMP(arcstat_l2_writes_error);

/*
* All writes completed, or an error was hit.
*/
Expand Down Expand Up @@ -8091,8 +8151,7 @@ l2arc_write_done(zio_t *zio)
arc_hdr_clear_flags(hdr, ARC_FLAG_HAS_L2HDR);

uint64_t psize = HDR_GET_PSIZE(hdr);
ARCSTAT_INCR(arcstat_l2_psize, -psize);
ARCSTAT_INCR(arcstat_l2_lsize, -HDR_GET_LSIZE(hdr));
l2arc_hdr_arcstats_update(hdr, B_FALSE);

bytes_dropped +=
vdev_psize_to_asize(dev->l2ad_vdev, psize);
Expand Down Expand Up @@ -8140,6 +8199,8 @@ l2arc_write_done(zio_t *zio)
list_destroy(&cb->l2wcb_abd_list);

if (zio->io_error != 0) {
ARCSTAT_BUMP(arcstat_l2_writes_error);

/*
* Restore the lbps array in the header to its previous state.
* If the list of log block pointers is empty, zero out the
Expand Down Expand Up @@ -9024,6 +9085,8 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
hdr->b_l2hdr.b_hits = 0;

hdr->b_l2hdr.b_daddr = dev->l2ad_hand;
hdr->b_l2hdr.b_arcs_state =
hdr->b_l1hdr.b_state->arcs_state;
arc_hdr_set_flags(hdr, ARC_FLAG_HAS_L2HDR);

mutex_enter(&dev->l2ad_mtx);
Expand All @@ -9046,6 +9109,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
write_psize += psize;
write_asize += asize;
dev->l2ad_hand += asize;
l2arc_hdr_arcstats_update(hdr, B_TRUE);
vdev_space_update(dev->l2ad_vdev, asize, 0, 0);

mutex_exit(hash_lock);
Expand Down Expand Up @@ -10023,19 +10087,18 @@ l2arc_hdr_restore(const l2arc_log_ent_phys_t *le, l2arc_dev_t *dev)
L2BLK_GET_PSIZE((le)->le_prop), le->le_birth,
L2BLK_GET_COMPRESS((le)->le_prop),
L2BLK_GET_PROTECTED((le)->le_prop),
L2BLK_GET_PREFETCH((le)->le_prop));
L2BLK_GET_PREFETCH((le)->le_prop),
L2BLK_GET_STATE((le)->le_prop));
asize = vdev_psize_to_asize(dev->l2ad_vdev,
L2BLK_GET_PSIZE((le)->le_prop));

/*
* vdev_space_update() has to be called before arc_hdr_destroy() to
* avoid underflow since the latter also calls the former.
* avoid underflow since the latter also calls vdev_space_update().
*/
l2arc_hdr_arcstats_update(hdr, B_TRUE);
vdev_space_update(dev->l2ad_vdev, asize, 0, 0);

ARCSTAT_INCR(arcstat_l2_lsize, HDR_GET_LSIZE(hdr));
ARCSTAT_INCR(arcstat_l2_psize, HDR_GET_PSIZE(hdr));

mutex_enter(&dev->l2ad_mtx);
list_insert_tail(&dev->l2ad_buflist, hdr);
(void) zfs_refcount_add_many(&dev->l2ad_alloc, arc_hdr_size(hdr), hdr);
Expand All @@ -10055,14 +10118,15 @@ l2arc_hdr_restore(const l2arc_log_ent_phys_t *le, l2arc_dev_t *dev)
arc_hdr_set_flags(exists, ARC_FLAG_HAS_L2HDR);
exists->b_l2hdr.b_dev = dev;
exists->b_l2hdr.b_daddr = le->le_daddr;
exists->b_l2hdr.b_arcs_state =
L2BLK_GET_STATE((le)->le_prop);
mutex_enter(&dev->l2ad_mtx);
list_insert_tail(&dev->l2ad_buflist, exists);
(void) zfs_refcount_add_many(&dev->l2ad_alloc,
arc_hdr_size(exists), exists);
mutex_exit(&dev->l2ad_mtx);
l2arc_hdr_arcstats_update(exists, B_TRUE);
vdev_space_update(dev->l2ad_vdev, asize, 0, 0);
ARCSTAT_INCR(arcstat_l2_lsize, HDR_GET_LSIZE(exists));
ARCSTAT_INCR(arcstat_l2_psize, HDR_GET_PSIZE(exists));
}
ARCSTAT_BUMP(arcstat_l2_rebuild_bufs_precached);
}
Expand Down Expand Up @@ -10357,6 +10421,7 @@ l2arc_log_blk_insert(l2arc_dev_t *dev, const arc_buf_hdr_t *hdr)
L2BLK_SET_TYPE((le)->le_prop, hdr->b_type);
L2BLK_SET_PROTECTED((le)->le_prop, !!(HDR_PROTECTED(hdr)));
L2BLK_SET_PREFETCH((le)->le_prop, !!(HDR_PREFETCH(hdr)));
L2BLK_SET_STATE((le)->le_prop, hdr->b_l1hdr.b_state->arcs_state);

dev->l2ad_log_blk_payload_asize += vdev_psize_to_asize(dev->l2ad_vdev,
HDR_GET_PSIZE(hdr));
Expand Down

0 comments on commit dbb3afb

Please sign in to comment.