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 http://www.opensolaris.org/os/licensing.
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 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
25 * Copyright (c) 2017, Joyent, Inc. All rights reserved.
28 /* Portions Copyright 2010 Robert Milkowski */
30 #include <mdb/mdb_ctf.h>
31 #include <sys/zfs_context.h>
32 #include <sys/mdb_modapi.h>
34 #include <sys/dmu_objset.h>
35 #include <sys/dsl_dir.h>
36 #include <sys/dsl_pool.h>
37 #include <sys/metaslab_impl.h>
38 #include <sys/space_map.h>
40 #include <sys/vdev_impl.h>
41 #include <sys/zap_leaf.h>
42 #include <sys/zap_impl.h>
44 #include <sys/zfs_acl.h>
45 #include <sys/sa_impl.h>
46 #include <sys/multilist.h>
49 #define ZFS_OBJ_NAME "zfs"
50 extern int64_t mdb_gethrtime(void);
52 #define ZFS_OBJ_NAME "libzpool.so.1"
55 #define ZFS_STRUCT "struct " ZFS_OBJ_NAME "`"
62 SPA_FLAG_CONFIG
= 1 << 0,
63 SPA_FLAG_VDEVS
= 1 << 1,
64 SPA_FLAG_ERRORS
= 1 << 2,
65 SPA_FLAG_METASLAB_GROUPS
= 1 << 3,
66 SPA_FLAG_METASLABS
= 1 << 4,
67 SPA_FLAG_HISTOGRAMS
= 1 << 5
71 * If any of these flags are set, call spa_vdevs in spa_print
73 #define SPA_FLAG_ALL_VDEV \
74 (SPA_FLAG_VDEVS | SPA_FLAG_ERRORS | SPA_FLAG_METASLAB_GROUPS | \
78 getmember(uintptr_t addr
, const char *type
, mdb_ctf_id_t
*idp
,
79 const char *member
, int len
, void *buf
)
86 if (mdb_ctf_lookup_by_name(type
, &id
) == -1) {
87 mdb_warn("couldn't find type %s", type
);
93 mdb_ctf_type_name(*idp
, name
, sizeof (name
));
96 if (mdb_ctf_offsetof(*idp
, member
, &off
) == -1) {
97 mdb_warn("couldn't find member %s of type %s\n", member
, type
);
101 mdb_warn("member %s of type %s is unsupported bitfield",
107 if (mdb_vread(buf
, len
, addr
+ off
) == -1) {
108 mdb_warn("failed to read %s from %s at %p",
109 member
, type
, addr
+ off
);
112 /* mdb_warn("read %s from %s at %p+%llx\n", member, type, addr, off); */
117 #define GETMEMB(addr, structname, member, dest) \
118 getmember(addr, ZFS_STRUCT structname, NULL, #member, \
119 sizeof (dest), &(dest))
121 #define GETMEMBID(addr, ctfid, member, dest) \
122 getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest))
125 strisprint(const char *cp
)
134 #define NICENUM_BUFLEN 6
137 snprintfrac(char *buf
, int len
,
138 uint64_t numerator
, uint64_t denom
, int frac_digits
)
143 for (i
= frac_digits
; i
; i
--)
145 whole
= numerator
/ denom
;
146 frac
= mul
* numerator
/ denom
- mul
* whole
;
147 return (mdb_snprintf(buf
, len
, "%u.%0*u", whole
, frac_digits
, frac
));
151 mdb_nicenum(uint64_t num
, char *buf
)
158 n
= (n
+ (1024 / 2)) / 1024; /* Round up or down */
162 u
= &" \0K\0M\0G\0T\0P\0E\0"[index
*2];
165 (void) mdb_snprintf(buf
, NICENUM_BUFLEN
, "%llu",
167 } else if (n
< 10 && (num
& (num
- 1)) != 0) {
168 (void) snprintfrac(buf
, NICENUM_BUFLEN
,
169 num
, 1ULL << 10 * index
, 2);
171 } else if (n
< 100 && (num
& (num
- 1)) != 0) {
172 (void) snprintfrac(buf
, NICENUM_BUFLEN
,
173 num
, 1ULL << 10 * index
, 1);
176 (void) mdb_snprintf(buf
, NICENUM_BUFLEN
, "%llu%s",
182 * <addr>::sm_entries <buffer length in bytes>
184 * Treat the buffer specified by the given address as a buffer that contains
185 * space map entries. Iterate over the specified number of entries and print
186 * them in both encoded and decoded form.
190 sm_entries(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
193 boolean_t preview
= B_FALSE
;
195 if (!(flags
& DCMD_ADDRSPEC
))
201 } else if (argc
!= 1) {
204 switch (argv
[0].a_type
) {
205 case MDB_TYPE_STRING
:
206 bufsz
= mdb_strtoull(argv
[0].a_un
.a_str
);
208 case MDB_TYPE_IMMEDIATE
:
209 bufsz
= argv
[0].a_un
.a_val
;
216 char *actions
[] = { "ALLOC", "FREE", "INVALID" };
217 for (uintptr_t bufend
= addr
+ bufsz
; addr
< bufend
;
218 addr
+= sizeof (uint64_t)) {
220 uint64_t start_addr
= addr
;
223 if (mdb_vread(&word
, sizeof (word
), addr
) == -1) {
224 mdb_warn("failed to read space map entry %p", addr
);
228 if (SM_PREFIX_DECODE(word
) == SM_DEBUG_PREFIX
) {
229 (void) mdb_printf("\t [%6llu] %s: txg %llu, "
231 (u_longlong_t
)(addr
),
232 actions
[SM_DEBUG_ACTION_DECODE(word
)],
233 (u_longlong_t
)SM_DEBUG_TXG_DECODE(word
),
234 (u_longlong_t
)SM_DEBUG_SYNCPASS_DECODE(word
));
239 uint64_t raw_offset
, raw_run
, vdev_id
= SM_NO_VDEVID
;
241 if (SM_PREFIX_DECODE(word
) != SM2_PREFIX
) {
242 entry_type
= (SM_TYPE_DECODE(word
) == SM_ALLOC
) ?
244 raw_offset
= SM_OFFSET_DECODE(word
);
245 raw_run
= SM_RUN_DECODE(word
);
248 ASSERT3U(SM_PREFIX_DECODE(word
), ==, SM2_PREFIX
);
250 raw_run
= SM2_RUN_DECODE(word
);
251 vdev_id
= SM2_VDEV_DECODE(word
);
253 /* it is a two-word entry so we read another word */
254 addr
+= sizeof (uint64_t);
255 if (addr
>= bufend
) {
256 mdb_warn("buffer ends in the middle of a two "
257 "word entry\n", addr
);
261 if (mdb_vread(&word
, sizeof (word
), addr
) == -1) {
262 mdb_warn("failed to read space map entry %p",
267 entry_type
= (SM2_TYPE_DECODE(word
) == SM_ALLOC
) ?
269 raw_offset
= SM2_OFFSET_DECODE(word
);
273 (void) mdb_printf("\t [%6llx] %c range:"
274 " %010llx-%010llx size: %06llx vdev: %06llu words: %llu\n",
275 (u_longlong_t
)start_addr
,
276 entry_type
, (u_longlong_t
)raw_offset
,
277 (u_longlong_t
)(raw_offset
+ raw_run
),
278 (u_longlong_t
)raw_run
,
279 (u_longlong_t
)vdev_id
, (u_longlong_t
)nwords
);
288 mdb_dsl_dir_name(uintptr_t addr
, char *buf
)
291 static mdb_ctf_id_t dd_id
;
293 char dd_myname
[ZFS_MAX_DATASET_NAME_LEN
];
296 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"dsl_dir",
298 mdb_warn("couldn't find struct dsl_dir");
303 if (GETMEMBID(addr
, &dd_id
, dd_parent
, dd_parent
) ||
304 GETMEMBID(addr
, &dd_id
, dd_myname
, dd_myname
)) {
309 if (mdb_dsl_dir_name(dd_parent
, buf
))
315 strcat(buf
, dd_myname
);
323 objset_name(uintptr_t addr
, char *buf
)
326 static mdb_ctf_id_t os_id
, ds_id
;
327 uintptr_t os_dsl_dataset
;
328 char ds_snapname
[ZFS_MAX_DATASET_NAME_LEN
];
334 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"objset",
336 mdb_warn("couldn't find struct objset");
339 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"dsl_dataset",
341 mdb_warn("couldn't find struct dsl_dataset");
348 if (GETMEMBID(addr
, &os_id
, os_dsl_dataset
, os_dsl_dataset
))
351 if (os_dsl_dataset
== 0) {
356 if (GETMEMBID(os_dsl_dataset
, &ds_id
, ds_snapname
, ds_snapname
) ||
357 GETMEMBID(os_dsl_dataset
, &ds_id
, ds_dir
, ds_dir
)) {
361 if (ds_dir
&& mdb_dsl_dir_name(ds_dir
, buf
))
364 if (ds_snapname
[0]) {
366 strcat(buf
, ds_snapname
);
372 enum_lookup(char *type
, int val
, const char *prefix
, size_t size
, char *out
)
375 size_t len
= strlen(prefix
);
376 mdb_ctf_id_t enum_type
;
378 if (mdb_ctf_lookup_by_name(type
, &enum_type
) != 0) {
379 mdb_warn("Could not find enum for %s", type
);
383 if ((cp
= mdb_ctf_enum_name(enum_type
, val
)) != NULL
) {
384 if (strncmp(cp
, prefix
, len
) == 0)
386 (void) strncpy(out
, cp
, size
);
388 mdb_snprintf(out
, size
, "? (%d)", val
);
395 zfs_params(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
398 * This table can be approximately generated by running:
399 * egrep "^[a-z0-9_]+ [a-z0-9_]+( =.*)?;" *.c | cut -d ' ' -f 2
401 static const char *params
[] = {
402 "arc_reduce_dnlc_percent",
403 "arc_lotsfree_percent",
404 "zfs_dirty_data_max",
405 "zfs_dirty_data_sync",
407 "zfs_delay_min_dirty_percent",
409 "zfs_vdev_max_active",
410 "zfs_vdev_sync_read_min_active",
411 "zfs_vdev_sync_read_max_active",
412 "zfs_vdev_sync_write_min_active",
413 "zfs_vdev_sync_write_max_active",
414 "zfs_vdev_async_read_min_active",
415 "zfs_vdev_async_read_max_active",
416 "zfs_vdev_async_write_min_active",
417 "zfs_vdev_async_write_max_active",
418 "zfs_vdev_scrub_min_active",
419 "zfs_vdev_scrub_max_active",
420 "zfs_vdev_async_write_active_min_dirty_percent",
421 "zfs_vdev_async_write_active_max_dirty_percent",
422 "spa_asize_inflation",
426 "zfs_mdcomp_disable",
427 "zfs_prefetch_disable",
428 "zfetch_max_streams",
429 "zfetch_min_sec_reap",
431 "zfetch_array_rd_sz",
435 "reference_tracking_enable",
437 "spa_max_replication_override",
441 "zfs_vdev_cache_max",
442 "zfs_vdev_cache_size",
443 "zfs_vdev_cache_bshift",
447 "zfs_no_scrub_prefetch",
448 "zfs_vdev_aggregation_limit",
449 "fzap_default_block_shift",
450 "zfs_immediate_write_sz",
451 "zfs_read_chunk_size",
453 "zil_replay_disable",
454 "metaslab_force_ganging",
455 "metaslab_df_alloc_threshold",
456 "metaslab_df_free_pct",
457 "zio_injection_enabled",
458 "zvol_immediate_write_sz",
461 for (int i
= 0; i
< sizeof (params
) / sizeof (params
[0]); i
++) {
464 uint32_t *val32p
= (uint32_t *)&val64
;
466 sz
= mdb_readvar(&val64
, params
[i
]);
468 mdb_printf("%s = 0x%x\n", params
[i
], *val32p
);
469 } else if (sz
== 8) {
470 mdb_printf("%s = 0x%llx\n", params
[i
], val64
);
472 mdb_warn("variable %s not found", params
[i
]);
481 dva(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
484 if (mdb_vread(&dva
, sizeof (dva_t
), addr
) == -1) {
485 mdb_warn("failed to read dva_t");
488 mdb_printf("<%llu:%llx:%llx>\n",
489 (u_longlong_t
)DVA_GET_VDEV(&dva
),
490 (u_longlong_t
)DVA_GET_OFFSET(&dva
),
491 (u_longlong_t
)DVA_GET_ASIZE(&dva
));
498 blkptr(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
500 char type
[80], checksum
[80], compress
[80];
501 blkptr_t blk
, *bp
= &blk
;
502 char buf
[BP_SPRINTF_LEN
];
504 if (mdb_vread(&blk
, sizeof (blkptr_t
), addr
) == -1) {
505 mdb_warn("failed to read blkptr_t");
509 if (enum_lookup("enum dmu_object_type", BP_GET_TYPE(bp
), "DMU_OT_",
510 sizeof (type
), type
) == -1 ||
511 enum_lookup("enum zio_checksum", BP_GET_CHECKSUM(bp
),
512 "ZIO_CHECKSUM_", sizeof (checksum
), checksum
) == -1 ||
513 enum_lookup("enum zio_compress", BP_GET_COMPRESS(bp
),
514 "ZIO_COMPRESS_", sizeof (compress
), compress
) == -1) {
515 mdb_warn("Could not find blkptr enumerated types");
519 SNPRINTF_BLKPTR(mdb_snprintf
, '\n', buf
, sizeof (buf
), bp
, type
,
522 mdb_printf("%s\n", buf
);
527 typedef struct mdb_dmu_buf_impl
{
538 } mdb_dmu_buf_impl_t
;
542 dbuf(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
544 mdb_dmu_buf_impl_t db
;
547 char path
[ZFS_MAX_DATASET_NAME_LEN
];
548 int ptr_width
= (int)(sizeof (void *)) * 2;
550 if (DCMD_HDRSPEC(flags
))
551 mdb_printf("%*s %8s %3s %9s %5s %s\n",
552 ptr_width
, "addr", "object", "lvl", "blkid", "holds", "os");
554 if (mdb_ctf_vread(&db
, ZFS_STRUCT
"dmu_buf_impl", "mdb_dmu_buf_impl_t",
558 if (db
.db
.db_object
== DMU_META_DNODE_OBJECT
)
559 (void) strcpy(objectname
, "mdn");
561 (void) mdb_snprintf(objectname
, sizeof (objectname
), "%llx",
562 (u_longlong_t
)db
.db
.db_object
);
564 if (db
.db_blkid
== DMU_BONUS_BLKID
)
565 (void) strcpy(blkidname
, "bonus");
567 (void) mdb_snprintf(blkidname
, sizeof (blkidname
), "%llx",
568 (u_longlong_t
)db
.db_blkid
);
570 if (objset_name(db
.db_objset
, path
)) {
574 mdb_printf("%*p %8s %3u %9s %5llu %s\n", ptr_width
, addr
,
575 objectname
, (int)db
.db_level
, blkidname
,
576 db
.db_holds
.rc_count
, path
);
583 dbuf_stats(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
588 dbuf_hash_table_t ht
;
589 uint64_t bucket
, ndbufs
;
590 uint64_t histo
[HISTOSZ
];
591 uint64_t histo2
[HISTOSZ
];
594 if (mdb_readvar(&ht
, "dbuf_hash_table") == -1) {
595 mdb_warn("failed to read 'dbuf_hash_table'");
599 for (i
= 0; i
< HISTOSZ
; i
++) {
605 for (bucket
= 0; bucket
< ht
.hash_table_mask
+1; bucket
++) {
608 if (mdb_vread(&dbp
, sizeof (void *),
609 (uintptr_t)(ht
.hash_table
+bucket
)) == -1) {
610 mdb_warn("failed to read hash bucket %u at %p",
611 bucket
, ht
.hash_table
+bucket
);
617 if (mdb_vread(&db
, sizeof (dmu_buf_impl_t
),
619 mdb_warn("failed to read dbuf at %p", dbp
);
622 dbp
= (uintptr_t)db
.db_hash_next
;
623 for (i
= MIN(len
, HISTOSZ
- 1); i
>= 0; i
--)
634 mdb_printf("hash table has %llu buckets, %llu dbufs "
635 "(avg %llu buckets/dbuf)\n",
636 ht
.hash_table_mask
+1, ndbufs
,
637 (ht
.hash_table_mask
+1)/ndbufs
);
641 for (i
= 0; i
< HISTOSZ
; i
++)
644 mdb_printf("hash chain length number of buckets\n");
645 for (i
= 0; i
<= maxidx
; i
++)
646 mdb_printf("%u %llu\n", i
, histo
[i
]);
650 for (i
= 0; i
< HISTOSZ
; i
++)
653 mdb_printf("hash chain depth number of dbufs\n");
654 for (i
= 0; i
<= maxidx
; i
++)
655 mdb_printf("%u or more %llu %llu%%\n",
656 i
, histo2
[i
], histo2
[i
]*100/ndbufs
);
662 #define CHAIN_END 0xffff
666 * Print a zap_leaf_phys_t, assumed to be 16k
670 zap_leaf(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
673 int verbose
= B_FALSE
;
677 zap_leaf_phys_t
*zlp
= (void *)buf
;
680 if (mdb_getopts(argc
, argv
,
681 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
,
682 '4', MDB_OPT_SETBITS
, TRUE
, &four
,
686 l_dbuf
.db_data
= zlp
;
688 l
.l_bs
= 14; /* assume 16k blocks */
692 if (!(flags
& DCMD_ADDRSPEC
)) {
696 if (mdb_vread(buf
, sizeof (buf
), addr
) == -1) {
697 mdb_warn("failed to read zap_leaf_phys_t at %p", addr
);
701 if (zlp
->l_hdr
.lh_block_type
!= ZBT_LEAF
||
702 zlp
->l_hdr
.lh_magic
!= ZAP_LEAF_MAGIC
) {
703 mdb_warn("This does not appear to be a zap_leaf_phys_t");
707 mdb_printf("zap_leaf_phys_t at %p:\n", addr
);
708 mdb_printf(" lh_prefix_len = %u\n", zlp
->l_hdr
.lh_prefix_len
);
709 mdb_printf(" lh_prefix = %llx\n", zlp
->l_hdr
.lh_prefix
);
710 mdb_printf(" lh_nentries = %u\n", zlp
->l_hdr
.lh_nentries
);
711 mdb_printf(" lh_nfree = %u\n", zlp
->l_hdr
.lh_nfree
,
712 zlp
->l_hdr
.lh_nfree
* 100 / (ZAP_LEAF_NUMCHUNKS(&l
)));
713 mdb_printf(" lh_freelist = %u\n", zlp
->l_hdr
.lh_freelist
);
714 mdb_printf(" lh_flags = %x (%s)\n", zlp
->l_hdr
.lh_flags
,
715 zlp
->l_hdr
.lh_flags
& ZLF_ENTRIES_CDSORTED
?
716 "ENTRIES_CDSORTED" : "");
719 mdb_printf(" hash table:\n");
720 for (i
= 0; i
< ZAP_LEAF_HASH_NUMENTRIES(&l
); i
++) {
721 if (zlp
->l_hash
[i
] != CHAIN_END
)
722 mdb_printf(" %u: %u\n", i
, zlp
->l_hash
[i
]);
726 mdb_printf(" chunks:\n");
727 for (i
= 0; i
< ZAP_LEAF_NUMCHUNKS(&l
); i
++) {
728 /* LINTED: alignment */
729 zap_leaf_chunk_t
*zlc
= &ZAP_LEAF_CHUNK(&l
, i
);
730 switch (zlc
->l_entry
.le_type
) {
733 mdb_printf(" %u: free; lf_next = %u\n",
734 i
, zlc
->l_free
.lf_next
);
737 case ZAP_CHUNK_ENTRY
:
738 mdb_printf(" %u: entry\n", i
);
740 mdb_printf(" le_next = %u\n",
741 zlc
->l_entry
.le_next
);
743 mdb_printf(" le_name_chunk = %u\n",
744 zlc
->l_entry
.le_name_chunk
);
745 mdb_printf(" le_name_numints = %u\n",
746 zlc
->l_entry
.le_name_numints
);
747 mdb_printf(" le_value_chunk = %u\n",
748 zlc
->l_entry
.le_value_chunk
);
749 mdb_printf(" le_value_intlen = %u\n",
750 zlc
->l_entry
.le_value_intlen
);
751 mdb_printf(" le_value_numints = %u\n",
752 zlc
->l_entry
.le_value_numints
);
753 mdb_printf(" le_cd = %u\n",
755 mdb_printf(" le_hash = %llx\n",
756 zlc
->l_entry
.le_hash
);
758 case ZAP_CHUNK_ARRAY
:
759 mdb_printf(" %u: array", i
);
760 if (strisprint((char *)zlc
->l_array
.la_array
))
761 mdb_printf(" \"%s\"", zlc
->l_array
.la_array
);
766 for (j
= 0; j
< ZAP_LEAF_ARRAY_BYTES
; j
++) {
768 zlc
->l_array
.la_array
[j
]);
772 if (zlc
->l_array
.la_next
!= CHAIN_END
) {
773 mdb_printf(" lf_next = %u\n",
774 zlc
->l_array
.la_next
);
778 mdb_printf(" %u: undefined type %u\n",
779 zlc
->l_entry
.le_type
);
786 typedef struct dbufs_data
{
795 #define DBUFS_UNSET (0xbaddcafedeadbeefULL)
799 dbufs_cb(uintptr_t addr
, const void *unknown
, void *arg
)
801 dbufs_data_t
*data
= arg
;
806 char osname
[ZFS_MAX_DATASET_NAME_LEN
];
808 if (GETMEMBID(addr
, &data
->id
, db_objset
, objset
) ||
809 GETMEMBID(addr
, &data
->id
, db
, db
) ||
810 GETMEMBID(addr
, &data
->id
, db_level
, level
) ||
811 GETMEMBID(addr
, &data
->id
, db_blkid
, blkid
)) {
815 if ((data
->objset
== DBUFS_UNSET
|| data
->objset
== objset
) &&
816 (data
->osname
== NULL
|| (objset_name(objset
, osname
) == 0 &&
817 strcmp(data
->osname
, osname
) == 0)) &&
818 (data
->object
== DBUFS_UNSET
|| data
->object
== db
.db_object
) &&
819 (data
->level
== DBUFS_UNSET
|| data
->level
== level
) &&
820 (data
->blkid
== DBUFS_UNSET
|| data
->blkid
== blkid
)) {
821 mdb_printf("%#lr\n", addr
);
828 dbufs(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
834 data
.objset
= data
.object
= data
.level
= data
.blkid
= DBUFS_UNSET
;
837 if (mdb_getopts(argc
, argv
,
838 'O', MDB_OPT_UINT64
, &data
.objset
,
839 'n', MDB_OPT_STR
, &data
.osname
,
840 'o', MDB_OPT_STR
, &object
,
841 'l', MDB_OPT_UINT64
, &data
.level
,
842 'b', MDB_OPT_STR
, &blkid
) != argc
) {
847 if (strcmp(object
, "mdn") == 0) {
848 data
.object
= DMU_META_DNODE_OBJECT
;
850 data
.object
= mdb_strtoull(object
);
855 if (strcmp(blkid
, "bonus") == 0) {
856 data
.blkid
= DMU_BONUS_BLKID
;
858 data
.blkid
= mdb_strtoull(blkid
);
862 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"dmu_buf_impl", &data
.id
) == -1) {
863 mdb_warn("couldn't find struct dmu_buf_impl_t");
867 if (mdb_walk("dmu_buf_impl_t", dbufs_cb
, &data
) != 0) {
868 mdb_warn("can't walk dbufs");
875 typedef struct abuf_find_data
{
882 abuf_find_cb(uintptr_t addr
, const void *unknown
, void *arg
)
884 abuf_find_data_t
*data
= arg
;
887 if (GETMEMBID(addr
, &data
->id
, b_dva
, dva
)) {
891 if (dva
.dva_word
[0] == data
->dva
.dva_word
[0] &&
892 dva
.dva_word
[1] == data
->dva
.dva_word
[1]) {
893 mdb_printf("%#lr\n", addr
);
900 abuf_find(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
902 abuf_find_data_t data
;
905 const char *syms
[] = {
915 for (i
= 0; i
< 2; i
++) {
916 switch (argv
[i
].a_type
) {
917 case MDB_TYPE_STRING
:
918 data
.dva
.dva_word
[i
] = mdb_strtoull(argv
[i
].a_un
.a_str
);
920 case MDB_TYPE_IMMEDIATE
:
921 data
.dva
.dva_word
[i
] = argv
[i
].a_un
.a_val
;
928 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"arc_buf_hdr", &data
.id
) == -1) {
929 mdb_warn("couldn't find struct arc_buf_hdr");
933 for (i
= 0; i
< sizeof (syms
) / sizeof (syms
[0]); i
++) {
934 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, syms
[i
], &sym
)) {
935 mdb_warn("can't find symbol %s", syms
[i
]);
939 if (mdb_pwalk("list", abuf_find_cb
, &data
, sym
.st_value
) != 0) {
940 mdb_warn("can't walk %s", syms
[i
]);
949 typedef struct dbgmsg_arg
{
950 boolean_t da_verbose
;
951 boolean_t da_address
;
956 dbgmsg_cb(uintptr_t addr
, const void *unknown
, void *arg
)
958 static mdb_ctf_id_t id
;
959 static boolean_t gotid
;
962 dbgmsg_arg_t
*da
= arg
;
967 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"zfs_dbgmsg", &id
) ==
969 mdb_warn("couldn't find struct zfs_dbgmsg");
973 if (mdb_ctf_offsetof(id
, "zdm_msg", &off
) == -1) {
974 mdb_warn("couldn't find zdm_msg");
981 if (GETMEMBID(addr
, &id
, zdm_timestamp
, timestamp
)) {
985 if (mdb_readstr(buf
, sizeof (buf
), addr
+ off
) == -1) {
986 mdb_warn("failed to read zdm_msg at %p\n", addr
+ off
);
991 mdb_printf("%p ", addr
);
993 mdb_printf("%Y ", timestamp
);
995 mdb_printf("%s\n", buf
);
998 (void) mdb_call_dcmd("whatis", addr
, DCMD_ADDRSPEC
, 0, NULL
);
1005 dbgmsg(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1008 dbgmsg_arg_t da
= { 0 };
1010 if (mdb_getopts(argc
, argv
,
1011 'v', MDB_OPT_SETBITS
, B_TRUE
, &da
.da_verbose
,
1012 'a', MDB_OPT_SETBITS
, B_TRUE
, &da
.da_address
,
1014 return (DCMD_USAGE
);
1016 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, "zfs_dbgmsgs", &sym
)) {
1017 mdb_warn("can't find zfs_dbgmsgs");
1021 if (mdb_pwalk("list", dbgmsg_cb
, &da
, sym
.st_value
) != 0) {
1022 mdb_warn("can't walk zfs_dbgmsgs");
1031 arc_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1033 kstat_named_t
*stats
;
1036 uint_t opt_a
= FALSE
;
1037 uint_t opt_b
= FALSE
;
1041 static const char *bytestats
[] = {
1042 "p", "c", "c_min", "c_max", "size", "duplicate_buffers_size",
1043 "arc_meta_used", "arc_meta_limit", "arc_meta_max",
1044 "arc_meta_min", "hdr_size", "data_size", "metadata_size",
1045 "other_size", "anon_size", "anon_evictable_data",
1046 "anon_evictable_metadata", "mru_size", "mru_evictable_data",
1047 "mru_evictable_metadata", "mru_ghost_size",
1048 "mru_ghost_evictable_data", "mru_ghost_evictable_metadata",
1049 "mfu_size", "mfu_evictable_data", "mfu_evictable_metadata",
1050 "mfu_ghost_size", "mfu_ghost_evictable_data",
1051 "mfu_ghost_evictable_metadata", "evict_l2_cached",
1052 "evict_l2_eligible", "evict_l2_ineligible", "l2_read_bytes",
1053 "l2_write_bytes", "l2_size", "l2_asize", "l2_hdr_size",
1054 "compressed_size", "uncompressed_size", "overhead_size",
1058 static const char *extras
[] = {
1059 "arc_no_grow", "arc_tempreserve",
1063 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, "arc_stats", &sym
) == -1) {
1064 mdb_warn("failed to find 'arc_stats'");
1068 stats
= mdb_zalloc(sym
.st_size
, UM_SLEEP
| UM_GC
);
1070 if (mdb_vread(stats
, sym
.st_size
, sym
.st_value
) == -1) {
1071 mdb_warn("couldn't read 'arc_stats' at %p", sym
.st_value
);
1075 nstats
= sym
.st_size
/ sizeof (kstat_named_t
);
1077 /* NB: -a / opt_a are ignored for backwards compatability */
1078 if (mdb_getopts(argc
, argv
,
1079 'a', MDB_OPT_SETBITS
, TRUE
, &opt_a
,
1080 'b', MDB_OPT_SETBITS
, TRUE
, &opt_b
,
1081 'k', MDB_OPT_SETBITS
, 10, &shift
,
1082 'm', MDB_OPT_SETBITS
, 20, &shift
,
1083 'g', MDB_OPT_SETBITS
, 30, &shift
,
1085 return (DCMD_USAGE
);
1087 if (!opt_b
&& !shift
)
1107 for (i
= 0; i
< nstats
; i
++) {
1109 boolean_t bytes
= B_FALSE
;
1111 for (j
= 0; bytestats
[j
]; j
++) {
1112 if (strcmp(stats
[i
].name
, bytestats
[j
]) == 0) {
1119 mdb_printf("%-25s = %9llu %s\n", stats
[i
].name
,
1120 stats
[i
].value
.ui64
>> shift
, suffix
);
1122 mdb_printf("%-25s = %9llu\n", stats
[i
].name
,
1123 stats
[i
].value
.ui64
);
1127 for (i
= 0; extras
[i
]; i
++) {
1130 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, extras
[i
], &sym
) == -1) {
1131 mdb_warn("failed to find '%s'", extras
[i
]);
1135 if (sym
.st_size
!= sizeof (uint64_t) &&
1136 sym
.st_size
!= sizeof (uint32_t)) {
1137 mdb_warn("expected scalar for variable '%s'\n",
1142 if (mdb_vread(&buf
, sym
.st_size
, sym
.st_value
) == -1) {
1143 mdb_warn("couldn't read '%s'", extras
[i
]);
1147 mdb_printf("%-25s = ", extras
[i
]);
1149 /* NB: all the 64-bit extras happen to be byte counts */
1150 if (sym
.st_size
== sizeof (uint64_t))
1151 mdb_printf("%9llu %s\n", buf
>> shift
, suffix
);
1153 if (sym
.st_size
== sizeof (uint32_t))
1154 mdb_printf("%9d\n", *((uint32_t *)&buf
));
1159 typedef struct mdb_spa_print
{
1160 pool_state_t spa_state
;
1161 char spa_name
[ZFS_MAX_DATASET_NAME_LEN
];
1162 uintptr_t spa_normal_class
;
1166 const char histo_stars
[] = "****************************************";
1167 const int histo_width
= sizeof (histo_stars
) - 1;
1170 dump_histogram(const uint64_t *histo
, int size
, int offset
)
1173 int minidx
= size
- 1;
1177 for (i
= 0; i
< size
; i
++) {
1180 if (histo
[i
] > 0 && i
> maxidx
)
1182 if (histo
[i
] > 0 && i
< minidx
)
1186 if (max
< histo_width
)
1189 for (i
= minidx
; i
<= maxidx
; i
++) {
1190 mdb_printf("%3u: %6llu %s\n",
1191 i
+ offset
, (u_longlong_t
)histo
[i
],
1192 &histo_stars
[(max
- histo
[i
]) * histo_width
/ max
]);
1196 typedef struct mdb_metaslab_class
{
1197 uint64_t mc_histogram
[RANGE_TREE_HISTOGRAM_SIZE
];
1198 } mdb_metaslab_class_t
;
1201 * spa_class_histogram(uintptr_t class_addr)
1203 * Prints free space histogram for a device class
1205 * Returns DCMD_OK, or DCMD_ERR.
1208 spa_class_histogram(uintptr_t class_addr
)
1210 mdb_metaslab_class_t mc
;
1211 if (mdb_ctf_vread(&mc
, "metaslab_class_t",
1212 "mdb_metaslab_class_t", class_addr
, 0) == -1)
1216 dump_histogram(mc
.mc_histogram
, RANGE_TREE_HISTOGRAM_SIZE
, 0);
1224 * -c Print configuration information as well
1225 * -v Print vdev state
1226 * -e Print vdev error stats
1227 * -m Print vdev metaslab info
1228 * -M print vdev metaslab group info
1229 * -h Print histogram info (must be combined with -m or -M)
1231 * Print a summarized spa_t. When given no arguments, prints out a table of all
1232 * active pools on the system.
1236 spa_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1238 const char *statetab
[] = { "ACTIVE", "EXPORTED", "DESTROYED",
1239 "SPARE", "L2CACHE", "UNINIT", "UNAVAIL", "POTENTIAL" };
1243 if (mdb_getopts(argc
, argv
,
1244 'c', MDB_OPT_SETBITS
, SPA_FLAG_CONFIG
, &spa_flags
,
1245 'v', MDB_OPT_SETBITS
, SPA_FLAG_VDEVS
, &spa_flags
,
1246 'e', MDB_OPT_SETBITS
, SPA_FLAG_ERRORS
, &spa_flags
,
1247 'M', MDB_OPT_SETBITS
, SPA_FLAG_METASLAB_GROUPS
, &spa_flags
,
1248 'm', MDB_OPT_SETBITS
, SPA_FLAG_METASLABS
, &spa_flags
,
1249 'h', MDB_OPT_SETBITS
, SPA_FLAG_HISTOGRAMS
, &spa_flags
,
1251 return (DCMD_USAGE
);
1253 if (!(flags
& DCMD_ADDRSPEC
)) {
1254 if (mdb_walk_dcmd("spa", "spa", argc
, argv
) == -1) {
1255 mdb_warn("can't walk spa");
1262 if (flags
& DCMD_PIPE_OUT
) {
1263 mdb_printf("%#lr\n", addr
);
1267 if (DCMD_HDRSPEC(flags
))
1268 mdb_printf("%<u>%-?s %9s %-*s%</u>\n", "ADDR", "STATE",
1269 sizeof (uintptr_t) == 4 ? 60 : 52, "NAME");
1271 mdb_spa_print_t spa
;
1272 if (mdb_ctf_vread(&spa
, "spa_t", "mdb_spa_print_t", addr
, 0) == -1)
1275 if (spa
.spa_state
< 0 || spa
.spa_state
> POOL_STATE_UNAVAIL
)
1278 state
= statetab
[spa
.spa_state
];
1280 mdb_printf("%0?p %9s %s\n", addr
, state
, spa
.spa_name
);
1281 if (spa_flags
& SPA_FLAG_HISTOGRAMS
)
1282 spa_class_histogram(spa
.spa_normal_class
);
1284 if (spa_flags
& SPA_FLAG_CONFIG
) {
1287 if (mdb_call_dcmd("spa_config", addr
, flags
, 0,
1293 if (spa_flags
& SPA_FLAG_ALL_VDEV
) {
1295 char opts
[100] = "-";
1297 (spa_flags
| SPA_FLAG_VDEVS
) == SPA_FLAG_VDEVS
? 0 : 1;
1299 if (spa_flags
& SPA_FLAG_ERRORS
)
1301 if (spa_flags
& SPA_FLAG_METASLABS
)
1303 if (spa_flags
& SPA_FLAG_METASLAB_GROUPS
)
1305 if (spa_flags
& SPA_FLAG_HISTOGRAMS
)
1308 v
.a_type
= MDB_TYPE_STRING
;
1309 v
.a_un
.a_str
= opts
;
1313 if (mdb_call_dcmd("spa_vdevs", addr
, flags
, args
,
1322 typedef struct mdb_spa_config_spa
{
1323 uintptr_t spa_config
;
1324 } mdb_spa_config_spa_t
;
1329 * Given a spa_t, print the configuration information stored in spa_config.
1330 * Since it's just an nvlist, format it as an indented list of name=value pairs.
1331 * We simply read the value of spa_config and pass off to ::nvlist.
1335 spa_print_config(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1337 mdb_spa_config_spa_t spa
;
1339 if (argc
!= 0 || !(flags
& DCMD_ADDRSPEC
))
1340 return (DCMD_USAGE
);
1342 if (mdb_ctf_vread(&spa
, ZFS_STRUCT
"spa", "mdb_spa_config_spa_t",
1346 if (spa
.spa_config
== 0) {
1347 mdb_printf("(none)\n");
1351 return (mdb_call_dcmd("nvlist", spa
.spa_config
, flags
,
1357 typedef struct mdb_range_tree
{
1361 typedef struct mdb_metaslab_group
{
1362 uint64_t mg_fragmentation
;
1363 uint64_t mg_histogram
[RANGE_TREE_HISTOGRAM_SIZE
];
1365 } mdb_metaslab_group_t
;
1367 typedef struct mdb_metaslab
{
1371 int64_t ms_deferspace
;
1372 uint64_t ms_fragmentation
;
1374 uintptr_t ms_allocating
[TXG_SIZE
];
1375 uintptr_t ms_checkpointing
;
1376 uintptr_t ms_freeing
;
1378 uintptr_t ms_allocatable
;
1382 typedef struct mdb_space_map_phys_t
{
1384 uint64_t smp_histogram
[SPACE_MAP_HISTOGRAM_SIZE
];
1385 } mdb_space_map_phys_t
;
1387 typedef struct mdb_space_map
{
1394 typedef struct mdb_vdev
{
1395 uintptr_t vdev_path
;
1398 uint64_t vdev_ms_count
;
1400 vdev_stat_t vdev_stat
;
1403 typedef struct mdb_vdev_ops
{
1404 char vdev_op_type
[16];
1408 metaslab_stats(uintptr_t addr
, int spa_flags
)
1413 if (mdb_ctf_vread(&vdev
, "vdev_t", "mdb_vdev_t",
1414 (uintptr_t)addr
, 0) == -1) {
1415 mdb_warn("failed to read vdev at %p\n", addr
);
1420 mdb_printf("%<u>%-?s %6s %20s %10s %9s%</u>\n", "ADDR", "ID",
1421 "OFFSET", "FREE", "FRAGMENTATION");
1423 vdev_ms
= mdb_alloc(vdev
.vdev_ms_count
* sizeof (void *),
1425 if (mdb_vread(vdev_ms
, vdev
.vdev_ms_count
* sizeof (void *),
1426 (uintptr_t)vdev
.vdev_ms
) == -1) {
1427 mdb_warn("failed to read vdev_ms at %p\n", vdev
.vdev_ms
);
1431 for (int m
= 0; m
< vdev
.vdev_ms_count
; m
++) {
1433 mdb_space_map_t sm
= { 0 };
1434 char free
[NICENUM_BUFLEN
];
1436 if (mdb_ctf_vread(&ms
, "metaslab_t", "mdb_metaslab_t",
1437 (uintptr_t)vdev_ms
[m
], 0) == -1)
1440 if (ms
.ms_sm
!= (uintptr_t)NULL
&&
1441 mdb_ctf_vread(&sm
, "space_map_t", "mdb_space_map_t",
1445 mdb_nicenum(ms
.ms_size
- sm
.sm_alloc
, free
);
1447 mdb_printf("%0?p %6llu %20llx %10s ", vdev_ms
[m
], ms
.ms_id
,
1449 if (ms
.ms_fragmentation
== ZFS_FRAG_INVALID
)
1450 mdb_printf("%9s\n", "-");
1452 mdb_printf("%9llu%%\n", ms
.ms_fragmentation
);
1454 if ((spa_flags
& SPA_FLAG_HISTOGRAMS
) && ms
.ms_sm
!= 0) {
1455 mdb_space_map_phys_t smp
;
1457 if (sm
.sm_phys
== (uintptr_t)NULL
)
1460 (void) mdb_ctf_vread(&smp
, "space_map_phys_t",
1461 "mdb_space_map_phys_t", sm
.sm_phys
, 0);
1463 dump_histogram(smp
.smp_histogram
,
1464 SPACE_MAP_HISTOGRAM_SIZE
, sm
.sm_shift
);
1472 metaslab_group_stats(uintptr_t addr
, int spa_flags
)
1474 mdb_metaslab_group_t mg
;
1475 if (mdb_ctf_vread(&mg
, "metaslab_group_t", "mdb_metaslab_group_t",
1476 (uintptr_t)addr
, 0) == -1) {
1477 mdb_warn("failed to read vdev_mg at %p\n", addr
);
1482 mdb_printf("%<u>%-?s %15s%</u>\n", "ADDR", "FRAGMENTATION");
1483 if (mg
.mg_fragmentation
== ZFS_FRAG_INVALID
)
1484 mdb_printf("%0?p %15s\n", addr
, "-");
1486 mdb_printf("%0?p %15llu%%\n", addr
, mg
.mg_fragmentation
);
1488 if (spa_flags
& SPA_FLAG_HISTOGRAMS
)
1489 dump_histogram(mg
.mg_histogram
, RANGE_TREE_HISTOGRAM_SIZE
, 0);
1497 * Print out a summarized vdev_t, in the following form:
1499 * ADDR STATE AUX DESC
1500 * fffffffbcde23df0 HEALTHY - /dev/dsk/c0t0d0
1502 * If '-r' is specified, recursively visit all children.
1504 * With '-e', the statistics associated with the vdev are printed as well.
1507 do_print_vdev(uintptr_t addr
, int flags
, int depth
, boolean_t recursive
,
1511 char desc
[MAXNAMELEN
];
1514 const char *state
, *aux
;
1516 if (mdb_vread(&vdev
, sizeof (vdev
), (uintptr_t)addr
) == -1) {
1517 mdb_warn("failed to read vdev_t at %p\n", (uintptr_t)addr
);
1521 if (flags
& DCMD_PIPE_OUT
) {
1522 mdb_printf("%#lr\n", addr
);
1524 if (vdev
.vdev_path
!= NULL
) {
1525 if (mdb_readstr(desc
, sizeof (desc
),
1526 (uintptr_t)vdev
.vdev_path
) == -1) {
1527 mdb_warn("failed to read vdev_path at %p\n",
1531 } else if (vdev
.vdev_ops
!= NULL
) {
1533 if (mdb_vread(&ops
, sizeof (ops
),
1534 (uintptr_t)vdev
.vdev_ops
) == -1) {
1535 mdb_warn("failed to read vdev_ops at %p\n",
1539 (void) strcpy(desc
, ops
.vdev_op_type
);
1541 (void) strcpy(desc
, "<unknown>");
1544 if (depth
== 0 && DCMD_HDRSPEC(flags
))
1545 mdb_printf("%<u>%-?s %-9s %-12s %-*s%</u>\n",
1546 "ADDR", "STATE", "AUX",
1547 sizeof (uintptr_t) == 4 ? 43 : 35,
1550 mdb_printf("%0?p ", addr
);
1552 switch (vdev
.vdev_state
) {
1553 case VDEV_STATE_CLOSED
:
1556 case VDEV_STATE_OFFLINE
:
1559 case VDEV_STATE_CANT_OPEN
:
1560 state
= "CANT_OPEN";
1562 case VDEV_STATE_DEGRADED
:
1565 case VDEV_STATE_HEALTHY
:
1568 case VDEV_STATE_REMOVED
:
1571 case VDEV_STATE_FAULTED
:
1579 switch (vdev
.vdev_stat
.vs_aux
) {
1583 case VDEV_AUX_OPEN_FAILED
:
1584 aux
= "OPEN_FAILED";
1586 case VDEV_AUX_CORRUPT_DATA
:
1587 aux
= "CORRUPT_DATA";
1589 case VDEV_AUX_NO_REPLICAS
:
1590 aux
= "NO_REPLICAS";
1592 case VDEV_AUX_BAD_GUID_SUM
:
1593 aux
= "BAD_GUID_SUM";
1595 case VDEV_AUX_TOO_SMALL
:
1598 case VDEV_AUX_BAD_LABEL
:
1601 case VDEV_AUX_VERSION_NEWER
:
1604 case VDEV_AUX_VERSION_OLDER
:
1607 case VDEV_AUX_UNSUP_FEAT
:
1610 case VDEV_AUX_SPARED
:
1613 case VDEV_AUX_ERR_EXCEEDED
:
1614 aux
= "ERR_EXCEEDED";
1616 case VDEV_AUX_IO_FAILURE
:
1619 case VDEV_AUX_BAD_LOG
:
1622 case VDEV_AUX_EXTERNAL
:
1625 case VDEV_AUX_SPLIT_POOL
:
1628 case VDEV_AUX_CHILDREN_OFFLINE
:
1629 aux
= "CHILDREN_OFFLINE";
1636 mdb_printf("%-9s %-12s %*s%s\n", state
, aux
, depth
, "", desc
);
1638 if (spa_flags
& SPA_FLAG_ERRORS
) {
1639 vdev_stat_t
*vs
= &vdev
.vdev_stat
;
1644 mdb_printf("%<u> %12s %12s %12s %12s "
1645 "%12s%</u>\n", "READ", "WRITE", "FREE", "CLAIM",
1648 for (i
= 1; i
< ZIO_TYPES
; i
++)
1649 mdb_printf("%11#llx%s", vs
->vs_ops
[i
],
1650 i
== ZIO_TYPES
- 1 ? "" : " ");
1652 mdb_printf("BYTES ");
1653 for (i
= 1; i
< ZIO_TYPES
; i
++)
1654 mdb_printf("%11#llx%s", vs
->vs_bytes
[i
],
1655 i
== ZIO_TYPES
- 1 ? "" : " ");
1659 mdb_printf("EREAD %10#llx\n", vs
->vs_read_errors
);
1660 mdb_printf("EWRITE %10#llx\n", vs
->vs_write_errors
);
1661 mdb_printf("ECKSUM %10#llx\n",
1662 vs
->vs_checksum_errors
);
1667 if (spa_flags
& SPA_FLAG_METASLAB_GROUPS
&&
1668 vdev
.vdev_mg
!= NULL
) {
1669 metaslab_group_stats((uintptr_t)vdev
.vdev_mg
,
1672 if (spa_flags
& SPA_FLAG_METASLABS
&& vdev
.vdev_ms
!= NULL
) {
1673 metaslab_stats((uintptr_t)addr
, spa_flags
);
1677 children
= vdev
.vdev_children
;
1679 if (children
== 0 || !recursive
)
1682 child
= mdb_alloc(children
* sizeof (void *), UM_SLEEP
| UM_GC
);
1683 if (mdb_vread(child
, children
* sizeof (void *),
1684 (uintptr_t)vdev
.vdev_child
) == -1) {
1685 mdb_warn("failed to read vdev children at %p", vdev
.vdev_child
);
1689 for (c
= 0; c
< children
; c
++) {
1690 if (do_print_vdev(child
[c
], flags
, depth
+ 2, recursive
,
1700 vdev_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1703 boolean_t recursive
= B_FALSE
;
1706 if (mdb_getopts(argc
, argv
,
1707 'e', MDB_OPT_SETBITS
, SPA_FLAG_ERRORS
, &spa_flags
,
1708 'm', MDB_OPT_SETBITS
, SPA_FLAG_METASLABS
, &spa_flags
,
1709 'M', MDB_OPT_SETBITS
, SPA_FLAG_METASLAB_GROUPS
, &spa_flags
,
1710 'h', MDB_OPT_SETBITS
, SPA_FLAG_HISTOGRAMS
, &spa_flags
,
1711 'r', MDB_OPT_SETBITS
, TRUE
, &recursive
,
1712 'd', MDB_OPT_UINT64
, &depth
, NULL
) != argc
)
1713 return (DCMD_USAGE
);
1715 if (!(flags
& DCMD_ADDRSPEC
)) {
1716 mdb_warn("no vdev_t address given\n");
1720 return (do_print_vdev(addr
, flags
, (int)depth
, recursive
, spa_flags
));
1723 typedef struct mdb_metaslab_alloc_trace
{
1727 uint64_t mat_weight
;
1728 uint64_t mat_offset
;
1729 uint32_t mat_dva_id
;
1731 } mdb_metaslab_alloc_trace_t
;
1734 metaslab_print_weight(uint64_t weight
)
1738 if (WEIGHT_IS_SPACEBASED(weight
)) {
1740 weight
& ~(METASLAB_ACTIVE_MASK
| METASLAB_WEIGHT_TYPE
),
1743 char size
[NICENUM_BUFLEN
];
1744 mdb_nicenum(1ULL << WEIGHT_GET_INDEX(weight
), size
);
1745 (void) mdb_snprintf(buf
, sizeof (buf
), "%llu x %s",
1746 WEIGHT_GET_COUNT(weight
), size
);
1748 mdb_printf("%11s ", buf
);
1753 metaslab_weight(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1755 uint64_t weight
= 0;
1758 if (argc
== 0 && (flags
& DCMD_ADDRSPEC
)) {
1759 if (mdb_vread(&weight
, sizeof (uint64_t), addr
) == -1) {
1760 mdb_warn("failed to read weight at %p\n", addr
);
1763 } else if (argc
== 1 && !(flags
& DCMD_ADDRSPEC
)) {
1764 weight
= (argv
[0].a_type
== MDB_TYPE_IMMEDIATE
) ?
1765 argv
[0].a_un
.a_val
: mdb_strtoull(argv
[0].a_un
.a_str
);
1767 return (DCMD_USAGE
);
1770 if (DCMD_HDRSPEC(flags
)) {
1771 mdb_printf("%<u>%-6s %9s %9s%</u>\n",
1772 "ACTIVE", "ALGORITHM", "WEIGHT");
1775 if (weight
& METASLAB_WEIGHT_PRIMARY
)
1777 else if (weight
& METASLAB_WEIGHT_SECONDARY
)
1781 mdb_printf("%6c %8s ", active
,
1782 WEIGHT_IS_SPACEBASED(weight
) ? "SPACE" : "SEGMENT");
1783 metaslab_print_weight(weight
);
1791 metaslab_trace(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1793 mdb_metaslab_alloc_trace_t mat
;
1794 mdb_metaslab_group_t mg
= { 0 };
1795 char result_type
[100];
1797 if (mdb_ctf_vread(&mat
, "metaslab_alloc_trace_t",
1798 "mdb_metaslab_alloc_trace_t", addr
, 0) == -1) {
1802 if (!(flags
& DCMD_PIPE_OUT
) && DCMD_HDRSPEC(flags
)) {
1803 mdb_printf("%<u>%6s %6s %8s %11s %11s %18s %18s%</u>\n",
1804 "MSID", "DVA", "ASIZE", "ALLOCATOR", "WEIGHT", "RESULT",
1808 if (mat
.mat_msp
!= 0) {
1811 if (mdb_ctf_vread(&ms
, "metaslab_t", "mdb_metaslab_t",
1812 mat
.mat_msp
, 0) == -1) {
1815 mdb_printf("%6llu ", ms
.ms_id
);
1817 mdb_printf("%6s ", "-");
1820 mdb_printf("%6d %8llx %11llx ", mat
.mat_dva_id
, mat
.mat_size
,
1823 metaslab_print_weight(mat
.mat_weight
);
1825 if ((int64_t)mat
.mat_offset
< 0) {
1826 if (enum_lookup("enum trace_alloc_type", mat
.mat_offset
,
1827 "TRACE_", sizeof (result_type
), result_type
) == -1) {
1828 mdb_warn("Could not find enum for trace_alloc_type");
1831 mdb_printf("%18s ", result_type
);
1833 mdb_printf("%<b>%18llx%</b> ", mat
.mat_offset
);
1836 if (mat
.mat_mg
!= 0 &&
1837 mdb_ctf_vread(&mg
, "metaslab_group_t", "mdb_metaslab_group_t",
1838 mat
.mat_mg
, 0) == -1) {
1842 if (mg
.mg_vd
!= 0) {
1844 char desc
[MAXNAMELEN
];
1846 if (mdb_ctf_vread(&vdev
, "vdev_t", "mdb_vdev_t",
1847 mg
.mg_vd
, 0) == -1) {
1851 if (vdev
.vdev_path
!= 0) {
1852 char path
[MAXNAMELEN
];
1854 if (mdb_readstr(path
, sizeof (path
),
1855 vdev
.vdev_path
) == -1) {
1856 mdb_warn("failed to read vdev_path at %p\n",
1861 if ((slash
= strrchr(path
, '/')) != NULL
) {
1862 strcpy(desc
, slash
+ 1);
1866 } else if (vdev
.vdev_ops
!= 0) {
1868 if (mdb_ctf_vread(&ops
, "vdev_ops_t", "mdb_vdev_ops_t",
1869 vdev
.vdev_ops
, 0) == -1) {
1870 mdb_warn("failed to read vdev_ops at %p\n",
1874 (void) mdb_snprintf(desc
, sizeof (desc
),
1875 "%s-%llu", ops
.vdev_op_type
, vdev
.vdev_id
);
1877 (void) strcpy(desc
, "<unknown>");
1879 mdb_printf("%18s\n", desc
);
1885 typedef struct metaslab_walk_data
{
1886 uint64_t mw_numvdevs
;
1887 uintptr_t *mw_vdevs
;
1892 } metaslab_walk_data_t
;
1895 metaslab_walk_step(mdb_walk_state_t
*wsp
)
1897 metaslab_walk_data_t
*mw
= wsp
->walk_data
;
1901 if (mw
->mw_curvdev
>= mw
->mw_numvdevs
)
1904 if (mw
->mw_mss
== NULL
) {
1908 ASSERT(mw
->mw_curms
== 0);
1909 ASSERT(mw
->mw_nummss
== 0);
1911 vdevp
= mw
->mw_vdevs
[mw
->mw_curvdev
];
1912 if (GETMEMB(vdevp
, "vdev", vdev_ms
, mssp
) ||
1913 GETMEMB(vdevp
, "vdev", vdev_ms_count
, mw
->mw_nummss
)) {
1917 mw
->mw_mss
= mdb_alloc(mw
->mw_nummss
* sizeof (void*),
1919 if (mdb_vread(mw
->mw_mss
, mw
->mw_nummss
* sizeof (void*),
1921 mdb_warn("failed to read vdev_ms at %p", mssp
);
1926 if (mw
->mw_curms
>= mw
->mw_nummss
) {
1934 msp
= mw
->mw_mss
[mw
->mw_curms
];
1935 if (mdb_vread(&ms
, sizeof (metaslab_t
), msp
) == -1) {
1936 mdb_warn("failed to read metaslab_t at %p", msp
);
1942 return (wsp
->walk_callback(msp
, &ms
, wsp
->walk_cbdata
));
1946 metaslab_walk_init(mdb_walk_state_t
*wsp
)
1948 metaslab_walk_data_t
*mw
;
1949 uintptr_t root_vdevp
;
1952 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
1953 mdb_warn("must supply address of spa_t\n");
1957 mw
= mdb_zalloc(sizeof (metaslab_walk_data_t
), UM_SLEEP
| UM_GC
);
1959 if (GETMEMB(wsp
->walk_addr
, "spa", spa_root_vdev
, root_vdevp
) ||
1960 GETMEMB(root_vdevp
, "vdev", vdev_children
, mw
->mw_numvdevs
) ||
1961 GETMEMB(root_vdevp
, "vdev", vdev_child
, childp
)) {
1965 mw
->mw_vdevs
= mdb_alloc(mw
->mw_numvdevs
* sizeof (void *),
1967 if (mdb_vread(mw
->mw_vdevs
, mw
->mw_numvdevs
* sizeof (void *),
1969 mdb_warn("failed to read root vdev children at %p", childp
);
1973 wsp
->walk_data
= mw
;
1978 typedef struct mdb_spa
{
1979 uintptr_t spa_dsl_pool
;
1980 uintptr_t spa_root_vdev
;
1983 typedef struct mdb_dsl_pool
{
1984 uintptr_t dp_root_dir
;
1987 typedef struct mdb_dsl_dir
{
1989 int64_t dd_space_towrite
[TXG_SIZE
];
1992 typedef struct mdb_dsl_dir_phys
{
1993 uint64_t dd_used_bytes
;
1994 uint64_t dd_compressed_bytes
;
1995 uint64_t dd_uncompressed_bytes
;
1996 } mdb_dsl_dir_phys_t
;
1998 typedef struct space_data
{
1999 uint64_t ms_allocating
[TXG_SIZE
];
2000 uint64_t ms_checkpointing
;
2001 uint64_t ms_freeing
;
2003 uint64_t ms_allocatable
;
2004 int64_t ms_deferspace
;
2011 space_cb(uintptr_t addr
, const void *unknown
, void *arg
)
2013 space_data_t
*sd
= arg
;
2015 mdb_range_tree_t rt
;
2016 mdb_space_map_t sm
= { 0 };
2017 mdb_space_map_phys_t smp
= { 0 };
2020 if (mdb_ctf_vread(&ms
, "metaslab_t", "mdb_metaslab_t",
2024 for (i
= 0; i
< TXG_SIZE
; i
++) {
2025 if (mdb_ctf_vread(&rt
, "range_tree_t",
2026 "mdb_range_tree_t", ms
.ms_allocating
[i
], 0) == -1)
2029 sd
->ms_allocating
[i
] += rt
.rt_space
;
2033 if (mdb_ctf_vread(&rt
, "range_tree_t",
2034 "mdb_range_tree_t", ms
.ms_checkpointing
, 0) == -1)
2036 sd
->ms_checkpointing
+= rt
.rt_space
;
2038 if (mdb_ctf_vread(&rt
, "range_tree_t",
2039 "mdb_range_tree_t", ms
.ms_freeing
, 0) == -1)
2041 sd
->ms_freeing
+= rt
.rt_space
;
2043 if (mdb_ctf_vread(&rt
, "range_tree_t",
2044 "mdb_range_tree_t", ms
.ms_freed
, 0) == -1)
2046 sd
->ms_freed
+= rt
.rt_space
;
2048 if (mdb_ctf_vread(&rt
, "range_tree_t",
2049 "mdb_range_tree_t", ms
.ms_allocatable
, 0) == -1)
2051 sd
->ms_allocatable
+= rt
.rt_space
;
2053 if (ms
.ms_sm
!= (uintptr_t)NULL
&&
2054 mdb_ctf_vread(&sm
, "space_map_t",
2055 "mdb_space_map_t", ms
.ms_sm
, 0) == -1)
2058 if (sm
.sm_phys
!= (uintptr_t)NULL
) {
2059 (void) mdb_ctf_vread(&smp
, "space_map_phys_t",
2060 "mdb_space_map_phys_t", sm
.sm_phys
, 0);
2063 sd
->ms_deferspace
+= ms
.ms_deferspace
;
2064 sd
->avail
+= sm
.sm_size
- sm
.sm_alloc
;
2065 sd
->nowavail
+= sm
.sm_size
- smp
.smp_alloc
;
2073 * Given a spa_t, print out it's on-disk space usage and in-core
2074 * estimates of future usage. If -b is given, print space in bytes.
2075 * Otherwise print in megabytes.
2079 spa_space(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2084 mdb_dmu_buf_impl_t db
;
2085 mdb_dsl_dir_phys_t dsp
;
2089 int bytes
= B_FALSE
;
2091 if (mdb_getopts(argc
, argv
, 'b', MDB_OPT_SETBITS
, TRUE
, &bytes
, NULL
) !=
2093 return (DCMD_USAGE
);
2094 if (!(flags
& DCMD_ADDRSPEC
))
2095 return (DCMD_USAGE
);
2102 if (mdb_ctf_vread(&spa
, ZFS_STRUCT
"spa", "mdb_spa_t",
2104 mdb_ctf_vread(&dp
, ZFS_STRUCT
"dsl_pool", "mdb_dsl_pool_t",
2105 spa
.spa_dsl_pool
, 0) == -1 ||
2106 mdb_ctf_vread(&dd
, ZFS_STRUCT
"dsl_dir", "mdb_dsl_dir_t",
2107 dp
.dp_root_dir
, 0) == -1 ||
2108 mdb_ctf_vread(&db
, ZFS_STRUCT
"dmu_buf_impl", "mdb_dmu_buf_impl_t",
2109 dd
.dd_dbuf
, 0) == -1 ||
2110 mdb_ctf_vread(&dsp
, ZFS_STRUCT
"dsl_dir_phys",
2111 "mdb_dsl_dir_phys_t", db
.db
.db_data
, 0) == -1) {
2115 mdb_printf("dd_space_towrite = %llu%s %llu%s %llu%s %llu%s\n",
2116 dd
.dd_space_towrite
[0] >> shift
, suffix
,
2117 dd
.dd_space_towrite
[1] >> shift
, suffix
,
2118 dd
.dd_space_towrite
[2] >> shift
, suffix
,
2119 dd
.dd_space_towrite
[3] >> shift
, suffix
);
2121 mdb_printf("dd_phys.dd_used_bytes = %llu%s\n",
2122 dsp
.dd_used_bytes
>> shift
, suffix
);
2123 mdb_printf("dd_phys.dd_compressed_bytes = %llu%s\n",
2124 dsp
.dd_compressed_bytes
>> shift
, suffix
);
2125 mdb_printf("dd_phys.dd_uncompressed_bytes = %llu%s\n",
2126 dsp
.dd_uncompressed_bytes
>> shift
, suffix
);
2128 bzero(&sd
, sizeof (sd
));
2129 if (mdb_pwalk("metaslab", space_cb
, &sd
, addr
) != 0) {
2130 mdb_warn("can't walk metaslabs");
2134 mdb_printf("ms_allocmap = %llu%s %llu%s %llu%s %llu%s\n",
2135 sd
.ms_allocating
[0] >> shift
, suffix
,
2136 sd
.ms_allocating
[1] >> shift
, suffix
,
2137 sd
.ms_allocating
[2] >> shift
, suffix
,
2138 sd
.ms_allocating
[3] >> shift
, suffix
);
2139 mdb_printf("ms_checkpointing = %llu%s\n",
2140 sd
.ms_checkpointing
>> shift
, suffix
);
2141 mdb_printf("ms_freeing = %llu%s\n",
2142 sd
.ms_freeing
>> shift
, suffix
);
2143 mdb_printf("ms_freed = %llu%s\n",
2144 sd
.ms_freed
>> shift
, suffix
);
2145 mdb_printf("ms_allocatable = %llu%s\n",
2146 sd
.ms_allocatable
>> shift
, suffix
);
2147 mdb_printf("ms_deferspace = %llu%s\n",
2148 sd
.ms_deferspace
>> shift
, suffix
);
2149 mdb_printf("last synced avail = %llu%s\n",
2150 sd
.avail
>> shift
, suffix
);
2151 mdb_printf("current syncing avail = %llu%s\n",
2152 sd
.nowavail
>> shift
, suffix
);
2157 typedef struct mdb_spa_aux_vdev
{
2159 uintptr_t sav_vdevs
;
2160 } mdb_spa_aux_vdev_t
;
2162 typedef struct mdb_spa_vdevs
{
2163 uintptr_t spa_root_vdev
;
2164 mdb_spa_aux_vdev_t spa_l2cache
;
2165 mdb_spa_aux_vdev_t spa_spares
;
2169 spa_print_aux(mdb_spa_aux_vdev_t
*sav
, uint_t flags
, mdb_arg_t
*v
,
2177 * Iterate over aux vdevs and print those out as well. This is a
2178 * little annoying because we don't have a root vdev to pass to ::vdev.
2179 * Instead, we print a single line and then call it for each child
2182 if (sav
->sav_count
!= 0) {
2183 v
[1].a_type
= MDB_TYPE_STRING
;
2184 v
[1].a_un
.a_str
= "-d";
2185 v
[2].a_type
= MDB_TYPE_IMMEDIATE
;
2186 v
[2].a_un
.a_val
= 2;
2188 len
= sav
->sav_count
* sizeof (uintptr_t);
2189 aux
= mdb_alloc(len
, UM_SLEEP
);
2190 if (mdb_vread(aux
, len
, sav
->sav_vdevs
) == -1) {
2192 mdb_warn("failed to read l2cache vdevs at %p",
2197 mdb_printf("%-?s %-9s %-12s %s\n", "-", "-", "-", name
);
2199 for (i
= 0; i
< sav
->sav_count
; i
++) {
2200 ret
= mdb_call_dcmd("vdev", aux
[i
], flags
, 3, v
);
2201 if (ret
!= DCMD_OK
) {
2216 * -e Include error stats
2217 * -m Include metaslab information
2218 * -M Include metaslab group information
2219 * -h Include histogram information (requires -m or -M)
2221 * Print out a summarized list of vdevs for the given spa_t.
2222 * This is accomplished by invoking "::vdev -re" on the root vdev, as well as
2223 * iterating over the cache devices.
2227 spa_vdevs(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2231 char opts
[100] = "-r";
2234 if (mdb_getopts(argc
, argv
,
2235 'e', MDB_OPT_SETBITS
, SPA_FLAG_ERRORS
, &spa_flags
,
2236 'm', MDB_OPT_SETBITS
, SPA_FLAG_METASLABS
, &spa_flags
,
2237 'M', MDB_OPT_SETBITS
, SPA_FLAG_METASLAB_GROUPS
, &spa_flags
,
2238 'h', MDB_OPT_SETBITS
, SPA_FLAG_HISTOGRAMS
, &spa_flags
,
2240 return (DCMD_USAGE
);
2242 if (!(flags
& DCMD_ADDRSPEC
))
2243 return (DCMD_USAGE
);
2245 mdb_spa_vdevs_t spa
;
2246 if (mdb_ctf_vread(&spa
, "spa_t", "mdb_spa_vdevs_t", addr
, 0) == -1)
2250 * Unitialized spa_t structures can have a NULL root vdev.
2252 if (spa
.spa_root_vdev
== (uintptr_t)NULL
) {
2253 mdb_printf("no associated vdevs\n");
2257 if (spa_flags
& SPA_FLAG_ERRORS
)
2259 if (spa_flags
& SPA_FLAG_METASLABS
)
2261 if (spa_flags
& SPA_FLAG_METASLAB_GROUPS
)
2263 if (spa_flags
& SPA_FLAG_HISTOGRAMS
)
2266 v
[0].a_type
= MDB_TYPE_STRING
;
2267 v
[0].a_un
.a_str
= opts
;
2269 ret
= mdb_call_dcmd("vdev", (uintptr_t)spa
.spa_root_vdev
,
2274 if (spa_print_aux(&spa
.spa_l2cache
, flags
, v
, "cache") != 0 ||
2275 spa_print_aux(&spa
.spa_spares
, flags
, v
, "spares") != 0)
2284 * Print a summary of zio_t and all its children. This is intended to display a
2285 * zio tree, and hence we only pick the most important pieces of information for
2286 * the main summary. More detailed information can always be found by doing a
2287 * '::print zio' on the underlying zio_t. The columns we display are:
2289 * ADDRESS TYPE STAGE WAITER TIME_ELAPSED
2291 * The 'address' column is indented by one space for each depth level as we
2292 * descend down the tree.
2295 #define ZIO_MAXINDENT 7
2296 #define ZIO_MAXWIDTH (sizeof (uintptr_t) * 2 + ZIO_MAXINDENT)
2297 #define ZIO_WALK_SELF 0
2298 #define ZIO_WALK_CHILD 1
2299 #define ZIO_WALK_PARENT 2
2301 typedef struct zio_print_args
{
2302 int zpa_current_depth
;
2309 typedef struct mdb_zio
{
2310 enum zio_type io_type
;
2311 enum zio_stage io_stage
;
2312 uintptr_t io_waiter
;
2316 uintptr_t list_next
;
2322 typedef struct mdb_zio_timestamp
{
2323 hrtime_t io_timestamp
;
2324 } mdb_zio_timestamp_t
;
2326 static int zio_child_cb(uintptr_t addr
, const void *unknown
, void *arg
);
2329 zio_print_cb(uintptr_t addr
, zio_print_args_t
*zpa
)
2331 mdb_ctf_id_t type_enum
, stage_enum
;
2332 int indent
= zpa
->zpa_current_depth
;
2333 const char *type
, *stage
;
2336 mdb_zio_timestamp_t zio_timestamp
= { 0 };
2338 if (mdb_ctf_vread(&zio
, ZFS_STRUCT
"zio", "mdb_zio_t", addr
, 0) == -1)
2340 (void) mdb_ctf_vread(&zio_timestamp
, ZFS_STRUCT
"zio",
2341 "mdb_zio_timestamp_t", addr
, MDB_CTF_VREAD_QUIET
);
2343 if (indent
> ZIO_MAXINDENT
)
2344 indent
= ZIO_MAXINDENT
;
2346 if (mdb_ctf_lookup_by_name("enum zio_type", &type_enum
) == -1 ||
2347 mdb_ctf_lookup_by_name("enum zio_stage", &stage_enum
) == -1) {
2348 mdb_warn("failed to lookup zio enums");
2352 if ((type
= mdb_ctf_enum_name(type_enum
, zio
.io_type
)) != NULL
)
2353 type
+= sizeof ("ZIO_TYPE_") - 1;
2357 if (zio
.io_error
== 0) {
2358 stage
= mdb_ctf_enum_name(stage_enum
, zio
.io_stage
);
2360 stage
+= sizeof ("ZIO_STAGE_") - 1;
2367 if (zpa
->zpa_current_depth
>= zpa
->zpa_min_depth
) {
2368 if (zpa
->zpa_flags
& DCMD_PIPE_OUT
) {
2369 mdb_printf("%?p\n", addr
);
2371 mdb_printf("%*s%-*p %-5s %-16s ", indent
, "",
2372 ZIO_MAXWIDTH
- indent
, addr
, type
, stage
);
2373 if (zio
.io_waiter
!= 0)
2374 mdb_printf("%-16lx ", zio
.io_waiter
);
2376 mdb_printf("%-16s ", "-");
2378 if (zio_timestamp
.io_timestamp
!= 0) {
2379 mdb_printf("%llums", (mdb_gethrtime() -
2380 zio_timestamp
.io_timestamp
) /
2383 mdb_printf("%-12s ", "-");
2386 mdb_printf("%-12s ", "-");
2392 if (zpa
->zpa_current_depth
>= zpa
->zpa_max_depth
)
2395 if (zpa
->zpa_type
== ZIO_WALK_PARENT
)
2396 laddr
= addr
+ mdb_ctf_offsetof_by_name(ZFS_STRUCT
"zio",
2399 laddr
= addr
+ mdb_ctf_offsetof_by_name(ZFS_STRUCT
"zio",
2402 zpa
->zpa_current_depth
++;
2403 if (mdb_pwalk("list", zio_child_cb
, zpa
, laddr
) != 0) {
2404 mdb_warn("failed to walk zio_t children at %p\n", laddr
);
2407 zpa
->zpa_current_depth
--;
2414 zio_child_cb(uintptr_t addr
, const void *unknown
, void *arg
)
2418 zio_print_args_t
*zpa
= arg
;
2420 if (mdb_vread(&zl
, sizeof (zl
), addr
) == -1) {
2421 mdb_warn("failed to read zio_link_t at %p", addr
);
2425 if (zpa
->zpa_type
== ZIO_WALK_PARENT
)
2426 ziop
= (uintptr_t)zl
.zl_parent
;
2428 ziop
= (uintptr_t)zl
.zl_child
;
2430 return (zio_print_cb(ziop
, zpa
));
2435 zio_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2437 zio_print_args_t zpa
= { 0 };
2439 if (!(flags
& DCMD_ADDRSPEC
))
2440 return (DCMD_USAGE
);
2442 if (mdb_getopts(argc
, argv
,
2443 'r', MDB_OPT_SETBITS
, INT_MAX
, &zpa
.zpa_max_depth
,
2444 'c', MDB_OPT_SETBITS
, ZIO_WALK_CHILD
, &zpa
.zpa_type
,
2445 'p', MDB_OPT_SETBITS
, ZIO_WALK_PARENT
, &zpa
.zpa_type
,
2447 return (DCMD_USAGE
);
2449 zpa
.zpa_flags
= flags
;
2450 if (zpa
.zpa_max_depth
!= 0) {
2451 if (zpa
.zpa_type
== ZIO_WALK_SELF
)
2452 zpa
.zpa_type
= ZIO_WALK_CHILD
;
2453 } else if (zpa
.zpa_type
!= ZIO_WALK_SELF
) {
2454 zpa
.zpa_min_depth
= 1;
2455 zpa
.zpa_max_depth
= 1;
2458 if (!(flags
& DCMD_PIPE_OUT
) && DCMD_HDRSPEC(flags
)) {
2459 mdb_printf("%<u>%-*s %-5s %-16s %-16s %-12s%</u>\n",
2460 ZIO_MAXWIDTH
, "ADDRESS", "TYPE", "STAGE", "WAITER",
2464 if (zio_print_cb(addr
, &zpa
) != WALK_NEXT
)
2473 * Print a summary of all zio_t structures on the system, or for a particular
2474 * pool. This is equivalent to '::walk zio_root | ::zio'.
2478 zio_state(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2481 * MDB will remember the last address of the pipeline, so if we don't
2482 * zero this we'll end up trying to walk zio structures for a
2483 * non-existent spa_t.
2485 if (!(flags
& DCMD_ADDRSPEC
))
2488 return (mdb_pwalk_dcmd("zio_root", "zio", argc
, argv
, addr
));
2491 typedef struct mdb_multilist
{
2492 uint64_t ml_num_sublists
;
2493 uintptr_t ml_sublists
;
2496 typedef struct multilist_walk_data
{
2498 mdb_multilist_t mwd_ml
;
2499 } multilist_walk_data_t
;
2503 multilist_print_cb(uintptr_t addr
, const void *unknown
, void *arg
)
2505 mdb_printf("%#lr\n", addr
);
2510 multilist_walk_step(mdb_walk_state_t
*wsp
)
2512 multilist_walk_data_t
*mwd
= wsp
->walk_data
;
2514 if (mwd
->mwd_idx
>= mwd
->mwd_ml
.ml_num_sublists
)
2517 wsp
->walk_addr
= mwd
->mwd_ml
.ml_sublists
+
2518 mdb_ctf_sizeof_by_name("multilist_sublist_t") * mwd
->mwd_idx
+
2519 mdb_ctf_offsetof_by_name("multilist_sublist_t", "mls_list");
2521 mdb_pwalk("list", multilist_print_cb
, NULL
, wsp
->walk_addr
);
2528 multilist_walk_init(mdb_walk_state_t
*wsp
)
2530 multilist_walk_data_t
*mwd
;
2532 if (wsp
->walk_addr
== 0) {
2533 mdb_warn("must supply address of multilist_t\n");
2537 mwd
= mdb_zalloc(sizeof (multilist_walk_data_t
), UM_SLEEP
| UM_GC
);
2538 if (mdb_ctf_vread(&mwd
->mwd_ml
, "multilist_t", "mdb_multilist_t",
2539 wsp
->walk_addr
, 0) == -1) {
2543 if (mwd
->mwd_ml
.ml_num_sublists
== 0 ||
2544 mwd
->mwd_ml
.ml_sublists
== 0) {
2545 mdb_warn("invalid or uninitialized multilist at %#lx\n",
2550 wsp
->walk_data
= mwd
;
2554 typedef struct mdb_txg_list
{
2556 uintptr_t tl_head
[TXG_SIZE
];
2559 typedef struct txg_list_walk_data
{
2560 uintptr_t lw_head
[TXG_SIZE
];
2565 } txg_list_walk_data_t
;
2568 txg_list_walk_init_common(mdb_walk_state_t
*wsp
, int txg
, int maxoff
)
2570 txg_list_walk_data_t
*lwd
;
2571 mdb_txg_list_t list
;
2574 lwd
= mdb_alloc(sizeof (txg_list_walk_data_t
), UM_SLEEP
| UM_GC
);
2575 if (mdb_ctf_vread(&list
, "txg_list_t", "mdb_txg_list_t", wsp
->walk_addr
,
2577 mdb_warn("failed to read txg_list_t at %#lx", wsp
->walk_addr
);
2581 for (i
= 0; i
< TXG_SIZE
; i
++)
2582 lwd
->lw_head
[i
] = list
.tl_head
[i
];
2583 lwd
->lw_offset
= list
.tl_offset
;
2584 lwd
->lw_obj
= mdb_alloc(lwd
->lw_offset
+ sizeof (txg_node_t
),
2586 lwd
->lw_txgoff
= txg
;
2587 lwd
->lw_maxoff
= maxoff
;
2589 wsp
->walk_addr
= lwd
->lw_head
[lwd
->lw_txgoff
];
2590 wsp
->walk_data
= lwd
;
2596 txg_list_walk_init(mdb_walk_state_t
*wsp
)
2598 return (txg_list_walk_init_common(wsp
, 0, TXG_SIZE
-1));
2602 txg_list0_walk_init(mdb_walk_state_t
*wsp
)
2604 return (txg_list_walk_init_common(wsp
, 0, 0));
2608 txg_list1_walk_init(mdb_walk_state_t
*wsp
)
2610 return (txg_list_walk_init_common(wsp
, 1, 1));
2614 txg_list2_walk_init(mdb_walk_state_t
*wsp
)
2616 return (txg_list_walk_init_common(wsp
, 2, 2));
2620 txg_list3_walk_init(mdb_walk_state_t
*wsp
)
2622 return (txg_list_walk_init_common(wsp
, 3, 3));
2626 txg_list_walk_step(mdb_walk_state_t
*wsp
)
2628 txg_list_walk_data_t
*lwd
= wsp
->walk_data
;
2633 while (wsp
->walk_addr
== (uintptr_t)NULL
&&
2634 lwd
->lw_txgoff
< lwd
->lw_maxoff
) {
2636 wsp
->walk_addr
= lwd
->lw_head
[lwd
->lw_txgoff
];
2639 if (wsp
->walk_addr
== (uintptr_t)NULL
)
2642 addr
= wsp
->walk_addr
- lwd
->lw_offset
;
2644 if (mdb_vread(lwd
->lw_obj
,
2645 lwd
->lw_offset
+ sizeof (txg_node_t
), addr
) == -1) {
2646 mdb_warn("failed to read list element at %#lx", addr
);
2650 status
= wsp
->walk_callback(addr
, lwd
->lw_obj
, wsp
->walk_cbdata
);
2651 node
= (txg_node_t
*)((uintptr_t)lwd
->lw_obj
+ lwd
->lw_offset
);
2652 wsp
->walk_addr
= (uintptr_t)node
->tn_next
[lwd
->lw_txgoff
];
2660 * Walk all named spa_t structures in the namespace. This is nothing more than
2661 * a layered avl walk.
2664 spa_walk_init(mdb_walk_state_t
*wsp
)
2668 if (wsp
->walk_addr
!= (uintptr_t)NULL
) {
2669 mdb_warn("spa walk only supports global walks\n");
2673 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, "spa_namespace_avl", &sym
) == -1) {
2674 mdb_warn("failed to find symbol 'spa_namespace_avl'");
2678 wsp
->walk_addr
= (uintptr_t)sym
.st_value
;
2680 if (mdb_layered_walk("avl", wsp
) == -1) {
2681 mdb_warn("failed to walk 'avl'\n");
2689 spa_walk_step(mdb_walk_state_t
*wsp
)
2691 return (wsp
->walk_callback(wsp
->walk_addr
, NULL
, wsp
->walk_cbdata
));
2697 * Walk all active zio_t structures on the system. This is simply a layered
2698 * walk on top of ::walk zio_cache, with the optional ability to limit the
2699 * structures to a particular pool.
2702 zio_walk_init(mdb_walk_state_t
*wsp
)
2704 wsp
->walk_data
= (void *)wsp
->walk_addr
;
2706 if (mdb_layered_walk("zio_cache", wsp
) == -1) {
2707 mdb_warn("failed to walk 'zio_cache'\n");
2715 zio_walk_step(mdb_walk_state_t
*wsp
)
2718 uintptr_t spa
= (uintptr_t)wsp
->walk_data
;
2720 if (mdb_ctf_vread(&zio
, ZFS_STRUCT
"zio", "mdb_zio_t",
2721 wsp
->walk_addr
, 0) == -1)
2724 if (spa
!= 0 && spa
!= zio
.io_spa
)
2727 return (wsp
->walk_callback(wsp
->walk_addr
, &zio
, wsp
->walk_cbdata
));
2731 * [addr]::walk zio_root
2733 * Walk only root zio_t structures, optionally for a particular spa_t.
2736 zio_walk_root_step(mdb_walk_state_t
*wsp
)
2739 uintptr_t spa
= (uintptr_t)wsp
->walk_data
;
2741 if (mdb_ctf_vread(&zio
, ZFS_STRUCT
"zio", "mdb_zio_t",
2742 wsp
->walk_addr
, 0) == -1)
2745 if (spa
!= 0 && spa
!= zio
.io_spa
)
2748 /* If the parent list is not empty, ignore */
2749 if (zio
.io_parent_list
.list_head
.list_next
!=
2751 mdb_ctf_offsetof_by_name(ZFS_STRUCT
"zio", "io_parent_list") +
2752 mdb_ctf_offsetof_by_name("struct list", "list_head"))
2755 return (wsp
->walk_callback(wsp
->walk_addr
, &zio
, wsp
->walk_cbdata
));
2761 * -v print verbose per-level information
2765 zfs_blkstats(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2767 boolean_t verbose
= B_FALSE
;
2768 zfs_all_blkstats_t stats
;
2769 dmu_object_type_t t
;
2772 dmu_object_type_info_t dmu_ot
[DMU_OT_NUMTYPES
+ 10];
2773 /* +10 in case it grew */
2775 if (mdb_readvar(&dmu_ot
, "dmu_ot") == -1) {
2776 mdb_warn("failed to read 'dmu_ot'");
2780 if (mdb_getopts(argc
, argv
,
2781 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
,
2783 return (DCMD_USAGE
);
2785 if (!(flags
& DCMD_ADDRSPEC
))
2786 return (DCMD_USAGE
);
2788 if (GETMEMB(addr
, "spa", spa_dsl_pool
, addr
) ||
2789 GETMEMB(addr
, "dsl_pool", dp_blkstats
, addr
) ||
2790 mdb_vread(&stats
, sizeof (zfs_all_blkstats_t
), addr
) == -1) {
2791 mdb_warn("failed to read data at %p;", addr
);
2792 mdb_printf("maybe no stats? run \"zpool scrub\" first.");
2796 tzb
= &stats
.zab_type
[DN_MAX_LEVELS
][DMU_OT_TOTAL
];
2797 if (tzb
->zb_gangs
!= 0) {
2798 mdb_printf("Ganged blocks: %llu\n",
2799 (longlong_t
)tzb
->zb_gangs
);
2802 ditto
= tzb
->zb_ditto_2_of_2_samevdev
+ tzb
->zb_ditto_2_of_3_samevdev
+
2803 tzb
->zb_ditto_3_of_3_samevdev
;
2805 mdb_printf("Dittoed blocks on same vdev: %llu\n",
2809 mdb_printf("\nBlocks\tLSIZE\tPSIZE\tASIZE"
2810 "\t avg\t comp\t%%Total\tType\n");
2812 for (t
= 0; t
<= DMU_OT_TOTAL
; t
++) {
2813 char csize
[NICENUM_BUFLEN
], lsize
[NICENUM_BUFLEN
];
2814 char psize
[NICENUM_BUFLEN
], asize
[NICENUM_BUFLEN
];
2815 char avg
[NICENUM_BUFLEN
];
2816 char comp
[NICENUM_BUFLEN
], pct
[NICENUM_BUFLEN
];
2821 if (t
== DMU_OT_DEFERRED
)
2822 strcpy(typename
, "deferred free");
2823 else if (t
== DMU_OT_OTHER
)
2824 strcpy(typename
, "other");
2825 else if (t
== DMU_OT_TOTAL
)
2826 strcpy(typename
, "Total");
2827 else if (mdb_readstr(typename
, sizeof (typename
),
2828 (uintptr_t)dmu_ot
[t
].ot_name
) == -1) {
2829 mdb_warn("failed to read type name");
2833 if (stats
.zab_type
[DN_MAX_LEVELS
][t
].zb_asize
== 0)
2836 for (l
= -1; l
< DN_MAX_LEVELS
; l
++) {
2837 int level
= (l
== -1 ? DN_MAX_LEVELS
: l
);
2838 zfs_blkstat_t
*zb
= &stats
.zab_type
[level
][t
];
2840 if (zb
->zb_asize
== 0)
2844 * Don't print each level unless requested.
2846 if (!verbose
&& level
!= DN_MAX_LEVELS
)
2850 * If all the space is level 0, don't print the
2851 * level 0 separately.
2853 if (level
== 0 && zb
->zb_asize
==
2854 stats
.zab_type
[DN_MAX_LEVELS
][t
].zb_asize
)
2857 mdb_nicenum(zb
->zb_count
, csize
);
2858 mdb_nicenum(zb
->zb_lsize
, lsize
);
2859 mdb_nicenum(zb
->zb_psize
, psize
);
2860 mdb_nicenum(zb
->zb_asize
, asize
);
2861 mdb_nicenum(zb
->zb_asize
/ zb
->zb_count
, avg
);
2862 (void) snprintfrac(comp
, NICENUM_BUFLEN
,
2863 zb
->zb_lsize
, zb
->zb_psize
, 2);
2864 (void) snprintfrac(pct
, NICENUM_BUFLEN
,
2865 100 * zb
->zb_asize
, tzb
->zb_asize
, 2);
2867 mdb_printf("%6s\t%5s\t%5s\t%5s\t%5s"
2869 csize
, lsize
, psize
, asize
, avg
, comp
, pct
);
2871 if (level
== DN_MAX_LEVELS
)
2872 mdb_printf("%s\n", typename
);
2874 mdb_printf(" L%d %s\n",
2882 typedef struct mdb_reference
{
2883 uintptr_t ref_holder
;
2884 uintptr_t ref_removed
;
2885 uint64_t ref_number
;
2890 reference_cb(uintptr_t addr
, const void *ignored
, void *arg
)
2892 mdb_reference_t ref
;
2893 boolean_t holder_is_str
= B_FALSE
;
2894 char holder_str
[128];
2895 boolean_t removed
= (boolean_t
)arg
;
2897 if (mdb_ctf_vread(&ref
, "reference_t", "mdb_reference_t", addr
,
2901 if (mdb_readstr(holder_str
, sizeof (holder_str
),
2902 ref
.ref_holder
) != -1)
2903 holder_is_str
= strisprint(holder_str
);
2906 mdb_printf("removed ");
2907 mdb_printf("reference ");
2908 if (ref
.ref_number
!= 1)
2909 mdb_printf("with count=%llu ", ref
.ref_number
);
2910 mdb_printf("with tag %lx", ref
.ref_holder
);
2912 mdb_printf(" \"%s\"", holder_str
);
2913 mdb_printf(", held at:\n");
2915 (void) mdb_call_dcmd("whatis", addr
, DCMD_ADDRSPEC
, 0, NULL
);
2918 mdb_printf("removed at:\n");
2919 (void) mdb_call_dcmd("whatis", ref
.ref_removed
,
2920 DCMD_ADDRSPEC
, 0, NULL
);
2928 typedef struct mdb_refcount
{
2932 typedef struct mdb_refcount_removed
{
2933 uint64_t rc_removed_count
;
2934 } mdb_refcount_removed_t
;
2936 typedef struct mdb_refcount_tracked
{
2937 boolean_t rc_tracked
;
2938 } mdb_refcount_tracked_t
;
2942 refcount(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2945 mdb_refcount_removed_t rcr
;
2946 mdb_refcount_tracked_t rct
;
2948 boolean_t released
= B_FALSE
;
2950 if (!(flags
& DCMD_ADDRSPEC
))
2951 return (DCMD_USAGE
);
2953 if (mdb_getopts(argc
, argv
,
2954 'r', MDB_OPT_SETBITS
, B_TRUE
, &released
,
2956 return (DCMD_USAGE
);
2958 if (mdb_ctf_vread(&rc
, "refcount_t", "mdb_refcount_t", addr
,
2962 if (mdb_ctf_vread(&rcr
, "refcount_t", "mdb_refcount_removed_t", addr
,
2963 MDB_CTF_VREAD_QUIET
) == -1) {
2964 mdb_printf("refcount_t at %p has %llu holds (untracked)\n",
2965 addr
, (longlong_t
)rc
.rc_count
);
2969 if (mdb_ctf_vread(&rct
, "refcount_t", "mdb_refcount_tracked_t", addr
,
2970 MDB_CTF_VREAD_QUIET
) == -1) {
2971 /* If this is an old target, it might be tracked. */
2972 rct
.rc_tracked
= B_TRUE
;
2975 mdb_printf("refcount_t at %p has %llu current holds, "
2976 "%llu recently released holds\n",
2977 addr
, (longlong_t
)rc
.rc_count
, (longlong_t
)rcr
.rc_removed_count
);
2979 if (rct
.rc_tracked
&& rc
.rc_count
> 0)
2980 mdb_printf("current holds:\n");
2981 off
= mdb_ctf_offsetof_by_name("refcount_t", "rc_list");
2984 mdb_pwalk("list", reference_cb
, (void*)B_FALSE
, addr
+ off
);
2986 if (released
&& rcr
.rc_removed_count
> 0) {
2987 mdb_printf("released holds:\n");
2989 off
= mdb_ctf_offsetof_by_name("refcount_t", "rc_removed");
2992 mdb_pwalk("list", reference_cb
, (void*)B_TRUE
, addr
+ off
);
3000 sa_attr_table(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
3002 sa_attr_table_t
*table
;
3007 if (mdb_vread(&sa_os
, sizeof (sa_os_t
), addr
) == -1) {
3008 mdb_warn("failed to read sa_os at %p", addr
);
3012 table
= mdb_alloc(sizeof (sa_attr_table_t
) * sa_os
.sa_num_attrs
,
3014 name
= mdb_alloc(MAXPATHLEN
, UM_SLEEP
| UM_GC
);
3016 if (mdb_vread(table
, sizeof (sa_attr_table_t
) * sa_os
.sa_num_attrs
,
3017 (uintptr_t)sa_os
.sa_attr_table
) == -1) {
3018 mdb_warn("failed to read sa_os at %p", addr
);
3022 mdb_printf("%<u>%-10s %-10s %-10s %-10s %s%</u>\n",
3023 "ATTR ID", "REGISTERED", "LENGTH", "BSWAP", "NAME");
3024 for (i
= 0; i
!= sa_os
.sa_num_attrs
; i
++) {
3025 mdb_readstr(name
, MAXPATHLEN
, (uintptr_t)table
[i
].sa_name
);
3026 mdb_printf("%5x %8x %8x %8x %-s\n",
3027 (int)table
[i
].sa_attr
, (int)table
[i
].sa_registered
,
3028 (int)table
[i
].sa_length
, table
[i
].sa_byteswap
, name
);
3035 sa_get_off_table(uintptr_t addr
, uint32_t **off_tab
, int attr_count
)
3037 uintptr_t idx_table
;
3039 if (GETMEMB(addr
, "sa_idx_tab", sa_idx_tab
, idx_table
)) {
3040 mdb_printf("can't find offset table in sa_idx_tab\n");
3044 *off_tab
= mdb_alloc(attr_count
* sizeof (uint32_t),
3047 if (mdb_vread(*off_tab
,
3048 attr_count
* sizeof (uint32_t), idx_table
) == -1) {
3049 mdb_warn("failed to attribute offset table %p", idx_table
);
3058 sa_attr_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
3060 uint32_t *offset_tab
;
3063 uintptr_t attr_addr
;
3064 uintptr_t bonus_tab
, spill_tab
;
3065 uintptr_t db_bonus
, db_spill
;
3066 uintptr_t os
, os_sa
;
3070 return (DCMD_USAGE
);
3072 if (argv
[0].a_type
== MDB_TYPE_STRING
)
3073 attr_id
= mdb_strtoull(argv
[0].a_un
.a_str
);
3075 return (DCMD_USAGE
);
3077 if (GETMEMB(addr
, "sa_handle", sa_bonus_tab
, bonus_tab
) ||
3078 GETMEMB(addr
, "sa_handle", sa_spill_tab
, spill_tab
) ||
3079 GETMEMB(addr
, "sa_handle", sa_os
, os
) ||
3080 GETMEMB(addr
, "sa_handle", sa_bonus
, db_bonus
) ||
3081 GETMEMB(addr
, "sa_handle", sa_spill
, db_spill
)) {
3082 mdb_printf("Can't find necessary information in sa_handle "
3087 if (GETMEMB(os
, "objset", os_sa
, os_sa
)) {
3088 mdb_printf("Can't find os_sa in objset\n");
3092 if (GETMEMB(os_sa
, "sa_os", sa_num_attrs
, attr_count
)) {
3093 mdb_printf("Can't find sa_num_attrs\n");
3097 if (attr_id
> attr_count
) {
3098 mdb_printf("attribute id number is out of range\n");
3103 if (sa_get_off_table(bonus_tab
, &offset_tab
,
3104 attr_count
) == -1) {
3108 if (GETMEMB(db_bonus
, "dmu_buf", db_data
, db_data
)) {
3109 mdb_printf("can't find db_data in bonus dbuf\n");
3114 if (bonus_tab
&& !TOC_ATTR_PRESENT(offset_tab
[attr_id
]) &&
3115 spill_tab
== (uintptr_t)NULL
) {
3116 mdb_printf("Attribute does not exist\n");
3118 } else if (!TOC_ATTR_PRESENT(offset_tab
[attr_id
]) && spill_tab
) {
3119 if (sa_get_off_table(spill_tab
, &offset_tab
,
3120 attr_count
) == -1) {
3123 if (GETMEMB(db_spill
, "dmu_buf", db_data
, db_data
)) {
3124 mdb_printf("can't find db_data in spill dbuf\n");
3127 if (!TOC_ATTR_PRESENT(offset_tab
[attr_id
])) {
3128 mdb_printf("Attribute does not exist\n");
3132 attr_addr
= db_data
+ TOC_OFF(offset_tab
[attr_id
]);
3133 mdb_printf("%p\n", attr_addr
);
3139 zfs_ace_print_common(uintptr_t addr
, uint_t flags
,
3140 uint64_t id
, uint32_t access_mask
, uint16_t ace_flags
,
3141 uint16_t ace_type
, int verbose
)
3143 if (DCMD_HDRSPEC(flags
) && !verbose
)
3144 mdb_printf("%<u>%-?s %-8s %-8s %-8s %s%</u>\n",
3145 "ADDR", "FLAGS", "MASK", "TYPE", "ID");
3148 mdb_printf("%0?p %-8x %-8x %-8x %-llx\n", addr
,
3149 ace_flags
, access_mask
, ace_type
, id
);
3153 switch (ace_flags
& ACE_TYPE_FLAGS
) {
3155 mdb_printf("owner@:");
3157 case (ACE_IDENTIFIER_GROUP
| ACE_GROUP
):
3158 mdb_printf("group@:");
3161 mdb_printf("everyone@:");
3163 case ACE_IDENTIFIER_GROUP
:
3164 mdb_printf("group:%llx:", (u_longlong_t
)id
);
3166 case 0: /* User entry */
3167 mdb_printf("user:%llx:", (u_longlong_t
)id
);
3171 /* print out permission mask */
3172 if (access_mask
& ACE_READ_DATA
)
3176 if (access_mask
& ACE_WRITE_DATA
)
3180 if (access_mask
& ACE_EXECUTE
)
3184 if (access_mask
& ACE_APPEND_DATA
)
3188 if (access_mask
& ACE_DELETE
)
3192 if (access_mask
& ACE_DELETE_CHILD
)
3196 if (access_mask
& ACE_READ_ATTRIBUTES
)
3200 if (access_mask
& ACE_WRITE_ATTRIBUTES
)
3204 if (access_mask
& ACE_READ_NAMED_ATTRS
)
3208 if (access_mask
& ACE_WRITE_NAMED_ATTRS
)
3212 if (access_mask
& ACE_READ_ACL
)
3216 if (access_mask
& ACE_WRITE_ACL
)
3220 if (access_mask
& ACE_WRITE_OWNER
)
3224 if (access_mask
& ACE_SYNCHRONIZE
)
3231 /* Print out inheritance flags */
3232 if (ace_flags
& ACE_FILE_INHERIT_ACE
)
3236 if (ace_flags
& ACE_DIRECTORY_INHERIT_ACE
)
3240 if (ace_flags
& ACE_INHERIT_ONLY_ACE
)
3244 if (ace_flags
& ACE_NO_PROPAGATE_INHERIT_ACE
)
3248 if (ace_flags
& ACE_SUCCESSFUL_ACCESS_ACE_FLAG
)
3252 if (ace_flags
& ACE_FAILED_ACCESS_ACE_FLAG
)
3256 if (ace_flags
& ACE_INHERITED_ACE
)
3262 case ACE_ACCESS_ALLOWED_ACE_TYPE
:
3263 mdb_printf(":allow\n");
3265 case ACE_ACCESS_DENIED_ACE_TYPE
:
3266 mdb_printf(":deny\n");
3268 case ACE_SYSTEM_AUDIT_ACE_TYPE
:
3269 mdb_printf(":audit\n");
3271 case ACE_SYSTEM_ALARM_ACE_TYPE
:
3272 mdb_printf(":alarm\n");
3282 zfs_ace_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
3285 int verbose
= FALSE
;
3288 if (!(flags
& DCMD_ADDRSPEC
))
3289 return (DCMD_USAGE
);
3291 if (mdb_getopts(argc
, argv
,
3292 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
, TRUE
, NULL
) != argc
)
3293 return (DCMD_USAGE
);
3295 if (mdb_vread(&zace
, sizeof (zfs_ace_t
), addr
) == -1) {
3296 mdb_warn("failed to read zfs_ace_t");
3300 if ((zace
.z_hdr
.z_flags
& ACE_TYPE_FLAGS
) == 0 ||
3301 (zace
.z_hdr
.z_flags
& ACE_TYPE_FLAGS
) == ACE_IDENTIFIER_GROUP
)
3306 return (zfs_ace_print_common(addr
, flags
, id
, zace
.z_hdr
.z_access_mask
,
3307 zace
.z_hdr
.z_flags
, zace
.z_hdr
.z_type
, verbose
));
3312 zfs_ace0_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
3316 int verbose
= FALSE
;
3318 if (!(flags
& DCMD_ADDRSPEC
))
3319 return (DCMD_USAGE
);
3321 if (mdb_getopts(argc
, argv
,
3322 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
, TRUE
, NULL
) != argc
)
3323 return (DCMD_USAGE
);
3325 if (mdb_vread(&ace
, sizeof (ace_t
), addr
) == -1) {
3326 mdb_warn("failed to read ace_t");
3330 if ((ace
.a_flags
& ACE_TYPE_FLAGS
) == 0 ||
3331 (ace
.a_flags
& ACE_TYPE_FLAGS
) == ACE_IDENTIFIER_GROUP
)
3336 return (zfs_ace_print_common(addr
, flags
, id
, ace
.a_access_mask
,
3337 ace
.a_flags
, ace
.a_type
, verbose
));
3340 typedef struct acl_dump_args
{
3342 const mdb_arg_t
*a_argv
;
3349 acl_aces_cb(uintptr_t addr
, const void *unknown
, void *arg
)
3351 acl_dump_args_t
*acl_args
= (acl_dump_args_t
*)arg
;
3353 if (acl_args
->a_version
== 1) {
3354 if (mdb_call_dcmd("zfs_ace", addr
,
3355 DCMD_ADDRSPEC
|acl_args
->a_flags
, acl_args
->a_argc
,
3356 acl_args
->a_argv
) != DCMD_OK
) {
3360 if (mdb_call_dcmd("zfs_ace0", addr
,
3361 DCMD_ADDRSPEC
|acl_args
->a_flags
, acl_args
->a_argc
,
3362 acl_args
->a_argv
) != DCMD_OK
) {
3366 acl_args
->a_flags
= DCMD_LOOP
;
3372 acl_cb(uintptr_t addr
, const void *unknown
, void *arg
)
3374 acl_dump_args_t
*acl_args
= (acl_dump_args_t
*)arg
;
3376 if (acl_args
->a_version
== 1) {
3377 if (mdb_pwalk("zfs_acl_node_aces", acl_aces_cb
,
3379 mdb_warn("can't walk ACEs");
3383 if (mdb_pwalk("zfs_acl_node_aces0", acl_aces_cb
,
3385 mdb_warn("can't walk ACEs");
3394 zfs_acl_dump(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
3397 int verbose
= FALSE
;
3398 acl_dump_args_t acl_args
;
3400 if (!(flags
& DCMD_ADDRSPEC
))
3401 return (DCMD_USAGE
);
3403 if (mdb_getopts(argc
, argv
,
3404 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
, TRUE
, NULL
) != argc
)
3405 return (DCMD_USAGE
);
3407 if (mdb_vread(&zacl
, sizeof (zfs_acl_t
), addr
) == -1) {
3408 mdb_warn("failed to read zfs_acl_t");
3412 acl_args
.a_argc
= argc
;
3413 acl_args
.a_argv
= argv
;
3414 acl_args
.a_version
= zacl
.z_version
;
3415 acl_args
.a_flags
= DCMD_LOOPFIRST
;
3417 if (mdb_pwalk("zfs_acl_node", acl_cb
, &acl_args
, addr
) != 0) {
3418 mdb_warn("can't walk ACL");
3427 zfs_acl_node_walk_init(mdb_walk_state_t
*wsp
)
3429 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
3430 mdb_warn("must supply address of zfs_acl_node_t\n");
3435 mdb_ctf_offsetof_by_name(ZFS_STRUCT
"zfs_acl", "z_acl");
3437 if (mdb_layered_walk("list", wsp
) == -1) {
3438 mdb_warn("failed to walk 'list'\n");
3446 zfs_acl_node_walk_step(mdb_walk_state_t
*wsp
)
3448 zfs_acl_node_t aclnode
;
3450 if (mdb_vread(&aclnode
, sizeof (zfs_acl_node_t
),
3451 wsp
->walk_addr
) == -1) {
3452 mdb_warn("failed to read zfs_acl_node at %p", wsp
->walk_addr
);
3456 return (wsp
->walk_callback(wsp
->walk_addr
, &aclnode
, wsp
->walk_cbdata
));
3459 typedef struct ace_walk_data
{
3465 zfs_aces_walk_init_common(mdb_walk_state_t
*wsp
, int version
,
3466 int ace_count
, uintptr_t ace_data
)
3468 ace_walk_data_t
*ace_walk_data
;
3470 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
3471 mdb_warn("must supply address of zfs_acl_node_t\n");
3475 ace_walk_data
= mdb_alloc(sizeof (ace_walk_data_t
), UM_SLEEP
| UM_GC
);
3477 ace_walk_data
->ace_count
= ace_count
;
3478 ace_walk_data
->ace_version
= version
;
3480 wsp
->walk_addr
= ace_data
;
3481 wsp
->walk_data
= ace_walk_data
;
3487 zfs_acl_node_aces_walk_init_common(mdb_walk_state_t
*wsp
, int version
)
3490 static mdb_ctf_id_t acl_id
;
3492 uintptr_t z_acldata
;
3495 if (mdb_ctf_lookup_by_name("struct zfs_acl_node",
3497 mdb_warn("couldn't find struct zfs_acl_node");
3503 if (GETMEMBID(wsp
->walk_addr
, &acl_id
, z_ace_count
, z_ace_count
)) {
3506 if (GETMEMBID(wsp
->walk_addr
, &acl_id
, z_acldata
, z_acldata
)) {
3510 return (zfs_aces_walk_init_common(wsp
, version
,
3511 z_ace_count
, z_acldata
));
3516 zfs_acl_node_aces_walk_init(mdb_walk_state_t
*wsp
)
3518 return (zfs_acl_node_aces_walk_init_common(wsp
, 1));
3523 zfs_acl_node_aces0_walk_init(mdb_walk_state_t
*wsp
)
3525 return (zfs_acl_node_aces_walk_init_common(wsp
, 0));
3529 zfs_aces_walk_step(mdb_walk_state_t
*wsp
)
3531 ace_walk_data_t
*ace_data
= wsp
->walk_data
;
3539 if (ace_data
->ace_count
== 0)
3542 if (mdb_vread(&zace
, sizeof (zfs_ace_t
), wsp
->walk_addr
) == -1) {
3543 mdb_warn("failed to read zfs_ace_t at %#lx",
3548 switch (ace_data
->ace_version
) {
3550 acep
= (ace_t
*)&zace
;
3551 entry_type
= acep
->a_flags
& ACE_TYPE_FLAGS
;
3552 allow_type
= acep
->a_type
;
3555 entry_type
= zace
.z_hdr
.z_flags
& ACE_TYPE_FLAGS
;
3556 allow_type
= zace
.z_hdr
.z_type
;
3562 ptr
= (uintptr_t)wsp
->walk_addr
;
3563 switch (entry_type
) {
3566 case (ACE_IDENTIFIER_GROUP
| ACE_GROUP
):
3567 ptr
+= ace_data
->ace_version
== 0 ?
3568 sizeof (ace_t
) : sizeof (zfs_ace_hdr_t
);
3570 case ACE_IDENTIFIER_GROUP
:
3572 switch (allow_type
) {
3573 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE
:
3574 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE
:
3575 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE
:
3576 case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE
:
3577 ptr
+= ace_data
->ace_version
== 0 ?
3578 sizeof (ace_t
) : sizeof (zfs_object_ace_t
);
3581 ptr
+= ace_data
->ace_version
== 0 ?
3582 sizeof (ace_t
) : sizeof (zfs_ace_t
);
3587 ace_data
->ace_count
--;
3588 status
= wsp
->walk_callback(wsp
->walk_addr
,
3589 (void *)(uintptr_t)&zace
, wsp
->walk_cbdata
);
3591 wsp
->walk_addr
= ptr
;
3595 typedef struct mdb_zfs_rrwlock
{
3596 uintptr_t rr_writer
;
3597 boolean_t rr_writer_wanted
;
3598 } mdb_zfs_rrwlock_t
;
3600 static uint_t rrw_key
;
3604 rrwlock(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
3606 mdb_zfs_rrwlock_t rrw
;
3609 if (mdb_ctf_readsym(&rrw_key
, "uint_t", "rrw_tsd_key", 0) == -1)
3613 if (mdb_ctf_vread(&rrw
, "rrwlock_t", "mdb_zfs_rrwlock_t", addr
,
3617 if (rrw
.rr_writer
!= 0) {
3618 mdb_printf("write lock held by thread %lx\n", rrw
.rr_writer
);
3622 if (rrw
.rr_writer_wanted
) {
3623 mdb_printf("writer wanted\n");
3626 mdb_printf("anonymous references:\n");
3627 (void) mdb_call_dcmd("refcount", addr
+
3628 mdb_ctf_offsetof_by_name(ZFS_STRUCT
"rrwlock", "rr_anon_rcount"),
3629 DCMD_ADDRSPEC
, 0, NULL
);
3631 mdb_printf("linked references:\n");
3632 (void) mdb_call_dcmd("refcount", addr
+
3633 mdb_ctf_offsetof_by_name(ZFS_STRUCT
"rrwlock", "rr_linked_rcount"),
3634 DCMD_ADDRSPEC
, 0, NULL
);
3637 * XXX This should find references from
3638 * "::walk thread | ::tsd -v <rrw_key>", but there is no support
3639 * for programmatic consumption of dcmds, so this would be
3640 * difficult, potentially requiring reimplementing ::tsd (both
3641 * user and kernel versions) in this MDB module.
3647 typedef struct mdb_arc_buf_hdr_t
{
3654 } mdb_arc_buf_hdr_t
;
3657 ARC_CFLAG_VERBOSE
= 1 << 0,
3658 ARC_CFLAG_ANON
= 1 << 1,
3659 ARC_CFLAG_MRU
= 1 << 2,
3660 ARC_CFLAG_MFU
= 1 << 3,
3661 ARC_CFLAG_BUFS
= 1 << 4,
3664 typedef struct arc_compression_stats_data
{
3665 GElf_Sym anon_sym
; /* ARC_anon symbol */
3666 GElf_Sym mru_sym
; /* ARC_mru symbol */
3667 GElf_Sym mrug_sym
; /* ARC_mru_ghost symbol */
3668 GElf_Sym mfu_sym
; /* ARC_mfu symbol */
3669 GElf_Sym mfug_sym
; /* ARC_mfu_ghost symbol */
3670 GElf_Sym l2c_sym
; /* ARC_l2c_only symbol */
3671 uint64_t *anon_c_hist
; /* histogram of compressed sizes in anon */
3672 uint64_t *anon_u_hist
; /* histogram of uncompressed sizes in anon */
3673 uint64_t *anon_bufs
; /* histogram of buffer counts in anon state */
3674 uint64_t *mru_c_hist
; /* histogram of compressed sizes in mru */
3675 uint64_t *mru_u_hist
; /* histogram of uncompressed sizes in mru */
3676 uint64_t *mru_bufs
; /* histogram of buffer counts in mru */
3677 uint64_t *mfu_c_hist
; /* histogram of compressed sizes in mfu */
3678 uint64_t *mfu_u_hist
; /* histogram of uncompressed sizes in mfu */
3679 uint64_t *mfu_bufs
; /* histogram of buffer counts in mfu */
3680 uint64_t *all_c_hist
; /* histogram of compressed anon + mru + mfu */
3681 uint64_t *all_u_hist
; /* histogram of uncompressed anon + mru + mfu */
3682 uint64_t *all_bufs
; /* histogram of buffer counts in all states */
3683 int arc_cflags
; /* arc compression flags, specified by user */
3684 int hist_nbuckets
; /* number of buckets in each histogram */
3685 } arc_compression_stats_data_t
;
3688 highbit64(uint64_t i
)
3694 if (i
& 0xffffffff00000000ULL
) {
3697 if (i
& 0xffff0000) {
3717 arc_compression_stats_cb(uintptr_t addr
, const void *unknown
, void *arg
)
3719 arc_compression_stats_data_t
*data
= arg
;
3720 mdb_arc_buf_hdr_t hdr
;
3721 int cbucket
, ubucket
, bufcnt
;
3723 if (mdb_ctf_vread(&hdr
, "arc_buf_hdr_t", "mdb_arc_buf_hdr_t",
3729 * Headers in the ghost states, or the l2c_only state don't have
3730 * arc buffers linked off of them. Thus, their compressed size
3731 * is meaningless, so we skip these from the stats.
3733 if (hdr
.b_l1hdr
.b_state
== data
->mrug_sym
.st_value
||
3734 hdr
.b_l1hdr
.b_state
== data
->mfug_sym
.st_value
||
3735 hdr
.b_l1hdr
.b_state
== data
->l2c_sym
.st_value
) {
3740 * The physical size (compressed) and logical size
3741 * (uncompressed) are in units of SPA_MINBLOCKSIZE. By default,
3742 * we use the log2 of this value (rounded down to the nearest
3743 * integer) to determine the bucket to assign this header to.
3744 * Thus, the histogram is logarithmic with respect to the size
3745 * of the header. For example, the following is a mapping of the
3746 * bucket numbers and the range of header sizes they correspond to:
3749 * 1: 512 byte headers
3750 * 2: [1024 - 2048) byte headers
3751 * 3: [2048 - 4096) byte headers
3752 * 4: [4096 - 8192) byte headers
3753 * 5: [8192 - 16394) byte headers
3754 * 6: [16384 - 32768) byte headers
3755 * 7: [32768 - 65536) byte headers
3756 * 8: [65536 - 131072) byte headers
3757 * 9: 131072 byte headers
3759 * If the ARC_CFLAG_VERBOSE flag was specified, we use the
3760 * physical and logical sizes directly. Thus, the histogram will
3761 * no longer be logarithmic; instead it will be linear with
3762 * respect to the size of the header. The following is a mapping
3763 * of the first many bucket numbers and the header size they
3767 * 1: 512 byte headers
3768 * 2: 1024 byte headers
3769 * 3: 1536 byte headers
3770 * 4: 2048 byte headers
3771 * 5: 2560 byte headers
3772 * 6: 3072 byte headers
3774 * And so on. Keep in mind that a range of sizes isn't used in
3775 * the case of linear scale because the headers can only
3776 * increment or decrement in sizes of 512 bytes. So, it's not
3777 * possible for a header to be sized in between whats listed
3780 * Also, the above mapping values were calculated assuming a
3781 * SPA_MINBLOCKSHIFT of 512 bytes and a SPA_MAXBLOCKSIZE of 128K.
3784 if (data
->arc_cflags
& ARC_CFLAG_VERBOSE
) {
3785 cbucket
= hdr
.b_psize
;
3786 ubucket
= hdr
.b_lsize
;
3788 cbucket
= highbit64(hdr
.b_psize
);
3789 ubucket
= highbit64(hdr
.b_lsize
);
3792 bufcnt
= hdr
.b_l1hdr
.b_bufcnt
;
3793 if (bufcnt
>= data
->hist_nbuckets
)
3794 bufcnt
= data
->hist_nbuckets
- 1;
3796 /* Ensure we stay within the bounds of the histogram array */
3797 ASSERT3U(cbucket
, <, data
->hist_nbuckets
);
3798 ASSERT3U(ubucket
, <, data
->hist_nbuckets
);
3800 if (hdr
.b_l1hdr
.b_state
== data
->anon_sym
.st_value
) {
3801 data
->anon_c_hist
[cbucket
]++;
3802 data
->anon_u_hist
[ubucket
]++;
3803 data
->anon_bufs
[bufcnt
]++;
3804 } else if (hdr
.b_l1hdr
.b_state
== data
->mru_sym
.st_value
) {
3805 data
->mru_c_hist
[cbucket
]++;
3806 data
->mru_u_hist
[ubucket
]++;
3807 data
->mru_bufs
[bufcnt
]++;
3808 } else if (hdr
.b_l1hdr
.b_state
== data
->mfu_sym
.st_value
) {
3809 data
->mfu_c_hist
[cbucket
]++;
3810 data
->mfu_u_hist
[ubucket
]++;
3811 data
->mfu_bufs
[bufcnt
]++;
3814 data
->all_c_hist
[cbucket
]++;
3815 data
->all_u_hist
[ubucket
]++;
3816 data
->all_bufs
[bufcnt
]++;
3823 arc_compression_stats(uintptr_t addr
, uint_t flags
, int argc
,
3824 const mdb_arg_t
*argv
)
3826 arc_compression_stats_data_t data
= { 0 };
3827 unsigned int max_shifted
= SPA_MAXBLOCKSIZE
>> SPA_MINBLOCKSHIFT
;
3828 unsigned int hist_size
;
3832 if (mdb_getopts(argc
, argv
,
3833 'v', MDB_OPT_SETBITS
, ARC_CFLAG_VERBOSE
, &data
.arc_cflags
,
3834 'a', MDB_OPT_SETBITS
, ARC_CFLAG_ANON
, &data
.arc_cflags
,
3835 'b', MDB_OPT_SETBITS
, ARC_CFLAG_BUFS
, &data
.arc_cflags
,
3836 'r', MDB_OPT_SETBITS
, ARC_CFLAG_MRU
, &data
.arc_cflags
,
3837 'f', MDB_OPT_SETBITS
, ARC_CFLAG_MFU
, &data
.arc_cflags
) != argc
)
3838 return (DCMD_USAGE
);
3840 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, "ARC_anon", &data
.anon_sym
) ||
3841 mdb_lookup_by_obj(ZFS_OBJ_NAME
, "ARC_mru", &data
.mru_sym
) ||
3842 mdb_lookup_by_obj(ZFS_OBJ_NAME
, "ARC_mru_ghost", &data
.mrug_sym
) ||
3843 mdb_lookup_by_obj(ZFS_OBJ_NAME
, "ARC_mfu", &data
.mfu_sym
) ||
3844 mdb_lookup_by_obj(ZFS_OBJ_NAME
, "ARC_mfu_ghost", &data
.mfug_sym
) ||
3845 mdb_lookup_by_obj(ZFS_OBJ_NAME
, "ARC_l2c_only", &data
.l2c_sym
)) {
3846 mdb_warn("can't find arc state symbol");
3851 * Determine the maximum expected size for any header, and use
3852 * this to determine the number of buckets needed for each
3853 * histogram. If ARC_CFLAG_VERBOSE is specified, this value is
3854 * used directly; otherwise the log2 of the maximum size is
3855 * used. Thus, if using a log2 scale there's a maximum of 10
3856 * possible buckets, while the linear scale (when using
3857 * ARC_CFLAG_VERBOSE) has a maximum of 257 buckets.
3859 if (data
.arc_cflags
& ARC_CFLAG_VERBOSE
)
3860 data
.hist_nbuckets
= max_shifted
+ 1;
3862 data
.hist_nbuckets
= highbit64(max_shifted
) + 1;
3864 hist_size
= sizeof (uint64_t) * data
.hist_nbuckets
;
3866 data
.anon_c_hist
= mdb_zalloc(hist_size
, UM_SLEEP
);
3867 data
.anon_u_hist
= mdb_zalloc(hist_size
, UM_SLEEP
);
3868 data
.anon_bufs
= mdb_zalloc(hist_size
, UM_SLEEP
);
3870 data
.mru_c_hist
= mdb_zalloc(hist_size
, UM_SLEEP
);
3871 data
.mru_u_hist
= mdb_zalloc(hist_size
, UM_SLEEP
);
3872 data
.mru_bufs
= mdb_zalloc(hist_size
, UM_SLEEP
);
3874 data
.mfu_c_hist
= mdb_zalloc(hist_size
, UM_SLEEP
);
3875 data
.mfu_u_hist
= mdb_zalloc(hist_size
, UM_SLEEP
);
3876 data
.mfu_bufs
= mdb_zalloc(hist_size
, UM_SLEEP
);
3878 data
.all_c_hist
= mdb_zalloc(hist_size
, UM_SLEEP
);
3879 data
.all_u_hist
= mdb_zalloc(hist_size
, UM_SLEEP
);
3880 data
.all_bufs
= mdb_zalloc(hist_size
, UM_SLEEP
);
3882 if (mdb_walk("arc_buf_hdr_t_full", arc_compression_stats_cb
,
3884 mdb_warn("can't walk arc_buf_hdr's");
3889 if (data
.arc_cflags
& ARC_CFLAG_VERBOSE
) {
3890 rc
= mdb_snprintf(range
, sizeof (range
),
3891 "[n*%llu, (n+1)*%llu)", SPA_MINBLOCKSIZE
,
3894 rc
= mdb_snprintf(range
, sizeof (range
),
3895 "[2^(n-1)*%llu, 2^n*%llu)", SPA_MINBLOCKSIZE
,
3900 /* snprintf failed, abort the dcmd */
3904 /* snprintf succeeded above, reset return code */
3908 if (data
.arc_cflags
& ARC_CFLAG_ANON
) {
3909 if (data
.arc_cflags
& ARC_CFLAG_BUFS
) {
3910 mdb_printf("Histogram of the number of anon buffers "
3911 "that are associated with an arc hdr.\n");
3912 dump_histogram(data
.anon_bufs
, data
.hist_nbuckets
, 0);
3915 mdb_printf("Histogram of compressed anon buffers.\n"
3916 "Each bucket represents buffers of size: %s.\n", range
);
3917 dump_histogram(data
.anon_c_hist
, data
.hist_nbuckets
, 0);
3920 mdb_printf("Histogram of uncompressed anon buffers.\n"
3921 "Each bucket represents buffers of size: %s.\n", range
);
3922 dump_histogram(data
.anon_u_hist
, data
.hist_nbuckets
, 0);
3926 if (data
.arc_cflags
& ARC_CFLAG_MRU
) {
3927 if (data
.arc_cflags
& ARC_CFLAG_BUFS
) {
3928 mdb_printf("Histogram of the number of mru buffers "
3929 "that are associated with an arc hdr.\n");
3930 dump_histogram(data
.mru_bufs
, data
.hist_nbuckets
, 0);
3933 mdb_printf("Histogram of compressed mru buffers.\n"
3934 "Each bucket represents buffers of size: %s.\n", range
);
3935 dump_histogram(data
.mru_c_hist
, data
.hist_nbuckets
, 0);
3938 mdb_printf("Histogram of uncompressed mru buffers.\n"
3939 "Each bucket represents buffers of size: %s.\n", range
);
3940 dump_histogram(data
.mru_u_hist
, data
.hist_nbuckets
, 0);
3944 if (data
.arc_cflags
& ARC_CFLAG_MFU
) {
3945 if (data
.arc_cflags
& ARC_CFLAG_BUFS
) {
3946 mdb_printf("Histogram of the number of mfu buffers "
3947 "that are associated with an arc hdr.\n");
3948 dump_histogram(data
.mfu_bufs
, data
.hist_nbuckets
, 0);
3952 mdb_printf("Histogram of compressed mfu buffers.\n"
3953 "Each bucket represents buffers of size: %s.\n", range
);
3954 dump_histogram(data
.mfu_c_hist
, data
.hist_nbuckets
, 0);
3957 mdb_printf("Histogram of uncompressed mfu buffers.\n"
3958 "Each bucket represents buffers of size: %s.\n", range
);
3959 dump_histogram(data
.mfu_u_hist
, data
.hist_nbuckets
, 0);
3963 if (data
.arc_cflags
& ARC_CFLAG_BUFS
) {
3964 mdb_printf("Histogram of all buffers that "
3965 "are associated with an arc hdr.\n");
3966 dump_histogram(data
.all_bufs
, data
.hist_nbuckets
, 0);
3970 mdb_printf("Histogram of all compressed buffers.\n"
3971 "Each bucket represents buffers of size: %s.\n", range
);
3972 dump_histogram(data
.all_c_hist
, data
.hist_nbuckets
, 0);
3975 mdb_printf("Histogram of all uncompressed buffers.\n"
3976 "Each bucket represents buffers of size: %s.\n", range
);
3977 dump_histogram(data
.all_u_hist
, data
.hist_nbuckets
, 0);
3980 mdb_free(data
.anon_c_hist
, hist_size
);
3981 mdb_free(data
.anon_u_hist
, hist_size
);
3982 mdb_free(data
.anon_bufs
, hist_size
);
3984 mdb_free(data
.mru_c_hist
, hist_size
);
3985 mdb_free(data
.mru_u_hist
, hist_size
);
3986 mdb_free(data
.mru_bufs
, hist_size
);
3988 mdb_free(data
.mfu_c_hist
, hist_size
);
3989 mdb_free(data
.mfu_u_hist
, hist_size
);
3990 mdb_free(data
.mfu_bufs
, hist_size
);
3992 mdb_free(data
.all_c_hist
, hist_size
);
3993 mdb_free(data
.all_u_hist
, hist_size
);
3994 mdb_free(data
.all_bufs
, hist_size
);
4000 * MDB module linkage information:
4002 * We declare a list of structures describing our dcmds, and a function
4003 * named _mdb_init to return a pointer to our module information.
4006 static const mdb_dcmd_t dcmds
[] = {
4007 { "arc", "[-bkmg]", "print ARC variables", arc_print
},
4008 { "blkptr", ":", "print blkptr_t", blkptr
},
4009 { "dva", ":", "print dva_t", dva
},
4010 { "dbuf", ":", "print dmu_buf_impl_t", dbuf
},
4011 { "dbuf_stats", ":", "dbuf stats", dbuf_stats
},
4013 "\t[-O objset_t*] [-n objset_name | \"mos\"] "
4014 "[-o object | \"mdn\"] \n"
4015 "\t[-l level] [-b blkid | \"bonus\"]",
4016 "find dmu_buf_impl_t's that match specified criteria", dbufs
},
4017 { "abuf_find", "dva_word[0] dva_word[1]",
4018 "find arc_buf_hdr_t of a specified DVA",
4020 { "spa", "?[-cevmMh]\n"
4021 "\t-c display spa config\n"
4022 "\t-e display vdev statistics\n"
4023 "\t-v display vdev information\n"
4024 "\t-m display metaslab statistics\n"
4025 "\t-M display metaslab group statistics\n"
4026 "\t-h display histogram (requires -m or -M)\n",
4027 "spa_t summary", spa_print
},
4028 { "spa_config", ":", "print spa_t configuration", spa_print_config
},
4029 { "spa_space", ":[-b]", "print spa_t on-disk space usage", spa_space
},
4030 { "spa_vdevs", ":[-emMh]\n"
4031 "\t-e display vdev statistics\n"
4032 "\t-m dispaly metaslab statistics\n"
4033 "\t-M display metaslab group statistic\n"
4034 "\t-h display histogram (requires -m or -M)\n",
4035 "given a spa_t, print vdev summary", spa_vdevs
},
4036 { "sm_entries", "<buffer length in bytes>",
4037 "print out space map entries from a buffer decoded",
4039 { "vdev", ":[-remMh]\n"
4040 "\t-r display recursively\n"
4041 "\t-e display statistics\n"
4042 "\t-m display metaslab statistics (top level vdev only)\n"
4043 "\t-M display metaslab group statistics (top level vdev only)\n"
4044 "\t-h display histogram (requires -m or -M)\n",
4045 "vdev_t summary", vdev_print
},
4046 { "zio", ":[-cpr]\n"
4047 "\t-c display children\n"
4048 "\t-p display parents\n"
4049 "\t-r display recursively",
4050 "zio_t summary", zio_print
},
4051 { "zio_state", "?", "print out all zio_t structures on system or "
4052 "for a particular pool", zio_state
},
4053 { "zfs_blkstats", ":[-v]",
4054 "given a spa_t, print block type stats from last scrub",
4056 { "zfs_params", "", "print zfs tunable parameters", zfs_params
},
4057 { "refcount", ":[-r]\n"
4058 "\t-r display recently removed references",
4059 "print refcount_t holders", refcount
},
4060 { "zap_leaf", "", "print zap_leaf_phys_t", zap_leaf
},
4061 { "zfs_aces", ":[-v]", "print all ACEs from a zfs_acl_t",
4063 { "zfs_ace", ":[-v]", "print zfs_ace", zfs_ace_print
},
4064 { "zfs_ace0", ":[-v]", "print zfs_ace0", zfs_ace0_print
},
4065 { "sa_attr_table", ":", "print SA attribute table from sa_os_t",
4067 { "sa_attr", ": attr_id",
4068 "print SA attribute address when given sa_handle_t", sa_attr_print
},
4069 { "zfs_dbgmsg", ":[-va]",
4070 "print zfs debug log", dbgmsg
},
4072 "print rrwlock_t, including readers", rrwlock
},
4073 { "metaslab_weight", "weight",
4074 "print metaslab weight", metaslab_weight
},
4075 { "metaslab_trace", ":",
4076 "print metaslab allocation trace records", metaslab_trace
},
4077 { "arc_compression_stats", ":[-vabrf]\n"
4078 "\t-v verbose, display a linearly scaled histogram\n"
4079 "\t-a display ARC_anon state statistics individually\n"
4080 "\t-r display ARC_mru state statistics individually\n"
4081 "\t-f display ARC_mfu state statistics individually\n"
4082 "\t-b display histogram of buffer counts\n",
4083 "print a histogram of compressed arc buffer sizes",
4084 arc_compression_stats
},
4088 static const mdb_walker_t walkers
[] = {
4089 { "txg_list", "given any txg_list_t *, walk all entries in all txgs",
4090 txg_list_walk_init
, txg_list_walk_step
, NULL
},
4091 { "txg_list0", "given any txg_list_t *, walk all entries in txg 0",
4092 txg_list0_walk_init
, txg_list_walk_step
, NULL
},
4093 { "txg_list1", "given any txg_list_t *, walk all entries in txg 1",
4094 txg_list1_walk_init
, txg_list_walk_step
, NULL
},
4095 { "txg_list2", "given any txg_list_t *, walk all entries in txg 2",
4096 txg_list2_walk_init
, txg_list_walk_step
, NULL
},
4097 { "txg_list3", "given any txg_list_t *, walk all entries in txg 3",
4098 txg_list3_walk_init
, txg_list_walk_step
, NULL
},
4099 { "zio", "walk all zio structures, optionally for a particular spa_t",
4100 zio_walk_init
, zio_walk_step
, NULL
},
4102 "walk all root zio_t structures, optionally for a particular spa_t",
4103 zio_walk_init
, zio_walk_root_step
, NULL
},
4104 { "spa", "walk all spa_t entries in the namespace",
4105 spa_walk_init
, spa_walk_step
, NULL
},
4106 { "metaslab", "given a spa_t *, walk all metaslab_t structures",
4107 metaslab_walk_init
, metaslab_walk_step
, NULL
},
4108 { "multilist", "given a multilist_t *, walk all list_t structures",
4109 multilist_walk_init
, multilist_walk_step
, NULL
},
4110 { "zfs_acl_node", "given a zfs_acl_t, walk all zfs_acl_nodes",
4111 zfs_acl_node_walk_init
, zfs_acl_node_walk_step
, NULL
},
4112 { "zfs_acl_node_aces", "given a zfs_acl_node_t, walk all ACEs",
4113 zfs_acl_node_aces_walk_init
, zfs_aces_walk_step
, NULL
},
4114 { "zfs_acl_node_aces0",
4115 "given a zfs_acl_node_t, walk all ACEs as ace_t",
4116 zfs_acl_node_aces0_walk_init
, zfs_aces_walk_step
, NULL
},
4120 static const mdb_modinfo_t modinfo
= {
4121 MDB_API_VERSION
, dcmds
, walkers
4124 const mdb_modinfo_t
*