1*61145dc2SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2eda14cbcSMatt Macy /*
3eda14cbcSMatt Macy * CDDL HEADER START
4eda14cbcSMatt Macy *
5eda14cbcSMatt Macy * The contents of this file are subject to the terms of the
6eda14cbcSMatt Macy * Common Development and Distribution License (the "License").
7eda14cbcSMatt Macy * You may not use this file except in compliance with the License.
8eda14cbcSMatt Macy *
9eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0.
11eda14cbcSMatt Macy * See the License for the specific language governing permissions
12eda14cbcSMatt Macy * and limitations under the License.
13eda14cbcSMatt Macy *
14eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each
15eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the
17eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying
18eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner]
19eda14cbcSMatt Macy *
20eda14cbcSMatt Macy * CDDL HEADER END
21eda14cbcSMatt Macy */
22eda14cbcSMatt Macy
23eda14cbcSMatt Macy #include <sys/zfs_context.h>
24eda14cbcSMatt Macy #include <sys/dbuf.h>
25eda14cbcSMatt Macy #include <sys/dmu_objset.h>
26eda14cbcSMatt Macy
27eda14cbcSMatt Macy /*
28eda14cbcSMatt Macy * Calculate the index of the arc header for the state, disabled by default.
29eda14cbcSMatt Macy */
30eda14cbcSMatt Macy int zfs_dbuf_state_index = 0;
31eda14cbcSMatt Macy
32eda14cbcSMatt Macy /*
33eda14cbcSMatt Macy * ==========================================================================
34eda14cbcSMatt Macy * Dbuf Hash Read Routines
35eda14cbcSMatt Macy * ==========================================================================
36eda14cbcSMatt Macy */
37eda14cbcSMatt Macy typedef struct dbuf_stats_t {
38eda14cbcSMatt Macy kmutex_t lock;
39eda14cbcSMatt Macy kstat_t *kstat;
40eda14cbcSMatt Macy dbuf_hash_table_t *hash;
41eda14cbcSMatt Macy int idx;
42eda14cbcSMatt Macy } dbuf_stats_t;
43eda14cbcSMatt Macy
44eda14cbcSMatt Macy static dbuf_stats_t dbuf_stats_hash_table;
45eda14cbcSMatt Macy
46eda14cbcSMatt Macy static int
dbuf_stats_hash_table_headers(char * buf,size_t size)47eda14cbcSMatt Macy dbuf_stats_hash_table_headers(char *buf, size_t size)
48eda14cbcSMatt Macy {
49eda14cbcSMatt Macy (void) snprintf(buf, size,
50a2b560ccSMartin Matuska "%-105s | %-119s | %s\n"
51a2b560ccSMartin Matuska "%-16s %-8s %-8s %-8s %-8s %-10s %-8s %-8s %-5s %-5s %-7s %3s | "
52eda14cbcSMatt Macy "%-5s %-5s %-9s %-6s %-8s %-12s "
53eda14cbcSMatt Macy "%-6s %-6s %-6s %-6s %-6s %-8s %-8s %-8s %-6s | "
54eda14cbcSMatt Macy "%-6s %-6s %-8s %-8s %-6s %-6s %-6s %-8s %-8s\n",
55eda14cbcSMatt Macy "dbuf", "arcbuf", "dnode", "pool", "objset", "object", "level",
56a2b560ccSMartin Matuska "blkid", "offset", "dbsize", "usize", "meta", "state", "dbholds",
57a2b560ccSMartin Matuska "dbc", "list", "atype", "flags", "count", "asize", "access",
58eda14cbcSMatt Macy "mru", "gmru", "mfu", "gmfu", "l2", "l2_dattr", "l2_asize",
59eda14cbcSMatt Macy "l2_comp", "aholds", "dtype", "btype", "data_bs", "meta_bs",
60eda14cbcSMatt Macy "bsize", "lvls", "dholds", "blocks", "dsize");
61eda14cbcSMatt Macy
62eda14cbcSMatt Macy return (0);
63eda14cbcSMatt Macy }
64eda14cbcSMatt Macy
65eda14cbcSMatt Macy static int
__dbuf_stats_hash_table_data(char * buf,size_t size,dmu_buf_impl_t * db)66eda14cbcSMatt Macy __dbuf_stats_hash_table_data(char *buf, size_t size, dmu_buf_impl_t *db)
67eda14cbcSMatt Macy {
68eda14cbcSMatt Macy arc_buf_info_t abi = { 0 };
69eda14cbcSMatt Macy dmu_object_info_t doi = { 0 };
70eda14cbcSMatt Macy dnode_t *dn = DB_DNODE(db);
71eda14cbcSMatt Macy size_t nwritten;
72eda14cbcSMatt Macy
73eda14cbcSMatt Macy if (db->db_buf)
74eda14cbcSMatt Macy arc_buf_info(db->db_buf, &abi, zfs_dbuf_state_index);
75eda14cbcSMatt Macy
76eda14cbcSMatt Macy __dmu_object_info_from_dnode(dn, &doi);
77eda14cbcSMatt Macy
78eda14cbcSMatt Macy nwritten = snprintf(buf, size,
79a2b560ccSMartin Matuska "%-16s %-8llu %-8lld %-8lld %-8lld %-10llu %-8llu %-8llu "
80a2b560ccSMartin Matuska "%-5d %-5d %-7lu %-3d | %-5d %-5d 0x%-7x %-6lu %-8llu %-12llu "
81eda14cbcSMatt Macy "%-6lu %-6lu %-6lu %-6lu %-6lu %-8llu %-8llu %-8d %-6lu | "
82eda14cbcSMatt Macy "%-6d %-6d %-8lu %-8lu %-6llu %-6lu %-6lu %-8llu %-8llu\n",
83eda14cbcSMatt Macy /* dmu_buf_impl_t */
84eda14cbcSMatt Macy spa_name(dn->dn_objset->os_spa),
85eda14cbcSMatt Macy (u_longlong_t)dmu_objset_id(db->db_objset),
86eda14cbcSMatt Macy (longlong_t)db->db.db_object,
87eda14cbcSMatt Macy (longlong_t)db->db_level,
88eda14cbcSMatt Macy (longlong_t)db->db_blkid,
89eda14cbcSMatt Macy (u_longlong_t)db->db.db_offset,
90eda14cbcSMatt Macy (u_longlong_t)db->db.db_size,
91a2b560ccSMartin Matuska (u_longlong_t)dmu_buf_user_size(&db->db),
92eda14cbcSMatt Macy !!dbuf_is_metadata(db),
93eda14cbcSMatt Macy db->db_state,
94eda14cbcSMatt Macy (ulong_t)zfs_refcount_count(&db->db_holds),
95eda14cbcSMatt Macy multilist_link_active(&db->db_cache_link),
96eda14cbcSMatt Macy /* arc_buf_info_t */
97eda14cbcSMatt Macy abi.abi_state_type,
98eda14cbcSMatt Macy abi.abi_state_contents,
99eda14cbcSMatt Macy abi.abi_flags,
100eda14cbcSMatt Macy (ulong_t)abi.abi_bufcnt,
101eda14cbcSMatt Macy (u_longlong_t)abi.abi_size,
102eda14cbcSMatt Macy (u_longlong_t)abi.abi_access,
103eda14cbcSMatt Macy (ulong_t)abi.abi_mru_hits,
104eda14cbcSMatt Macy (ulong_t)abi.abi_mru_ghost_hits,
105eda14cbcSMatt Macy (ulong_t)abi.abi_mfu_hits,
106eda14cbcSMatt Macy (ulong_t)abi.abi_mfu_ghost_hits,
107eda14cbcSMatt Macy (ulong_t)abi.abi_l2arc_hits,
108eda14cbcSMatt Macy (u_longlong_t)abi.abi_l2arc_dattr,
109eda14cbcSMatt Macy (u_longlong_t)abi.abi_l2arc_asize,
110eda14cbcSMatt Macy abi.abi_l2arc_compress,
111eda14cbcSMatt Macy (ulong_t)abi.abi_holds,
112eda14cbcSMatt Macy /* dmu_object_info_t */
113eda14cbcSMatt Macy doi.doi_type,
114eda14cbcSMatt Macy doi.doi_bonus_type,
115eda14cbcSMatt Macy (ulong_t)doi.doi_data_block_size,
116eda14cbcSMatt Macy (ulong_t)doi.doi_metadata_block_size,
117eda14cbcSMatt Macy (u_longlong_t)doi.doi_bonus_size,
118eda14cbcSMatt Macy (ulong_t)doi.doi_indirection,
119eda14cbcSMatt Macy (ulong_t)zfs_refcount_count(&dn->dn_holds),
120eda14cbcSMatt Macy (u_longlong_t)doi.doi_fill_count,
121eda14cbcSMatt Macy (u_longlong_t)doi.doi_max_offset);
122eda14cbcSMatt Macy
123eda14cbcSMatt Macy if (nwritten >= size)
124eda14cbcSMatt Macy return (size);
125eda14cbcSMatt Macy
126eda14cbcSMatt Macy return (nwritten + 1);
127eda14cbcSMatt Macy }
128eda14cbcSMatt Macy
129eda14cbcSMatt Macy static int
dbuf_stats_hash_table_data(char * buf,size_t size,void * data)130eda14cbcSMatt Macy dbuf_stats_hash_table_data(char *buf, size_t size, void *data)
131eda14cbcSMatt Macy {
132eda14cbcSMatt Macy dbuf_stats_t *dsh = (dbuf_stats_t *)data;
133eda14cbcSMatt Macy dbuf_hash_table_t *h = dsh->hash;
134eda14cbcSMatt Macy dmu_buf_impl_t *db;
135eda14cbcSMatt Macy int length, error = 0;
136eda14cbcSMatt Macy
137eda14cbcSMatt Macy ASSERT3S(dsh->idx, >=, 0);
138eda14cbcSMatt Macy ASSERT3S(dsh->idx, <=, h->hash_table_mask);
139c40487d4SMatt Macy if (size)
140c40487d4SMatt Macy buf[0] = 0;
141eda14cbcSMatt Macy
142be181ee2SMartin Matuska mutex_enter(DBUF_HASH_MUTEX(h, dsh->idx));
143eda14cbcSMatt Macy for (db = h->hash_table[dsh->idx]; db != NULL; db = db->db_hash_next) {
144eda14cbcSMatt Macy /*
145eda14cbcSMatt Macy * Returning ENOMEM will cause the data and header functions
146eda14cbcSMatt Macy * to be called with a larger scratch buffers.
147eda14cbcSMatt Macy */
148eda14cbcSMatt Macy if (size < 512) {
149eda14cbcSMatt Macy error = SET_ERROR(ENOMEM);
150eda14cbcSMatt Macy break;
151eda14cbcSMatt Macy }
152eda14cbcSMatt Macy
153eda14cbcSMatt Macy mutex_enter(&db->db_mtx);
154eda14cbcSMatt Macy
155eda14cbcSMatt Macy if (db->db_state != DB_EVICTING) {
156eda14cbcSMatt Macy length = __dbuf_stats_hash_table_data(buf, size, db);
157eda14cbcSMatt Macy buf += length;
158eda14cbcSMatt Macy size -= length;
159eda14cbcSMatt Macy }
160eda14cbcSMatt Macy
161eda14cbcSMatt Macy mutex_exit(&db->db_mtx);
162eda14cbcSMatt Macy }
163be181ee2SMartin Matuska mutex_exit(DBUF_HASH_MUTEX(h, dsh->idx));
164eda14cbcSMatt Macy
165eda14cbcSMatt Macy return (error);
166eda14cbcSMatt Macy }
167eda14cbcSMatt Macy
168eda14cbcSMatt Macy static void *
dbuf_stats_hash_table_addr(kstat_t * ksp,loff_t n)169eda14cbcSMatt Macy dbuf_stats_hash_table_addr(kstat_t *ksp, loff_t n)
170eda14cbcSMatt Macy {
171eda14cbcSMatt Macy dbuf_stats_t *dsh = ksp->ks_private;
172eda14cbcSMatt Macy
173eda14cbcSMatt Macy ASSERT(MUTEX_HELD(&dsh->lock));
174eda14cbcSMatt Macy
175eda14cbcSMatt Macy if (n <= dsh->hash->hash_table_mask) {
176eda14cbcSMatt Macy dsh->idx = n;
177eda14cbcSMatt Macy return (dsh);
178eda14cbcSMatt Macy }
179eda14cbcSMatt Macy
180eda14cbcSMatt Macy return (NULL);
181eda14cbcSMatt Macy }
182eda14cbcSMatt Macy
183eda14cbcSMatt Macy static void
dbuf_stats_hash_table_init(dbuf_hash_table_t * hash)184eda14cbcSMatt Macy dbuf_stats_hash_table_init(dbuf_hash_table_t *hash)
185eda14cbcSMatt Macy {
186eda14cbcSMatt Macy dbuf_stats_t *dsh = &dbuf_stats_hash_table;
187eda14cbcSMatt Macy kstat_t *ksp;
188eda14cbcSMatt Macy
189eda14cbcSMatt Macy mutex_init(&dsh->lock, NULL, MUTEX_DEFAULT, NULL);
190eda14cbcSMatt Macy dsh->hash = hash;
191eda14cbcSMatt Macy
192eda14cbcSMatt Macy ksp = kstat_create("zfs", 0, "dbufs", "misc",
193eda14cbcSMatt Macy KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL);
194eda14cbcSMatt Macy dsh->kstat = ksp;
195eda14cbcSMatt Macy
196eda14cbcSMatt Macy if (ksp) {
197eda14cbcSMatt Macy ksp->ks_lock = &dsh->lock;
198eda14cbcSMatt Macy ksp->ks_ndata = UINT32_MAX;
199eda14cbcSMatt Macy ksp->ks_private = dsh;
200eda14cbcSMatt Macy kstat_set_raw_ops(ksp, dbuf_stats_hash_table_headers,
201eda14cbcSMatt Macy dbuf_stats_hash_table_data, dbuf_stats_hash_table_addr);
202eda14cbcSMatt Macy kstat_install(ksp);
203eda14cbcSMatt Macy }
204eda14cbcSMatt Macy }
205eda14cbcSMatt Macy
206eda14cbcSMatt Macy static void
dbuf_stats_hash_table_destroy(void)207eda14cbcSMatt Macy dbuf_stats_hash_table_destroy(void)
208eda14cbcSMatt Macy {
209eda14cbcSMatt Macy dbuf_stats_t *dsh = &dbuf_stats_hash_table;
210eda14cbcSMatt Macy kstat_t *ksp;
211eda14cbcSMatt Macy
212eda14cbcSMatt Macy ksp = dsh->kstat;
213eda14cbcSMatt Macy if (ksp)
214eda14cbcSMatt Macy kstat_delete(ksp);
215eda14cbcSMatt Macy
216eda14cbcSMatt Macy mutex_destroy(&dsh->lock);
217eda14cbcSMatt Macy }
218eda14cbcSMatt Macy
219eda14cbcSMatt Macy void
dbuf_stats_init(dbuf_hash_table_t * hash)220eda14cbcSMatt Macy dbuf_stats_init(dbuf_hash_table_t *hash)
221eda14cbcSMatt Macy {
222eda14cbcSMatt Macy dbuf_stats_hash_table_init(hash);
223eda14cbcSMatt Macy }
224eda14cbcSMatt Macy
225eda14cbcSMatt Macy void
dbuf_stats_destroy(void)226eda14cbcSMatt Macy dbuf_stats_destroy(void)
227eda14cbcSMatt Macy {
228eda14cbcSMatt Macy dbuf_stats_hash_table_destroy();
229eda14cbcSMatt Macy }
230eda14cbcSMatt Macy
231eda14cbcSMatt Macy ZFS_MODULE_PARAM(zfs, zfs_, dbuf_state_index, INT, ZMOD_RW,
232eda14cbcSMatt Macy "Calculate arc header index");
233