zdb -d should accept the numeric objset id

As an alternative to the dataset name, zdb now allows the decimal 
or hexadecimal objset ID to be specified.  When permanent errors
are reported as 2 hexadecimal numbers (objset ID : object ID) in 
zpool status; you can now use 'zdb <pool>[/objset ID] object' to
determine the names of the objset and object which have the error.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Ryan Moeller <ryan@ixsystems.com>
Signed-off-by: Paul Zuchowski <pzuchowski@datto.com>
Closes #9733
This commit is contained in:
Paul Zuchowski 2020-01-16 12:22:49 -05:00 committed by Brian Behlendorf
parent 1b64627e73
commit f12e42cccf
5 changed files with 173 additions and 14 deletions

View File

@ -26,7 +26,7 @@
* Copyright 2016 Nexenta Systems, Inc.
* Copyright (c) 2017, 2018 Lawrence Livermore National Security, LLC.
* Copyright (c) 2015, 2017, Intel Corporation.
* Copyright (c) 2019 Datto Inc.
* Copyright (c) 2020 Datto Inc.
*/
#include <stdio.h>
@ -144,9 +144,9 @@ usage(void)
"Usage:\t%s [-AbcdDFGhikLMPsvX] [-e [-V] [-p <path> ...]] "
"[-I <inflight I/Os>]\n"
"\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
"\t\t[<poolname> [<object> ...]]\n"
"\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>] <dataset>\n"
"\t\t[<object> ...]\n"
"\t\t[<poolname>[/<dataset | objset id>] [<object> ...]]\n"
"\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
"\t\t[<poolname>[/<dataset | objset id>] [<object> ...]\n"
"\t%s [-v] <bookmark>\n"
"\t%s -C [-A] [-U <cache>]\n"
"\t%s -l [-Aqu] <device>\n"
@ -6335,6 +6335,26 @@ name:
return (NULL);
}
static int
name_from_objset_id(spa_t *spa, uint64_t objset_id, char *outstr)
{
dsl_dataset_t *ds;
dsl_pool_config_enter(spa->spa_dsl_pool, FTAG);
int error = dsl_dataset_hold_obj(spa->spa_dsl_pool, objset_id,
NULL, &ds);
if (error != 0) {
(void) fprintf(stderr, "failed to hold objset %llu: %s\n",
(u_longlong_t)objset_id, strerror(error));
dsl_pool_config_exit(spa->spa_dsl_pool, FTAG);
return (error);
}
dsl_dataset_name(ds, outstr);
dsl_dataset_rele(ds, NULL);
dsl_pool_config_exit(spa->spa_dsl_pool, FTAG);
return (0);
}
static boolean_t
zdb_parse_block_sizes(char *sizes, uint64_t *lsize, uint64_t *psize)
{
@ -6713,13 +6733,14 @@ main(int argc, char **argv)
int error = 0;
char **searchdirs = NULL;
int nsearch = 0;
char *target, *target_pool;
char *target, *target_pool, dsname[ZFS_MAX_DATASET_NAME_LEN];
nvlist_t *policy = NULL;
uint64_t max_txg = UINT64_MAX;
int64_t objset_id = -1;
int flags = ZFS_IMPORT_MISSING_LOG;
int rewind = ZPOOL_NEVER_REWIND;
char *spa_config_path_env;
boolean_t target_is_spa = B_TRUE;
char *spa_config_path_env, *objset_str;
boolean_t target_is_spa = B_TRUE, dataset_lookup = B_FALSE;
nvlist_t *cfg = NULL;
(void) setrlimit(RLIMIT_NOFILE, &rl);
@ -6846,6 +6867,31 @@ main(int argc, char **argv)
(void) fprintf(stderr, "-p option requires use of -e\n");
usage();
}
if (dump_opt['d']) {
/* <pool>[/<dataset | objset id> is accepted */
if (argv[2] && (objset_str = strchr(argv[2], '/')) != NULL &&
objset_str++ != NULL) {
char *endptr;
errno = 0;
objset_id = strtoull(objset_str, &endptr, 0);
/* dataset 0 is the same as opening the pool */
if (errno == 0 && endptr != objset_str &&
objset_id != 0) {
target_is_spa = B_FALSE;
dataset_lookup = B_TRUE;
} else if (objset_id != 0) {
printf("failed to open objset %s "
"%llu %s", objset_str,
(u_longlong_t)objset_id,
strerror(errno));
exit(1);
}
/* normal dataset name not an objset ID */
if (endptr == objset_str) {
objset_id = -1;
}
}
}
#if defined(_LP64)
/*
@ -6890,7 +6936,6 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
if (argc < 2 && dump_opt['R'])
usage();
@ -7010,7 +7055,7 @@ main(int argc, char **argv)
checkpoint_pool, error);
}
} else if (target_is_spa || dump_opt['R']) {
} else if (target_is_spa || dump_opt['R'] || objset_id == 0) {
zdb_set_skip_mmp(target);
error = spa_open_rewind(target, &spa, FTAG, policy,
NULL);
@ -7049,7 +7094,22 @@ main(int argc, char **argv)
return (error);
} else {
zdb_set_skip_mmp(target);
error = open_objset(target, FTAG, &os);
if (dataset_lookup == B_TRUE) {
/*
* Use the supplied id to get the name
* for open_objset.
*/
error = spa_open(target, &spa, FTAG);
if (error == 0) {
error = name_from_objset_id(spa,
objset_id, dsname);
spa_close(spa, FTAG);
if (error == 0)
target = dsname;
}
}
if (error == 0)
error = open_objset(target, FTAG, &os);
if (error == 0)
spa = dmu_objset_spa(os);
}

View File

@ -30,12 +30,13 @@
.Op Fl t Ar txg
.Op Fl U Ar cache
.Op Fl x Ar dumpdir
.Op Ar poolname Op Ar object ...
.Op Ar poolname[/dataset | objset ID]
.Op Ar object ...
.Nm
.Op Fl AdiPv
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
.Op Fl U Ar cache
.Ar dataset Op Ar object ...
.Ar poolname[/dataset | objset ID] Op Ar object ...
.Nm
.Fl C
.Op Fl A

View File

@ -100,7 +100,8 @@ tags = ['functional', 'clean_mirror']
[tests/functional/cli_root/zdb]
tests = ['zdb_001_neg', 'zdb_002_pos', 'zdb_003_pos', 'zdb_004_pos',
'zdb_005_pos', 'zdb_006_pos', 'zdb_checksum', 'zdb_decompress']
'zdb_005_pos', 'zdb_006_pos', 'zdb_checksum', 'zdb_decompress',
'zdb_objset_id']
pre =
post =
tags = ['functional', 'cli_root', 'zdb']

View File

@ -7,4 +7,5 @@ dist_pkgdata_SCRIPTS = \
zdb_005_pos.ksh \
zdb_006_pos.ksh \
zdb_checksum.ksh \
zdb_decompress.ksh
zdb_decompress.ksh \
zdb_objset_id.ksh

View File

@ -0,0 +1,96 @@
#!/bin/ksh
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright (c) 2020 by Datto, Inc. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
#
# Description:
# zdb -d pool/<objset id> will display the dataset
#
# Strategy:
# 1. Create a pool
# 2. Write some data to a file
# 3. Get the inode number (object number) of the file
# 4. Run zdb -d to get the objset ID of the dataset
# 5. Run zdb -dddddd pool/objsetID objectID (decimal)
# 6. Confirm names
# 7. Run zdb -dddddd pool/objsetID objectID (hex)
# 8. Confirm names
# 9. Obtain objsetID from /proc/spl/kstat/zfs/testpool/obset-0x<ID>
# (linux only)
# 10. Run zdb -dddddd pool/objsetID (hex)
# 11. Match name from zdb against proc entry
#
function cleanup
{
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
}
log_assert "Verify zdb -d <pool>/<objset ID> generates the correct names."
log_onexit cleanup
init_data=$TESTDIR/file1
write_count=8
blksize=131072
verify_runnable "global"
verify_disk_count "$DISKS" 2
default_mirror_setup_noexit $DISKS
file_write -o create -w -f $init_data -b $blksize -c $write_count
# get object number of file
listing=$(ls -i $init_data)
set -A array $listing
obj=${array[0]}
log_note "file $init_data has object number $obj"
output=$(zdb -d $TESTPOOL/$TESTFS)
objset_id=$(echo $output | awk '{split($0,array,",")} END{print array[2]}' |
awk '{split($0,array," ")} END{print array[2]}')
objset_hex=$(printf "0x%X" $objset_id)
log_note "objset $TESTPOOL/$TESTFS has objset ID $objset_id ($objset_hex)"
for id in "$objset_id" "$objset_hex"
do
log_note "zdb -dddddd $TESTPOOL/$id $obj"
output=$(zdb -dddddd $TESTPOOL/$id $obj)
reason="($TESTPOOL/$TESTFS not in zdb output)"
echo $output |grep "$TESTPOOL/$TESTFS" > /dev/null
(( $? != 0 )) && log_fail \
"zdb -dddddd $TESTPOOL/$id $obj failed $reason"
reason="(file1 not in zdb output)"
echo $output |grep "file1" > /dev/null
(( $? != 0 )) && log_fail \
"zdb -dddddd $TESTPOOL/$id $obj failed $reason"
obj=$(printf "0x%X" $obj)
done
if is_linux; then
output=$(ls -1 /proc/spl/kstat/zfs/$TESTPOOL |grep objset- |tail -1)
objset_hex=${output#*-}
name_from_proc=$(cat /proc/spl/kstat/zfs/$TESTPOOL/$output |
grep dataset_name | awk '{split($0,array," ")} END{print array[3]}')
log_note "checking zdb output for $name_from_proc"
reason="(name $name_from_proc from proc not in zdb output)"
log_note "zdb -dddddd $TESTPOOL/$objset_hex"
output=$(zdb -dddddd $TESTPOOL/$objset_hex)
echo $output |grep "$name_from_proc" > /dev/null
(( $? != 0 )) && log_fail \
"zdb -dddddd $TESTPOOL/$objset_hex failed $reason"
fi
log_pass "zdb -d <pool>/<objset ID> generates the correct names."