]> git.proxmox.com Git - mirror_zfs.git/blame - module/zfs/dbuf_stats.c
Fix ENXIO from spa_ld_verify_logs() in ztest
[mirror_zfs.git] / module / zfs / dbuf_stats.c
CommitLineData
e0b0ca98
BB
1/*
2 * CDDL HEADER START
3 *
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.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22#include <sys/zfs_context.h>
23#include <sys/dbuf.h>
24#include <sys/dmu_objset.h>
25
26/*
27 * Calculate the index of the arc header for the state, disabled by default.
28 */
29int zfs_dbuf_state_index = 0;
30
31/*
32 * ==========================================================================
33 * Dbuf Hash Read Routines
34 * ==========================================================================
35 */
36typedef struct dbuf_stats_t {
37 kmutex_t lock;
38 kstat_t *kstat;
39 dbuf_hash_table_t *hash;
40 int idx;
41} dbuf_stats_t;
42
43static dbuf_stats_t dbuf_stats_hash_table;
44
45static int
46dbuf_stats_hash_table_headers(char *buf, size_t size)
47{
7b2d78a0 48 (void) snprintf(buf, size,
5e021f56
GDN
49 "%-96s | %-119s | %s\n"
50 "%-16s %-8s %-8s %-8s %-8s %-10s %-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",
e0b0ca98 54 "dbuf", "arcbuf", "dnode", "pool", "objset", "object", "level",
5e021f56
GDN
55 "blkid", "offset", "dbsize", "meta", "state", "dbholds", "dbc",
56 "list", "atype", "flags", "count", "asize", "access",
d1d7e268
MK
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");
e0b0ca98
BB
60
61 return (0);
62}
63
64int
65__dbuf_stats_hash_table_data(char *buf, size_t size, dmu_buf_impl_t *db)
66{
67 arc_buf_info_t abi = { 0 };
68 dmu_object_info_t doi = { 0 };
69 dnode_t *dn = DB_DNODE(db);
aa2ef419 70 size_t nwritten;
e0b0ca98
BB
71
72 if (db->db_buf)
73 arc_buf_info(db->db_buf, &abi, zfs_dbuf_state_index);
74
4c5b89f5 75 __dmu_object_info_from_dnode(dn, &doi);
e0b0ca98 76
aa2ef419 77 nwritten = snprintf(buf, size,
5e021f56
GDN
78 "%-16s %-8llu %-8lld %-8lld %-8lld %-10llu %-8llu %-5d %-5d "
79 "%-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",
e0b0ca98
BB
82 /* dmu_buf_impl_t */
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 !!dbuf_is_metadata(db),
91 db->db_state,
424fd7c3 92 (ulong_t)zfs_refcount_count(&db->db_holds),
5e021f56 93 multilist_link_active(&db->db_cache_link),
e0b0ca98
BB
94 /* arc_buf_info_t */
95 abi.abi_state_type,
96 abi.abi_state_contents,
e0b0ca98 97 abi.abi_flags,
d3c2ae1c 98 (ulong_t)abi.abi_bufcnt,
e0b0ca98
BB
99 (u_longlong_t)abi.abi_size,
100 (u_longlong_t)abi.abi_access,
101 (ulong_t)abi.abi_mru_hits,
102 (ulong_t)abi.abi_mru_ghost_hits,
103 (ulong_t)abi.abi_mfu_hits,
104 (ulong_t)abi.abi_mfu_ghost_hits,
105 (ulong_t)abi.abi_l2arc_hits,
106 (u_longlong_t)abi.abi_l2arc_dattr,
107 (u_longlong_t)abi.abi_l2arc_asize,
108 abi.abi_l2arc_compress,
109 (ulong_t)abi.abi_holds,
110 /* dmu_object_info_t */
111 doi.doi_type,
112 doi.doi_bonus_type,
113 (ulong_t)doi.doi_data_block_size,
114 (ulong_t)doi.doi_metadata_block_size,
115 (u_longlong_t)doi.doi_bonus_size,
116 (ulong_t)doi.doi_indirection,
424fd7c3 117 (ulong_t)zfs_refcount_count(&dn->dn_holds),
e0b0ca98
BB
118 (u_longlong_t)doi.doi_fill_count,
119 (u_longlong_t)doi.doi_max_offset);
e0b0ca98 120
aa2ef419
TC
121 if (nwritten >= size)
122 return (size);
123
124 return (nwritten + 1);
e0b0ca98
BB
125}
126
127static int
128dbuf_stats_hash_table_data(char *buf, size_t size, void *data)
129{
130 dbuf_stats_t *dsh = (dbuf_stats_t *)data;
131 dbuf_hash_table_t *h = dsh->hash;
132 dmu_buf_impl_t *db;
133 int length, error = 0;
134
135 ASSERT3S(dsh->idx, >=, 0);
136 ASSERT3S(dsh->idx, <=, h->hash_table_mask);
137 memset(buf, 0, size);
138
139 mutex_enter(DBUF_HASH_MUTEX(h, dsh->idx));
140 for (db = h->hash_table[dsh->idx]; db != NULL; db = db->db_hash_next) {
141 /*
142 * Returning ENOMEM will cause the data and header functions
143 * to be called with a larger scratch buffers.
144 */
145 if (size < 512) {
ecb2b7dc 146 error = SET_ERROR(ENOMEM);
e0b0ca98
BB
147 break;
148 }
149
150 mutex_enter(&db->db_mtx);
e0b0ca98 151
e2c4acde
BB
152 if (db->db_state != DB_EVICTING) {
153 length = __dbuf_stats_hash_table_data(buf, size, db);
154 buf += length;
155 size -= length;
156 }
e0b0ca98
BB
157
158 mutex_exit(&db->db_mtx);
e0b0ca98
BB
159 }
160 mutex_exit(DBUF_HASH_MUTEX(h, dsh->idx));
161
162 return (error);
163}
164
165static void *
166dbuf_stats_hash_table_addr(kstat_t *ksp, loff_t n)
167{
168 dbuf_stats_t *dsh = ksp->ks_private;
169
d1d7e268 170 ASSERT(MUTEX_HELD(&dsh->lock));
e0b0ca98
BB
171
172 if (n <= dsh->hash->hash_table_mask) {
173 dsh->idx = n;
174 return (dsh);
175 }
176
177 return (NULL);
178}
179
180static void
181dbuf_stats_hash_table_init(dbuf_hash_table_t *hash)
182{
183 dbuf_stats_t *dsh = &dbuf_stats_hash_table;
184 kstat_t *ksp;
185
186 mutex_init(&dsh->lock, NULL, MUTEX_DEFAULT, NULL);
187 dsh->hash = hash;
188
189 ksp = kstat_create("zfs", 0, "dbufs", "misc",
190 KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL);
191 dsh->kstat = ksp;
192
193 if (ksp) {
194 ksp->ks_lock = &dsh->lock;
195 ksp->ks_ndata = UINT32_MAX;
196 ksp->ks_private = dsh;
197 kstat_set_raw_ops(ksp, dbuf_stats_hash_table_headers,
198 dbuf_stats_hash_table_data, dbuf_stats_hash_table_addr);
199 kstat_install(ksp);
200 }
201}
202
203static void
204dbuf_stats_hash_table_destroy(void)
205{
206 dbuf_stats_t *dsh = &dbuf_stats_hash_table;
207 kstat_t *ksp;
208
209 ksp = dsh->kstat;
210 if (ksp)
211 kstat_delete(ksp);
212
213 mutex_destroy(&dsh->lock);
214}
215
216void
217dbuf_stats_init(dbuf_hash_table_t *hash)
218{
219 dbuf_stats_hash_table_init(hash);
220}
221
222void
223dbuf_stats_destroy(void)
224{
225 dbuf_stats_hash_table_destroy();
226}
227
93ce2b4c 228#if defined(_KERNEL)
e0b0ca98
BB
229module_param(zfs_dbuf_state_index, int, 0644);
230MODULE_PARM_DESC(zfs_dbuf_state_index, "Calculate arc header index");
231#endif