4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 #include <sys/zfs_context.h>
24 #include <sys/dmu_objset.h>
27 * Calculate the index of the arc header for the state, disabled by default.
29 int zfs_dbuf_state_index
= 0;
32 * ==========================================================================
33 * Dbuf Hash Read Routines
34 * ==========================================================================
36 typedef struct dbuf_stats_t
{
39 dbuf_hash_table_t
*hash
;
43 static dbuf_stats_t dbuf_stats_hash_table
;
46 dbuf_stats_hash_table_headers(char *buf
, size_t size
)
48 (void) snprintf(buf
, size
,
49 "%-105s | %-119s | %s\n"
50 "%-16s %-8s %-8s %-8s %-8s %-10s %-8s %-8s %-5s %-5s %-7s %3s | "
51 "%-5s %-5s %-9s %-6s %-8s %-12s "
52 "%-6s %-6s %-6s %-6s %-6s %-8s %-8s %-8s %-6s | "
53 "%-6s %-6s %-8s %-8s %-6s %-6s %-6s %-8s %-8s\n",
54 "dbuf", "arcbuf", "dnode", "pool", "objset", "object", "level",
55 "blkid", "offset", "dbsize", "usize", "meta", "state", "dbholds",
56 "dbc", "list", "atype", "flags", "count", "asize", "access",
57 "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", "l2_asize",
58 "l2_comp", "aholds", "dtype", "btype", "data_bs", "meta_bs",
59 "bsize", "lvls", "dholds", "blocks", "dsize");
65 __dbuf_stats_hash_table_data(char *buf
, size_t size
, dmu_buf_impl_t
*db
)
67 arc_buf_info_t abi
= { 0 };
68 dmu_object_info_t doi
= { 0 };
69 dnode_t
*dn
= DB_DNODE(db
);
73 arc_buf_info(db
->db_buf
, &abi
, zfs_dbuf_state_index
);
75 __dmu_object_info_from_dnode(dn
, &doi
);
77 nwritten
= snprintf(buf
, size
,
78 "%-16s %-8llu %-8lld %-8lld %-8lld %-10llu %-8llu %-8llu "
79 "%-5d %-5d %-7lu %-3d | %-5d %-5d 0x%-7x %-6lu %-8llu %-12llu "
80 "%-6lu %-6lu %-6lu %-6lu %-6lu %-8llu %-8llu %-8d %-6lu | "
81 "%-6d %-6d %-8lu %-8lu %-6llu %-6lu %-6lu %-8llu %-8llu\n",
83 spa_name(dn
->dn_objset
->os_spa
),
84 (u_longlong_t
)dmu_objset_id(db
->db_objset
),
85 (longlong_t
)db
->db
.db_object
,
86 (longlong_t
)db
->db_level
,
87 (longlong_t
)db
->db_blkid
,
88 (u_longlong_t
)db
->db
.db_offset
,
89 (u_longlong_t
)db
->db
.db_size
,
90 (u_longlong_t
)dmu_buf_user_size(&db
->db
),
91 !!dbuf_is_metadata(db
),
93 (ulong_t
)zfs_refcount_count(&db
->db_holds
),
94 multilist_link_active(&db
->db_cache_link
),
97 abi
.abi_state_contents
,
99 (ulong_t
)abi
.abi_bufcnt
,
100 (u_longlong_t
)abi
.abi_size
,
101 (u_longlong_t
)abi
.abi_access
,
102 (ulong_t
)abi
.abi_mru_hits
,
103 (ulong_t
)abi
.abi_mru_ghost_hits
,
104 (ulong_t
)abi
.abi_mfu_hits
,
105 (ulong_t
)abi
.abi_mfu_ghost_hits
,
106 (ulong_t
)abi
.abi_l2arc_hits
,
107 (u_longlong_t
)abi
.abi_l2arc_dattr
,
108 (u_longlong_t
)abi
.abi_l2arc_asize
,
109 abi
.abi_l2arc_compress
,
110 (ulong_t
)abi
.abi_holds
,
111 /* dmu_object_info_t */
114 (ulong_t
)doi
.doi_data_block_size
,
115 (ulong_t
)doi
.doi_metadata_block_size
,
116 (u_longlong_t
)doi
.doi_bonus_size
,
117 (ulong_t
)doi
.doi_indirection
,
118 (ulong_t
)zfs_refcount_count(&dn
->dn_holds
),
119 (u_longlong_t
)doi
.doi_fill_count
,
120 (u_longlong_t
)doi
.doi_max_offset
);
122 if (nwritten
>= size
)
125 return (nwritten
+ 1);
129 dbuf_stats_hash_table_data(char *buf
, size_t size
, void *data
)
131 dbuf_stats_t
*dsh
= (dbuf_stats_t
*)data
;
132 dbuf_hash_table_t
*h
= dsh
->hash
;
134 int length
, error
= 0;
136 ASSERT3S(dsh
->idx
, >=, 0);
137 ASSERT3S(dsh
->idx
, <=, h
->hash_table_mask
);
141 mutex_enter(DBUF_HASH_MUTEX(h
, dsh
->idx
));
142 for (db
= h
->hash_table
[dsh
->idx
]; db
!= NULL
; db
= db
->db_hash_next
) {
144 * Returning ENOMEM will cause the data and header functions
145 * to be called with a larger scratch buffers.
148 error
= SET_ERROR(ENOMEM
);
152 mutex_enter(&db
->db_mtx
);
154 if (db
->db_state
!= DB_EVICTING
) {
155 length
= __dbuf_stats_hash_table_data(buf
, size
, db
);
160 mutex_exit(&db
->db_mtx
);
162 mutex_exit(DBUF_HASH_MUTEX(h
, dsh
->idx
));
168 dbuf_stats_hash_table_addr(kstat_t
*ksp
, loff_t n
)
170 dbuf_stats_t
*dsh
= ksp
->ks_private
;
172 ASSERT(MUTEX_HELD(&dsh
->lock
));
174 if (n
<= dsh
->hash
->hash_table_mask
) {
183 dbuf_stats_hash_table_init(dbuf_hash_table_t
*hash
)
185 dbuf_stats_t
*dsh
= &dbuf_stats_hash_table
;
188 mutex_init(&dsh
->lock
, NULL
, MUTEX_DEFAULT
, NULL
);
191 ksp
= kstat_create("zfs", 0, "dbufs", "misc",
192 KSTAT_TYPE_RAW
, 0, KSTAT_FLAG_VIRTUAL
);
196 ksp
->ks_lock
= &dsh
->lock
;
197 ksp
->ks_ndata
= UINT32_MAX
;
198 ksp
->ks_private
= dsh
;
199 kstat_set_raw_ops(ksp
, dbuf_stats_hash_table_headers
,
200 dbuf_stats_hash_table_data
, dbuf_stats_hash_table_addr
);
206 dbuf_stats_hash_table_destroy(void)
208 dbuf_stats_t
*dsh
= &dbuf_stats_hash_table
;
215 mutex_destroy(&dsh
->lock
);
219 dbuf_stats_init(dbuf_hash_table_t
*hash
)
221 dbuf_stats_hash_table_init(hash
);
225 dbuf_stats_destroy(void)
227 dbuf_stats_hash_table_destroy();
230 ZFS_MODULE_PARAM(zfs
, zfs_
, dbuf_state_index
, INT
, ZMOD_RW
,
231 "Calculate arc header index");