Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/cmd/zdb/zdb.c
Show All 25 Lines | |||||
* Copyright 2016 Nexenta Systems, Inc. | * Copyright 2016 Nexenta Systems, Inc. | ||||
* Copyright (c) 2017, 2018 Lawrence Livermore National Security, LLC. | * Copyright (c) 2017, 2018 Lawrence Livermore National Security, LLC. | ||||
* Copyright (c) 2015, 2017, Intel Corporation. | * Copyright (c) 2015, 2017, Intel Corporation. | ||||
* Copyright (c) 2020 Datto Inc. | * Copyright (c) 2020 Datto Inc. | ||||
* Copyright (c) 2020, The FreeBSD Foundation [1] | * Copyright (c) 2020, The FreeBSD Foundation [1] | ||||
* | * | ||||
* [1] Portions of this software were developed by Allan Jude | * [1] Portions of this software were developed by Allan Jude | ||||
* under sponsorship from the FreeBSD Foundation. | * under sponsorship from the FreeBSD Foundation. | ||||
* Copyright (c) 2021 Allan Jude | |||||
*/ | */ | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <sys/zfs_context.h> | #include <sys/zfs_context.h> | ||||
#include <sys/spa.h> | #include <sys/spa.h> | ||||
▲ Show 20 Lines • Show All 708 Lines • ▼ Show 20 Lines | (void) fprintf(stderr, | ||||
"\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>]\n" | "\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>]\n" | ||||
"\t\t[<poolname>[/<dataset | objset id>] [<object | range> ...]\n" | "\t\t[<poolname>[/<dataset | objset id>] [<object | range> ...]\n" | ||||
"\t%s [-v] <bookmark>\n" | "\t%s [-v] <bookmark>\n" | ||||
"\t%s -C [-A] [-U <cache>]\n" | "\t%s -C [-A] [-U <cache>]\n" | ||||
"\t%s -l [-Aqu] <device>\n" | "\t%s -l [-Aqu] <device>\n" | ||||
"\t%s -m [-AFLPX] [-e [-V] [-p <path> ...]] [-t <txg>] " | "\t%s -m [-AFLPX] [-e [-V] [-p <path> ...]] [-t <txg>] " | ||||
"[-U <cache>]\n\t\t<poolname> [<vdev> [<metaslab> ...]]\n" | "[-U <cache>]\n\t\t<poolname> [<vdev> [<metaslab> ...]]\n" | ||||
"\t%s -O <dataset> <path>\n" | "\t%s -O <dataset> <path>\n" | ||||
"\t%s -r <dataset> <path> <destination>\n" | |||||
"\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n" | "\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n" | ||||
"\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n" | "\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n" | ||||
"\t%s -E [-A] word0:word1:...:word15\n" | "\t%s -E [-A] word0:word1:...:word15\n" | ||||
"\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] " | "\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] " | ||||
"<poolname>\n\n", | "<poolname>\n\n", | ||||
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, | cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, | ||||
cmdname, cmdname, cmdname); | cmdname, cmdname, cmdname, cmdname); | ||||
(void) fprintf(stderr, " Dataset name must include at least one " | (void) fprintf(stderr, " Dataset name must include at least one " | ||||
"separator character '/' or '@'\n"); | "separator character '/' or '@'\n"); | ||||
(void) fprintf(stderr, " If dataset name is specified, only that " | (void) fprintf(stderr, " If dataset name is specified, only that " | ||||
"dataset is dumped\n"); | "dataset is dumped\n"); | ||||
(void) fprintf(stderr, " If object numbers or object number " | (void) fprintf(stderr, " If object numbers or object number " | ||||
"ranges are specified, only those\n" | "ranges are specified, only those\n" | ||||
" objects or ranges are dumped.\n\n"); | " objects or ranges are dumped.\n\n"); | ||||
Show All 22 Lines | usage(void) | ||||
(void) fprintf(stderr, " -l read label contents\n"); | (void) fprintf(stderr, " -l read label contents\n"); | ||||
(void) fprintf(stderr, " -k examine the checkpointed state " | (void) fprintf(stderr, " -k examine the checkpointed state " | ||||
"of the pool\n"); | "of the pool\n"); | ||||
(void) fprintf(stderr, " -L disable leak tracking (do not " | (void) fprintf(stderr, " -L disable leak tracking (do not " | ||||
"load spacemaps)\n"); | "load spacemaps)\n"); | ||||
(void) fprintf(stderr, " -m metaslabs\n"); | (void) fprintf(stderr, " -m metaslabs\n"); | ||||
(void) fprintf(stderr, " -M metaslab groups\n"); | (void) fprintf(stderr, " -M metaslab groups\n"); | ||||
(void) fprintf(stderr, " -O perform object lookups by path\n"); | (void) fprintf(stderr, " -O perform object lookups by path\n"); | ||||
(void) fprintf(stderr, " -r copy an object by path to file\n"); | |||||
(void) fprintf(stderr, " -R read and display block from a " | (void) fprintf(stderr, " -R read and display block from a " | ||||
"device\n"); | "device\n"); | ||||
(void) fprintf(stderr, " -s report stats on zdb's I/O\n"); | (void) fprintf(stderr, " -s report stats on zdb's I/O\n"); | ||||
(void) fprintf(stderr, " -S simulate dedup to measure effect\n"); | (void) fprintf(stderr, " -S simulate dedup to measure effect\n"); | ||||
(void) fprintf(stderr, " -v verbose (applies to all " | (void) fprintf(stderr, " -v verbose (applies to all " | ||||
"others)\n"); | "others)\n"); | ||||
(void) fprintf(stderr, " -y perform livelist and metaslab " | (void) fprintf(stderr, " -y perform livelist and metaslab " | ||||
"validation on any livelists being deleted\n\n"); | "validation on any livelists being deleted\n\n"); | ||||
▲ Show 20 Lines • Show All 3,674 Lines • ▼ Show 20 Lines | |||||
static char curpath[PATH_MAX]; | static char curpath[PATH_MAX]; | ||||
/* | /* | ||||
* Iterate through the path components, recursively passing | * Iterate through the path components, recursively passing | ||||
* current one's obj and remaining path until we find the obj | * current one's obj and remaining path until we find the obj | ||||
* for the last one. | * for the last one. | ||||
*/ | */ | ||||
static int | static int | ||||
dump_path_impl(objset_t *os, uint64_t obj, char *name) | dump_path_impl(objset_t *os, uint64_t obj, char *name, uint64_t *retobj) | ||||
{ | { | ||||
int err; | int err; | ||||
boolean_t header = B_TRUE; | boolean_t header = B_TRUE; | ||||
uint64_t child_obj; | uint64_t child_obj; | ||||
char *s; | char *s; | ||||
dmu_buf_t *db; | dmu_buf_t *db; | ||||
dmu_object_info_t doi; | dmu_object_info_t doi; | ||||
Show All 33 Lines | (void) printf("obj=%llu %s type=%d bonustype=%d\n", | ||||
doi.doi_bonus_type); | doi.doi_bonus_type); | ||||
} | } | ||||
(void) strlcat(curpath, "/", sizeof (curpath)); | (void) strlcat(curpath, "/", sizeof (curpath)); | ||||
switch (doi.doi_type) { | switch (doi.doi_type) { | ||||
case DMU_OT_DIRECTORY_CONTENTS: | case DMU_OT_DIRECTORY_CONTENTS: | ||||
if (s != NULL && *(s + 1) != '\0') | if (s != NULL && *(s + 1) != '\0') | ||||
return (dump_path_impl(os, child_obj, s + 1)); | return (dump_path_impl(os, child_obj, s + 1, retobj)); | ||||
/*FALLTHROUGH*/ | /*FALLTHROUGH*/ | ||||
case DMU_OT_PLAIN_FILE_CONTENTS: | case DMU_OT_PLAIN_FILE_CONTENTS: | ||||
dump_object(os, child_obj, dump_opt['v'], &header, NULL, 0); | if (retobj != NULL) { | ||||
*retobj = child_obj; | |||||
} else { | |||||
dump_object(os, child_obj, dump_opt['v'], &header, | |||||
NULL, 0); | |||||
} | |||||
return (0); | return (0); | ||||
default: | default: | ||||
(void) fprintf(stderr, "object %llu has non-file/directory " | (void) fprintf(stderr, "object %llu has non-file/directory " | ||||
"type %d\n", (u_longlong_t)obj, doi.doi_type); | "type %d\n", (u_longlong_t)obj, doi.doi_type); | ||||
break; | break; | ||||
} | } | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* | /* | ||||
* Dump the blocks for the object specified by path inside the dataset. | * Dump the blocks for the object specified by path inside the dataset. | ||||
*/ | */ | ||||
static int | static int | ||||
dump_path(char *ds, char *path) | dump_path(char *ds, char *path, uint64_t *retobj) | ||||
{ | { | ||||
int err; | int err; | ||||
objset_t *os; | objset_t *os; | ||||
uint64_t root_obj; | uint64_t root_obj; | ||||
err = open_objset(ds, FTAG, &os); | err = open_objset(ds, FTAG, &os); | ||||
if (err != 0) | if (err != 0) | ||||
return (err); | return (err); | ||||
err = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, &root_obj); | err = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, &root_obj); | ||||
if (err != 0) { | if (err != 0) { | ||||
(void) fprintf(stderr, "can't lookup root znode: %s\n", | (void) fprintf(stderr, "can't lookup root znode: %s\n", | ||||
strerror(err)); | strerror(err)); | ||||
close_objset(os, FTAG); | close_objset(os, FTAG); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
(void) snprintf(curpath, sizeof (curpath), "dataset=%s path=/", ds); | (void) snprintf(curpath, sizeof (curpath), "dataset=%s path=/", ds); | ||||
err = dump_path_impl(os, root_obj, path); | err = dump_path_impl(os, root_obj, path, retobj); | ||||
close_objset(os, FTAG); | close_objset(os, FTAG); | ||||
return (err); | return (err); | ||||
} | } | ||||
static int | static int | ||||
zdb_copy_object(objset_t *os, uint64_t srcobj, char *destfile) | |||||
{ | |||||
int err = 0; | |||||
uint64_t size, readsize, oursize, offset; | |||||
ssize_t writesize; | |||||
sa_handle_t *hdl; | |||||
(void) printf("Copying object %" PRIu64 " to file %s\n", srcobj, | |||||
destfile); | |||||
VERIFY3P(os, ==, sa_os); | |||||
if ((err = sa_handle_get(os, srcobj, NULL, SA_HDL_PRIVATE, &hdl))) { | |||||
(void) printf("Failed to get handle for SA znode\n"); | |||||
return (err); | |||||
} | |||||
if ((err = sa_lookup(hdl, sa_attr_table[ZPL_SIZE], &size, 8))) { | |||||
(void) sa_handle_destroy(hdl); | |||||
return (err); | |||||
} | |||||
(void) sa_handle_destroy(hdl); | |||||
(void) printf("Object %" PRIu64 " is %" PRIu64 " bytes\n", srcobj, | |||||
size); | |||||
if (size == 0) { | |||||
return (EINVAL); | |||||
} | |||||
int fd = open(destfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); | |||||
/* | |||||
* We cap the size at 1 mebibyte here to prevent | |||||
* allocation failures and nigh-infinite printing if the | |||||
* object is extremely large. | |||||
*/ | |||||
oursize = MIN(size, 1 << 20); | |||||
offset = 0; | |||||
char *buf = kmem_alloc(oursize, KM_NOSLEEP); | |||||
if (buf == NULL) { | |||||
return (ENOMEM); | |||||
} | |||||
while (offset < size) { | |||||
readsize = MIN(size - offset, 1 << 20); | |||||
err = dmu_read(os, srcobj, offset, readsize, buf, 0); | |||||
if (err != 0) { | |||||
(void) printf("got error %u from dmu_read\n", err); | |||||
kmem_free(buf, oursize); | |||||
return (err); | |||||
} | |||||
if (dump_opt['v'] > 3) { | |||||
(void) printf("Read offset=%" PRIu64 " size=%" PRIu64 | |||||
" error=%d\n", offset, readsize, err); | |||||
} | |||||
writesize = write(fd, buf, readsize); | |||||
if (writesize < 0) { | |||||
err = errno; | |||||
break; | |||||
} else if (writesize != readsize) { | |||||
/* Incomplete write */ | |||||
(void) fprintf(stderr, "Short write, only wrote %llu of" | |||||
" %" PRIu64 " bytes, exiting...\n", | |||||
(u_longlong_t)writesize, readsize); | |||||
break; | |||||
} | |||||
offset += readsize; | |||||
} | |||||
(void) close(fd); | |||||
if (buf != NULL) | |||||
kmem_free(buf, oursize); | |||||
return (err); | |||||
} | |||||
static int | |||||
dump_label(const char *dev) | dump_label(const char *dev) | ||||
{ | { | ||||
char path[MAXPATHLEN]; | char path[MAXPATHLEN]; | ||||
zdb_label_t labels[VDEV_LABELS]; | zdb_label_t labels[VDEV_LABELS]; | ||||
uint64_t psize, ashift, l2cache; | uint64_t psize, ashift, l2cache; | ||||
struct stat64 statbuf; | struct stat64 statbuf; | ||||
boolean_t config_found = B_FALSE; | boolean_t config_found = B_FALSE; | ||||
boolean_t error = B_FALSE; | boolean_t error = B_FALSE; | ||||
▲ Show 20 Lines • Show All 1,243 Lines • ▼ Show 20 Lines | for (uint64_t c = 0; c < rvd->vdev_children; c++) { | ||||
*/ | */ | ||||
zcb->zcb_vd_obsolete_counts[c] = zdb_load_obsolete_counts(vd); | zcb->zcb_vd_obsolete_counts[c] = zdb_load_obsolete_counts(vd); | ||||
/* | /* | ||||
* Normally, indirect vdevs don't have any | * Normally, indirect vdevs don't have any | ||||
* metaslabs. We want to set them up for | * metaslabs. We want to set them up for | ||||
* zio_claim(). | * zio_claim(). | ||||
*/ | */ | ||||
vdev_metaslab_group_create(vd); | |||||
VERIFY0(vdev_metaslab_init(vd, 0)); | VERIFY0(vdev_metaslab_init(vd, 0)); | ||||
vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping; | vdev_indirect_mapping_t *vim = vd->vdev_indirect_mapping; | ||||
uint64_t vim_idx = 0; | uint64_t vim_idx = 0; | ||||
for (uint64_t m = 0; m < vd->vdev_ms_count; m++) { | for (uint64_t m = 0; m < vd->vdev_ms_count; m++) { | ||||
(void) fprintf(stderr, | (void) fprintf(stderr, | ||||
"\rloading indirect vdev %llu, " | "\rloading indirect vdev %llu, " | ||||
Show All 22 Lines | zdb_leak_init(spa_t *spa, zdb_cb_t *zcb) | ||||
/* | /* | ||||
* We are going to be changing the meaning of the metaslab's | * We are going to be changing the meaning of the metaslab's | ||||
* ms_allocatable. Ensure that the allocator doesn't try to | * ms_allocatable. Ensure that the allocator doesn't try to | ||||
* use the tree. | * use the tree. | ||||
*/ | */ | ||||
spa->spa_normal_class->mc_ops = &zdb_metaslab_ops; | spa->spa_normal_class->mc_ops = &zdb_metaslab_ops; | ||||
spa->spa_log_class->mc_ops = &zdb_metaslab_ops; | spa->spa_log_class->mc_ops = &zdb_metaslab_ops; | ||||
spa->spa_embedded_log_class->mc_ops = &zdb_metaslab_ops; | |||||
zcb->zcb_vd_obsolete_counts = | zcb->zcb_vd_obsolete_counts = | ||||
umem_zalloc(rvd->vdev_children * sizeof (uint32_t *), | umem_zalloc(rvd->vdev_children * sizeof (uint32_t *), | ||||
UMEM_NOFAIL); | UMEM_NOFAIL); | ||||
/* | /* | ||||
* For leak detection, we overload the ms_allocatable trees | * For leak detection, we overload the ms_allocatable trees | ||||
* to contain allocated segments instead of free segments. | * to contain allocated segments instead of free segments. | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
if (dump_opt['L']) | if (dump_opt['L']) | ||||
return (B_FALSE); | return (B_FALSE); | ||||
boolean_t leaks = B_FALSE; | boolean_t leaks = B_FALSE; | ||||
vdev_t *rvd = spa->spa_root_vdev; | vdev_t *rvd = spa->spa_root_vdev; | ||||
for (unsigned c = 0; c < rvd->vdev_children; c++) { | for (unsigned c = 0; c < rvd->vdev_children; c++) { | ||||
vdev_t *vd = rvd->vdev_child[c]; | vdev_t *vd = rvd->vdev_child[c]; | ||||
metaslab_group_t *mg __maybe_unused = vd->vdev_mg; | |||||
if (zcb->zcb_vd_obsolete_counts[c] != NULL) { | if (zcb->zcb_vd_obsolete_counts[c] != NULL) { | ||||
leaks |= zdb_check_for_obsolete_leaks(vd, zcb); | leaks |= zdb_check_for_obsolete_leaks(vd, zcb); | ||||
} | } | ||||
for (uint64_t m = 0; m < vd->vdev_ms_count; m++) { | for (uint64_t m = 0; m < vd->vdev_ms_count; m++) { | ||||
metaslab_t *msp = vd->vdev_ms[m]; | metaslab_t *msp = vd->vdev_ms[m]; | ||||
ASSERT3P(mg, ==, msp->ms_group); | ASSERT3P(msp->ms_group, ==, (msp->ms_group->mg_class == | ||||
spa_embedded_log_class(spa)) ? | |||||
vd->vdev_log_mg : vd->vdev_mg); | |||||
/* | /* | ||||
* ms_allocatable has been overloaded | * ms_allocatable has been overloaded | ||||
* to contain allocated segments. Now that | * to contain allocated segments. Now that | ||||
* we finished traversing all blocks, any | * we finished traversing all blocks, any | ||||
* block that remains in the ms_allocatable | * block that remains in the ms_allocatable | ||||
* represents an allocated block that we | * represents an allocated block that we | ||||
* did not claim during the traversal. | * did not claim during the traversal. | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | dump_block_stats(spa_t *spa) | ||||
deleted_livelists_count_blocks(spa, &zcb); | deleted_livelists_count_blocks(spa, &zcb); | ||||
if (dump_opt['c'] > 1) | if (dump_opt['c'] > 1) | ||||
flags |= TRAVERSE_PREFETCH_DATA; | flags |= TRAVERSE_PREFETCH_DATA; | ||||
zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa)); | zcb.zcb_totalasize = metaslab_class_get_alloc(spa_normal_class(spa)); | ||||
zcb.zcb_totalasize += metaslab_class_get_alloc(spa_special_class(spa)); | zcb.zcb_totalasize += metaslab_class_get_alloc(spa_special_class(spa)); | ||||
zcb.zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa)); | zcb.zcb_totalasize += metaslab_class_get_alloc(spa_dedup_class(spa)); | ||||
zcb.zcb_totalasize += | |||||
metaslab_class_get_alloc(spa_embedded_log_class(spa)); | |||||
zcb.zcb_start = zcb.zcb_lastprint = gethrtime(); | zcb.zcb_start = zcb.zcb_lastprint = gethrtime(); | ||||
err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb); | err = traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb); | ||||
/* | /* | ||||
* If we've traversed the data blocks then we need to wait for those | * If we've traversed the data blocks then we need to wait for those | ||||
* I/Os to complete. We leverage "The Godfather" zio to wait on | * I/Os to complete. We leverage "The Godfather" zio to wait on | ||||
* all async I/Os to complete. | * all async I/Os to complete. | ||||
*/ | */ | ||||
Show All 31 Lines | dump_block_stats(spa_t *spa) | ||||
tzb = &zcb.zcb_type[ZB_TOTAL][ZDB_OT_TOTAL]; | tzb = &zcb.zcb_type[ZB_TOTAL][ZDB_OT_TOTAL]; | ||||
norm_alloc = metaslab_class_get_alloc(spa_normal_class(spa)); | norm_alloc = metaslab_class_get_alloc(spa_normal_class(spa)); | ||||
norm_space = metaslab_class_get_space(spa_normal_class(spa)); | norm_space = metaslab_class_get_space(spa_normal_class(spa)); | ||||
total_alloc = norm_alloc + | total_alloc = norm_alloc + | ||||
metaslab_class_get_alloc(spa_log_class(spa)) + | metaslab_class_get_alloc(spa_log_class(spa)) + | ||||
metaslab_class_get_alloc(spa_embedded_log_class(spa)) + | |||||
metaslab_class_get_alloc(spa_special_class(spa)) + | metaslab_class_get_alloc(spa_special_class(spa)) + | ||||
metaslab_class_get_alloc(spa_dedup_class(spa)) + | metaslab_class_get_alloc(spa_dedup_class(spa)) + | ||||
get_unflushed_alloc_space(spa); | get_unflushed_alloc_space(spa); | ||||
total_found = tzb->zb_asize - zcb.zcb_dedup_asize + | total_found = tzb->zb_asize - zcb.zcb_dedup_asize + | ||||
zcb.zcb_removing_size + zcb.zcb_checkpoint_size; | zcb.zcb_removing_size + zcb.zcb_checkpoint_size; | ||||
if (total_found == total_alloc && !dump_opt['L']) { | if (total_found == total_alloc && !dump_opt['L']) { | ||||
(void) printf("\n\tNo leaks (block sum matches space" | (void) printf("\n\tNo leaks (block sum matches space" | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | if (spa_dedup_class(spa)->mc_allocator[0].mca_rotor != NULL) { | ||||
uint64_t space = metaslab_class_get_space( | uint64_t space = metaslab_class_get_space( | ||||
spa_dedup_class(spa)); | spa_dedup_class(spa)); | ||||
(void) printf("\t%-16s %14llu used: %5.2f%%\n", | (void) printf("\t%-16s %14llu used: %5.2f%%\n", | ||||
"Dedup class", (u_longlong_t)alloc, | "Dedup class", (u_longlong_t)alloc, | ||||
100.0 * alloc / space); | 100.0 * alloc / space); | ||||
} | } | ||||
if (spa_embedded_log_class(spa)->mc_allocator[0].mca_rotor != NULL) { | |||||
uint64_t alloc = metaslab_class_get_alloc( | |||||
spa_embedded_log_class(spa)); | |||||
uint64_t space = metaslab_class_get_space( | |||||
spa_embedded_log_class(spa)); | |||||
(void) printf("\t%-16s %14llu used: %5.2f%%\n", | |||||
"Embedded log class", (u_longlong_t)alloc, | |||||
100.0 * alloc / space); | |||||
} | |||||
for (i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) { | for (i = 0; i < NUM_BP_EMBEDDED_TYPES; i++) { | ||||
if (zcb.zcb_embedded_blocks[i] == 0) | if (zcb.zcb_embedded_blocks[i] == 0) | ||||
continue; | continue; | ||||
(void) printf("\n"); | (void) printf("\n"); | ||||
(void) printf("\tadditional, non-pointer bps of type %u: " | (void) printf("\tadditional, non-pointer bps of type %u: " | ||||
"%10llu\n", | "%10llu\n", | ||||
i, (u_longlong_t)zcb.zcb_embedded_blocks[i]); | i, (u_longlong_t)zcb.zcb_embedded_blocks[i]); | ||||
▲ Show 20 Lines • Show All 1,790 Lines • ▼ Show 20 Lines | main(int argc, char **argv) | ||||
int verbose = 0; | int verbose = 0; | ||||
int error = 0; | int error = 0; | ||||
char **searchdirs = NULL; | char **searchdirs = NULL; | ||||
int nsearch = 0; | int nsearch = 0; | ||||
char *target, *target_pool, dsname[ZFS_MAX_DATASET_NAME_LEN]; | char *target, *target_pool, dsname[ZFS_MAX_DATASET_NAME_LEN]; | ||||
nvlist_t *policy = NULL; | nvlist_t *policy = NULL; | ||||
uint64_t max_txg = UINT64_MAX; | uint64_t max_txg = UINT64_MAX; | ||||
int64_t objset_id = -1; | int64_t objset_id = -1; | ||||
uint64_t object; | |||||
int flags = ZFS_IMPORT_MISSING_LOG; | int flags = ZFS_IMPORT_MISSING_LOG; | ||||
int rewind = ZPOOL_NEVER_REWIND; | int rewind = ZPOOL_NEVER_REWIND; | ||||
char *spa_config_path_env, *objset_str; | char *spa_config_path_env, *objset_str; | ||||
boolean_t target_is_spa = B_TRUE, dataset_lookup = B_FALSE; | boolean_t target_is_spa = B_TRUE, dataset_lookup = B_FALSE; | ||||
nvlist_t *cfg = NULL; | nvlist_t *cfg = NULL; | ||||
(void) setrlimit(RLIMIT_NOFILE, &rl); | (void) setrlimit(RLIMIT_NOFILE, &rl); | ||||
(void) enable_extended_FILE_stdio(-1, -1); | (void) enable_extended_FILE_stdio(-1, -1); | ||||
Show All 12 Lines | main(int argc, char **argv) | ||||
/* | /* | ||||
* For performance reasons, we set this tunable down. We do so before | * For performance reasons, we set this tunable down. We do so before | ||||
* the arg parsing section so that the user can override this value if | * the arg parsing section so that the user can override this value if | ||||
* they choose. | * they choose. | ||||
*/ | */ | ||||
zfs_btree_verify_intensity = 3; | zfs_btree_verify_intensity = 3; | ||||
while ((c = getopt(argc, argv, | while ((c = getopt(argc, argv, | ||||
"AbcCdDeEFGhiI:klLmMo:Op:PqRsSt:uU:vVx:XYyZ")) != -1) { | "AbcCdDeEFGhiI:klLmMo:Op:PqrRsSt:uU:vVx:XYyZ")) != -1) { | ||||
switch (c) { | switch (c) { | ||||
case 'b': | case 'b': | ||||
case 'c': | case 'c': | ||||
case 'C': | case 'C': | ||||
case 'd': | case 'd': | ||||
case 'D': | case 'D': | ||||
case 'E': | case 'E': | ||||
case 'G': | case 'G': | ||||
case 'h': | case 'h': | ||||
case 'i': | case 'i': | ||||
case 'l': | case 'l': | ||||
case 'm': | case 'm': | ||||
case 'M': | case 'M': | ||||
case 'O': | case 'O': | ||||
case 'r': | |||||
case 'R': | case 'R': | ||||
case 's': | case 's': | ||||
case 'S': | case 'S': | ||||
case 'u': | case 'u': | ||||
case 'y': | case 'y': | ||||
case 'Z': | case 'Z': | ||||
dump_opt[c]++; | dump_opt[c]++; | ||||
dump_all = 0; | dump_all = 0; | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (!dump_opt['e'] && searchdirs != NULL) { | if (!dump_opt['e'] && searchdirs != NULL) { | ||||
(void) fprintf(stderr, "-p option requires use of -e\n"); | (void) fprintf(stderr, "-p option requires use of -e\n"); | ||||
usage(); | usage(); | ||||
} | } | ||||
if (dump_opt['d']) { | if (dump_opt['d'] || dump_opt['r']) { | ||||
/* <pool>[/<dataset | objset id> is accepted */ | /* <pool>[/<dataset | objset id> is accepted */ | ||||
if (argv[2] && (objset_str = strchr(argv[2], '/')) != NULL && | if (argv[2] && (objset_str = strchr(argv[2], '/')) != NULL && | ||||
objset_str++ != NULL) { | objset_str++ != NULL) { | ||||
char *endptr; | char *endptr; | ||||
errno = 0; | errno = 0; | ||||
objset_id = strtoull(objset_str, &endptr, 0); | objset_id = strtoull(objset_str, &endptr, 0); | ||||
/* dataset 0 is the same as opening the pool */ | /* dataset 0 is the same as opening the pool */ | ||||
if (errno == 0 && endptr != objset_str && | if (errno == 0 && endptr != objset_str && | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | #endif | ||||
spa_load_verify_dryrun = B_TRUE; | spa_load_verify_dryrun = B_TRUE; | ||||
kernel_init(SPA_MODE_READ); | kernel_init(SPA_MODE_READ); | ||||
if (dump_all) | if (dump_all) | ||||
verbose = MAX(verbose, 1); | verbose = MAX(verbose, 1); | ||||
for (c = 0; c < 256; c++) { | for (c = 0; c < 256; c++) { | ||||
if (dump_all && strchr("AeEFklLOPRSXy", c) == NULL) | if (dump_all && strchr("AeEFklLOPrRSXy", c) == NULL) | ||||
dump_opt[c] = 1; | dump_opt[c] = 1; | ||||
if (dump_opt[c]) | if (dump_opt[c]) | ||||
dump_opt[c] += verbose; | dump_opt[c] += verbose; | ||||
} | } | ||||
aok = (dump_opt['A'] == 1) || (dump_opt['A'] > 2); | aok = (dump_opt['A'] == 1) || (dump_opt['A'] > 2); | ||||
zfs_recover = (dump_opt['A'] > 1); | zfs_recover = (dump_opt['A'] > 1); | ||||
Show All 19 Lines | #endif | ||||
if (dump_opt['l']) | if (dump_opt['l']) | ||||
return (dump_label(argv[0])); | return (dump_label(argv[0])); | ||||
if (dump_opt['O']) { | if (dump_opt['O']) { | ||||
if (argc != 2) | if (argc != 2) | ||||
usage(); | usage(); | ||||
dump_opt['v'] = verbose + 3; | dump_opt['v'] = verbose + 3; | ||||
return (dump_path(argv[0], argv[1])); | return (dump_path(argv[0], argv[1], NULL)); | ||||
} | } | ||||
if (dump_opt['r']) { | |||||
if (argc != 3) | |||||
usage(); | |||||
dump_opt['v'] = verbose; | |||||
error = dump_path(argv[0], argv[1], &object); | |||||
} | |||||
if (dump_opt['X'] || dump_opt['F']) | if (dump_opt['X'] || dump_opt['F']) | ||||
rewind = ZPOOL_DO_REWIND | | rewind = ZPOOL_DO_REWIND | | ||||
(dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0); | (dump_opt['X'] ? ZPOOL_EXTREME_REWIND : 0); | ||||
if (nvlist_alloc(&policy, NV_UNIQUE_NAME_TYPE, 0) != 0 || | if (nvlist_alloc(&policy, NV_UNIQUE_NAME_TYPE, 0) != 0 || | ||||
nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, max_txg) != 0 || | nvlist_add_uint64(policy, ZPOOL_LOAD_REQUEST_TXG, max_txg) != 0 || | ||||
nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, rewind) != 0) | nvlist_add_uint32(policy, ZPOOL_LOAD_REWIND_POLICY, rewind) != 0) | ||||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | #endif | ||||
* from suspending. A suspended I/O will have no way to resume and | * from suspending. A suspended I/O will have no way to resume and | ||||
* can prevent the zdb(8) command from terminating as expected. | * can prevent the zdb(8) command from terminating as expected. | ||||
*/ | */ | ||||
if (spa != NULL) | if (spa != NULL) | ||||
spa->spa_failmode = ZIO_FAILURE_MODE_PANIC; | spa->spa_failmode = ZIO_FAILURE_MODE_PANIC; | ||||
argv++; | argv++; | ||||
argc--; | argc--; | ||||
if (!dump_opt['R']) { | if (dump_opt['r']) { | ||||
error = zdb_copy_object(os, object, argv[1]); | |||||
} else if (!dump_opt['R']) { | |||||
flagbits['d'] = ZOR_FLAG_DIRECTORY; | flagbits['d'] = ZOR_FLAG_DIRECTORY; | ||||
flagbits['f'] = ZOR_FLAG_PLAIN_FILE; | flagbits['f'] = ZOR_FLAG_PLAIN_FILE; | ||||
flagbits['m'] = ZOR_FLAG_SPACE_MAP; | flagbits['m'] = ZOR_FLAG_SPACE_MAP; | ||||
flagbits['z'] = ZOR_FLAG_ZAP; | flagbits['z'] = ZOR_FLAG_ZAP; | ||||
flagbits['A'] = ZOR_FLAG_ALL_TYPES; | flagbits['A'] = ZOR_FLAG_ALL_TYPES; | ||||
if (argc > 0 && dump_opt['d']) { | if (argc > 0 && dump_opt['d']) { | ||||
zopt_object_args = argc; | zopt_object_args = argc; | ||||
▲ Show 20 Lines • Show All 65 Lines • Show Last 20 Lines |