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, 2014 by Delphix. All rights reserved.
27 /* Portions Copyright 2010 Robert Milkowski */
29 #include <mdb/mdb_ctf.h>
30 #include <sys/zfs_context.h>
31 #include <sys/mdb_modapi.h>
33 #include <sys/dmu_objset.h>
34 #include <sys/dsl_dir.h>
35 #include <sys/dsl_pool.h>
36 #include <sys/metaslab_impl.h>
37 #include <sys/space_map.h>
39 #include <sys/vdev_impl.h>
40 #include <sys/zap_leaf.h>
41 #include <sys/zap_impl.h>
43 #include <sys/zfs_acl.h>
44 #include <sys/sa_impl.h>
47 #define ZFS_OBJ_NAME "zfs"
48 extern int64_t mdb_gethrtime(void);
50 #define ZFS_OBJ_NAME "libzpool.so.1"
53 #define ZFS_STRUCT "struct " ZFS_OBJ_NAME "`"
60 SPA_FLAG_CONFIG
= 1 << 0,
61 SPA_FLAG_VDEVS
= 1 << 1,
62 SPA_FLAG_ERRORS
= 1 << 2,
63 SPA_FLAG_METASLAB_GROUPS
= 1 << 3,
64 SPA_FLAG_METASLABS
= 1 << 4,
65 SPA_FLAG_HISTOGRAMS
= 1 << 5
68 #define SPA_FLAG_ALL_VDEV \
69 (SPA_FLAG_VDEVS | SPA_FLAG_ERRORS | SPA_FLAG_METASLAB_GROUPS | \
70 SPA_FLAG_METASLABS | SPA_FLAG_HISTOGRAMS)
73 getmember(uintptr_t addr
, const char *type
, mdb_ctf_id_t
*idp
,
74 const char *member
, int len
, void *buf
)
81 if (mdb_ctf_lookup_by_name(type
, &id
) == -1) {
82 mdb_warn("couldn't find type %s", type
);
88 mdb_ctf_type_name(*idp
, name
, sizeof (name
));
91 if (mdb_ctf_offsetof(*idp
, member
, &off
) == -1) {
92 mdb_warn("couldn't find member %s of type %s\n", member
, type
);
96 mdb_warn("member %s of type %s is unsupported bitfield",
102 if (mdb_vread(buf
, len
, addr
+ off
) == -1) {
103 mdb_warn("failed to read %s from %s at %p",
104 member
, type
, addr
+ off
);
107 /* mdb_warn("read %s from %s at %p+%llx\n", member, type, addr, off); */
112 #define GETMEMB(addr, structname, member, dest) \
113 getmember(addr, ZFS_STRUCT structname, NULL, #member, \
114 sizeof (dest), &(dest))
116 #define GETMEMBID(addr, ctfid, member, dest) \
117 getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest))
120 strisprint(const char *cp
)
129 #define NICENUM_BUFLEN 6
132 snprintfrac(char *buf
, int len
,
133 uint64_t numerator
, uint64_t denom
, int frac_digits
)
138 for (i
= frac_digits
; i
; i
--)
140 whole
= numerator
/ denom
;
141 frac
= mul
* numerator
/ denom
- mul
* whole
;
142 return (mdb_snprintf(buf
, len
, "%u.%0*u", whole
, frac_digits
, frac
));
146 mdb_nicenum(uint64_t num
, char *buf
)
153 n
= (n
+ (1024 / 2)) / 1024; /* Round up or down */
157 u
= &" \0K\0M\0G\0T\0P\0E\0"[index
*2];
160 (void) mdb_snprintf(buf
, NICENUM_BUFLEN
, "%llu",
162 } else if (n
< 10 && (num
& (num
- 1)) != 0) {
163 (void) snprintfrac(buf
, NICENUM_BUFLEN
,
164 num
, 1ULL << 10 * index
, 2);
166 } else if (n
< 100 && (num
& (num
- 1)) != 0) {
167 (void) snprintfrac(buf
, NICENUM_BUFLEN
,
168 num
, 1ULL << 10 * index
, 1);
171 (void) mdb_snprintf(buf
, NICENUM_BUFLEN
, "%llu%s",
179 freelist_walk_init(mdb_walk_state_t
*wsp
)
181 if (wsp
->walk_addr
== NULL
) {
182 mdb_warn("must supply starting address\n");
186 wsp
->walk_data
= 0; /* Index into the freelist */
191 freelist_walk_step(mdb_walk_state_t
*wsp
)
194 uintptr_t number
= (uintptr_t)wsp
->walk_data
;
195 char *ddata
[] = { "ALLOC", "FREE", "CONDENSE", "INVALID",
196 "INVALID", "INVALID", "INVALID", "INVALID" };
197 int mapshift
= SPA_MINBLOCKSHIFT
;
199 if (mdb_vread(&entry
, sizeof (entry
), wsp
->walk_addr
) == -1) {
200 mdb_warn("failed to read freelist entry %p", wsp
->walk_addr
);
203 wsp
->walk_addr
+= sizeof (entry
);
204 wsp
->walk_data
= (void *)(number
+ 1);
206 if (SM_DEBUG_DECODE(entry
)) {
207 mdb_printf("DEBUG: %3u %10s: txg=%llu pass=%llu\n",
209 ddata
[SM_DEBUG_ACTION_DECODE(entry
)],
210 SM_DEBUG_TXG_DECODE(entry
),
211 SM_DEBUG_SYNCPASS_DECODE(entry
));
213 mdb_printf("Entry: %3u offsets=%08llx-%08llx type=%c "
214 "size=%06llx", number
,
215 SM_OFFSET_DECODE(entry
) << mapshift
,
216 (SM_OFFSET_DECODE(entry
) + SM_RUN_DECODE(entry
)) <<
218 SM_TYPE_DECODE(entry
) == SM_ALLOC
? 'A' : 'F',
219 SM_RUN_DECODE(entry
) << mapshift
);
221 mdb_printf(" (raw=%012llx)\n", entry
);
228 mdb_dsl_dir_name(uintptr_t addr
, char *buf
)
231 static mdb_ctf_id_t dd_id
;
233 char dd_myname
[MAXNAMELEN
];
236 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"dsl_dir",
238 mdb_warn("couldn't find struct dsl_dir");
243 if (GETMEMBID(addr
, &dd_id
, dd_parent
, dd_parent
) ||
244 GETMEMBID(addr
, &dd_id
, dd_myname
, dd_myname
)) {
249 if (mdb_dsl_dir_name(dd_parent
, buf
))
255 strcat(buf
, dd_myname
);
263 objset_name(uintptr_t addr
, char *buf
)
266 static mdb_ctf_id_t os_id
, ds_id
;
267 uintptr_t os_dsl_dataset
;
268 char ds_snapname
[MAXNAMELEN
];
274 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"objset",
276 mdb_warn("couldn't find struct objset");
279 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"dsl_dataset",
281 mdb_warn("couldn't find struct dsl_dataset");
288 if (GETMEMBID(addr
, &os_id
, os_dsl_dataset
, os_dsl_dataset
))
291 if (os_dsl_dataset
== 0) {
296 if (GETMEMBID(os_dsl_dataset
, &ds_id
, ds_snapname
, ds_snapname
) ||
297 GETMEMBID(os_dsl_dataset
, &ds_id
, ds_dir
, ds_dir
)) {
301 if (ds_dir
&& mdb_dsl_dir_name(ds_dir
, buf
))
304 if (ds_snapname
[0]) {
306 strcat(buf
, ds_snapname
);
312 enum_lookup(char *out
, size_t size
, mdb_ctf_id_t id
, int val
,
316 size_t len
= strlen(prefix
);
318 if ((cp
= mdb_ctf_enum_name(id
, val
)) != NULL
) {
319 if (strncmp(cp
, prefix
, len
) == 0)
321 (void) strncpy(out
, cp
, size
);
323 mdb_snprintf(out
, size
, "? (%d)", val
);
329 zfs_params(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
332 * This table can be approximately generated by running:
333 * egrep "^[a-z0-9_]+ [a-z0-9_]+( =.*)?;" *.c | cut -d ' ' -f 2
335 static const char *params
[] = {
336 "arc_reduce_dnlc_percent",
337 "arc_lotsfree_percent",
338 "zfs_dirty_data_max",
339 "zfs_dirty_data_sync",
341 "zfs_delay_min_dirty_percent",
343 "zfs_vdev_max_active",
344 "zfs_vdev_sync_read_min_active",
345 "zfs_vdev_sync_read_max_active",
346 "zfs_vdev_sync_write_min_active",
347 "zfs_vdev_sync_write_max_active",
348 "zfs_vdev_async_read_min_active",
349 "zfs_vdev_async_read_max_active",
350 "zfs_vdev_async_write_min_active",
351 "zfs_vdev_async_write_max_active",
352 "zfs_vdev_scrub_min_active",
353 "zfs_vdev_scrub_max_active",
354 "zfs_vdev_async_write_active_min_dirty_percent",
355 "zfs_vdev_async_write_active_max_dirty_percent",
356 "spa_asize_inflation",
360 "zfs_mdcomp_disable",
361 "zfs_prefetch_disable",
362 "zfetch_max_streams",
363 "zfetch_min_sec_reap",
365 "zfetch_array_rd_sz",
369 "reference_tracking_enable",
371 "spa_max_replication_override",
375 "zfs_vdev_cache_max",
376 "zfs_vdev_cache_size",
377 "zfs_vdev_cache_bshift",
381 "zfs_no_scrub_prefetch",
382 "zfs_vdev_aggregation_limit",
383 "fzap_default_block_shift",
384 "zfs_immediate_write_sz",
385 "zfs_read_chunk_size",
387 "zil_replay_disable",
388 "metaslab_gang_bang",
389 "metaslab_df_alloc_threshold",
390 "metaslab_df_free_pct",
391 "zio_injection_enabled",
392 "zvol_immediate_write_sz",
395 for (int i
= 0; i
< sizeof (params
) / sizeof (params
[0]); i
++) {
398 uint32_t *val32p
= (uint32_t *)&val64
;
400 sz
= mdb_readvar(&val64
, params
[i
]);
402 mdb_printf("%s = 0x%x\n", params
[i
], *val32p
);
403 } else if (sz
== 8) {
404 mdb_printf("%s = 0x%llx\n", params
[i
], val64
);
406 mdb_warn("variable %s not found", params
[i
]);
415 blkptr(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
417 mdb_ctf_id_t type_enum
, checksum_enum
, compress_enum
;
418 char type
[80], checksum
[80], compress
[80];
419 blkptr_t blk
, *bp
= &blk
;
420 char buf
[BP_SPRINTF_LEN
];
422 if (mdb_vread(&blk
, sizeof (blkptr_t
), addr
) == -1) {
423 mdb_warn("failed to read blkptr_t");
427 if (mdb_ctf_lookup_by_name("enum dmu_object_type", &type_enum
) == -1 ||
428 mdb_ctf_lookup_by_name("enum zio_checksum", &checksum_enum
) == -1 ||
429 mdb_ctf_lookup_by_name("enum zio_compress", &compress_enum
) == -1) {
430 mdb_warn("Could not find blkptr enumerated types");
434 enum_lookup(type
, sizeof (type
), type_enum
,
435 BP_GET_TYPE(bp
), "DMU_OT_");
436 enum_lookup(checksum
, sizeof (checksum
), checksum_enum
,
437 BP_GET_CHECKSUM(bp
), "ZIO_CHECKSUM_");
438 enum_lookup(compress
, sizeof (compress
), compress_enum
,
439 BP_GET_COMPRESS(bp
), "ZIO_COMPRESS_");
441 SNPRINTF_BLKPTR(mdb_snprintf
, '\n', buf
, sizeof (buf
), bp
, type
,
444 mdb_printf("%s\n", buf
);
449 typedef struct mdb_dmu_buf_impl
{
459 } mdb_dmu_buf_impl_t
;
463 dbuf(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
465 mdb_dmu_buf_impl_t db
;
468 char path
[MAXNAMELEN
];
470 if (DCMD_HDRSPEC(flags
))
471 mdb_printf(" addr object lvl blkid holds os\n");
473 if (mdb_ctf_vread(&db
, ZFS_STRUCT
"dmu_buf_impl", "mdb_dmu_buf_impl_t",
477 if (db
.db
.db_object
== DMU_META_DNODE_OBJECT
)
478 (void) strcpy(objectname
, "mdn");
480 (void) mdb_snprintf(objectname
, sizeof (objectname
), "%llx",
481 (u_longlong_t
)db
.db
.db_object
);
483 if (db
.db_blkid
== DMU_BONUS_BLKID
)
484 (void) strcpy(blkidname
, "bonus");
486 (void) mdb_snprintf(blkidname
, sizeof (blkidname
), "%llx",
487 (u_longlong_t
)db
.db_blkid
);
489 if (objset_name(db
.db_objset
, path
)) {
493 mdb_printf("%p %8s %1u %9s %2llu %s\n", addr
,
494 objectname
, (int)db
.db_level
, blkidname
,
495 db
.db_holds
.rc_count
, path
);
502 dbuf_stats(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
507 dbuf_hash_table_t ht
;
508 uint64_t bucket
, ndbufs
;
509 uint64_t histo
[HISTOSZ
];
510 uint64_t histo2
[HISTOSZ
];
513 if (mdb_readvar(&ht
, "dbuf_hash_table") == -1) {
514 mdb_warn("failed to read 'dbuf_hash_table'");
518 for (i
= 0; i
< HISTOSZ
; i
++) {
524 for (bucket
= 0; bucket
< ht
.hash_table_mask
+1; bucket
++) {
527 if (mdb_vread(&dbp
, sizeof (void *),
528 (uintptr_t)(ht
.hash_table
+bucket
)) == -1) {
529 mdb_warn("failed to read hash bucket %u at %p",
530 bucket
, ht
.hash_table
+bucket
);
536 if (mdb_vread(&db
, sizeof (dmu_buf_impl_t
),
538 mdb_warn("failed to read dbuf at %p", dbp
);
541 dbp
= (uintptr_t)db
.db_hash_next
;
542 for (i
= MIN(len
, HISTOSZ
- 1); i
>= 0; i
--)
553 mdb_printf("hash table has %llu buckets, %llu dbufs "
554 "(avg %llu buckets/dbuf)\n",
555 ht
.hash_table_mask
+1, ndbufs
,
556 (ht
.hash_table_mask
+1)/ndbufs
);
560 for (i
= 0; i
< HISTOSZ
; i
++)
563 mdb_printf("hash chain length number of buckets\n");
564 for (i
= 0; i
<= maxidx
; i
++)
565 mdb_printf("%u %llu\n", i
, histo
[i
]);
569 for (i
= 0; i
< HISTOSZ
; i
++)
572 mdb_printf("hash chain depth number of dbufs\n");
573 for (i
= 0; i
<= maxidx
; i
++)
574 mdb_printf("%u or more %llu %llu%%\n",
575 i
, histo2
[i
], histo2
[i
]*100/ndbufs
);
581 #define CHAIN_END 0xffff
585 * Print a zap_leaf_phys_t, assumed to be 16k
589 zap_leaf(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
592 int verbose
= B_FALSE
;
595 zap_leaf_phys_t
*zlp
= (void *)buf
;
598 if (mdb_getopts(argc
, argv
,
599 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
,
600 '4', MDB_OPT_SETBITS
, TRUE
, &four
,
605 l
.l_bs
= 14; /* assume 16k blocks */
609 if (!(flags
& DCMD_ADDRSPEC
)) {
613 if (mdb_vread(buf
, sizeof (buf
), addr
) == -1) {
614 mdb_warn("failed to read zap_leaf_phys_t at %p", addr
);
618 if (zlp
->l_hdr
.lh_block_type
!= ZBT_LEAF
||
619 zlp
->l_hdr
.lh_magic
!= ZAP_LEAF_MAGIC
) {
620 mdb_warn("This does not appear to be a zap_leaf_phys_t");
624 mdb_printf("zap_leaf_phys_t at %p:\n", addr
);
625 mdb_printf(" lh_prefix_len = %u\n", zlp
->l_hdr
.lh_prefix_len
);
626 mdb_printf(" lh_prefix = %llx\n", zlp
->l_hdr
.lh_prefix
);
627 mdb_printf(" lh_nentries = %u\n", zlp
->l_hdr
.lh_nentries
);
628 mdb_printf(" lh_nfree = %u\n", zlp
->l_hdr
.lh_nfree
,
629 zlp
->l_hdr
.lh_nfree
* 100 / (ZAP_LEAF_NUMCHUNKS(&l
)));
630 mdb_printf(" lh_freelist = %u\n", zlp
->l_hdr
.lh_freelist
);
631 mdb_printf(" lh_flags = %x (%s)\n", zlp
->l_hdr
.lh_flags
,
632 zlp
->l_hdr
.lh_flags
& ZLF_ENTRIES_CDSORTED
?
633 "ENTRIES_CDSORTED" : "");
636 mdb_printf(" hash table:\n");
637 for (i
= 0; i
< ZAP_LEAF_HASH_NUMENTRIES(&l
); i
++) {
638 if (zlp
->l_hash
[i
] != CHAIN_END
)
639 mdb_printf(" %u: %u\n", i
, zlp
->l_hash
[i
]);
643 mdb_printf(" chunks:\n");
644 for (i
= 0; i
< ZAP_LEAF_NUMCHUNKS(&l
); i
++) {
645 /* LINTED: alignment */
646 zap_leaf_chunk_t
*zlc
= &ZAP_LEAF_CHUNK(&l
, i
);
647 switch (zlc
->l_entry
.le_type
) {
650 mdb_printf(" %u: free; lf_next = %u\n",
651 i
, zlc
->l_free
.lf_next
);
654 case ZAP_CHUNK_ENTRY
:
655 mdb_printf(" %u: entry\n", i
);
657 mdb_printf(" le_next = %u\n",
658 zlc
->l_entry
.le_next
);
660 mdb_printf(" le_name_chunk = %u\n",
661 zlc
->l_entry
.le_name_chunk
);
662 mdb_printf(" le_name_numints = %u\n",
663 zlc
->l_entry
.le_name_numints
);
664 mdb_printf(" le_value_chunk = %u\n",
665 zlc
->l_entry
.le_value_chunk
);
666 mdb_printf(" le_value_intlen = %u\n",
667 zlc
->l_entry
.le_value_intlen
);
668 mdb_printf(" le_value_numints = %u\n",
669 zlc
->l_entry
.le_value_numints
);
670 mdb_printf(" le_cd = %u\n",
672 mdb_printf(" le_hash = %llx\n",
673 zlc
->l_entry
.le_hash
);
675 case ZAP_CHUNK_ARRAY
:
676 mdb_printf(" %u: array", i
);
677 if (strisprint((char *)zlc
->l_array
.la_array
))
678 mdb_printf(" \"%s\"", zlc
->l_array
.la_array
);
683 for (j
= 0; j
< ZAP_LEAF_ARRAY_BYTES
; j
++) {
685 zlc
->l_array
.la_array
[j
]);
689 if (zlc
->l_array
.la_next
!= CHAIN_END
) {
690 mdb_printf(" lf_next = %u\n",
691 zlc
->l_array
.la_next
);
695 mdb_printf(" %u: undefined type %u\n",
696 zlc
->l_entry
.le_type
);
703 typedef struct dbufs_data
{
712 #define DBUFS_UNSET (0xbaddcafedeadbeefULL)
716 dbufs_cb(uintptr_t addr
, const void *unknown
, void *arg
)
718 dbufs_data_t
*data
= arg
;
723 char osname
[MAXNAMELEN
];
725 if (GETMEMBID(addr
, &data
->id
, db_objset
, objset
) ||
726 GETMEMBID(addr
, &data
->id
, db
, db
) ||
727 GETMEMBID(addr
, &data
->id
, db_level
, level
) ||
728 GETMEMBID(addr
, &data
->id
, db_blkid
, blkid
)) {
732 if ((data
->objset
== DBUFS_UNSET
|| data
->objset
== objset
) &&
733 (data
->osname
== NULL
|| (objset_name(objset
, osname
) == 0 &&
734 strcmp(data
->osname
, osname
) == 0)) &&
735 (data
->object
== DBUFS_UNSET
|| data
->object
== db
.db_object
) &&
736 (data
->level
== DBUFS_UNSET
|| data
->level
== level
) &&
737 (data
->blkid
== DBUFS_UNSET
|| data
->blkid
== blkid
)) {
738 mdb_printf("%#lr\n", addr
);
745 dbufs(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
751 data
.objset
= data
.object
= data
.level
= data
.blkid
= DBUFS_UNSET
;
754 if (mdb_getopts(argc
, argv
,
755 'O', MDB_OPT_UINT64
, &data
.objset
,
756 'n', MDB_OPT_STR
, &data
.osname
,
757 'o', MDB_OPT_STR
, &object
,
758 'l', MDB_OPT_UINT64
, &data
.level
,
759 'b', MDB_OPT_STR
, &blkid
) != argc
) {
764 if (strcmp(object
, "mdn") == 0) {
765 data
.object
= DMU_META_DNODE_OBJECT
;
767 data
.object
= mdb_strtoull(object
);
772 if (strcmp(blkid
, "bonus") == 0) {
773 data
.blkid
= DMU_BONUS_BLKID
;
775 data
.blkid
= mdb_strtoull(blkid
);
779 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"dmu_buf_impl", &data
.id
) == -1) {
780 mdb_warn("couldn't find struct dmu_buf_impl_t");
784 if (mdb_walk("dmu_buf_impl_t", dbufs_cb
, &data
) != 0) {
785 mdb_warn("can't walk dbufs");
792 typedef struct abuf_find_data
{
799 abuf_find_cb(uintptr_t addr
, const void *unknown
, void *arg
)
801 abuf_find_data_t
*data
= arg
;
804 if (GETMEMBID(addr
, &data
->id
, b_dva
, dva
)) {
808 if (dva
.dva_word
[0] == data
->dva
.dva_word
[0] &&
809 dva
.dva_word
[1] == data
->dva
.dva_word
[1]) {
810 mdb_printf("%#lr\n", addr
);
817 abuf_find(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
819 abuf_find_data_t data
;
822 const char *syms
[] = {
832 for (i
= 0; i
< 2; i
++) {
833 switch (argv
[i
].a_type
) {
834 case MDB_TYPE_STRING
:
835 data
.dva
.dva_word
[i
] = mdb_strtoull(argv
[i
].a_un
.a_str
);
837 case MDB_TYPE_IMMEDIATE
:
838 data
.dva
.dva_word
[i
] = argv
[i
].a_un
.a_val
;
845 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"arc_buf_hdr", &data
.id
) == -1) {
846 mdb_warn("couldn't find struct arc_buf_hdr");
850 for (i
= 0; i
< sizeof (syms
) / sizeof (syms
[0]); i
++) {
851 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, syms
[i
], &sym
)) {
852 mdb_warn("can't find symbol %s", syms
[i
]);
856 if (mdb_pwalk("list", abuf_find_cb
, &data
, sym
.st_value
) != 0) {
857 mdb_warn("can't walk %s", syms
[i
]);
866 typedef struct dbgmsg_arg
{
867 boolean_t da_verbose
;
868 boolean_t da_address
;
873 dbgmsg_cb(uintptr_t addr
, const void *unknown
, void *arg
)
875 static mdb_ctf_id_t id
;
876 static boolean_t gotid
;
879 dbgmsg_arg_t
*da
= arg
;
884 if (mdb_ctf_lookup_by_name(ZFS_STRUCT
"zfs_dbgmsg", &id
) ==
886 mdb_warn("couldn't find struct zfs_dbgmsg");
890 if (mdb_ctf_offsetof(id
, "zdm_msg", &off
) == -1) {
891 mdb_warn("couldn't find zdm_msg");
898 if (GETMEMBID(addr
, &id
, zdm_timestamp
, timestamp
)) {
902 if (mdb_readstr(buf
, sizeof (buf
), addr
+ off
) == -1) {
903 mdb_warn("failed to read zdm_msg at %p\n", addr
+ off
);
908 mdb_printf("%p ", addr
);
910 mdb_printf("%Y ", timestamp
);
912 mdb_printf("%s\n", buf
);
915 (void) mdb_call_dcmd("whatis", addr
, DCMD_ADDRSPEC
, 0, NULL
);
922 dbgmsg(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
925 dbgmsg_arg_t da
= { 0 };
927 if (mdb_getopts(argc
, argv
,
928 'v', MDB_OPT_SETBITS
, B_TRUE
, &da
.da_verbose
,
929 'a', MDB_OPT_SETBITS
, B_TRUE
, &da
.da_address
,
933 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, "zfs_dbgmsgs", &sym
)) {
934 mdb_warn("can't find zfs_dbgmsgs");
938 if (mdb_pwalk("list", dbgmsg_cb
, &da
, sym
.st_value
) != 0) {
939 mdb_warn("can't walk zfs_dbgmsgs");
948 arc_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
950 kstat_named_t
*stats
;
953 uint_t opt_a
= FALSE
;
954 uint_t opt_b
= FALSE
;
958 static const char *bytestats
[] = {
959 "p", "c", "c_min", "c_max", "size", "duplicate_buffers_size",
960 "arc_meta_used", "arc_meta_limit", "arc_meta_max",
961 "arc_meta_min", "hdr_size", "data_size", "other_size",
965 static const char *extras
[] = {
966 "arc_no_grow", "arc_tempreserve",
970 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, "arc_stats", &sym
) == -1) {
971 mdb_warn("failed to find 'arc_stats'");
975 stats
= mdb_zalloc(sym
.st_size
, UM_SLEEP
| UM_GC
);
977 if (mdb_vread(stats
, sym
.st_size
, sym
.st_value
) == -1) {
978 mdb_warn("couldn't read 'arc_stats' at %p", sym
.st_value
);
982 nstats
= sym
.st_size
/ sizeof (kstat_named_t
);
984 /* NB: -a / opt_a are ignored for backwards compatability */
985 if (mdb_getopts(argc
, argv
,
986 'a', MDB_OPT_SETBITS
, TRUE
, &opt_a
,
987 'b', MDB_OPT_SETBITS
, TRUE
, &opt_b
,
988 'k', MDB_OPT_SETBITS
, 10, &shift
,
989 'm', MDB_OPT_SETBITS
, 20, &shift
,
990 'g', MDB_OPT_SETBITS
, 30, &shift
,
994 if (!opt_b
&& !shift
)
1014 for (i
= 0; i
< nstats
; i
++) {
1016 boolean_t bytes
= B_FALSE
;
1018 for (j
= 0; bytestats
[j
]; j
++) {
1019 if (strcmp(stats
[i
].name
, bytestats
[j
]) == 0) {
1026 mdb_printf("%-25s = %9llu %s\n", stats
[i
].name
,
1027 stats
[i
].value
.ui64
>> shift
, suffix
);
1029 mdb_printf("%-25s = %9llu\n", stats
[i
].name
,
1030 stats
[i
].value
.ui64
);
1034 for (i
= 0; extras
[i
]; i
++) {
1037 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, extras
[i
], &sym
) == -1) {
1038 mdb_warn("failed to find '%s'", extras
[i
]);
1042 if (sym
.st_size
!= sizeof (uint64_t) &&
1043 sym
.st_size
!= sizeof (uint32_t)) {
1044 mdb_warn("expected scalar for variable '%s'\n",
1049 if (mdb_vread(&buf
, sym
.st_size
, sym
.st_value
) == -1) {
1050 mdb_warn("couldn't read '%s'", extras
[i
]);
1054 mdb_printf("%-25s = ", extras
[i
]);
1056 /* NB: all the 64-bit extras happen to be byte counts */
1057 if (sym
.st_size
== sizeof (uint64_t))
1058 mdb_printf("%9llu %s\n", buf
>> shift
, suffix
);
1060 if (sym
.st_size
== sizeof (uint32_t))
1061 mdb_printf("%9d\n", *((uint32_t *)&buf
));
1066 typedef struct mdb_spa_print
{
1067 pool_state_t spa_state
;
1068 char spa_name
[MAXNAMELEN
];
1074 * -c Print configuration information as well
1075 * -v Print vdev state
1076 * -e Print vdev error stats
1077 * -m Print vdev metaslab info
1078 * -M print vdev metaslab group info
1079 * -h Print histogram info (must be combined with -m or -M)
1081 * Print a summarized spa_t. When given no arguments, prints out a table of all
1082 * active pools on the system.
1086 spa_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1088 const char *statetab
[] = { "ACTIVE", "EXPORTED", "DESTROYED",
1089 "SPARE", "L2CACHE", "UNINIT", "UNAVAIL", "POTENTIAL" };
1093 if (mdb_getopts(argc
, argv
,
1094 'c', MDB_OPT_SETBITS
, SPA_FLAG_CONFIG
, &spa_flags
,
1095 'v', MDB_OPT_SETBITS
, SPA_FLAG_VDEVS
, &spa_flags
,
1096 'e', MDB_OPT_SETBITS
, SPA_FLAG_ERRORS
, &spa_flags
,
1097 'M', MDB_OPT_SETBITS
, SPA_FLAG_METASLAB_GROUPS
, &spa_flags
,
1098 'm', MDB_OPT_SETBITS
, SPA_FLAG_METASLABS
, &spa_flags
,
1099 'h', MDB_OPT_SETBITS
, SPA_FLAG_HISTOGRAMS
, &spa_flags
,
1101 return (DCMD_USAGE
);
1103 if (!(flags
& DCMD_ADDRSPEC
)) {
1104 if (mdb_walk_dcmd("spa", "spa", argc
, argv
) == -1) {
1105 mdb_warn("can't walk spa");
1112 if (flags
& DCMD_PIPE_OUT
) {
1113 mdb_printf("%#lr\n", addr
);
1117 if (DCMD_HDRSPEC(flags
))
1118 mdb_printf("%<u>%-?s %9s %-*s%</u>\n", "ADDR", "STATE",
1119 sizeof (uintptr_t) == 4 ? 60 : 52, "NAME");
1121 mdb_spa_print_t spa
;
1122 if (mdb_ctf_vread(&spa
, "spa_t", "mdb_spa_print_t", addr
, 0) == -1)
1125 if (spa
.spa_state
< 0 || spa
.spa_state
> POOL_STATE_UNAVAIL
)
1128 state
= statetab
[spa
.spa_state
];
1130 mdb_printf("%0?p %9s %s\n", addr
, state
, spa
.spa_name
);
1132 if (spa_flags
& SPA_FLAG_CONFIG
) {
1135 if (mdb_call_dcmd("spa_config", addr
, flags
, 0,
1141 if (spa_flags
& SPA_FLAG_ALL_VDEV
) {
1143 char opts
[100] = "-";
1145 (spa_flags
| SPA_FLAG_VDEVS
) == SPA_FLAG_VDEVS
? 0 : 1;
1147 if (spa_flags
& SPA_FLAG_ERRORS
)
1149 if (spa_flags
& SPA_FLAG_METASLABS
)
1151 if (spa_flags
& SPA_FLAG_METASLAB_GROUPS
)
1153 if (spa_flags
& SPA_FLAG_HISTOGRAMS
)
1156 v
.a_type
= MDB_TYPE_STRING
;
1157 v
.a_un
.a_str
= opts
;
1161 if (mdb_call_dcmd("spa_vdevs", addr
, flags
, args
,
1170 typedef struct mdb_spa_config_spa
{
1171 uintptr_t spa_config
;
1172 } mdb_spa_config_spa_t
;
1177 * Given a spa_t, print the configuration information stored in spa_config.
1178 * Since it's just an nvlist, format it as an indented list of name=value pairs.
1179 * We simply read the value of spa_config and pass off to ::nvlist.
1183 spa_print_config(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1185 mdb_spa_config_spa_t spa
;
1187 if (argc
!= 0 || !(flags
& DCMD_ADDRSPEC
))
1188 return (DCMD_USAGE
);
1190 if (mdb_ctf_vread(&spa
, ZFS_STRUCT
"spa", "mdb_spa_config_spa_t",
1194 if (spa
.spa_config
== 0) {
1195 mdb_printf("(none)\n");
1199 return (mdb_call_dcmd("nvlist", spa
.spa_config
, flags
,
1203 const char histo_stars
[] = "****************************************";
1204 const int histo_width
= sizeof (histo_stars
) - 1;
1207 dump_histogram(const uint64_t *histo
, int size
, int offset
)
1210 int minidx
= size
- 1;
1214 for (i
= 0; i
< size
; i
++) {
1217 if (histo
[i
] > 0 && i
> maxidx
)
1219 if (histo
[i
] > 0 && i
< minidx
)
1223 if (max
< histo_width
)
1226 for (i
= minidx
; i
<= maxidx
; i
++) {
1227 mdb_printf("%3u: %6llu %s\n",
1228 i
+ offset
, (u_longlong_t
)histo
[i
],
1229 &histo_stars
[(max
- histo
[i
]) * histo_width
/ max
]);
1233 typedef struct mdb_range_tree
{
1237 typedef struct mdb_metaslab_group
{
1238 uint64_t mg_fragmentation
;
1239 uint64_t mg_histogram
[RANGE_TREE_HISTOGRAM_SIZE
];
1240 } mdb_metaslab_group_t
;
1242 typedef struct mdb_metaslab
{
1246 uint64_t ms_fragmentation
;
1247 uintptr_t ms_alloctree
[TXG_SIZE
];
1248 uintptr_t ms_freetree
[TXG_SIZE
];
1253 typedef struct mdb_space_map_phys_t
{
1255 uint64_t smp_histogram
[SPACE_MAP_HISTOGRAM_SIZE
];
1256 } mdb_space_map_phys_t
;
1258 typedef struct mdb_space_map
{
1265 typedef struct mdb_vdev
{
1267 uint64_t vdev_ms_count
;
1268 vdev_stat_t vdev_stat
;
1272 metaslab_stats(uintptr_t addr
, int spa_flags
)
1277 if (mdb_ctf_vread(&vdev
, "vdev_t", "mdb_vdev_t",
1278 (uintptr_t)addr
, 0) == -1) {
1279 mdb_warn("failed to read vdev at %p\n", addr
);
1284 mdb_printf("%<u>%-?s %6s %20s %10s %9s%</u>\n", "ADDR", "ID",
1285 "OFFSET", "FREE", "FRAGMENTATION");
1287 vdev_ms
= mdb_alloc(vdev
.vdev_ms_count
* sizeof (void *),
1289 if (mdb_vread(vdev_ms
, vdev
.vdev_ms_count
* sizeof (void *),
1290 (uintptr_t)vdev
.vdev_ms
) == -1) {
1291 mdb_warn("failed to read vdev_ms at %p\n", vdev
.vdev_ms
);
1295 for (int m
= 0; m
< vdev
.vdev_ms_count
; m
++) {
1297 mdb_space_map_t sm
= { 0 };
1298 char free
[NICENUM_BUFLEN
];
1300 if (mdb_ctf_vread(&ms
, "metaslab_t", "mdb_metaslab_t",
1301 (uintptr_t)vdev_ms
[m
], 0) == -1)
1304 if (ms
.ms_sm
!= NULL
&&
1305 mdb_ctf_vread(&sm
, "space_map_t", "mdb_space_map_t",
1309 mdb_nicenum(ms
.ms_size
- sm
.sm_alloc
, free
);
1311 mdb_printf("%0?p %6llu %20llx %10s ", vdev_ms
[m
], ms
.ms_id
,
1313 if (ms
.ms_fragmentation
== ZFS_FRAG_INVALID
)
1314 mdb_printf("%9s\n", "-");
1316 mdb_printf("%9llu%%\n", ms
.ms_fragmentation
);
1318 if ((spa_flags
& SPA_FLAG_HISTOGRAMS
) && ms
.ms_sm
!= NULL
) {
1319 mdb_space_map_phys_t smp
;
1321 if (sm
.sm_phys
== NULL
)
1324 (void) mdb_ctf_vread(&smp
, "space_map_phys_t",
1325 "mdb_space_map_phys_t", sm
.sm_phys
, 0);
1327 dump_histogram(smp
.smp_histogram
,
1328 SPACE_MAP_HISTOGRAM_SIZE
, sm
.sm_shift
);
1336 metaslab_group_stats(uintptr_t addr
, int spa_flags
)
1338 mdb_metaslab_group_t mg
;
1339 if (mdb_ctf_vread(&mg
, "metaslab_group_t", "mdb_metaslab_group_t",
1340 (uintptr_t)addr
, 0) == -1) {
1341 mdb_warn("failed to read vdev_mg at %p\n", addr
);
1346 mdb_printf("%<u>%-?s %15s%</u>\n", "ADDR", "FRAGMENTATION");
1347 if (mg
.mg_fragmentation
== ZFS_FRAG_INVALID
)
1348 mdb_printf("%0?p %15s\n", addr
, "-");
1350 mdb_printf("%0?p %15llu%%\n", addr
, mg
.mg_fragmentation
);
1352 if (spa_flags
& SPA_FLAG_HISTOGRAMS
)
1353 dump_histogram(mg
.mg_histogram
, RANGE_TREE_HISTOGRAM_SIZE
, 0);
1361 * Print out a summarized vdev_t, in the following form:
1363 * ADDR STATE AUX DESC
1364 * fffffffbcde23df0 HEALTHY - /dev/dsk/c0t0d0
1366 * If '-r' is specified, recursively visit all children.
1368 * With '-e', the statistics associated with the vdev are printed as well.
1371 do_print_vdev(uintptr_t addr
, int flags
, int depth
, boolean_t recursive
,
1375 char desc
[MAXNAMELEN
];
1378 const char *state
, *aux
;
1380 if (mdb_vread(&vdev
, sizeof (vdev
), (uintptr_t)addr
) == -1) {
1381 mdb_warn("failed to read vdev_t at %p\n", (uintptr_t)addr
);
1385 if (flags
& DCMD_PIPE_OUT
) {
1386 mdb_printf("%#lr\n", addr
);
1388 if (vdev
.vdev_path
!= NULL
) {
1389 if (mdb_readstr(desc
, sizeof (desc
),
1390 (uintptr_t)vdev
.vdev_path
) == -1) {
1391 mdb_warn("failed to read vdev_path at %p\n",
1395 } else if (vdev
.vdev_ops
!= NULL
) {
1397 if (mdb_vread(&ops
, sizeof (ops
),
1398 (uintptr_t)vdev
.vdev_ops
) == -1) {
1399 mdb_warn("failed to read vdev_ops at %p\n",
1403 (void) strcpy(desc
, ops
.vdev_op_type
);
1405 (void) strcpy(desc
, "<unknown>");
1408 if (depth
== 0 && DCMD_HDRSPEC(flags
))
1409 mdb_printf("%<u>%-?s %-9s %-12s %-*s%</u>\n",
1410 "ADDR", "STATE", "AUX",
1411 sizeof (uintptr_t) == 4 ? 43 : 35,
1414 mdb_printf("%0?p ", addr
);
1416 switch (vdev
.vdev_state
) {
1417 case VDEV_STATE_CLOSED
:
1420 case VDEV_STATE_OFFLINE
:
1423 case VDEV_STATE_CANT_OPEN
:
1424 state
= "CANT_OPEN";
1426 case VDEV_STATE_DEGRADED
:
1429 case VDEV_STATE_HEALTHY
:
1432 case VDEV_STATE_REMOVED
:
1435 case VDEV_STATE_FAULTED
:
1443 switch (vdev
.vdev_stat
.vs_aux
) {
1447 case VDEV_AUX_OPEN_FAILED
:
1448 aux
= "OPEN_FAILED";
1450 case VDEV_AUX_CORRUPT_DATA
:
1451 aux
= "CORRUPT_DATA";
1453 case VDEV_AUX_NO_REPLICAS
:
1454 aux
= "NO_REPLICAS";
1456 case VDEV_AUX_BAD_GUID_SUM
:
1457 aux
= "BAD_GUID_SUM";
1459 case VDEV_AUX_TOO_SMALL
:
1462 case VDEV_AUX_BAD_LABEL
:
1465 case VDEV_AUX_VERSION_NEWER
:
1468 case VDEV_AUX_VERSION_OLDER
:
1471 case VDEV_AUX_UNSUP_FEAT
:
1474 case VDEV_AUX_SPARED
:
1477 case VDEV_AUX_ERR_EXCEEDED
:
1478 aux
= "ERR_EXCEEDED";
1480 case VDEV_AUX_IO_FAILURE
:
1483 case VDEV_AUX_BAD_LOG
:
1486 case VDEV_AUX_EXTERNAL
:
1489 case VDEV_AUX_SPLIT_POOL
:
1497 mdb_printf("%-9s %-12s %*s%s\n", state
, aux
, depth
, "", desc
);
1499 if (spa_flags
& SPA_FLAG_ERRORS
) {
1500 vdev_stat_t
*vs
= &vdev
.vdev_stat
;
1505 mdb_printf("%<u> %12s %12s %12s %12s "
1506 "%12s%</u>\n", "READ", "WRITE", "FREE", "CLAIM",
1509 for (i
= 1; i
< ZIO_TYPES
; i
++)
1510 mdb_printf("%11#llx%s", vs
->vs_ops
[i
],
1511 i
== ZIO_TYPES
- 1 ? "" : " ");
1513 mdb_printf("BYTES ");
1514 for (i
= 1; i
< ZIO_TYPES
; i
++)
1515 mdb_printf("%11#llx%s", vs
->vs_bytes
[i
],
1516 i
== ZIO_TYPES
- 1 ? "" : " ");
1520 mdb_printf("EREAD %10#llx\n", vs
->vs_read_errors
);
1521 mdb_printf("EWRITE %10#llx\n", vs
->vs_write_errors
);
1522 mdb_printf("ECKSUM %10#llx\n",
1523 vs
->vs_checksum_errors
);
1528 if (spa_flags
& SPA_FLAG_METASLAB_GROUPS
&&
1529 vdev
.vdev_mg
!= NULL
) {
1530 metaslab_group_stats((uintptr_t)vdev
.vdev_mg
,
1533 if (spa_flags
& SPA_FLAG_METASLABS
&& vdev
.vdev_ms
!= NULL
) {
1534 metaslab_stats((uintptr_t)addr
, spa_flags
);
1538 children
= vdev
.vdev_children
;
1540 if (children
== 0 || !recursive
)
1543 child
= mdb_alloc(children
* sizeof (void *), UM_SLEEP
| UM_GC
);
1544 if (mdb_vread(child
, children
* sizeof (void *),
1545 (uintptr_t)vdev
.vdev_child
) == -1) {
1546 mdb_warn("failed to read vdev children at %p", vdev
.vdev_child
);
1550 for (c
= 0; c
< children
; c
++) {
1551 if (do_print_vdev(child
[c
], flags
, depth
+ 2, recursive
,
1561 vdev_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1564 boolean_t recursive
= B_FALSE
;
1567 if (mdb_getopts(argc
, argv
,
1568 'e', MDB_OPT_SETBITS
, SPA_FLAG_ERRORS
, &spa_flags
,
1569 'm', MDB_OPT_SETBITS
, SPA_FLAG_METASLABS
, &spa_flags
,
1570 'M', MDB_OPT_SETBITS
, SPA_FLAG_METASLAB_GROUPS
, &spa_flags
,
1571 'h', MDB_OPT_SETBITS
, SPA_FLAG_HISTOGRAMS
, &spa_flags
,
1572 'r', MDB_OPT_SETBITS
, TRUE
, &recursive
,
1573 'd', MDB_OPT_UINT64
, &depth
, NULL
) != argc
)
1574 return (DCMD_USAGE
);
1576 if (!(flags
& DCMD_ADDRSPEC
)) {
1577 mdb_warn("no vdev_t address given\n");
1581 return (do_print_vdev(addr
, flags
, (int)depth
, recursive
, spa_flags
));
1584 typedef struct metaslab_walk_data
{
1585 uint64_t mw_numvdevs
;
1586 uintptr_t *mw_vdevs
;
1591 } metaslab_walk_data_t
;
1594 metaslab_walk_step(mdb_walk_state_t
*wsp
)
1596 metaslab_walk_data_t
*mw
= wsp
->walk_data
;
1600 if (mw
->mw_curvdev
>= mw
->mw_numvdevs
)
1603 if (mw
->mw_mss
== NULL
) {
1607 ASSERT(mw
->mw_curms
== 0);
1608 ASSERT(mw
->mw_nummss
== 0);
1610 vdevp
= mw
->mw_vdevs
[mw
->mw_curvdev
];
1611 if (GETMEMB(vdevp
, "vdev", vdev_ms
, mssp
) ||
1612 GETMEMB(vdevp
, "vdev", vdev_ms_count
, mw
->mw_nummss
)) {
1616 mw
->mw_mss
= mdb_alloc(mw
->mw_nummss
* sizeof (void*),
1618 if (mdb_vread(mw
->mw_mss
, mw
->mw_nummss
* sizeof (void*),
1620 mdb_warn("failed to read vdev_ms at %p", mssp
);
1625 if (mw
->mw_curms
>= mw
->mw_nummss
) {
1633 msp
= mw
->mw_mss
[mw
->mw_curms
];
1634 if (mdb_vread(&ms
, sizeof (metaslab_t
), msp
) == -1) {
1635 mdb_warn("failed to read metaslab_t at %p", msp
);
1641 return (wsp
->walk_callback(msp
, &ms
, wsp
->walk_cbdata
));
1646 metaslab_walk_init(mdb_walk_state_t
*wsp
)
1648 metaslab_walk_data_t
*mw
;
1649 uintptr_t root_vdevp
;
1652 if (wsp
->walk_addr
== NULL
) {
1653 mdb_warn("must supply address of spa_t\n");
1657 mw
= mdb_zalloc(sizeof (metaslab_walk_data_t
), UM_SLEEP
| UM_GC
);
1659 if (GETMEMB(wsp
->walk_addr
, "spa", spa_root_vdev
, root_vdevp
) ||
1660 GETMEMB(root_vdevp
, "vdev", vdev_children
, mw
->mw_numvdevs
) ||
1661 GETMEMB(root_vdevp
, "vdev", vdev_child
, childp
)) {
1665 mw
->mw_vdevs
= mdb_alloc(mw
->mw_numvdevs
* sizeof (void *),
1667 if (mdb_vread(mw
->mw_vdevs
, mw
->mw_numvdevs
* sizeof (void *),
1669 mdb_warn("failed to read root vdev children at %p", childp
);
1673 wsp
->walk_data
= mw
;
1678 typedef struct mdb_spa
{
1679 uintptr_t spa_dsl_pool
;
1680 uintptr_t spa_root_vdev
;
1683 typedef struct mdb_dsl_dir
{
1685 int64_t dd_space_towrite
[TXG_SIZE
];
1688 typedef struct mdb_dsl_dir_phys
{
1689 uint64_t dd_used_bytes
;
1690 uint64_t dd_compressed_bytes
;
1691 uint64_t dd_uncompressed_bytes
;
1692 } mdb_dsl_dir_phys_t
;
1694 typedef struct space_data
{
1695 uint64_t ms_alloctree
[TXG_SIZE
];
1696 uint64_t ms_freetree
[TXG_SIZE
];
1704 space_cb(uintptr_t addr
, const void *unknown
, void *arg
)
1706 space_data_t
*sd
= arg
;
1708 mdb_range_tree_t rt
;
1709 mdb_space_map_t sm
= { 0 };
1710 mdb_space_map_phys_t smp
= { 0 };
1713 if (mdb_ctf_vread(&ms
, "metaslab_t", "mdb_metaslab_t",
1717 for (i
= 0; i
< TXG_SIZE
; i
++) {
1718 if (mdb_ctf_vread(&rt
, "range_tree_t",
1719 "mdb_range_tree_t", ms
.ms_alloctree
[i
], 0) == -1)
1722 sd
->ms_alloctree
[i
] += rt
.rt_space
;
1724 if (mdb_ctf_vread(&rt
, "range_tree_t",
1725 "mdb_range_tree_t", ms
.ms_freetree
[i
], 0) == -1)
1728 sd
->ms_freetree
[i
] += rt
.rt_space
;
1731 if (mdb_ctf_vread(&rt
, "range_tree_t",
1732 "mdb_range_tree_t", ms
.ms_tree
, 0) == -1)
1735 if (ms
.ms_sm
!= NULL
&&
1736 mdb_ctf_vread(&sm
, "space_map_t",
1737 "mdb_space_map_t", ms
.ms_sm
, 0) == -1)
1740 if (sm
.sm_phys
!= NULL
) {
1741 (void) mdb_ctf_vread(&smp
, "space_map_phys_t",
1742 "mdb_space_map_phys_t", sm
.sm_phys
, 0);
1745 sd
->ms_tree
+= rt
.rt_space
;
1746 sd
->avail
+= sm
.sm_size
- sm
.sm_alloc
;
1747 sd
->nowavail
+= sm
.sm_size
- smp
.smp_alloc
;
1755 * Given a spa_t, print out it's on-disk space usage and in-core
1756 * estimates of future usage. If -b is given, print space in bytes.
1757 * Otherwise print in megabytes.
1761 spa_space(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1764 uintptr_t dp_root_dir
;
1766 mdb_dsl_dir_phys_t dsp
;
1768 uintptr_t childaddr
;
1772 int bytes
= B_FALSE
;
1774 if (mdb_getopts(argc
, argv
, 'b', MDB_OPT_SETBITS
, TRUE
, &bytes
, NULL
) !=
1776 return (DCMD_USAGE
);
1777 if (!(flags
& DCMD_ADDRSPEC
))
1778 return (DCMD_USAGE
);
1785 if (GETMEMB(addr
, "spa", spa_dsl_pool
, spa
.spa_dsl_pool
) ||
1786 GETMEMB(addr
, "spa", spa_root_vdev
, spa
.spa_root_vdev
) ||
1787 GETMEMB(spa
.spa_root_vdev
, "vdev", vdev_children
, children
) ||
1788 GETMEMB(spa
.spa_root_vdev
, "vdev", vdev_child
, childaddr
) ||
1789 GETMEMB(spa
.spa_dsl_pool
, "dsl_pool",
1790 dp_root_dir
, dp_root_dir
) ||
1791 GETMEMB(dp_root_dir
, "dsl_dir", dd_phys
, dd
.dd_phys
) ||
1792 GETMEMB(dp_root_dir
, "dsl_dir",
1793 dd_space_towrite
, dd
.dd_space_towrite
) ||
1794 GETMEMB(dd
.dd_phys
, "dsl_dir_phys",
1795 dd_used_bytes
, dsp
.dd_used_bytes
) ||
1796 GETMEMB(dd
.dd_phys
, "dsl_dir_phys",
1797 dd_compressed_bytes
, dsp
.dd_compressed_bytes
) ||
1798 GETMEMB(dd
.dd_phys
, "dsl_dir_phys",
1799 dd_uncompressed_bytes
, dsp
.dd_uncompressed_bytes
)) {
1803 mdb_printf("dd_space_towrite = %llu%s %llu%s %llu%s %llu%s\n",
1804 dd
.dd_space_towrite
[0] >> shift
, suffix
,
1805 dd
.dd_space_towrite
[1] >> shift
, suffix
,
1806 dd
.dd_space_towrite
[2] >> shift
, suffix
,
1807 dd
.dd_space_towrite
[3] >> shift
, suffix
);
1809 mdb_printf("dd_phys.dd_used_bytes = %llu%s\n",
1810 dsp
.dd_used_bytes
>> shift
, suffix
);
1811 mdb_printf("dd_phys.dd_compressed_bytes = %llu%s\n",
1812 dsp
.dd_compressed_bytes
>> shift
, suffix
);
1813 mdb_printf("dd_phys.dd_uncompressed_bytes = %llu%s\n",
1814 dsp
.dd_uncompressed_bytes
>> shift
, suffix
);
1816 bzero(&sd
, sizeof (sd
));
1817 if (mdb_pwalk("metaslab", space_cb
, &sd
, addr
) != 0) {
1818 mdb_warn("can't walk metaslabs");
1822 mdb_printf("ms_allocmap = %llu%s %llu%s %llu%s %llu%s\n",
1823 sd
.ms_alloctree
[0] >> shift
, suffix
,
1824 sd
.ms_alloctree
[1] >> shift
, suffix
,
1825 sd
.ms_alloctree
[2] >> shift
, suffix
,
1826 sd
.ms_alloctree
[3] >> shift
, suffix
);
1827 mdb_printf("ms_freemap = %llu%s %llu%s %llu%s %llu%s\n",
1828 sd
.ms_freetree
[0] >> shift
, suffix
,
1829 sd
.ms_freetree
[1] >> shift
, suffix
,
1830 sd
.ms_freetree
[2] >> shift
, suffix
,
1831 sd
.ms_freetree
[3] >> shift
, suffix
);
1832 mdb_printf("ms_tree = %llu%s\n", sd
.ms_tree
>> shift
, suffix
);
1833 mdb_printf("last synced avail = %llu%s\n", sd
.avail
>> shift
, suffix
);
1834 mdb_printf("current syncing avail = %llu%s\n",
1835 sd
.nowavail
>> shift
, suffix
);
1840 typedef struct mdb_spa_aux_vdev
{
1842 uintptr_t sav_vdevs
;
1843 } mdb_spa_aux_vdev_t
;
1845 typedef struct mdb_spa_vdevs
{
1846 uintptr_t spa_root_vdev
;
1847 mdb_spa_aux_vdev_t spa_l2cache
;
1848 mdb_spa_aux_vdev_t spa_spares
;
1852 spa_print_aux(mdb_spa_aux_vdev_t
*sav
, uint_t flags
, mdb_arg_t
*v
,
1860 * Iterate over aux vdevs and print those out as well. This is a
1861 * little annoying because we don't have a root vdev to pass to ::vdev.
1862 * Instead, we print a single line and then call it for each child
1865 if (sav
->sav_count
!= 0) {
1866 v
[1].a_type
= MDB_TYPE_STRING
;
1867 v
[1].a_un
.a_str
= "-d";
1868 v
[2].a_type
= MDB_TYPE_IMMEDIATE
;
1869 v
[2].a_un
.a_val
= 2;
1871 len
= sav
->sav_count
* sizeof (uintptr_t);
1872 aux
= mdb_alloc(len
, UM_SLEEP
);
1873 if (mdb_vread(aux
, len
, sav
->sav_vdevs
) == -1) {
1875 mdb_warn("failed to read l2cache vdevs at %p",
1880 mdb_printf("%-?s %-9s %-12s %s\n", "-", "-", "-", name
);
1882 for (i
= 0; i
< sav
->sav_count
; i
++) {
1883 ret
= mdb_call_dcmd("vdev", aux
[i
], flags
, 3, v
);
1884 if (ret
!= DCMD_OK
) {
1899 * -e Include error stats
1900 * -m Include metaslab information
1901 * -M Include metaslab group information
1902 * -h Include histogram information (requires -m or -M)
1904 * Print out a summarized list of vdevs for the given spa_t.
1905 * This is accomplished by invoking "::vdev -re" on the root vdev, as well as
1906 * iterating over the cache devices.
1910 spa_vdevs(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
1914 char opts
[100] = "-r";
1917 if (mdb_getopts(argc
, argv
,
1918 'e', MDB_OPT_SETBITS
, SPA_FLAG_ERRORS
, &spa_flags
,
1919 'm', MDB_OPT_SETBITS
, SPA_FLAG_METASLABS
, &spa_flags
,
1920 'M', MDB_OPT_SETBITS
, SPA_FLAG_METASLAB_GROUPS
, &spa_flags
,
1921 'h', MDB_OPT_SETBITS
, SPA_FLAG_HISTOGRAMS
, &spa_flags
,
1923 return (DCMD_USAGE
);
1925 if (!(flags
& DCMD_ADDRSPEC
))
1926 return (DCMD_USAGE
);
1928 mdb_spa_vdevs_t spa
;
1929 if (mdb_ctf_vread(&spa
, "spa_t", "mdb_spa_vdevs_t", addr
, 0) == -1)
1933 * Unitialized spa_t structures can have a NULL root vdev.
1935 if (spa
.spa_root_vdev
== NULL
) {
1936 mdb_printf("no associated vdevs\n");
1940 if (spa_flags
& SPA_FLAG_ERRORS
)
1942 if (spa_flags
& SPA_FLAG_METASLABS
)
1944 if (spa_flags
& SPA_FLAG_METASLAB_GROUPS
)
1946 if (spa_flags
& SPA_FLAG_HISTOGRAMS
)
1949 v
[0].a_type
= MDB_TYPE_STRING
;
1950 v
[0].a_un
.a_str
= opts
;
1952 ret
= mdb_call_dcmd("vdev", (uintptr_t)spa
.spa_root_vdev
,
1957 if (spa_print_aux(&spa
.spa_l2cache
, flags
, v
, "cache") != 0 ||
1958 spa_print_aux(&spa
.spa_spares
, flags
, v
, "spares") != 0)
1967 * Print a summary of zio_t and all its children. This is intended to display a
1968 * zio tree, and hence we only pick the most important pieces of information for
1969 * the main summary. More detailed information can always be found by doing a
1970 * '::print zio' on the underlying zio_t. The columns we display are:
1972 * ADDRESS TYPE STAGE WAITER TIME_ELAPSED
1974 * The 'address' column is indented by one space for each depth level as we
1975 * descend down the tree.
1978 #define ZIO_MAXINDENT 7
1979 #define ZIO_MAXWIDTH (sizeof (uintptr_t) * 2 + ZIO_MAXINDENT)
1980 #define ZIO_WALK_SELF 0
1981 #define ZIO_WALK_CHILD 1
1982 #define ZIO_WALK_PARENT 2
1984 typedef struct zio_print_args
{
1985 int zpa_current_depth
;
1992 typedef struct mdb_zio
{
1993 enum zio_type io_type
;
1994 enum zio_stage io_stage
;
1995 uintptr_t io_waiter
;
1999 uintptr_t list_next
;
2005 typedef struct mdb_zio_timestamp
{
2006 hrtime_t io_timestamp
;
2007 } mdb_zio_timestamp_t
;
2009 static int zio_child_cb(uintptr_t addr
, const void *unknown
, void *arg
);
2012 zio_print_cb(uintptr_t addr
, zio_print_args_t
*zpa
)
2014 mdb_ctf_id_t type_enum
, stage_enum
;
2015 int indent
= zpa
->zpa_current_depth
;
2016 const char *type
, *stage
;
2019 mdb_zio_timestamp_t zio_timestamp
= { 0 };
2021 if (mdb_ctf_vread(&zio
, ZFS_STRUCT
"zio", "mdb_zio_t", addr
, 0) == -1)
2023 (void) mdb_ctf_vread(&zio_timestamp
, ZFS_STRUCT
"zio",
2024 "mdb_zio_timestamp_t", addr
, MDB_CTF_VREAD_QUIET
);
2026 if (indent
> ZIO_MAXINDENT
)
2027 indent
= ZIO_MAXINDENT
;
2029 if (mdb_ctf_lookup_by_name("enum zio_type", &type_enum
) == -1 ||
2030 mdb_ctf_lookup_by_name("enum zio_stage", &stage_enum
) == -1) {
2031 mdb_warn("failed to lookup zio enums");
2035 if ((type
= mdb_ctf_enum_name(type_enum
, zio
.io_type
)) != NULL
)
2036 type
+= sizeof ("ZIO_TYPE_") - 1;
2040 if (zio
.io_error
== 0) {
2041 stage
= mdb_ctf_enum_name(stage_enum
, zio
.io_stage
);
2043 stage
+= sizeof ("ZIO_STAGE_") - 1;
2050 if (zpa
->zpa_current_depth
>= zpa
->zpa_min_depth
) {
2051 if (zpa
->zpa_flags
& DCMD_PIPE_OUT
) {
2052 mdb_printf("%?p\n", addr
);
2054 mdb_printf("%*s%-*p %-5s %-16s ", indent
, "",
2055 ZIO_MAXWIDTH
- indent
, addr
, type
, stage
);
2056 if (zio
.io_waiter
!= 0)
2057 mdb_printf("%-16lx ", zio
.io_waiter
);
2059 mdb_printf("%-16s ", "-");
2061 if (zio_timestamp
.io_timestamp
!= 0) {
2062 mdb_printf("%llums", (mdb_gethrtime() -
2063 zio_timestamp
.io_timestamp
) /
2066 mdb_printf("%-12s ", "-");
2069 mdb_printf("%-12s ", "-");
2075 if (zpa
->zpa_current_depth
>= zpa
->zpa_max_depth
)
2078 if (zpa
->zpa_type
== ZIO_WALK_PARENT
)
2079 laddr
= addr
+ mdb_ctf_offsetof_by_name(ZFS_STRUCT
"zio",
2082 laddr
= addr
+ mdb_ctf_offsetof_by_name(ZFS_STRUCT
"zio",
2085 zpa
->zpa_current_depth
++;
2086 if (mdb_pwalk("list", zio_child_cb
, zpa
, laddr
) != 0) {
2087 mdb_warn("failed to walk zio_t children at %p\n", laddr
);
2090 zpa
->zpa_current_depth
--;
2097 zio_child_cb(uintptr_t addr
, const void *unknown
, void *arg
)
2101 zio_print_args_t
*zpa
= arg
;
2103 if (mdb_vread(&zl
, sizeof (zl
), addr
) == -1) {
2104 mdb_warn("failed to read zio_link_t at %p", addr
);
2108 if (zpa
->zpa_type
== ZIO_WALK_PARENT
)
2109 ziop
= (uintptr_t)zl
.zl_parent
;
2111 ziop
= (uintptr_t)zl
.zl_child
;
2113 return (zio_print_cb(ziop
, zpa
));
2118 zio_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2120 zio_print_args_t zpa
= { 0 };
2122 if (!(flags
& DCMD_ADDRSPEC
))
2123 return (DCMD_USAGE
);
2125 if (mdb_getopts(argc
, argv
,
2126 'r', MDB_OPT_SETBITS
, INT_MAX
, &zpa
.zpa_max_depth
,
2127 'c', MDB_OPT_SETBITS
, ZIO_WALK_CHILD
, &zpa
.zpa_type
,
2128 'p', MDB_OPT_SETBITS
, ZIO_WALK_PARENT
, &zpa
.zpa_type
,
2130 return (DCMD_USAGE
);
2132 zpa
.zpa_flags
= flags
;
2133 if (zpa
.zpa_max_depth
!= 0) {
2134 if (zpa
.zpa_type
== ZIO_WALK_SELF
)
2135 zpa
.zpa_type
= ZIO_WALK_CHILD
;
2136 } else if (zpa
.zpa_type
!= ZIO_WALK_SELF
) {
2137 zpa
.zpa_min_depth
= 1;
2138 zpa
.zpa_max_depth
= 1;
2141 if (!(flags
& DCMD_PIPE_OUT
) && DCMD_HDRSPEC(flags
)) {
2142 mdb_printf("%<u>%-*s %-5s %-16s %-16s %-12s%</u>\n",
2143 ZIO_MAXWIDTH
, "ADDRESS", "TYPE", "STAGE", "WAITER",
2147 if (zio_print_cb(addr
, &zpa
) != WALK_NEXT
)
2156 * Print a summary of all zio_t structures on the system, or for a particular
2157 * pool. This is equivalent to '::walk zio_root | ::zio'.
2161 zio_state(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2164 * MDB will remember the last address of the pipeline, so if we don't
2165 * zero this we'll end up trying to walk zio structures for a
2166 * non-existent spa_t.
2168 if (!(flags
& DCMD_ADDRSPEC
))
2171 return (mdb_pwalk_dcmd("zio_root", "zio", argc
, argv
, addr
));
2174 typedef struct txg_list_walk_data
{
2175 uintptr_t lw_head
[TXG_SIZE
];
2180 } txg_list_walk_data_t
;
2183 txg_list_walk_init_common(mdb_walk_state_t
*wsp
, int txg
, int maxoff
)
2185 txg_list_walk_data_t
*lwd
;
2189 lwd
= mdb_alloc(sizeof (txg_list_walk_data_t
), UM_SLEEP
| UM_GC
);
2190 if (mdb_vread(&list
, sizeof (txg_list_t
), wsp
->walk_addr
) == -1) {
2191 mdb_warn("failed to read txg_list_t at %#lx", wsp
->walk_addr
);
2195 for (i
= 0; i
< TXG_SIZE
; i
++)
2196 lwd
->lw_head
[i
] = (uintptr_t)list
.tl_head
[i
];
2197 lwd
->lw_offset
= list
.tl_offset
;
2198 lwd
->lw_obj
= mdb_alloc(lwd
->lw_offset
+ sizeof (txg_node_t
),
2200 lwd
->lw_txgoff
= txg
;
2201 lwd
->lw_maxoff
= maxoff
;
2203 wsp
->walk_addr
= lwd
->lw_head
[lwd
->lw_txgoff
];
2204 wsp
->walk_data
= lwd
;
2210 txg_list_walk_init(mdb_walk_state_t
*wsp
)
2212 return (txg_list_walk_init_common(wsp
, 0, TXG_SIZE
-1));
2216 txg_list0_walk_init(mdb_walk_state_t
*wsp
)
2218 return (txg_list_walk_init_common(wsp
, 0, 0));
2222 txg_list1_walk_init(mdb_walk_state_t
*wsp
)
2224 return (txg_list_walk_init_common(wsp
, 1, 1));
2228 txg_list2_walk_init(mdb_walk_state_t
*wsp
)
2230 return (txg_list_walk_init_common(wsp
, 2, 2));
2234 txg_list3_walk_init(mdb_walk_state_t
*wsp
)
2236 return (txg_list_walk_init_common(wsp
, 3, 3));
2240 txg_list_walk_step(mdb_walk_state_t
*wsp
)
2242 txg_list_walk_data_t
*lwd
= wsp
->walk_data
;
2247 while (wsp
->walk_addr
== NULL
&& lwd
->lw_txgoff
< lwd
->lw_maxoff
) {
2249 wsp
->walk_addr
= lwd
->lw_head
[lwd
->lw_txgoff
];
2252 if (wsp
->walk_addr
== NULL
)
2255 addr
= wsp
->walk_addr
- lwd
->lw_offset
;
2257 if (mdb_vread(lwd
->lw_obj
,
2258 lwd
->lw_offset
+ sizeof (txg_node_t
), addr
) == -1) {
2259 mdb_warn("failed to read list element at %#lx", addr
);
2263 status
= wsp
->walk_callback(addr
, lwd
->lw_obj
, wsp
->walk_cbdata
);
2264 node
= (txg_node_t
*)((uintptr_t)lwd
->lw_obj
+ lwd
->lw_offset
);
2265 wsp
->walk_addr
= (uintptr_t)node
->tn_next
[lwd
->lw_txgoff
];
2273 * Walk all named spa_t structures in the namespace. This is nothing more than
2274 * a layered avl walk.
2277 spa_walk_init(mdb_walk_state_t
*wsp
)
2281 if (wsp
->walk_addr
!= NULL
) {
2282 mdb_warn("spa walk only supports global walks\n");
2286 if (mdb_lookup_by_obj(ZFS_OBJ_NAME
, "spa_namespace_avl", &sym
) == -1) {
2287 mdb_warn("failed to find symbol 'spa_namespace_avl'");
2291 wsp
->walk_addr
= (uintptr_t)sym
.st_value
;
2293 if (mdb_layered_walk("avl", wsp
) == -1) {
2294 mdb_warn("failed to walk 'avl'\n");
2302 spa_walk_step(mdb_walk_state_t
*wsp
)
2304 return (wsp
->walk_callback(wsp
->walk_addr
, NULL
, wsp
->walk_cbdata
));
2310 * Walk all active zio_t structures on the system. This is simply a layered
2311 * walk on top of ::walk zio_cache, with the optional ability to limit the
2312 * structures to a particular pool.
2315 zio_walk_init(mdb_walk_state_t
*wsp
)
2317 wsp
->walk_data
= (void *)wsp
->walk_addr
;
2319 if (mdb_layered_walk("zio_cache", wsp
) == -1) {
2320 mdb_warn("failed to walk 'zio_cache'\n");
2328 zio_walk_step(mdb_walk_state_t
*wsp
)
2331 uintptr_t spa
= (uintptr_t)wsp
->walk_data
;
2333 if (mdb_ctf_vread(&zio
, ZFS_STRUCT
"zio", "mdb_zio_t",
2334 wsp
->walk_addr
, 0) == -1)
2337 if (spa
!= 0 && spa
!= zio
.io_spa
)
2340 return (wsp
->walk_callback(wsp
->walk_addr
, &zio
, wsp
->walk_cbdata
));
2344 * [addr]::walk zio_root
2346 * Walk only root zio_t structures, optionally for a particular spa_t.
2349 zio_walk_root_step(mdb_walk_state_t
*wsp
)
2352 uintptr_t spa
= (uintptr_t)wsp
->walk_data
;
2354 if (mdb_ctf_vread(&zio
, ZFS_STRUCT
"zio", "mdb_zio_t",
2355 wsp
->walk_addr
, 0) == -1)
2358 if (spa
!= 0 && spa
!= zio
.io_spa
)
2361 /* If the parent list is not empty, ignore */
2362 if (zio
.io_parent_list
.list_head
.list_next
!=
2364 mdb_ctf_offsetof_by_name(ZFS_STRUCT
"zio", "io_parent_list") +
2365 mdb_ctf_offsetof_by_name("struct list", "list_head"))
2368 return (wsp
->walk_callback(wsp
->walk_addr
, &zio
, wsp
->walk_cbdata
));
2374 * -v print verbose per-level information
2378 zfs_blkstats(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2380 boolean_t verbose
= B_FALSE
;
2381 zfs_all_blkstats_t stats
;
2382 dmu_object_type_t t
;
2385 dmu_object_type_info_t dmu_ot
[DMU_OT_NUMTYPES
+ 10];
2386 /* +10 in case it grew */
2388 if (mdb_readvar(&dmu_ot
, "dmu_ot") == -1) {
2389 mdb_warn("failed to read 'dmu_ot'");
2393 if (mdb_getopts(argc
, argv
,
2394 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
,
2396 return (DCMD_USAGE
);
2398 if (!(flags
& DCMD_ADDRSPEC
))
2399 return (DCMD_USAGE
);
2401 if (GETMEMB(addr
, "spa", spa_dsl_pool
, addr
) ||
2402 GETMEMB(addr
, "dsl_pool", dp_blkstats
, addr
) ||
2403 mdb_vread(&stats
, sizeof (zfs_all_blkstats_t
), addr
) == -1) {
2404 mdb_warn("failed to read data at %p;", addr
);
2405 mdb_printf("maybe no stats? run \"zpool scrub\" first.");
2409 tzb
= &stats
.zab_type
[DN_MAX_LEVELS
][DMU_OT_TOTAL
];
2410 if (tzb
->zb_gangs
!= 0) {
2411 mdb_printf("Ganged blocks: %llu\n",
2412 (longlong_t
)tzb
->zb_gangs
);
2415 ditto
= tzb
->zb_ditto_2_of_2_samevdev
+ tzb
->zb_ditto_2_of_3_samevdev
+
2416 tzb
->zb_ditto_3_of_3_samevdev
;
2418 mdb_printf("Dittoed blocks on same vdev: %llu\n",
2422 mdb_printf("\nBlocks\tLSIZE\tPSIZE\tASIZE"
2423 "\t avg\t comp\t%%Total\tType\n");
2425 for (t
= 0; t
<= DMU_OT_TOTAL
; t
++) {
2426 char csize
[NICENUM_BUFLEN
], lsize
[NICENUM_BUFLEN
];
2427 char psize
[NICENUM_BUFLEN
], asize
[NICENUM_BUFLEN
];
2428 char avg
[NICENUM_BUFLEN
];
2429 char comp
[NICENUM_BUFLEN
], pct
[NICENUM_BUFLEN
];
2434 if (t
== DMU_OT_DEFERRED
)
2435 strcpy(typename
, "deferred free");
2436 else if (t
== DMU_OT_OTHER
)
2437 strcpy(typename
, "other");
2438 else if (t
== DMU_OT_TOTAL
)
2439 strcpy(typename
, "Total");
2440 else if (mdb_readstr(typename
, sizeof (typename
),
2441 (uintptr_t)dmu_ot
[t
].ot_name
) == -1) {
2442 mdb_warn("failed to read type name");
2446 if (stats
.zab_type
[DN_MAX_LEVELS
][t
].zb_asize
== 0)
2449 for (l
= -1; l
< DN_MAX_LEVELS
; l
++) {
2450 int level
= (l
== -1 ? DN_MAX_LEVELS
: l
);
2451 zfs_blkstat_t
*zb
= &stats
.zab_type
[level
][t
];
2453 if (zb
->zb_asize
== 0)
2457 * Don't print each level unless requested.
2459 if (!verbose
&& level
!= DN_MAX_LEVELS
)
2463 * If all the space is level 0, don't print the
2464 * level 0 separately.
2466 if (level
== 0 && zb
->zb_asize
==
2467 stats
.zab_type
[DN_MAX_LEVELS
][t
].zb_asize
)
2470 mdb_nicenum(zb
->zb_count
, csize
);
2471 mdb_nicenum(zb
->zb_lsize
, lsize
);
2472 mdb_nicenum(zb
->zb_psize
, psize
);
2473 mdb_nicenum(zb
->zb_asize
, asize
);
2474 mdb_nicenum(zb
->zb_asize
/ zb
->zb_count
, avg
);
2475 (void) snprintfrac(comp
, NICENUM_BUFLEN
,
2476 zb
->zb_lsize
, zb
->zb_psize
, 2);
2477 (void) snprintfrac(pct
, NICENUM_BUFLEN
,
2478 100 * zb
->zb_asize
, tzb
->zb_asize
, 2);
2480 mdb_printf("%6s\t%5s\t%5s\t%5s\t%5s"
2482 csize
, lsize
, psize
, asize
, avg
, comp
, pct
);
2484 if (level
== DN_MAX_LEVELS
)
2485 mdb_printf("%s\n", typename
);
2487 mdb_printf(" L%d %s\n",
2495 typedef struct mdb_reference
{
2496 uintptr_t ref_holder
;
2497 uintptr_t ref_removed
;
2498 uint64_t ref_number
;
2503 reference_cb(uintptr_t addr
, const void *ignored
, void *arg
)
2505 mdb_reference_t ref
;
2506 boolean_t holder_is_str
= B_FALSE
;
2507 char holder_str
[128];
2508 boolean_t removed
= (boolean_t
)arg
;
2510 if (mdb_ctf_vread(&ref
, "reference_t", "mdb_reference_t", addr
,
2514 if (mdb_readstr(holder_str
, sizeof (holder_str
),
2515 ref
.ref_holder
) != -1)
2516 holder_is_str
= strisprint(holder_str
);
2519 mdb_printf("removed ");
2520 mdb_printf("reference ");
2521 if (ref
.ref_number
!= 1)
2522 mdb_printf("with count=%llu ", ref
.ref_number
);
2523 mdb_printf("with tag %lx", ref
.ref_holder
);
2525 mdb_printf(" \"%s\"", holder_str
);
2526 mdb_printf(", held at:\n");
2528 (void) mdb_call_dcmd("whatis", addr
, DCMD_ADDRSPEC
, 0, NULL
);
2531 mdb_printf("removed at:\n");
2532 (void) mdb_call_dcmd("whatis", ref
.ref_removed
,
2533 DCMD_ADDRSPEC
, 0, NULL
);
2541 typedef struct mdb_refcount
{
2545 typedef struct mdb_refcount_removed
{
2546 uint64_t rc_removed_count
;
2547 } mdb_refcount_removed_t
;
2549 typedef struct mdb_refcount_tracked
{
2550 boolean_t rc_tracked
;
2551 } mdb_refcount_tracked_t
;
2555 refcount(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2558 mdb_refcount_removed_t rcr
;
2559 mdb_refcount_tracked_t rct
;
2561 boolean_t released
= B_FALSE
;
2563 if (!(flags
& DCMD_ADDRSPEC
))
2564 return (DCMD_USAGE
);
2566 if (mdb_getopts(argc
, argv
,
2567 'r', MDB_OPT_SETBITS
, B_TRUE
, &released
,
2569 return (DCMD_USAGE
);
2571 if (mdb_ctf_vread(&rc
, "refcount_t", "mdb_refcount_t", addr
,
2575 if (mdb_ctf_vread(&rcr
, "refcount_t", "mdb_refcount_removed_t", addr
,
2576 MDB_CTF_VREAD_QUIET
) == -1) {
2577 mdb_printf("refcount_t at %p has %llu holds (untracked)\n",
2578 addr
, (longlong_t
)rc
.rc_count
);
2582 if (mdb_ctf_vread(&rct
, "refcount_t", "mdb_refcount_tracked_t", addr
,
2583 MDB_CTF_VREAD_QUIET
) == -1) {
2584 /* If this is an old target, it might be tracked. */
2585 rct
.rc_tracked
= B_TRUE
;
2588 mdb_printf("refcount_t at %p has %llu current holds, "
2589 "%llu recently released holds\n",
2590 addr
, (longlong_t
)rc
.rc_count
, (longlong_t
)rcr
.rc_removed_count
);
2592 if (rct
.rc_tracked
&& rc
.rc_count
> 0)
2593 mdb_printf("current holds:\n");
2594 off
= mdb_ctf_offsetof_by_name("refcount_t", "rc_list");
2597 mdb_pwalk("list", reference_cb
, (void*)B_FALSE
, addr
+ off
);
2599 if (released
&& rcr
.rc_removed_count
> 0) {
2600 mdb_printf("released holds:\n");
2602 off
= mdb_ctf_offsetof_by_name("refcount_t", "rc_removed");
2605 mdb_pwalk("list", reference_cb
, (void*)B_FALSE
, addr
+ off
);
2613 sa_attr_table(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2615 sa_attr_table_t
*table
;
2620 if (mdb_vread(&sa_os
, sizeof (sa_os_t
), addr
) == -1) {
2621 mdb_warn("failed to read sa_os at %p", addr
);
2625 table
= mdb_alloc(sizeof (sa_attr_table_t
) * sa_os
.sa_num_attrs
,
2627 name
= mdb_alloc(MAXPATHLEN
, UM_SLEEP
| UM_GC
);
2629 if (mdb_vread(table
, sizeof (sa_attr_table_t
) * sa_os
.sa_num_attrs
,
2630 (uintptr_t)sa_os
.sa_attr_table
) == -1) {
2631 mdb_warn("failed to read sa_os at %p", addr
);
2635 mdb_printf("%<u>%-10s %-10s %-10s %-10s %s%</u>\n",
2636 "ATTR ID", "REGISTERED", "LENGTH", "BSWAP", "NAME");
2637 for (i
= 0; i
!= sa_os
.sa_num_attrs
; i
++) {
2638 mdb_readstr(name
, MAXPATHLEN
, (uintptr_t)table
[i
].sa_name
);
2639 mdb_printf("%5x %8x %8x %8x %-s\n",
2640 (int)table
[i
].sa_attr
, (int)table
[i
].sa_registered
,
2641 (int)table
[i
].sa_length
, table
[i
].sa_byteswap
, name
);
2648 sa_get_off_table(uintptr_t addr
, uint32_t **off_tab
, int attr_count
)
2650 uintptr_t idx_table
;
2652 if (GETMEMB(addr
, "sa_idx_tab", sa_idx_tab
, idx_table
)) {
2653 mdb_printf("can't find offset table in sa_idx_tab\n");
2657 *off_tab
= mdb_alloc(attr_count
* sizeof (uint32_t),
2660 if (mdb_vread(*off_tab
,
2661 attr_count
* sizeof (uint32_t), idx_table
) == -1) {
2662 mdb_warn("failed to attribute offset table %p", idx_table
);
2671 sa_attr_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2673 uint32_t *offset_tab
;
2676 uintptr_t attr_addr
;
2677 uintptr_t bonus_tab
, spill_tab
;
2678 uintptr_t db_bonus
, db_spill
;
2679 uintptr_t os
, os_sa
;
2683 return (DCMD_USAGE
);
2685 if (argv
[0].a_type
== MDB_TYPE_STRING
)
2686 attr_id
= mdb_strtoull(argv
[0].a_un
.a_str
);
2688 return (DCMD_USAGE
);
2690 if (GETMEMB(addr
, "sa_handle", sa_bonus_tab
, bonus_tab
) ||
2691 GETMEMB(addr
, "sa_handle", sa_spill_tab
, spill_tab
) ||
2692 GETMEMB(addr
, "sa_handle", sa_os
, os
) ||
2693 GETMEMB(addr
, "sa_handle", sa_bonus
, db_bonus
) ||
2694 GETMEMB(addr
, "sa_handle", sa_spill
, db_spill
)) {
2695 mdb_printf("Can't find necessary information in sa_handle "
2700 if (GETMEMB(os
, "objset", os_sa
, os_sa
)) {
2701 mdb_printf("Can't find os_sa in objset\n");
2705 if (GETMEMB(os_sa
, "sa_os", sa_num_attrs
, attr_count
)) {
2706 mdb_printf("Can't find sa_num_attrs\n");
2710 if (attr_id
> attr_count
) {
2711 mdb_printf("attribute id number is out of range\n");
2716 if (sa_get_off_table(bonus_tab
, &offset_tab
,
2717 attr_count
) == -1) {
2721 if (GETMEMB(db_bonus
, "dmu_buf", db_data
, db_data
)) {
2722 mdb_printf("can't find db_data in bonus dbuf\n");
2727 if (bonus_tab
&& !TOC_ATTR_PRESENT(offset_tab
[attr_id
]) &&
2728 spill_tab
== NULL
) {
2729 mdb_printf("Attribute does not exist\n");
2731 } else if (!TOC_ATTR_PRESENT(offset_tab
[attr_id
]) && spill_tab
) {
2732 if (sa_get_off_table(spill_tab
, &offset_tab
,
2733 attr_count
) == -1) {
2736 if (GETMEMB(db_spill
, "dmu_buf", db_data
, db_data
)) {
2737 mdb_printf("can't find db_data in spill dbuf\n");
2740 if (!TOC_ATTR_PRESENT(offset_tab
[attr_id
])) {
2741 mdb_printf("Attribute does not exist\n");
2745 attr_addr
= db_data
+ TOC_OFF(offset_tab
[attr_id
]);
2746 mdb_printf("%p\n", attr_addr
);
2752 zfs_ace_print_common(uintptr_t addr
, uint_t flags
,
2753 uint64_t id
, uint32_t access_mask
, uint16_t ace_flags
,
2754 uint16_t ace_type
, int verbose
)
2756 if (DCMD_HDRSPEC(flags
) && !verbose
)
2757 mdb_printf("%<u>%-?s %-8s %-8s %-8s %s%</u>\n",
2758 "ADDR", "FLAGS", "MASK", "TYPE", "ID");
2761 mdb_printf("%0?p %-8x %-8x %-8x %-llx\n", addr
,
2762 ace_flags
, access_mask
, ace_type
, id
);
2766 switch (ace_flags
& ACE_TYPE_FLAGS
) {
2768 mdb_printf("owner@:");
2770 case (ACE_IDENTIFIER_GROUP
| ACE_GROUP
):
2771 mdb_printf("group@:");
2774 mdb_printf("everyone@:");
2776 case ACE_IDENTIFIER_GROUP
:
2777 mdb_printf("group:%llx:", (u_longlong_t
)id
);
2779 case 0: /* User entry */
2780 mdb_printf("user:%llx:", (u_longlong_t
)id
);
2784 /* print out permission mask */
2785 if (access_mask
& ACE_READ_DATA
)
2789 if (access_mask
& ACE_WRITE_DATA
)
2793 if (access_mask
& ACE_EXECUTE
)
2797 if (access_mask
& ACE_APPEND_DATA
)
2801 if (access_mask
& ACE_DELETE
)
2805 if (access_mask
& ACE_DELETE_CHILD
)
2809 if (access_mask
& ACE_READ_ATTRIBUTES
)
2813 if (access_mask
& ACE_WRITE_ATTRIBUTES
)
2817 if (access_mask
& ACE_READ_NAMED_ATTRS
)
2821 if (access_mask
& ACE_WRITE_NAMED_ATTRS
)
2825 if (access_mask
& ACE_READ_ACL
)
2829 if (access_mask
& ACE_WRITE_ACL
)
2833 if (access_mask
& ACE_WRITE_OWNER
)
2837 if (access_mask
& ACE_SYNCHRONIZE
)
2844 /* Print out inheritance flags */
2845 if (ace_flags
& ACE_FILE_INHERIT_ACE
)
2849 if (ace_flags
& ACE_DIRECTORY_INHERIT_ACE
)
2853 if (ace_flags
& ACE_INHERIT_ONLY_ACE
)
2857 if (ace_flags
& ACE_NO_PROPAGATE_INHERIT_ACE
)
2861 if (ace_flags
& ACE_SUCCESSFUL_ACCESS_ACE_FLAG
)
2865 if (ace_flags
& ACE_FAILED_ACCESS_ACE_FLAG
)
2869 if (ace_flags
& ACE_INHERITED_ACE
)
2875 case ACE_ACCESS_ALLOWED_ACE_TYPE
:
2876 mdb_printf(":allow\n");
2878 case ACE_ACCESS_DENIED_ACE_TYPE
:
2879 mdb_printf(":deny\n");
2881 case ACE_SYSTEM_AUDIT_ACE_TYPE
:
2882 mdb_printf(":audit\n");
2884 case ACE_SYSTEM_ALARM_ACE_TYPE
:
2885 mdb_printf(":alarm\n");
2895 zfs_ace_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2898 int verbose
= FALSE
;
2901 if (!(flags
& DCMD_ADDRSPEC
))
2902 return (DCMD_USAGE
);
2904 if (mdb_getopts(argc
, argv
,
2905 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
, TRUE
, NULL
) != argc
)
2906 return (DCMD_USAGE
);
2908 if (mdb_vread(&zace
, sizeof (zfs_ace_t
), addr
) == -1) {
2909 mdb_warn("failed to read zfs_ace_t");
2913 if ((zace
.z_hdr
.z_flags
& ACE_TYPE_FLAGS
) == 0 ||
2914 (zace
.z_hdr
.z_flags
& ACE_TYPE_FLAGS
) == ACE_IDENTIFIER_GROUP
)
2919 return (zfs_ace_print_common(addr
, flags
, id
, zace
.z_hdr
.z_access_mask
,
2920 zace
.z_hdr
.z_flags
, zace
.z_hdr
.z_type
, verbose
));
2925 zfs_ace0_print(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
2929 int verbose
= FALSE
;
2931 if (!(flags
& DCMD_ADDRSPEC
))
2932 return (DCMD_USAGE
);
2934 if (mdb_getopts(argc
, argv
,
2935 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
, TRUE
, NULL
) != argc
)
2936 return (DCMD_USAGE
);
2938 if (mdb_vread(&ace
, sizeof (ace_t
), addr
) == -1) {
2939 mdb_warn("failed to read ace_t");
2943 if ((ace
.a_flags
& ACE_TYPE_FLAGS
) == 0 ||
2944 (ace
.a_flags
& ACE_TYPE_FLAGS
) == ACE_IDENTIFIER_GROUP
)
2949 return (zfs_ace_print_common(addr
, flags
, id
, ace
.a_access_mask
,
2950 ace
.a_flags
, ace
.a_type
, verbose
));
2953 typedef struct acl_dump_args
{
2955 const mdb_arg_t
*a_argv
;
2962 acl_aces_cb(uintptr_t addr
, const void *unknown
, void *arg
)
2964 acl_dump_args_t
*acl_args
= (acl_dump_args_t
*)arg
;
2966 if (acl_args
->a_version
== 1) {
2967 if (mdb_call_dcmd("zfs_ace", addr
,
2968 DCMD_ADDRSPEC
|acl_args
->a_flags
, acl_args
->a_argc
,
2969 acl_args
->a_argv
) != DCMD_OK
) {
2973 if (mdb_call_dcmd("zfs_ace0", addr
,
2974 DCMD_ADDRSPEC
|acl_args
->a_flags
, acl_args
->a_argc
,
2975 acl_args
->a_argv
) != DCMD_OK
) {
2979 acl_args
->a_flags
= DCMD_LOOP
;
2985 acl_cb(uintptr_t addr
, const void *unknown
, void *arg
)
2987 acl_dump_args_t
*acl_args
= (acl_dump_args_t
*)arg
;
2989 if (acl_args
->a_version
== 1) {
2990 if (mdb_pwalk("zfs_acl_node_aces", acl_aces_cb
,
2992 mdb_warn("can't walk ACEs");
2996 if (mdb_pwalk("zfs_acl_node_aces0", acl_aces_cb
,
2998 mdb_warn("can't walk ACEs");
3007 zfs_acl_dump(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
3010 int verbose
= FALSE
;
3011 acl_dump_args_t acl_args
;
3013 if (!(flags
& DCMD_ADDRSPEC
))
3014 return (DCMD_USAGE
);
3016 if (mdb_getopts(argc
, argv
,
3017 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
, TRUE
, NULL
) != argc
)
3018 return (DCMD_USAGE
);
3020 if (mdb_vread(&zacl
, sizeof (zfs_acl_t
), addr
) == -1) {
3021 mdb_warn("failed to read zfs_acl_t");
3025 acl_args
.a_argc
= argc
;
3026 acl_args
.a_argv
= argv
;
3027 acl_args
.a_version
= zacl
.z_version
;
3028 acl_args
.a_flags
= DCMD_LOOPFIRST
;
3030 if (mdb_pwalk("zfs_acl_node", acl_cb
, &acl_args
, addr
) != 0) {
3031 mdb_warn("can't walk ACL");
3040 zfs_acl_node_walk_init(mdb_walk_state_t
*wsp
)
3042 if (wsp
->walk_addr
== NULL
) {
3043 mdb_warn("must supply address of zfs_acl_node_t\n");
3048 mdb_ctf_offsetof_by_name(ZFS_STRUCT
"zfs_acl", "z_acl");
3050 if (mdb_layered_walk("list", wsp
) == -1) {
3051 mdb_warn("failed to walk 'list'\n");
3059 zfs_acl_node_walk_step(mdb_walk_state_t
*wsp
)
3061 zfs_acl_node_t aclnode
;
3063 if (mdb_vread(&aclnode
, sizeof (zfs_acl_node_t
),
3064 wsp
->walk_addr
) == -1) {
3065 mdb_warn("failed to read zfs_acl_node at %p", wsp
->walk_addr
);
3069 return (wsp
->walk_callback(wsp
->walk_addr
, &aclnode
, wsp
->walk_cbdata
));
3072 typedef struct ace_walk_data
{
3078 zfs_aces_walk_init_common(mdb_walk_state_t
*wsp
, int version
,
3079 int ace_count
, uintptr_t ace_data
)
3081 ace_walk_data_t
*ace_walk_data
;
3083 if (wsp
->walk_addr
== NULL
) {
3084 mdb_warn("must supply address of zfs_acl_node_t\n");
3088 ace_walk_data
= mdb_alloc(sizeof (ace_walk_data_t
), UM_SLEEP
| UM_GC
);
3090 ace_walk_data
->ace_count
= ace_count
;
3091 ace_walk_data
->ace_version
= version
;
3093 wsp
->walk_addr
= ace_data
;
3094 wsp
->walk_data
= ace_walk_data
;
3100 zfs_acl_node_aces_walk_init_common(mdb_walk_state_t
*wsp
, int version
)
3103 static mdb_ctf_id_t acl_id
;
3105 uintptr_t z_acldata
;
3108 if (mdb_ctf_lookup_by_name("struct zfs_acl_node",
3110 mdb_warn("couldn't find struct zfs_acl_node");
3116 if (GETMEMBID(wsp
->walk_addr
, &acl_id
, z_ace_count
, z_ace_count
)) {
3119 if (GETMEMBID(wsp
->walk_addr
, &acl_id
, z_acldata
, z_acldata
)) {
3123 return (zfs_aces_walk_init_common(wsp
, version
,
3124 z_ace_count
, z_acldata
));
3129 zfs_acl_node_aces_walk_init(mdb_walk_state_t
*wsp
)
3131 return (zfs_acl_node_aces_walk_init_common(wsp
, 1));
3136 zfs_acl_node_aces0_walk_init(mdb_walk_state_t
*wsp
)
3138 return (zfs_acl_node_aces_walk_init_common(wsp
, 0));
3142 zfs_aces_walk_step(mdb_walk_state_t
*wsp
)
3144 ace_walk_data_t
*ace_data
= wsp
->walk_data
;
3152 if (ace_data
->ace_count
== 0)
3155 if (mdb_vread(&zace
, sizeof (zfs_ace_t
), wsp
->walk_addr
) == -1) {
3156 mdb_warn("failed to read zfs_ace_t at %#lx",
3161 switch (ace_data
->ace_version
) {
3163 acep
= (ace_t
*)&zace
;
3164 entry_type
= acep
->a_flags
& ACE_TYPE_FLAGS
;
3165 allow_type
= acep
->a_type
;
3168 entry_type
= zace
.z_hdr
.z_flags
& ACE_TYPE_FLAGS
;
3169 allow_type
= zace
.z_hdr
.z_type
;
3175 ptr
= (uintptr_t)wsp
->walk_addr
;
3176 switch (entry_type
) {
3179 case (ACE_IDENTIFIER_GROUP
| ACE_GROUP
):
3180 ptr
+= ace_data
->ace_version
== 0 ?
3181 sizeof (ace_t
) : sizeof (zfs_ace_hdr_t
);
3183 case ACE_IDENTIFIER_GROUP
:
3185 switch (allow_type
) {
3186 case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE
:
3187 case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE
:
3188 case ACE_SYSTEM_AUDIT_OBJECT_ACE_TYPE
:
3189 case ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE
:
3190 ptr
+= ace_data
->ace_version
== 0 ?
3191 sizeof (ace_t
) : sizeof (zfs_object_ace_t
);
3194 ptr
+= ace_data
->ace_version
== 0 ?
3195 sizeof (ace_t
) : sizeof (zfs_ace_t
);
3200 ace_data
->ace_count
--;
3201 status
= wsp
->walk_callback(wsp
->walk_addr
,
3202 (void *)(uintptr_t)&zace
, wsp
->walk_cbdata
);
3204 wsp
->walk_addr
= ptr
;
3208 typedef struct mdb_zfs_rrwlock
{
3209 uintptr_t rr_writer
;
3210 boolean_t rr_writer_wanted
;
3211 } mdb_zfs_rrwlock_t
;
3213 static uint_t rrw_key
;
3217 rrwlock(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
3219 mdb_zfs_rrwlock_t rrw
;
3222 if (mdb_ctf_readsym(&rrw_key
, "uint_t", "rrw_tsd_key", 0) == -1)
3226 if (mdb_ctf_vread(&rrw
, "rrwlock_t", "mdb_zfs_rrwlock_t", addr
,
3230 if (rrw
.rr_writer
!= 0) {
3231 mdb_printf("write lock held by thread %lx\n", rrw
.rr_writer
);
3235 if (rrw
.rr_writer_wanted
) {
3236 mdb_printf("writer wanted\n");
3239 mdb_printf("anonymous references:\n");
3240 (void) mdb_call_dcmd("refcount", addr
+
3241 mdb_ctf_offsetof_by_name(ZFS_STRUCT
"rrwlock", "rr_anon_rcount"),
3242 DCMD_ADDRSPEC
, 0, NULL
);
3244 mdb_printf("linked references:\n");
3245 (void) mdb_call_dcmd("refcount", addr
+
3246 mdb_ctf_offsetof_by_name(ZFS_STRUCT
"rrwlock", "rr_linked_rcount"),
3247 DCMD_ADDRSPEC
, 0, NULL
);
3250 * XXX This should find references from
3251 * "::walk thread | ::tsd -v <rrw_key>", but there is no support
3252 * for programmatic consumption of dcmds, so this would be
3253 * difficult, potentially requiring reimplementing ::tsd (both
3254 * user and kernel versions) in this MDB module.
3261 * MDB module linkage information:
3263 * We declare a list of structures describing our dcmds, and a function
3264 * named _mdb_init to return a pointer to our module information.
3267 static const mdb_dcmd_t dcmds
[] = {
3268 { "arc", "[-bkmg]", "print ARC variables", arc_print
},
3269 { "blkptr", ":", "print blkptr_t", blkptr
},
3270 { "dbuf", ":", "print dmu_buf_impl_t", dbuf
},
3271 { "dbuf_stats", ":", "dbuf stats", dbuf_stats
},
3273 "\t[-O objset_t*] [-n objset_name | \"mos\"] "
3274 "[-o object | \"mdn\"] \n"
3275 "\t[-l level] [-b blkid | \"bonus\"]",
3276 "find dmu_buf_impl_t's that match specified criteria", dbufs
},
3277 { "abuf_find", "dva_word[0] dva_word[1]",
3278 "find arc_buf_hdr_t of a specified DVA",
3280 { "spa", "?[-cevmMh]\n"
3281 "\t-c display spa config\n"
3282 "\t-e display vdev statistics\n"
3283 "\t-v display vdev information\n"
3284 "\t-m display metaslab statistics\n"
3285 "\t-M display metaslab group statistics\n"
3286 "\t-h display histogram (requires -m or -M)\n",
3287 "spa_t summary", spa_print
},
3288 { "spa_config", ":", "print spa_t configuration", spa_print_config
},
3289 { "spa_space", ":[-b]", "print spa_t on-disk space usage", spa_space
},
3290 { "spa_vdevs", ":[-emMh]\n"
3291 "\t-e display vdev statistics\n"
3292 "\t-m dispaly metaslab statistics\n"
3293 "\t-M display metaslab group statistic\n"
3294 "\t-h display histogram (requires -m or -M)\n",
3295 "given a spa_t, print vdev summary", spa_vdevs
},
3296 { "vdev", ":[-re]\n"
3297 "\t-r display recursively\n"
3298 "\t-e display statistics\n"
3299 "\t-m display metaslab statistics\n"
3300 "\t-M display metaslab group statistics\n"
3301 "\t-h display histogram (requires -m or -M)\n",
3302 "vdev_t summary", vdev_print
},
3303 { "zio", ":[-cpr]\n"
3304 "\t-c display children\n"
3305 "\t-p display parents\n"
3306 "\t-r display recursively",
3307 "zio_t summary", zio_print
},
3308 { "zio_state", "?", "print out all zio_t structures on system or "
3309 "for a particular pool", zio_state
},
3310 { "zfs_blkstats", ":[-v]",
3311 "given a spa_t, print block type stats from last scrub",
3313 { "zfs_params", "", "print zfs tunable parameters", zfs_params
},
3314 { "refcount", ":[-r]\n"
3315 "\t-r display recently removed references",
3316 "print refcount_t holders", refcount
},
3317 { "zap_leaf", "", "print zap_leaf_phys_t", zap_leaf
},
3318 { "zfs_aces", ":[-v]", "print all ACEs from a zfs_acl_t",
3320 { "zfs_ace", ":[-v]", "print zfs_ace", zfs_ace_print
},
3321 { "zfs_ace0", ":[-v]", "print zfs_ace0", zfs_ace0_print
},
3322 { "sa_attr_table", ":", "print SA attribute table from sa_os_t",
3324 { "sa_attr", ": attr_id",
3325 "print SA attribute address when given sa_handle_t", sa_attr_print
},
3326 { "zfs_dbgmsg", ":[-va]",
3327 "print zfs debug log", dbgmsg
},
3329 "print rrwlock_t, including readers", rrwlock
},
3333 static const mdb_walker_t walkers
[] = {
3334 { "zms_freelist", "walk ZFS metaslab freelist",
3335 freelist_walk_init
, freelist_walk_step
, NULL
},
3336 { "txg_list", "given any txg_list_t *, walk all entries in all txgs",
3337 txg_list_walk_init
, txg_list_walk_step
, NULL
},
3338 { "txg_list0", "given any txg_list_t *, walk all entries in txg 0",
3339 txg_list0_walk_init
, txg_list_walk_step
, NULL
},
3340 { "txg_list1", "given any txg_list_t *, walk all entries in txg 1",
3341 txg_list1_walk_init
, txg_list_walk_step
, NULL
},
3342 { "txg_list2", "given any txg_list_t *, walk all entries in txg 2",
3343 txg_list2_walk_init
, txg_list_walk_step
, NULL
},
3344 { "txg_list3", "given any txg_list_t *, walk all entries in txg 3",
3345 txg_list3_walk_init
, txg_list_walk_step
, NULL
},
3346 { "zio", "walk all zio structures, optionally for a particular spa_t",
3347 zio_walk_init
, zio_walk_step
, NULL
},
3349 "walk all root zio_t structures, optionally for a particular spa_t",
3350 zio_walk_init
, zio_walk_root_step
, NULL
},
3351 { "spa", "walk all spa_t entries in the namespace",
3352 spa_walk_init
, spa_walk_step
, NULL
},
3353 { "metaslab", "given a spa_t *, walk all metaslab_t structures",
3354 metaslab_walk_init
, metaslab_walk_step
, NULL
},
3355 { "zfs_acl_node", "given a zfs_acl_t, walk all zfs_acl_nodes",
3356 zfs_acl_node_walk_init
, zfs_acl_node_walk_step
, NULL
},
3357 { "zfs_acl_node_aces", "given a zfs_acl_node_t, walk all ACEs",
3358 zfs_acl_node_aces_walk_init
, zfs_aces_walk_step
, NULL
},
3359 { "zfs_acl_node_aces0",
3360 "given a zfs_acl_node_t, walk all ACEs as ace_t",
3361 zfs_acl_node_aces0_walk_init
, zfs_aces_walk_step
, NULL
},
3365 static const mdb_modinfo_t modinfo
= {
3366 MDB_API_VERSION
, dcmds
, walkers
3369 const mdb_modinfo_t
*