Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Aug 2018 01:10:18 +0000 (UTC)
From:      Matt Macy <mmacy@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r337670 - in head/sys/cddl: compat/opensolaris/sys contrib/opensolaris/uts/common contrib/opensolaris/uts/common/fs/zfs contrib/opensolaris/uts/common/fs/zfs/sys
Message-ID:  <201808120110.w7C1AIL1087851@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mmacy
Date: Sun Aug 12 01:10:18 2018
New Revision: 337670
URL: https://svnweb.freebsd.org/changeset/base/337670

Log:
  MFV/ZoL: add dbuf stats
  
  NB: disabled pending the addition of KSTAT_TYPE_RAW support to the
  SPL
  
  commit e0b0ca983d6897bcddf05af2c0e5d01ff66f90db
  Author: Brian Behlendorf <behlendorf1@llnl.gov>
  Date:   Wed Oct 2 17:11:19 2013 -0700
  
      Add visibility in to cached dbufs
  
      Currently there is no mechanism to inspect which dbufs are being
      cached by the system.  There are some coarse counters in arcstats
      by they only give a rough idea of what's being cached.  This patch
      aims to improve the current situation by adding a new dbufs kstat.
  
      When read this new kstat will walk all cached dbufs linked in to
      the dbuf_hash.  For each dbuf it will dump detailed information
      about the buffer.  It will also dump additional information about
      the referenced arc buffer and its related dnode.  This provides a
      more complete view in to exactly what is being cached.
  
      With this generic infrastructure in place utilities can be written
      to post-process the data to understand exactly how the caching is
      working.  For example, the data could be processed to show a list
      of all cached dnodes and how much space they're consuming.  Or a
      similar list could be generated based on dnode type.  Many other
      ways to interpret the data exist based on what kinds of questions
      you're trying to answer.
  
      Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
      Signed-off-by: Prakash Surya <surya1@llnl.gov>

Added:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf_stats.c
Modified:
  head/sys/cddl/compat/opensolaris/sys/kstat.h
  head/sys/cddl/contrib/opensolaris/uts/common/Makefile.files
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h

Modified: head/sys/cddl/compat/opensolaris/sys/kstat.h
==============================================================================
--- head/sys/cddl/compat/opensolaris/sys/kstat.h	Sun Aug 12 00:45:53 2018	(r337669)
+++ head/sys/cddl/compat/opensolaris/sys/kstat.h	Sun Aug 12 01:10:18 2018	(r337670)
@@ -31,7 +31,18 @@
 
 #include <sys/sysctl.h>
 
-#define	KSTAT_TYPE_NAMED	1
+#define	KSTAT_TYPE_RAW		0	/* can be anything */
+					/* ks_ndata >= 1 */
+#define	KSTAT_TYPE_NAMED	1	/* name/value pair */
+					/* ks_ndata >= 1 */
+#define	KSTAT_TYPE_INTR		2	/* interrupt statistics */
+					/* ks_ndata == 1 */
+#define	KSTAT_TYPE_IO		3	/* I/O statistics */
+					/* ks_ndata == 1 */
+#define	KSTAT_TYPE_TIMER	4	/* event timer */
+					/* ks_ndata >= 1 */
+
+#define	KSTAT_NUM_TYPES		5
 
 #define	KSTAT_FLAG_VIRTUAL	0x01
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/Makefile.files
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/Makefile.files	Sun Aug 12 00:45:53 2018	(r337669)
+++ head/sys/cddl/contrib/opensolaris/uts/common/Makefile.files	Sun Aug 12 01:10:18 2018	(r337670)
@@ -72,6 +72,7 @@ ZFS_COMMON_OBJS +=		\
 	bqueue.o		\
 	cityhash.o		\
 	dbuf.o			\
+	dbuf_stats.o		\
 	ddt.o			\
 	ddt_zap.o		\
 	dmu.o			\

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c	Sun Aug 12 00:45:53 2018	(r337669)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c	Sun Aug 12 01:10:18 2018	(r337670)
@@ -523,6 +523,10 @@ typedef struct arc_state {
 	 * non-evictable, ARC_BUFC_DATA, and ARC_BUFC_METADATA.
 	 */
 	refcount_t arcs_size;
+	/*
+	 * supports the "dbufs" kstat
+	 */
+	arc_state_type_t arcs_state;
 } arc_state_t;
 
 /*
@@ -1111,6 +1115,11 @@ typedef struct l1arc_buf_hdr {
 
 	/* updated atomically */
 	clock_t			b_arc_access;
+	uint32_t		b_mru_hits;
+	uint32_t		b_mru_ghost_hits;
+	uint32_t		b_mfu_hits;
+	uint32_t		b_mfu_ghost_hits;
+	uint32_t		b_l2_hits;
 
 	/* self protecting */
 	refcount_t		b_refcnt;
@@ -1125,6 +1134,7 @@ typedef struct l2arc_buf_hdr {
 	/* protected by arc_buf_hdr mutex */
 	l2arc_dev_t		*b_dev;		/* L2ARC device */
 	uint64_t		b_daddr;	/* disk address, offset byte */
+	uint32_t		b_hits;
 
 	list_node_t		b_l2node;
 } l2arc_buf_hdr_t;
@@ -2552,6 +2562,55 @@ remove_reference(arc_buf_hdr_t *hdr, kmutex_t *hash_lo
 }
 
 /*
+ * Returns detailed information about a specific arc buffer.  When the
+ * state_index argument is set the function will calculate the arc header
+ * list position for its arc state.  Since this requires a linear traversal
+ * callers are strongly encourage not to do this.  However, it can be helpful
+ * for targeted analysis so the functionality is provided.
+ */
+void
+arc_buf_info(arc_buf_t *ab, arc_buf_info_t *abi, int state_index)
+{
+	arc_buf_hdr_t *hdr = ab->b_hdr;
+	l1arc_buf_hdr_t *l1hdr = NULL;
+	l2arc_buf_hdr_t *l2hdr = NULL;
+	arc_state_t *state = NULL;
+
+	memset(abi, 0, sizeof (arc_buf_info_t));
+
+	if (hdr == NULL)
+		return;
+
+	abi->abi_flags = hdr->b_flags;
+
+	if (HDR_HAS_L1HDR(hdr)) {
+		l1hdr = &hdr->b_l1hdr;
+		state = l1hdr->b_state;
+	}
+	if (HDR_HAS_L2HDR(hdr))
+		l2hdr = &hdr->b_l2hdr;
+
+	if (l1hdr) {
+		abi->abi_bufcnt = l1hdr->b_bufcnt;
+		abi->abi_access = l1hdr->b_arc_access;
+		abi->abi_mru_hits = l1hdr->b_mru_hits;
+		abi->abi_mru_ghost_hits = l1hdr->b_mru_ghost_hits;
+		abi->abi_mfu_hits = l1hdr->b_mfu_hits;
+		abi->abi_mfu_ghost_hits = l1hdr->b_mfu_ghost_hits;
+		abi->abi_holds = refcount_count(&l1hdr->b_refcnt);
+	}
+
+	if (l2hdr) {
+		abi->abi_l2arc_dattr = l2hdr->b_daddr;
+		abi->abi_l2arc_hits = l2hdr->b_hits;
+	}
+
+	abi->abi_state_type = state ? state->arcs_state : ARC_STATE_ANON;
+	abi->abi_state_contents = arc_buf_type(hdr);
+	abi->abi_size = arc_hdr_size(hdr);
+}
+
+/*
  * Move the supplied buffer to the indicated state. The hash lock
  * for the buffer must be held by the caller.
  */
@@ -5258,6 +5317,7 @@ arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
 			DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
 			arc_change_state(arc_mfu, hdr, hash_lock);
 		}
+		atomic_inc_32(&hdr->b_l1hdr.b_mru_hits);
 		ARCSTAT_BUMP(arcstat_mru_hits);
 	} else if (hdr->b_l1hdr.b_state == arc_mru_ghost) {
 		arc_state_t	*new_state;
@@ -5283,6 +5343,7 @@ arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
 		hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
 		arc_change_state(new_state, hdr, hash_lock);
 
+		atomic_inc_32(&hdr->b_l1hdr.b_mru_ghost_hits);
 		ARCSTAT_BUMP(arcstat_mru_ghost_hits);
 	} else if (hdr->b_l1hdr.b_state == arc_mfu) {
 		/*
@@ -5295,6 +5356,7 @@ arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
 		 * the head of the list now.
 		 */
 
+		atomic_inc_32(&hdr->b_l1hdr.b_mfu_hits);
 		ARCSTAT_BUMP(arcstat_mfu_hits);
 		hdr->b_l1hdr.b_arc_access = ddi_get_lbolt();
 	} else if (hdr->b_l1hdr.b_state == arc_mfu_ghost) {
@@ -5317,6 +5379,7 @@ arc_access(arc_buf_hdr_t *hdr, kmutex_t *hash_lock)
 		DTRACE_PROBE1(new_state__mfu, arc_buf_hdr_t *, hdr);
 		arc_change_state(new_state, hdr, hash_lock);
 
+		atomic_inc_32(&hdr->b_l1hdr.b_mfu_ghost_hits);
 		ARCSTAT_BUMP(arcstat_mfu_ghost_hits);
 	} else if (hdr->b_l1hdr.b_state == arc_l2c_only) {
 		/*
@@ -5913,6 +5976,7 @@ top:
 
 				DTRACE_PROBE1(l2arc__hit, arc_buf_hdr_t *, hdr);
 				ARCSTAT_BUMP(arcstat_l2_hits);
+				atomic_inc_32(&hdr->b_l2hdr.b_hits);
 
 				cb = kmem_zalloc(sizeof (l2arc_read_callback_t),
 				    KM_SLEEP);

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c	Sun Aug 12 00:45:53 2018	(r337669)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c	Sun Aug 12 01:10:18 2018	(r337670)
@@ -649,6 +649,7 @@ retry:
 	for (i = 0; i < DBUF_MUTEXES; i++)
 		mutex_init(&h->hash_mutexes[i], NULL, MUTEX_DEFAULT, NULL);
 
+	dbuf_stats_init(h);
 	/*
 	 * Setup the parameters for the dbuf caches. We set the sizes of the
 	 * dbuf cache and the metadata cache to 1/32nd and 1/16th (default)
@@ -692,6 +693,8 @@ dbuf_fini(void)
 {
 	dbuf_hash_table_t *h = &dbuf_hash_table;
 	int i;
+
+	dbuf_stats_destroy();
 
 	for (i = 0; i < DBUF_MUTEXES; i++)
 		mutex_destroy(&h->hash_mutexes[i]);

Added: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf_stats.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf_stats.c	Sun Aug 12 01:10:18 2018	(r337670)
@@ -0,0 +1,242 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+#include <sys/zfs_context.h>
+#include <sys/dbuf.h>
+#include <sys/dmu_objset.h>
+
+/*
+ * Calculate the index of the arc header for the state, disabled by default.
+ */
+int zfs_dbuf_state_index = 0;
+
+/*
+ * ==========================================================================
+ * Dbuf Hash Read Routines
+ * ==========================================================================
+ */
+typedef struct dbuf_stats_t {
+	kmutex_t		lock;
+	kstat_t			*kstat;
+	dbuf_hash_table_t	*hash;
+	int			idx;
+} dbuf_stats_t;
+
+static dbuf_stats_t dbuf_stats_hash_table;
+
+static int
+dbuf_stats_hash_table_headers(char *buf, size_t size)
+{
+	size = snprintf(buf, size - 1,
+	    "%-88s | %-124s | %s\n"
+	    "%-16s %-8s %-8s %-8s %-8s %-8s %-8s %-5s %-5s %5s | "
+	    "%-5s %-5s %-6s %-8s %-6s %-8s %-12s "
+	    "%-6s %-6s %-6s %-6s %-6s %-8s %-8s %-8s %-5s | "
+	    "%-6s %-6s %-8s %-8s %-6s %-6s %-5s %-8s %-8s\n",
+	    "dbuf", "arcbuf", "dnode", "pool", "objset", "object", "level",
+	    "blkid", "offset", "dbsize", "meta", "state", "dbholds", "list",
+	    "atype", "index", "flags", "count", "asize", "access", "mru", "gmru",
+	    "mfu", "gmfu", "l2", "l2_dattr", "l2_asize", "l2_comp", "aholds",
+	    "dtype", "btype", "data_bs", "meta_bs", "bsize",
+	    "lvls", "dholds", "blocks", "dsize");
+        buf[size] = '\0';
+
+	return (0);
+}
+
+int
+__dbuf_stats_hash_table_data(char *buf, size_t size, dmu_buf_impl_t *db)
+{
+	arc_buf_info_t abi = { 0 };
+	dmu_object_info_t doi = { 0 };
+	dnode_t *dn = DB_DNODE(db);
+
+	if (db->db_buf)
+		arc_buf_info(db->db_buf, &abi, zfs_dbuf_state_index);
+
+	if (dn)
+		__dmu_object_info_from_dnode(dn, &doi);
+
+	size = snprintf(buf, size - 1,
+	    "%-16s %-8llu %-8lld %-8lld %-8lld %-8llu %-8llu %-5d %-5d %-5lu | "
+	    "%-5d %-5d %-6lld 0x%-6x %-6lu %-8llu %-12llu "
+	    "%-6lu %-6lu %-6lu %-6lu %-6lu %-8llu %-8llu %-8d %-5lu | "
+	    "%-6d %-6d %-8lu %-8lu %-6llu %-6lu %-5lu %-8llu %-8llu\n",
+	    /* dmu_buf_impl_t */
+	    spa_name(dn->dn_objset->os_spa),
+	    (u_longlong_t)dmu_objset_id(db->db_objset),
+	    (longlong_t)db->db.db_object,
+	    (longlong_t)db->db_level,
+	    (longlong_t)db->db_blkid,
+	    (u_longlong_t)db->db.db_offset,
+	    (u_longlong_t)db->db.db_size,
+	    !!dbuf_is_metadata(db),
+	    db->db_state,
+	    (ulong_t)refcount_count(&db->db_holds),
+	    /* arc_buf_info_t */
+	    abi.abi_state_type,
+	    abi.abi_state_contents,
+	    (longlong_t)abi.abi_state_index,
+	    abi.abi_flags,
+	    (ulong_t)abi.abi_bufcnt,
+	    (u_longlong_t)abi.abi_size,
+	    (u_longlong_t)abi.abi_access,
+	    (ulong_t)abi.abi_mru_hits,
+	    (ulong_t)abi.abi_mru_ghost_hits,
+	    (ulong_t)abi.abi_mfu_hits,
+	    (ulong_t)abi.abi_mfu_ghost_hits,
+	    (ulong_t)abi.abi_l2arc_hits,
+	    (u_longlong_t)abi.abi_l2arc_dattr,
+	    (u_longlong_t)abi.abi_l2arc_asize,
+	    abi.abi_l2arc_compress,
+	    (ulong_t)abi.abi_holds,
+	    /* dmu_object_info_t */
+	    doi.doi_type,
+	    doi.doi_bonus_type,
+	    (ulong_t)doi.doi_data_block_size,
+	    (ulong_t)doi.doi_metadata_block_size,
+	    (u_longlong_t)doi.doi_bonus_size,
+	    (ulong_t)doi.doi_indirection,
+	    (ulong_t)refcount_count(&dn->dn_holds),
+	    (u_longlong_t)doi.doi_fill_count,
+	    (u_longlong_t)doi.doi_max_offset);
+        buf[size] = '\0';
+
+	return (size);
+}
+
+static int
+dbuf_stats_hash_table_data(char *buf, size_t size, void *data)
+{
+	dbuf_stats_t *dsh = (dbuf_stats_t *)data;
+	dbuf_hash_table_t *h = dsh->hash;
+	dmu_buf_impl_t *db;
+	int length, error = 0;
+
+	ASSERT3S(dsh->idx, >=, 0);
+	ASSERT3S(dsh->idx, <=, h->hash_table_mask);
+	memset(buf, 0, size);
+
+	mutex_enter(DBUF_HASH_MUTEX(h, dsh->idx));
+	for (db = h->hash_table[dsh->idx]; db != NULL; db = db->db_hash_next) {
+		/*
+		 * Returning ENOMEM will cause the data and header functions
+		 * to be called with a larger scratch buffers.
+		 */
+		if (size < 512) {
+			error = ENOMEM;
+			break;
+		}
+
+		mutex_enter(&db->db_mtx);
+		mutex_exit(DBUF_HASH_MUTEX(h, dsh->idx));
+
+		length = __dbuf_stats_hash_table_data(buf, size, db);
+		buf += length;
+		size -= length;
+
+		mutex_exit(&db->db_mtx);
+		mutex_enter(DBUF_HASH_MUTEX(h, dsh->idx));
+	}
+	mutex_exit(DBUF_HASH_MUTEX(h, dsh->idx));
+
+	return (error);
+}
+
+static void *
+dbuf_stats_hash_table_addr(kstat_t *ksp, off_t n)
+{
+	dbuf_stats_t *dsh = ksp->ks_private;
+
+        ASSERT(MUTEX_HELD(&dsh->lock));
+
+	if (n <= dsh->hash->hash_table_mask) {
+		dsh->idx = n;
+		return (dsh);
+	}
+
+	return (NULL);
+}
+
+#ifndef __FreeBSD__
+/*
+ * XXX The FreeBSD SPL is missing support for KSTAT_TYPE_RAW
+ * we can enable this as soon as that's implemented. See the
+ * lindebugfs module for similar callback semantics.
+ */
+static void
+dbuf_stats_hash_table_init(dbuf_hash_table_t *hash)
+{
+	dbuf_stats_t *dsh = &dbuf_stats_hash_table;
+	kstat_t *ksp;
+
+	mutex_init(&dsh->lock, NULL, MUTEX_DEFAULT, NULL);
+	dsh->hash = hash;
+
+	ksp = kstat_create("zfs", 0, "dbufs", "misc",
+	    KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL);
+	dsh->kstat = ksp;
+
+	if (ksp) {
+		ksp->ks_lock = &dsh->lock;
+		ksp->ks_ndata = UINT32_MAX;
+		ksp->ks_private = dsh;
+		kstat_set_raw_ops(ksp, dbuf_stats_hash_table_headers,
+		    dbuf_stats_hash_table_data, dbuf_stats_hash_table_addr);
+		kstat_install(ksp);
+	}
+}
+
+static void
+dbuf_stats_hash_table_destroy(void)
+{
+	dbuf_stats_t *dsh = &dbuf_stats_hash_table;
+	kstat_t *ksp;
+
+	ksp = dsh->kstat;
+	if (ksp)
+		kstat_delete(ksp);
+
+	mutex_destroy(&dsh->lock);
+}
+#else
+static void
+dbuf_stats_hash_table_init(dbuf_hash_table_t *hash)
+{
+}
+
+static void
+dbuf_stats_hash_table_destroy(void)
+{
+}
+#endif
+
+void
+dbuf_stats_init(dbuf_hash_table_t *hash)
+{
+	dbuf_stats_hash_table_init(hash);
+}
+
+void
+dbuf_stats_destroy(void)
+{
+	dbuf_stats_hash_table_destroy();
+}

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c	Sun Aug 12 00:45:53 2018	(r337669)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c	Sun Aug 12 01:10:18 2018	(r337670)
@@ -2509,15 +2509,10 @@ dmu_object_wait_synced(objset_t *os, uint64_t object)
 }
 
 void
-dmu_object_info_from_dnode(dnode_t *dn, dmu_object_info_t *doi)
+__dmu_object_info_from_dnode(dnode_t *dn, dmu_object_info_t *doi)
 {
-	dnode_phys_t *dnp;
+	dnode_phys_t *dnp = dn->dn_phys;
 
-	rw_enter(&dn->dn_struct_rwlock, RW_READER);
-	mutex_enter(&dn->dn_mtx);
-
-	dnp = dn->dn_phys;
-
 	doi->doi_data_block_size = dn->dn_datablksz;
 	doi->doi_metadata_block_size = dn->dn_indblkshift ?
 	    1ULL << dn->dn_indblkshift : 0;
@@ -2534,6 +2529,15 @@ dmu_object_info_from_dnode(dnode_t *dn, dmu_object_inf
 	doi->doi_fill_count = 0;
 	for (int i = 0; i < dnp->dn_nblkptr; i++)
 		doi->doi_fill_count += BP_GET_FILL(&dnp->dn_blkptr[i]);
+}
+
+void
+dmu_object_info_from_dnode(dnode_t *dn, dmu_object_info_t *doi)
+{
+	rw_enter(&dn->dn_struct_rwlock, RW_READER);
+	mutex_enter(&dn->dn_mtx);
+
+	__dmu_object_info_from_dnode(dn, doi);
 
 	mutex_exit(&dn->dn_mtx);
 	rw_exit(&dn->dn_struct_rwlock);

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h	Sun Aug 12 00:45:53 2018	(r337669)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h	Sun Aug 12 01:10:18 2018	(r337670)
@@ -185,6 +185,36 @@ typedef enum arc_space_type {
 	ARC_SPACE_NUMTYPES
 } arc_space_type_t;
 
+typedef enum arc_state_type {
+	ARC_STATE_ANON,
+	ARC_STATE_MRU,
+	ARC_STATE_MRU_GHOST,
+	ARC_STATE_MFU,
+	ARC_STATE_MFU_GHOST,
+	ARC_STATE_L2C_ONLY,
+	ARC_STATE_NUMTYPES
+} arc_state_type_t;
+
+typedef struct arc_buf_info {
+	arc_state_type_t	abi_state_type;
+	arc_buf_contents_t	abi_state_contents;
+	uint64_t		abi_state_index;
+	uint32_t		abi_flags;
+	uint32_t		abi_bufcnt;
+	uint64_t		abi_size;
+	uint64_t		abi_spa;
+	uint64_t		abi_access;
+	uint32_t		abi_mru_hits;
+	uint32_t		abi_mru_ghost_hits;
+	uint32_t		abi_mfu_hits;
+	uint32_t		abi_mfu_ghost_hits;
+	uint32_t		abi_l2arc_hits;
+	uint32_t		abi_holds;
+	uint64_t		abi_l2arc_dattr;
+	uint64_t		abi_l2arc_asize;
+	enum zio_compress	abi_l2arc_compress;
+} arc_buf_info_t;
+
 void arc_space_consume(uint64_t space, arc_space_type_t type);
 void arc_space_return(uint64_t space, arc_space_type_t type);
 boolean_t arc_is_metadata(arc_buf_t *buf);
@@ -200,6 +230,7 @@ arc_buf_t *arc_loan_compressed_buf(spa_t *spa, uint64_
 void arc_return_buf(arc_buf_t *buf, void *tag);
 void arc_loan_inuse_buf(arc_buf_t *buf, void *tag);
 void arc_buf_destroy(arc_buf_t *buf, void *tag);
+void arc_buf_info(arc_buf_t *buf, arc_buf_info_t *abi, int state_index);
 int arc_buf_size(arc_buf_t *buf);
 int arc_buf_lsize(arc_buf_t *buf);
 void arc_buf_access(arc_buf_t *buf);

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h	Sun Aug 12 00:45:53 2018	(r337669)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h	Sun Aug 12 01:10:18 2018	(r337670)
@@ -333,6 +333,9 @@ void dbuf_free_range(struct dnode *dn, uint64_t start,
 
 void dbuf_new_size(dmu_buf_impl_t *db, int size, dmu_tx_t *tx);
 
+void dbuf_stats_init(dbuf_hash_table_t *hash);
+void dbuf_stats_destroy(void);
+
 #define	DB_DNODE(_db)		((_db)->db_dnode_handle->dnh_dnode)
 #define	DB_DNODE_LOCK(_db)	((_db)->db_dnode_handle->dnh_zrlock)
 #define	DB_DNODE_ENTER(_db)	(zrl_add(&DB_DNODE_LOCK(_db)))

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h	Sun Aug 12 00:45:53 2018	(r337669)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h	Sun Aug 12 01:10:18 2018	(r337670)
@@ -855,6 +855,7 @@ extern const dmu_object_byteswap_info_t dmu_ot_byteswa
  * If doi is NULL, just indicates whether the object exists.
  */
 int dmu_object_info(objset_t *os, uint64_t object, dmu_object_info_t *doi);
+void __dmu_object_info_from_dnode(struct dnode *dn, dmu_object_info_t *doi);
 /* Like dmu_object_info, but faster if you have a held dnode in hand. */
 void dmu_object_info_from_dnode(dnode_t *dn, dmu_object_info_t *doi);
 /* Like dmu_object_info, but faster if you have a held dbuf in hand. */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808120110.w7C1AIL1087851>