zfs.c revision 88b7b0f29b20b808b9e06071885b1d6a3ddb6328
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/zfs_context.h>
#include <sys/mdb_modapi.h>
#include <sys/dmu_objset.h>
#include <sys/dsl_pool.h>
#include <sys/metaslab_impl.h>
#include <sys/space_map.h>
#include <sys/spa_impl.h>
#include <sys/vdev_impl.h>
#include <sys/zio_compress.h>
#ifndef _KERNEL
#endif
#ifdef _KERNEL
#define ZFS_OBJ_NAME "zfs"
#else
#define ZFS_OBJ_NAME "libzpool.so.1"
#endif
static char *
local_strdup(const char *s)
{
return (s1);
}
static int
{
char name[64];
return (DCMD_ERR);
}
} else {
}
return (DCMD_ERR);
}
if (off % 8 != 0) {
mdb_warn("member %s of type %s is unsupported bitfield",
return (DCMD_ERR);
}
off /= 8;
mdb_warn("failed to read %s from %s at %p",
return (DCMD_ERR);
}
/* mdb_warn("read %s from %s at %p+%llx\n", member, type, addr, off); */
return (0);
}
static int
{
static int gotid;
static mdb_ctf_id_t rc_id;
if (!gotid) {
mdb_warn("couldn't find struct refcount");
return (DCMD_ERR);
}
}
char name[64];
return (DCMD_ERR);
}
off /= 8;
}
static int
{
return (DCMD_ERR);
}
return (DCMD_ERR);
}
return (DCMD_OK);
}
static int verbose;
static int
{
mdb_warn("must supply starting address\n");
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
"INVALID", "INVALID", "INVALID", "INVALID" };
int mapshift = SPA_MINBLOCKSHIFT;
return (WALK_DONE);
}
if (SM_DEBUG_DECODE(entry)) {
mdb_printf("DEBUG: %3u %10s: txg=%llu pass=%llu\n",
} else {
mdb_printf("Entry: %3u offsets=%08llx-%08llx type=%c "
"size=%06llx", number,
if (verbose)
mdb_printf("\n");
}
return (WALK_NEXT);
}
static int
{
static int gotid;
static mdb_ctf_id_t dd_id;
char dd_myname[MAXNAMELEN];
if (!gotid) {
if (mdb_ctf_lookup_by_name("struct dsl_dir",
&dd_id) == -1) {
mdb_warn("couldn't find struct dsl_dir");
return (DCMD_ERR);
}
}
return (DCMD_ERR);
}
if (dd_parent) {
return (DCMD_ERR);
}
if (dd_myname[0])
else
return (0);
}
static int
{
static int gotid;
char ds_snapname[MAXNAMELEN];
buf[0] = '\0';
if (!gotid) {
if (mdb_ctf_lookup_by_name("struct objset_impl",
&osi_id) == -1) {
mdb_warn("couldn't find struct objset_impl");
return (DCMD_ERR);
}
if (mdb_ctf_lookup_by_name("struct dsl_dataset",
&ds_id) == -1) {
mdb_warn("couldn't find struct dsl_dataset");
return (DCMD_ERR);
}
}
return (DCMD_ERR);
if (os_dsl_dataset == 0) {
return (0);
}
return (DCMD_ERR);
}
return (DCMD_ERR);
if (ds_snapname[0]) {
}
return (0);
}
static void
const char *prefix)
{
const char *cp;
} else {
}
}
/* ARGSUSED */
static int
{
int i;
char stage[1024];
mdb_warn("Could not find enum zio_stage");
return (DCMD_ERR);
}
for (i = 0; i < 32; i++) {
if (addr & (1U << i)) {
"ZIO_STAGE_");
}
}
return (DCMD_OK);
}
/* ARGSUSED */
static int
{
/*
* This table can be approximately generated by running:
* egrep "^[a-z0-9_]+ [a-z0-9_]+( =.*)?;" *.c | cut -d ' ' -f 2
*/
static const char *params[] = {
"arc_reduce_dnlc_percent",
"zfs_arc_max",
"zfs_arc_min",
"arc_shrink_shift",
"zfs_mdcomp_disable",
"zfs_prefetch_disable",
"zfetch_max_streams",
"zfetch_min_sec_reap",
"zfetch_block_cap",
"zfetch_array_rd_sz",
"zfs_default_bs",
"zfs_default_ibs",
"metaslab_aliquot",
"reference_tracking_enable",
"reference_history",
"zio_taskq_threads",
"spa_max_replication_override",
"spa_mode",
"zfs_flags",
"zfs_txg_synctime",
"zfs_txg_timeout",
"zfs_write_limit_min",
"zfs_write_limit_max",
"zfs_write_limit_shift",
"zfs_write_limit_override",
"zfs_no_write_throttle",
"zfs_vdev_cache_max",
"zfs_vdev_cache_size",
"zfs_vdev_cache_bshift",
"vdev_mirror_shift",
"zfs_vdev_max_pending",
"zfs_vdev_min_pending",
"zfs_scrub_limit",
"zfs_vdev_time_shift",
"zfs_vdev_ramp_rate",
"zfs_vdev_aggregation_limit",
"fzap_default_block_shift",
"zfs_immediate_write_sz",
"zfs_read_chunk_size",
"zil_disable",
"zfs_nocacheflush",
"metaslab_gang_bang",
"zio_injection_enabled",
"zvol_immediate_write_sz",
};
int i;
int sz;
if (sz == 4) {
} else if (sz == 8) {
} else {
}
}
return (DCMD_OK);
}
/* ARGSUSED */
static int
{
int i;
char buf[MAXPATHLEN];
mdb_warn("failed to read blkptr_t");
return (DCMD_ERR);
}
return (DCMD_ERR);
for (i = 0; i < DMU_OT_NUMTYPES; i++) {
}
return (DCMD_ERR);
for (i = 0; i < ZIO_CHECKSUM_FUNCTIONS; i++) {
}
return (DCMD_ERR);
for (i = 0; i < ZIO_COMPRESS_FUNCTIONS; i++) {
}
/*
* Super-ick warning: This code is also duplicated in
*/
for (i = 0; i < BP_GET_NDVAS(&bp); i++) {
mdb_printf("DVA[%d]: vdev_id %lld / %llx\n", i,
mdb_printf("DVA[%d]: GANG: %-5s GRID: %04x\t"
mdb_printf("DVA[%d]: :%llu:%llx:%llx:%s%s%s%s\n", i,
}
mdb_printf("LSIZE: %-16llx\t\tPSIZE: %llx\n",
mdb_printf("ENDIAN: %6s\t\t\t\t\tTYPE: %s\n",
mdb_printf("BIRTH: %-16llx LEVEL: %-2d\tFILL: %llx\n",
mdb_printf("CKFUNC: %-16s\t\tCOMP: %s\n",
mdb_printf("CKSUM: %llx:%llx:%llx:%llx\n",
return (DCMD_OK);
}
/* ARGSUSED */
static int
{
char objectname[32];
char blkidname[32];
char path[MAXNAMELEN];
if (DCMD_HDRSPEC(flags)) {
mdb_printf(" addr object lvl blkid holds os\n");
}
mdb_warn("couldn't find struct dmu_buf_impl_t");
return (DCMD_ERR);
}
return (WALK_ERR);
}
return (WALK_ERR);
}
else
if (blkid == DB_BONUS_BLKID)
else
return (WALK_ERR);
}
mdb_printf("%p %8s %1u %9s %2llu %s\n",
return (DCMD_OK);
}
/* ARGSUSED */
static int
{
#define HISTOSZ 32
int i, maxidx;
mdb_warn("failed to read 'dbuf_hash_table'");
return (DCMD_ERR);
}
for (i = 0; i < HISTOSZ; i++) {
histo[i] = 0;
histo2[i] = 0;
}
ndbufs = 0;
int len;
mdb_warn("failed to read hash bucket %u at %p",
return (DCMD_ERR);
}
len = 0;
while (dbp != 0) {
dbp) == -1) {
return (DCMD_ERR);
}
histo2[i]++;
len++;
ndbufs++;
}
}
mdb_printf("hash table has %llu buckets, %llu dbufs "
mdb_printf("\n");
maxidx = 0;
for (i = 0; i < HISTOSZ; i++)
if (histo[i] > 0)
maxidx = i;
mdb_printf("hash chain length number of buckets\n");
for (i = 0; i <= maxidx; i++)
mdb_printf("\n");
maxidx = 0;
for (i = 0; i < HISTOSZ; i++)
if (histo2[i] > 0)
maxidx = i;
mdb_printf("hash chain depth number of dbufs\n");
for (i = 0; i <= maxidx; i++)
mdb_printf("%u or more %llu %llu%%\n",
return (DCMD_OK);
}
typedef struct dbufs_data {
char *osname;
} dbufs_data_t;
#define DBUFS_UNSET (0xbaddcafedeadbeefULL)
/* ARGSUSED */
static int
{
char osname[MAXNAMELEN];
return (WALK_ERR);
}
}
return (WALK_NEXT);
}
/* ARGSUSED */
static int
{
return (DCMD_USAGE);
}
if (object) {
} else {
}
}
if (blkid) {
} else {
}
}
mdb_warn("couldn't find struct dmu_buf_impl_t");
return (DCMD_ERR);
}
mdb_warn("can't walk dbufs");
return (DCMD_ERR);
}
return (DCMD_OK);
}
typedef struct abuf_find_data {
/* ARGSUSED */
static int
{
return (WALK_ERR);
}
}
return (WALK_NEXT);
}
/* ARGSUSED */
static int
{
int i;
const char *syms[] = {
"ARC_mru",
"ARC_mru_ghost",
"ARC_mfu",
"ARC_mfu_ghost",
};
if (argc != 2)
return (DCMD_USAGE);
for (i = 0; i < 2; i ++) {
case MDB_TYPE_STRING:
break;
case MDB_TYPE_IMMEDIATE:
break;
default:
return (DCMD_USAGE);
}
}
mdb_warn("couldn't find struct arc_buf_hdr");
return (DCMD_ERR);
}
return (DCMD_ERR);
}
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
/*ARGSUSED*/
static int
{
int nstats, i;
const char *suffix;
static const char *bytestats[] = {
};
static const char *extras[] = {
"arc_no_grow", "arc_tempreserve",
"arc_meta_used", "arc_meta_limit", "arc_meta_max",
};
mdb_warn("failed to find 'arc_stats'");
return (DCMD_ERR);
}
return (DCMD_ERR);
}
/* NB: -a / opt_a are ignored for backwards compatability */
return (DCMD_USAGE);
shift = 20;
switch (shift) {
case 0:
suffix = "B";
break;
case 10:
suffix = "KB";
break;
case 20:
suffix = "MB";
break;
case 30:
suffix = "GB";
break;
default:
suffix = "XX";
}
for (i = 0; i < nstats; i++) {
int j;
for (j = 0; bytestats[j]; j++) {
break;
}
}
if (bytes) {
} else {
}
}
for (i = 0; extras[i]; i++) {
return (DCMD_ERR);
}
mdb_warn("expected scalar for variable '%s'\n",
extras[i]);
return (DCMD_ERR);
}
return (DCMD_ERR);
}
/* NB: all the 64-bit extras happen to be byte counts */
}
return (DCMD_OK);
}
/*
* ::spa
*
* -c Print configuration information as well
* -v Print vdev state
* -e Print vdev error stats
*
* Print a summarized spa_t. When given no arguments, prints out a table of all
* active pools on the system.
*/
/* ARGSUSED */
static int
{
"SPARE", "L2CACHE", "UNINIT", "UNAVAIL", "POTENTIAL" };
const char *state;
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("can't walk spa");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (flags & DCMD_PIPE_OUT) {
return (DCMD_OK);
}
if (DCMD_HDRSPEC(flags))
return (DCMD_ERR);
}
state = "UNKNOWN";
else
if (config) {
mdb_printf("\n");
mdb_inc_indent(4);
return (DCMD_ERR);
mdb_dec_indent(4);
}
mdb_arg_t v;
v.a_type = MDB_TYPE_STRING;
mdb_printf("\n");
mdb_inc_indent(4);
&v) != DCMD_OK)
return (DCMD_ERR);
mdb_dec_indent(4);
}
return (DCMD_OK);
}
/*
* ::spa_config
*
* Given a spa_t, print the configuration information stored in spa_config.
* Since it's just an nvlist, format it as an indented list of name=value pairs.
* We simply read the value of spa_config and pass off to ::nvlist.
*/
/* ARGSUSED */
static int
{
return (DCMD_USAGE);
return (DCMD_ERR);
}
mdb_printf("(none)\n");
return (DCMD_OK);
}
0, NULL));
}
/*
* ::vdev
*
* Print out a summarized vdev_t, in the following form:
*
* ADDR STATE AUX DESC
*
* If '-r' is specified, recursively visit all children.
*
* With '-e', the statistics associated with the vdev are printed as well.
*/
static int
int recursive)
{
char desc[MAXNAMELEN];
int c, children;
return (DCMD_ERR);
}
if (flags & DCMD_PIPE_OUT) {
} else {
mdb_warn("failed to read vdev_path at %p\n",
return (DCMD_ERR);
}
mdb_warn("failed to read vdev_ops at %p\n",
return (DCMD_ERR);
}
} else {
}
mdb_printf("%<u>%-?s %-9s %-12s %-*s%</u>\n",
"ADDR", "STATE", "AUX",
"DESCRIPTION");
switch (vdev.vdev_state) {
case VDEV_STATE_CLOSED:
state = "CLOSED";
break;
case VDEV_STATE_OFFLINE:
state = "OFFLINE";
break;
case VDEV_STATE_CANT_OPEN:
state = "CANT_OPEN";
break;
case VDEV_STATE_DEGRADED:
state = "DEGRADED";
break;
case VDEV_STATE_HEALTHY:
state = "HEALTHY";
break;
case VDEV_STATE_REMOVED:
state = "REMOVED";
break;
case VDEV_STATE_FAULTED:
state = "FAULTED";
break;
default:
state = "UNKNOWN";
break;
}
case VDEV_AUX_NONE:
aux = "-";
break;
case VDEV_AUX_OPEN_FAILED:
aux = "OPEN_FAILED";
break;
case VDEV_AUX_CORRUPT_DATA:
aux = "CORRUPT_DATA";
break;
case VDEV_AUX_NO_REPLICAS:
aux = "NO_REPLICAS";
break;
case VDEV_AUX_BAD_GUID_SUM:
aux = "BAD_GUID_SUM";
break;
case VDEV_AUX_TOO_SMALL:
aux = "TOO_SMALL";
break;
case VDEV_AUX_BAD_LABEL:
aux = "BAD_LABEL";
break;
case VDEV_AUX_VERSION_NEWER:
aux = "VERS_NEWER";
break;
case VDEV_AUX_VERSION_OLDER:
aux = "VERS_OLDER";
break;
case VDEV_AUX_SPARED:
aux = "SPARED";
break;
case VDEV_AUX_ERR_EXCEEDED:
aux = "ERR_EXCEEDED";
break;
case VDEV_AUX_IO_FAILURE:
aux = "IO_FAILURE";
break;
case VDEV_AUX_BAD_LOG:
aux = "BAD_LOG";
break;
default:
aux = "UNKNOWN";
break;
}
if (stats) {
int i;
mdb_inc_indent(4);
mdb_printf("\n");
mdb_printf("%<u> %12s %12s %12s %12s "
"%12s%</u>\n", "READ", "WRITE", "FREE", "CLAIM",
"IOCTL");
mdb_printf("OPS ");
for (i = 1; i < ZIO_TYPES; i++)
mdb_printf("\n");
mdb_printf("BYTES ");
for (i = 1; i < ZIO_TYPES; i++)
mdb_printf("\n");
mdb_printf("ECKSUM %10#llx\n",
mdb_dec_indent(4);
}
if (stats)
mdb_printf("\n");
}
return (DCMD_OK);
return (DCMD_ERR);
}
for (c = 0; c < children; c++) {
return (DCMD_ERR);
}
return (DCMD_OK);
}
static int
{
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("no vdev_t address given\n");
return (DCMD_ERR);
}
}
typedef struct metaslab_walk_data {
int mw_curvdev;
int mw_curms;
static int
{
return (WALK_DONE);
return (WALK_ERR);
}
mssp) == -1) {
return (WALK_ERR);
}
}
mw->mw_curvdev++;
return (WALK_NEXT);
}
return (WALK_ERR);
}
}
/* ARGSUSED */
static int
{
mdb_warn("must supply address of spa_t\n");
return (WALK_ERR);
}
return (DCMD_ERR);
}
childp) == -1) {
return (DCMD_ERR);
}
return (WALK_NEXT);
}
typedef struct mdb_spa {
} mdb_spa_t;
typedef struct mdb_dsl_dir {
typedef struct mdb_dsl_dir_phys {
typedef struct mdb_vdev {
} mdb_vdev_t;
typedef struct mdb_metaslab {
typedef struct space_data {
} space_data_t;
/* ARGSUSED */
static int
{
return (WALK_ERR);
}
return (WALK_NEXT);
}
/*
* ::spa_space [-b]
*
* Given a spa_t, print out it's on-disk space usage and in-core
* estimates of future usage. If -b is given, print space in bytes.
* Otherwise print in megabytes.
*/
/* ARGSUSED */
static int
{
int shift = 20;
char *suffix = "M";
argc)
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
if (bits) {
shift = 0;
suffix = "";
}
dp_root_dir, dp_root_dir) ||
return (DCMD_ERR);
}
mdb_printf("dd_space_towrite = %llu%s %llu%s %llu%s %llu%s\n",
mdb_printf("dd_phys.dd_used_bytes = %llu%s\n",
mdb_printf("dd_phys.dd_compressed_bytes = %llu%s\n",
mdb_printf("dd_phys.dd_uncompressed_bytes = %llu%s\n",
mdb_warn("can't walk metaslabs");
return (DCMD_ERR);
}
mdb_printf("ms_allocmap = %llu%s %llu%s %llu%s %llu%s\n",
mdb_printf("ms_freemap = %llu%s %llu%s %llu%s %llu%s\n",
mdb_printf("current syncing avail = %llu%s\n",
return (DCMD_OK);
}
/*
* ::spa_verify
*
* Given a spa_t, verify that that the pool is self-consistent.
* Currently, it only checks to make sure that the vdev tree exists.
*/
/* ARGSUSED */
static int
{
return (DCMD_USAGE);
return (DCMD_ERR);
}
mdb_printf("no vdev tree present\n");
return (DCMD_OK);
}
return (DCMD_OK);
}
/*
* ::spa_vdevs
*
* -e Include error stats
*
* Print out a summarized list of vdevs for the given spa_t.
* This is accomplished by invoking "::vdev -re" on the root vdev, as well as
* iterating over the cache devices.
*/
/* ARGSUSED */
static int
{
mdb_arg_t v[3];
int ret, i;
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
/*
* Unitialized spa_t structures can have a NULL root vdev.
*/
mdb_printf("no associated vdevs\n");
return (DCMD_OK);
}
v[0].a_type = MDB_TYPE_STRING;
flags, 1, v);
return (ret);
/*
* Iterate over cache devices and print those out as well. This is a
* little annoying because we don't have a root vdev to pass to ::vdev.
* Instead, we print a single 'cache' line and then call it for each
* child vdev.
*/
mdb_warn("failed to read l2cache vdevs at %p",
return (DCMD_ERR);
}
return (ret);
}
}
}
return (DCMD_OK);
}
/*
* ::zio
*
* Print a summary of zio_t and all its children. This is intended to display a
* zio tree, and hence we only pick the most important pieces of information for
* the main summary. More detailed information can always be found by doing a
* '::print zio' on the underlying zio_t. The columns we display are:
*
* ADDRESS TYPE STAGE WAITER
*
* The 'address' column is indented by one space for each depth level as we
* descend down the tree.
*/
#define ZIO_MAXDEPTH 16
static int
{
int maxdepth;
if (depth > ZIO_MAXDEPTH)
mdb_warn("failed to lookup zio enums");
return (WALK_ERR);
}
else
type = "?";
else
stage = "?";
mdb_printf("%*s%-*p %-5s %-22s ",
else
mdb_printf("-\n");
addr) != 0) {
return (WALK_ERR);
}
return (WALK_NEXT);
}
/*ARGSUSED*/
static int
{
int maxdepth;
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
if (DCMD_HDRSPEC(flags))
"ADDRESS", "TYPE", "STAGE", "WAITER");
return (DCMD_ERR);
return (DCMD_OK);
}
/*
* [addr]::zio_state
*
* Print a summary of all zio_t structures on the system, or for a particular
* pool. This is equivalent to '::walk zio_root | ::zio'.
*/
/*ARGSUSED*/
static int
{
/*
* MDB will remember the last address of the pipeline, so if we don't
* zero this we'll end up trying to walk zio structures for a
* non-existent spa_t.
*/
if (!(flags & DCMD_ADDRSPEC))
addr = 0;
}
typedef struct txg_list_walk_data {
int lw_txgoff;
int lw_maxoff;
void *lw_obj;
static int
{
int i;
return (WALK_ERR);
}
for (i = 0; i < TXG_SIZE; i++)
return (WALK_NEXT);
}
static int
{
}
static int
{
return (txg_list_walk_init_common(wsp, 0, 0));
}
static int
{
}
static int
{
}
static int
{
}
static int
{
int status;
}
return (WALK_DONE);
return (WALK_ERR);
}
return (status);
}
/*
* ::walk spa
*
* Walk all named spa_t structures in the namespace. This is nothing more than
* a layered avl walk.
*/
static int
{
mdb_warn("spa walk only supports global walks\n");
return (WALK_ERR);
}
mdb_warn("failed to find symbol 'spa_namespace_avl'");
return (WALK_ERR);
}
mdb_warn("failed to walk 'avl'\n");
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
return (WALK_ERR);
}
}
/*
* [addr]::walk zio
*
* Walk all active zio_t structures on the system. This is simply a layered
* walk on top of ::walk zio_cache, with the optional ability to limit the
* structures to a particular pool.
*/
static int
{
mdb_warn("failed to walk 'zio_cache'\n");
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
return (WALK_ERR);
}
return (WALK_NEXT);
}
/*
* ::walk zio_child
*
* Walk the children of a zio_t structure.
*/
static int
{
mdb_warn("::walk zio_child doesn't support global walks\n");
return (WALK_ERR);
}
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
int status;
return (WALK_DONE);
return (WALK_ERR);
}
return (status);
}
/*
* [addr]::walk zio_root
*
* Walk only root zio_t structures, optionally for a particular spa_t.
*/
static int
{
return (WALK_ERR);
}
return (WALK_NEXT);
return (WALK_NEXT);
}
#define NICENUM_BUFLEN 6
static int
{
float mul = 1;
for (i = frac_digits; i; i--)
mul *= 10;
whole = (int)f;
}
static void
{
int index = 0;
char *u;
while (n >= 1024) {
n = (n + (1024 / 2)) / 1024; /* Round up or down */
index++;
}
if (index == 0) {
(u_longlong_t)n);
} else {
(u_longlong_t)n, u);
}
}
/*
* ::zfs_blkstats
*
* -v print verbose per-level information
*
*/
static int
{
/* +10 in case it grew */
mdb_warn("failed to read 'dmu_ot'");
return (DCMD_ERR);
}
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
mdb_printf("maybe no stats? run \"zpool scrub\" first.");
return (DCMD_ERR);
}
mdb_printf("Ganged blocks: %llu\n",
}
if (ditto != 0) {
mdb_printf("Dittoed blocks on same vdev: %llu\n",
(longlong_t)ditto);
}
mdb_printf("\nBlocks\tLSIZE\tPSIZE\tASIZE"
"\t avg\t comp\t%%Total\tType\n");
for (t = 0; t <= DMU_OT_NUMTYPES; t++) {
char avg[NICENUM_BUFLEN];
char typename[64];
int l;
if (t == DMU_OT_DEFERRED)
else if (t == DMU_OT_TOTAL)
mdb_warn("failed to read type name");
return (DCMD_ERR);
}
continue;
for (l = -1; l < DN_MAX_LEVELS; l++) {
continue;
/*
* Don't print each level unless requested.
*/
continue;
/*
* If all the space is level 0, don't print the
* level 0 separately.
*/
continue;
mdb_printf("%6s\t%5s\t%5s\t%5s\t%5s"
"\t%5s\t%6s\t",
if (level == DN_MAX_LEVELS)
else
mdb_printf(" L%d %s\n",
}
}
return (DCMD_OK);
}
/*
* MDB module linkage information:
*
* We declare a list of structures describing our dcmds, and a function
* named _mdb_init to return a pointer to our module information.
*/
static const mdb_dcmd_t dcmds[] = {
{ "dbufs",
"\t[-O objset_impl_t*] [-n objset_name | \"mos\"] "
"[-o object | \"mdn\"] \n"
"\t[-l level] [-b blkid | \"bonus\"]",
"find dmu_buf_impl_t's that match specified criteria", dbufs },
{ "abuf_find", "dva_word[0] dva_word[1]",
"find arc_buf_hdr_t of a specified DVA",
abuf_find },
{ "vdev", ":[-re]\n"
"\t-r display recursively\n"
"\t-e print statistics\n",
"vdev_t summary", vdev_print },
{ "zio_state", "?", "print out all zio_t structures on system or "
"for a particular pool", zio_state },
{ "zfs_blkstats", ":[-v]",
"given a spa_t, print block type stats from last scrub",
zfs_blkstats },
{ NULL }
};
static const mdb_walker_t walkers[] = {
/*
* In userland, there is no generic provider of list_t walkers, so we
* need to add it.
*/
#ifndef _KERNEL
#endif
{ "zms_freelist", "walk ZFS metaslab freelist",
{ "txg_list", "given any txg_list_t *, walk all entries in all txgs",
{ "txg_list0", "given any txg_list_t *, walk all entries in txg 0",
{ "txg_list1", "given any txg_list_t *, walk all entries in txg 1",
{ "txg_list2", "given any txg_list_t *, walk all entries in txg 2",
{ "txg_list3", "given any txg_list_t *, walk all entries in txg 3",
{ "zio", "walk all zio structures, optionally for a particular spa_t",
{ "zio_child", "walk children of a zio_t structure",
{ "zio_root", "walk all root zio_t structures, optionally for a "
"particular spa_t",
{ "spa", "walk all spa_t entries in the namespace",
{ "metaslab", "given a spa_t *, walk all metaslab_t structures",
{ NULL }
};
static const mdb_modinfo_t modinfo = {
};
const mdb_modinfo_t *
_mdb_init(void)
{
return (&modinfo);
}