mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
MFV r277427: 5445 Add more visibility via arcstats; specifically
arc_state_t stats and differentiate between "data" and "metadata" Reviewed by: Basil Crow <basil.crow@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Bayard Bell <bayard.bell@nexenta.com> Approved by: Robert Mustacchi <rm@joyent.com> Author: Prakash Surya <prakash.surya@delphix.com> illumos/illumos-gate@4076b1bf41
This commit is contained in:
parent
db51871b42
commit
f13e9e1470
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=286574
@ -35,12 +35,17 @@
|
||||
|
||||
#define KSTAT_FLAG_VIRTUAL 0x01
|
||||
|
||||
#define KSTAT_READ 0
|
||||
#define KSTAT_WRITE 1
|
||||
|
||||
typedef struct kstat {
|
||||
void *ks_data;
|
||||
u_int ks_ndata;
|
||||
#ifdef _KERNEL
|
||||
struct sysctl_ctx_list ks_sysctl_ctx;
|
||||
struct sysctl_oid *ks_sysctl_root;
|
||||
int (*ks_update)(struct kstat *, int); /* dynamic update */
|
||||
void *ks_private; /* arbitrary provider-private data */
|
||||
#endif
|
||||
} kstat_t;
|
||||
|
||||
|
@ -384,9 +384,137 @@ typedef struct arc_stats {
|
||||
kstat_named_t arcstat_c_min;
|
||||
kstat_named_t arcstat_c_max;
|
||||
kstat_named_t arcstat_size;
|
||||
/*
|
||||
* Number of bytes consumed by internal ARC structures necessary
|
||||
* for tracking purposes; these structures are not actually
|
||||
* backed by ARC buffers. This includes arc_buf_hdr_t structures
|
||||
* (allocated via arc_buf_hdr_t_full and arc_buf_hdr_t_l2only
|
||||
* caches), and arc_buf_t structures (allocated via arc_buf_t
|
||||
* cache).
|
||||
*/
|
||||
kstat_named_t arcstat_hdr_size;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers of type equal to
|
||||
* ARC_BUFC_DATA. This is generally consumed by buffers backing
|
||||
* on disk user data (e.g. plain file contents).
|
||||
*/
|
||||
kstat_named_t arcstat_data_size;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers of type equal to
|
||||
* ARC_BUFC_METADATA. This is generally consumed by buffers
|
||||
* backing on disk data that is used for internal ZFS
|
||||
* structures (e.g. ZAP, dnode, indirect blocks, etc).
|
||||
*/
|
||||
kstat_named_t arcstat_metadata_size;
|
||||
/*
|
||||
* Number of bytes consumed by various buffers and structures
|
||||
* not actually backed with ARC buffers. This includes bonus
|
||||
* buffers (allocated directly via zio_buf_* functions),
|
||||
* dmu_buf_impl_t structures (allocated via dmu_buf_impl_t
|
||||
* cache), and dnode_t structures (allocated via dnode_t cache).
|
||||
*/
|
||||
kstat_named_t arcstat_other_size;
|
||||
/*
|
||||
* Total number of bytes consumed by ARC buffers residing in the
|
||||
* arc_anon state. This includes *all* buffers in the arc_anon
|
||||
* state; e.g. data, metadata, evictable, and unevictable buffers
|
||||
* are all included in this value.
|
||||
*/
|
||||
kstat_named_t arcstat_anon_size;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers that meet the
|
||||
* following criteria: backing buffers of type ARC_BUFC_DATA,
|
||||
* residing in the arc_anon state, and are eligible for eviction
|
||||
* (e.g. have no outstanding holds on the buffer).
|
||||
*/
|
||||
kstat_named_t arcstat_anon_evictable_data;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers that meet the
|
||||
* following criteria: backing buffers of type ARC_BUFC_METADATA,
|
||||
* residing in the arc_anon state, and are eligible for eviction
|
||||
* (e.g. have no outstanding holds on the buffer).
|
||||
*/
|
||||
kstat_named_t arcstat_anon_evictable_metadata;
|
||||
/*
|
||||
* Total number of bytes consumed by ARC buffers residing in the
|
||||
* arc_mru state. This includes *all* buffers in the arc_mru
|
||||
* state; e.g. data, metadata, evictable, and unevictable buffers
|
||||
* are all included in this value.
|
||||
*/
|
||||
kstat_named_t arcstat_mru_size;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers that meet the
|
||||
* following criteria: backing buffers of type ARC_BUFC_DATA,
|
||||
* residing in the arc_mru state, and are eligible for eviction
|
||||
* (e.g. have no outstanding holds on the buffer).
|
||||
*/
|
||||
kstat_named_t arcstat_mru_evictable_data;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers that meet the
|
||||
* following criteria: backing buffers of type ARC_BUFC_METADATA,
|
||||
* residing in the arc_mru state, and are eligible for eviction
|
||||
* (e.g. have no outstanding holds on the buffer).
|
||||
*/
|
||||
kstat_named_t arcstat_mru_evictable_metadata;
|
||||
/*
|
||||
* Total number of bytes that *would have been* consumed by ARC
|
||||
* buffers in the arc_mru_ghost state. The key thing to note
|
||||
* here, is the fact that this size doesn't actually indicate
|
||||
* RAM consumption. The ghost lists only consist of headers and
|
||||
* don't actually have ARC buffers linked off of these headers.
|
||||
* Thus, *if* the headers had associated ARC buffers, these
|
||||
* buffers *would have* consumed this number of bytes.
|
||||
*/
|
||||
kstat_named_t arcstat_mru_ghost_size;
|
||||
/*
|
||||
* Number of bytes that *would have been* consumed by ARC
|
||||
* buffers that are eligible for eviction, of type
|
||||
* ARC_BUFC_DATA, and linked off the arc_mru_ghost state.
|
||||
*/
|
||||
kstat_named_t arcstat_mru_ghost_evictable_data;
|
||||
/*
|
||||
* Number of bytes that *would have been* consumed by ARC
|
||||
* buffers that are eligible for eviction, of type
|
||||
* ARC_BUFC_METADATA, and linked off the arc_mru_ghost state.
|
||||
*/
|
||||
kstat_named_t arcstat_mru_ghost_evictable_metadata;
|
||||
/*
|
||||
* Total number of bytes consumed by ARC buffers residing in the
|
||||
* arc_mfu state. This includes *all* buffers in the arc_mfu
|
||||
* state; e.g. data, metadata, evictable, and unevictable buffers
|
||||
* are all included in this value.
|
||||
*/
|
||||
kstat_named_t arcstat_mfu_size;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers that are eligible for
|
||||
* eviction, of type ARC_BUFC_DATA, and reside in the arc_mfu
|
||||
* state.
|
||||
*/
|
||||
kstat_named_t arcstat_mfu_evictable_data;
|
||||
/*
|
||||
* Number of bytes consumed by ARC buffers that are eligible for
|
||||
* eviction, of type ARC_BUFC_METADATA, and reside in the
|
||||
* arc_mfu state.
|
||||
*/
|
||||
kstat_named_t arcstat_mfu_evictable_metadata;
|
||||
/*
|
||||
* Total number of bytes that *would have been* consumed by ARC
|
||||
* buffers in the arc_mfu_ghost state. See the comment above
|
||||
* arcstat_mru_ghost_size for more details.
|
||||
*/
|
||||
kstat_named_t arcstat_mfu_ghost_size;
|
||||
/*
|
||||
* Number of bytes that *would have been* consumed by ARC
|
||||
* buffers that are eligible for eviction, of type
|
||||
* ARC_BUFC_DATA, and linked off the arc_mfu_ghost state.
|
||||
*/
|
||||
kstat_named_t arcstat_mfu_ghost_evictable_data;
|
||||
/*
|
||||
* Number of bytes that *would have been* consumed by ARC
|
||||
* buffers that are eligible for eviction, of type
|
||||
* ARC_BUFC_METADATA, and linked off the arc_mru_ghost state.
|
||||
*/
|
||||
kstat_named_t arcstat_mfu_ghost_evictable_metadata;
|
||||
kstat_named_t arcstat_l2_hits;
|
||||
kstat_named_t arcstat_l2_misses;
|
||||
kstat_named_t arcstat_l2_feeds;
|
||||
@ -469,7 +597,23 @@ static arc_stats_t arc_stats = {
|
||||
{ "size", KSTAT_DATA_UINT64 },
|
||||
{ "hdr_size", KSTAT_DATA_UINT64 },
|
||||
{ "data_size", KSTAT_DATA_UINT64 },
|
||||
{ "metadata_size", KSTAT_DATA_UINT64 },
|
||||
{ "other_size", KSTAT_DATA_UINT64 },
|
||||
{ "anon_size", KSTAT_DATA_UINT64 },
|
||||
{ "anon_evictable_data", KSTAT_DATA_UINT64 },
|
||||
{ "anon_evictable_metadata", KSTAT_DATA_UINT64 },
|
||||
{ "mru_size", KSTAT_DATA_UINT64 },
|
||||
{ "mru_evictable_data", KSTAT_DATA_UINT64 },
|
||||
{ "mru_evictable_metadata", KSTAT_DATA_UINT64 },
|
||||
{ "mru_ghost_size", KSTAT_DATA_UINT64 },
|
||||
{ "mru_ghost_evictable_data", KSTAT_DATA_UINT64 },
|
||||
{ "mru_ghost_evictable_metadata", KSTAT_DATA_UINT64 },
|
||||
{ "mfu_size", KSTAT_DATA_UINT64 },
|
||||
{ "mfu_evictable_data", KSTAT_DATA_UINT64 },
|
||||
{ "mfu_evictable_metadata", KSTAT_DATA_UINT64 },
|
||||
{ "mfu_ghost_size", KSTAT_DATA_UINT64 },
|
||||
{ "mfu_ghost_evictable_data", KSTAT_DATA_UINT64 },
|
||||
{ "mfu_ghost_evictable_metadata", KSTAT_DATA_UINT64 },
|
||||
{ "l2_hits", KSTAT_DATA_UINT64 },
|
||||
{ "l2_misses", KSTAT_DATA_UINT64 },
|
||||
{ "l2_feeds", KSTAT_DATA_UINT64 },
|
||||
@ -1727,6 +1871,9 @@ arc_space_consume(uint64_t space, arc_space_type_t type)
|
||||
case ARC_SPACE_DATA:
|
||||
ARCSTAT_INCR(arcstat_data_size, space);
|
||||
break;
|
||||
case ARC_SPACE_META:
|
||||
ARCSTAT_INCR(arcstat_metadata_size, space);
|
||||
break;
|
||||
case ARC_SPACE_OTHER:
|
||||
ARCSTAT_INCR(arcstat_other_size, space);
|
||||
break;
|
||||
@ -1738,7 +1885,9 @@ arc_space_consume(uint64_t space, arc_space_type_t type)
|
||||
break;
|
||||
}
|
||||
|
||||
ARCSTAT_INCR(arcstat_meta_used, space);
|
||||
if (type != ARC_SPACE_DATA)
|
||||
ARCSTAT_INCR(arcstat_meta_used, space);
|
||||
|
||||
atomic_add_64(&arc_size, space);
|
||||
}
|
||||
|
||||
@ -1751,6 +1900,9 @@ arc_space_return(uint64_t space, arc_space_type_t type)
|
||||
case ARC_SPACE_DATA:
|
||||
ARCSTAT_INCR(arcstat_data_size, -space);
|
||||
break;
|
||||
case ARC_SPACE_META:
|
||||
ARCSTAT_INCR(arcstat_metadata_size, -space);
|
||||
break;
|
||||
case ARC_SPACE_OTHER:
|
||||
ARCSTAT_INCR(arcstat_other_size, -space);
|
||||
break;
|
||||
@ -1762,10 +1914,13 @@ arc_space_return(uint64_t space, arc_space_type_t type)
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(arc_meta_used >= space);
|
||||
if (arc_meta_max < arc_meta_used)
|
||||
arc_meta_max = arc_meta_used;
|
||||
ARCSTAT_INCR(arcstat_meta_used, -space);
|
||||
if (type != ARC_SPACE_DATA) {
|
||||
ASSERT(arc_meta_used >= space);
|
||||
if (arc_meta_max < arc_meta_used)
|
||||
arc_meta_max = arc_meta_used;
|
||||
ARCSTAT_INCR(arcstat_meta_used, -space);
|
||||
}
|
||||
|
||||
ASSERT(arc_size >= space);
|
||||
atomic_add_64(&arc_size, -space);
|
||||
}
|
||||
@ -2006,12 +2161,11 @@ arc_buf_destroy(arc_buf_t *buf, boolean_t recycle, boolean_t remove)
|
||||
if (!recycle) {
|
||||
if (type == ARC_BUFC_METADATA) {
|
||||
arc_buf_data_free(buf, zio_buf_free);
|
||||
arc_space_return(size, ARC_SPACE_DATA);
|
||||
arc_space_return(size, ARC_SPACE_META);
|
||||
} else {
|
||||
ASSERT(type == ARC_BUFC_DATA);
|
||||
arc_buf_data_free(buf, zio_data_buf_free);
|
||||
ARCSTAT_INCR(arcstat_data_size, -size);
|
||||
atomic_add_64(&arc_size, -size);
|
||||
arc_space_return(size, ARC_SPACE_DATA);
|
||||
}
|
||||
}
|
||||
if (list_link_active(&buf->b_hdr->b_l1hdr.b_arc_node)) {
|
||||
@ -3096,6 +3250,20 @@ arc_reclaim_thread(void *dummy __unused)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is necessary in order for the mdb ::arc dcmd to
|
||||
* show up to date information. Since the ::arc command
|
||||
* does not call the kstat's update function, without
|
||||
* this call, the command may show stale stats for the
|
||||
* anon, mru, mru_ghost, mfu, and mfu_ghost lists. Even
|
||||
* with this change, the data might be up to 1 second
|
||||
* out of date; but that should suffice. The arc_state_t
|
||||
* structures can be queried directly if more accurate
|
||||
* information is needed.
|
||||
*/
|
||||
if (arc_ksp != NULL)
|
||||
arc_ksp->ks_update(arc_ksp, KSTAT_READ);
|
||||
|
||||
/* block until needed, or one second, whichever is shorter */
|
||||
CALLB_CPR_SAFE_BEGIN(&cpr);
|
||||
(void) cv_timedwait(&arc_reclaim_thr_cv,
|
||||
@ -3233,12 +3401,11 @@ arc_get_data_buf(arc_buf_t *buf)
|
||||
if (!arc_evict_needed(type)) {
|
||||
if (type == ARC_BUFC_METADATA) {
|
||||
buf->b_data = zio_buf_alloc(size);
|
||||
arc_space_consume(size, ARC_SPACE_DATA);
|
||||
arc_space_consume(size, ARC_SPACE_META);
|
||||
} else {
|
||||
ASSERT(type == ARC_BUFC_DATA);
|
||||
buf->b_data = zio_data_buf_alloc(size);
|
||||
ARCSTAT_INCR(arcstat_data_size, size);
|
||||
atomic_add_64(&arc_size, size);
|
||||
arc_space_consume(size, ARC_SPACE_DATA);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
@ -3265,12 +3432,11 @@ arc_get_data_buf(arc_buf_t *buf)
|
||||
if ((buf->b_data = arc_evict(state, 0, size, TRUE, type)) == NULL) {
|
||||
if (type == ARC_BUFC_METADATA) {
|
||||
buf->b_data = zio_buf_alloc(size);
|
||||
arc_space_consume(size, ARC_SPACE_DATA);
|
||||
arc_space_consume(size, ARC_SPACE_META);
|
||||
} else {
|
||||
ASSERT(type == ARC_BUFC_DATA);
|
||||
buf->b_data = zio_data_buf_alloc(size);
|
||||
ARCSTAT_INCR(arcstat_data_size, size);
|
||||
atomic_add_64(&arc_size, size);
|
||||
arc_space_consume(size, ARC_SPACE_DATA);
|
||||
}
|
||||
ARCSTAT_BUMP(arcstat_recycle_miss);
|
||||
}
|
||||
@ -4431,6 +4597,48 @@ arc_memory_throttle(uint64_t reserve, uint64_t txg)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
arc_kstat_update_state(arc_state_t *state, kstat_named_t *size,
|
||||
kstat_named_t *evict_data, kstat_named_t *evict_metadata)
|
||||
{
|
||||
size->value.ui64 = state->arcs_size;
|
||||
evict_data->value.ui64 = state->arcs_lsize[ARC_BUFC_DATA];
|
||||
evict_metadata->value.ui64 = state->arcs_lsize[ARC_BUFC_METADATA];
|
||||
}
|
||||
|
||||
static int
|
||||
arc_kstat_update(kstat_t *ksp, int rw)
|
||||
{
|
||||
arc_stats_t *as = ksp->ks_data;
|
||||
|
||||
if (rw == KSTAT_WRITE) {
|
||||
return (EACCES);
|
||||
} else {
|
||||
arc_kstat_update_state(arc_anon,
|
||||
&as->arcstat_anon_size,
|
||||
&as->arcstat_anon_evictable_data,
|
||||
&as->arcstat_anon_evictable_metadata);
|
||||
arc_kstat_update_state(arc_mru,
|
||||
&as->arcstat_mru_size,
|
||||
&as->arcstat_mru_evictable_data,
|
||||
&as->arcstat_mru_evictable_metadata);
|
||||
arc_kstat_update_state(arc_mru_ghost,
|
||||
&as->arcstat_mru_ghost_size,
|
||||
&as->arcstat_mru_ghost_evictable_data,
|
||||
&as->arcstat_mru_ghost_evictable_metadata);
|
||||
arc_kstat_update_state(arc_mfu,
|
||||
&as->arcstat_mfu_size,
|
||||
&as->arcstat_mfu_evictable_data,
|
||||
&as->arcstat_mfu_evictable_metadata);
|
||||
arc_kstat_update_state(arc_mfu_ghost,
|
||||
&as->arcstat_mfu_ghost_size,
|
||||
&as->arcstat_mfu_ghost_evictable_data,
|
||||
&as->arcstat_mfu_ghost_evictable_metadata);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
arc_tempreserve_clear(uint64_t reserve)
|
||||
{
|
||||
@ -4654,6 +4862,7 @@ arc_init(void)
|
||||
|
||||
if (arc_ksp != NULL) {
|
||||
arc_ksp->ks_data = &arc_stats;
|
||||
arc_ksp->ks_update = arc_kstat_update;
|
||||
kstat_install(arc_ksp);
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,7 @@ typedef enum arc_buf_contents {
|
||||
*/
|
||||
typedef enum arc_space_type {
|
||||
ARC_SPACE_DATA,
|
||||
ARC_SPACE_META,
|
||||
ARC_SPACE_HDRS,
|
||||
ARC_SPACE_L2HDRS,
|
||||
ARC_SPACE_OTHER,
|
||||
|
Loading…
Reference in New Issue
Block a user