summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2015-01-05 14:25:10 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2015-01-05 14:25:10 +0000
commit74062ae5aace32d0cf69986fceedef7334b08399 (patch)
treec1ae04af03575d602dd723cdc7c387a65a912226
parent0173c3089b5d2cc973f4453ad6410855e13ad28a (diff)
parentad69a33458cf73ee14857d57799cf686946e0b88 (diff)
downloadillumos-joyent-74062ae5aace32d0cf69986fceedef7334b08399.tar.gz
[illumos-gate merge]
commit ad69a33458cf73ee14857d57799cf686946e0b88 5491 libipadm`i_ipadm_init_ifs() calls free() on bogus memory address commit 4076b1bf41cfd9f968a33ed54a7ae76d9e996fe8 5445 Add more visibility via arcstats; specifically arc_state_t stats and differentiate between "data" and "metadata"
-rw-r--r--usr/src/cmd/mdb/common/modules/zfs/zfs.c14
-rw-r--r--usr/src/lib/libipadm/common/libipadm.c12
-rw-r--r--usr/src/uts/common/fs/zfs/arc.c237
-rw-r--r--usr/src/uts/common/fs/zfs/sys/arc.h1
4 files changed, 241 insertions, 23 deletions
diff --git a/usr/src/cmd/mdb/common/modules/zfs/zfs.c b/usr/src/cmd/mdb/common/modules/zfs/zfs.c
index e940623d22..225cf3dee1 100644
--- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c
+++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c
@@ -960,10 +960,16 @@ arc_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
static const char *bytestats[] = {
"p", "c", "c_min", "c_max", "size", "duplicate_buffers_size",
"arc_meta_used", "arc_meta_limit", "arc_meta_max",
- "arc_meta_min", "hdr_size", "data_size", "other_size",
- "evict_l2_cached", "evict_l2_eligible", "evict_l2_ineligible",
- "l2_read_bytes", "l2_write_bytes", "l2_size", "l2_asize",
- "l2_hdr_size",
+ "arc_meta_min", "hdr_size", "data_size", "metadata_size",
+ "other_size", "anon_size", "anon_evictable_data",
+ "anon_evictable_metadata", "mru_size", "mru_evictable_data",
+ "mru_evictable_metadata", "mru_ghost_size",
+ "mru_ghost_evictable_data", "mru_ghost_evictable_metadata",
+ "mfu_size", "mfu_evictable_data", "mfu_evictable_metadata",
+ "mfu_ghost_size", "mfu_ghost_evictable_data",
+ "mfu_ghost_evictable_metadata", "evict_l2_cached",
+ "evict_l2_eligible", "evict_l2_ineligible", "l2_read_bytes",
+ "l2_write_bytes", "l2_size", "l2_asize", "l2_hdr_size",
NULL
};
diff --git a/usr/src/lib/libipadm/common/libipadm.c b/usr/src/lib/libipadm/common/libipadm.c
index e897771556..068c8d6535 100644
--- a/usr/src/lib/libipadm/common/libipadm.c
+++ b/usr/src/lib/libipadm/common/libipadm.c
@@ -18,9 +18,11 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2014, Joyent, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <stdio.h>
@@ -815,14 +817,14 @@ i_ipadm_init_ifs(ipadm_handle_t iph, const char *ifs, nvlist_t **allifs)
status = ipadm_errno2status(err);
goto done;
}
- nvlsize = rvalp->ir_nvlsize;
- nvlbuf = (char *)rvalp + sizeof (ipmgmt_get_rval_t);
/*
- * nvlbuf contains a list of nvlists, each of which represents
- * configuration information for the given interface(s)
+ * Daemon reply pointed to by rvalp contains ipmgmt_get_rval_t structure
+ * followed by a list of packed nvlists, each of which represents
+ * configuration information for the given interface(s).
*/
- err = nvlist_unpack(nvlbuf, nvlsize, allifs, NV_ENCODE_NATIVE);
+ err = nvlist_unpack((char *)rvalp + sizeof (ipmgmt_get_rval_t),
+ rvalp->ir_nvlsize, allifs, NV_ENCODE_NATIVE);
if (err != 0)
status = ipadm_errno2status(err);
done:
diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c
index 01843c4b43..55a99b7944 100644
--- a/usr/src/uts/common/fs/zfs/arc.c
+++ b/usr/src/uts/common/fs/zfs/arc.c
@@ -301,9 +301,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;
@@ -372,7 +500,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 },
@@ -1503,6 +1647,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;
@@ -1514,7 +1661,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);
}
@@ -1527,6 +1676,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;
@@ -1538,10 +1690,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);
}
@@ -1747,12 +1902,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)) {
@@ -2745,6 +2899,20 @@ arc_reclaim_thread(void)
if (arc_eviction_list != NULL)
arc_do_user_evicts();
+ /*
+ * 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,
@@ -2882,15 +3050,14 @@ arc_get_data_buf(arc_buf_t *buf)
if (type == ARC_BUFC_METADATA) {
buf->b_data = zio_buf_alloc_canfail(size);
if (buf->b_data != NULL) {
- arc_space_consume(size, ARC_SPACE_DATA);
+ arc_space_consume(size, ARC_SPACE_META);
goto out;
}
} else {
ASSERT(type == ARC_BUFC_DATA);
buf->b_data = zio_data_buf_alloc_canfail(size);
if (buf->b_data != NULL) {
- ARCSTAT_INCR(arcstat_data_size, size);
- atomic_add_64(&arc_size, size);
+ arc_space_consume(size, ARC_SPACE_DATA);
goto out;
}
}
@@ -2925,12 +3092,11 @@ arc_get_data_buf(arc_buf_t *buf)
if ((buf->b_data = arc_evict(state, NULL, 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);
}
@@ -4138,6 +4304,48 @@ arc_tempreserve_space(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_init(void)
{
@@ -4284,6 +4492,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);
}
diff --git a/usr/src/uts/common/fs/zfs/sys/arc.h b/usr/src/uts/common/fs/zfs/sys/arc.h
index 4e9e8e202a..60112baaba 100644
--- a/usr/src/uts/common/fs/zfs/sys/arc.h
+++ b/usr/src/uts/common/fs/zfs/sys/arc.h
@@ -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,