Add display of checksums to zdb -R
The function zdb_read_block (zdb -R) was always intended to have a :c flag which would read the DVA and length supplied by the user, and display the checksum. Since we don't know which checksum goes with the data, we should calculate and display them all. For each checksum in the table, read in the data at the supplied DVA:length, calculate the checksum, and display it. Update the man page and create a zfs test for the new feature. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Kjeld Schouten <kjeld@schouten-lebbing.nl> Signed-off-by: Paul Zuchowski <pzuchowski@datto.com> Closes #9607
This commit is contained in:
parent
bc21c56c2d
commit
c9ac5ec178
|
@ -26,6 +26,7 @@
|
||||||
* 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) 2019 Datto Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -5591,7 +5592,7 @@ name:
|
||||||
* size - Amount of data to read, in hex, in bytes
|
* size - Amount of data to read, in hex, in bytes
|
||||||
* flags - A string of characters specifying options
|
* flags - A string of characters specifying options
|
||||||
* b: Decode a blkptr at given offset within block
|
* b: Decode a blkptr at given offset within block
|
||||||
* *c: Calculate and display checksums
|
* c: Calculate and display checksums
|
||||||
* d: Decompress data before dumping
|
* d: Decompress data before dumping
|
||||||
* e: Byteswap data before dumping
|
* e: Byteswap data before dumping
|
||||||
* g: Display data as a gang block header
|
* g: Display data as a gang block header
|
||||||
|
@ -5599,7 +5600,6 @@ name:
|
||||||
* p: Do I/O to physical offset
|
* p: Do I/O to physical offset
|
||||||
* r: Dump raw data to stdout
|
* r: Dump raw data to stdout
|
||||||
*
|
*
|
||||||
* * = not yet implemented
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
zdb_read_block(char *thing, spa_t *spa)
|
zdb_read_block(char *thing, spa_t *spa)
|
||||||
|
@ -5817,6 +5817,62 @@ zdb_read_block(char *thing, spa_t *spa)
|
||||||
else
|
else
|
||||||
zdb_dump_block(thing, buf, size, flags);
|
zdb_dump_block(thing, buf, size, flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If :c was specified, iterate through the checksum table to
|
||||||
|
* calculate and display each checksum for our specified
|
||||||
|
* DVA and length.
|
||||||
|
*/
|
||||||
|
if ((flags & ZDB_FLAG_CHECKSUM) && !(flags & ZDB_FLAG_RAW) &&
|
||||||
|
!(flags & ZDB_FLAG_GBH)) {
|
||||||
|
zio_t *czio, *cio;
|
||||||
|
(void) printf("\n");
|
||||||
|
for (enum zio_checksum ck = ZIO_CHECKSUM_LABEL;
|
||||||
|
ck < ZIO_CHECKSUM_FUNCTIONS; ck++) {
|
||||||
|
|
||||||
|
if ((zio_checksum_table[ck].ci_flags &
|
||||||
|
ZCHECKSUM_FLAG_EMBEDDED) ||
|
||||||
|
ck == ZIO_CHECKSUM_NOPARITY) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
BP_SET_CHECKSUM(bp, ck);
|
||||||
|
spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
|
||||||
|
czio = zio_root(spa, NULL, NULL, ZIO_FLAG_CANFAIL);
|
||||||
|
czio->io_bp = bp;
|
||||||
|
|
||||||
|
if (vd == vd->vdev_top) {
|
||||||
|
cio = zio_read(czio, spa, bp, pabd, psize,
|
||||||
|
NULL, NULL,
|
||||||
|
ZIO_PRIORITY_SYNC_READ,
|
||||||
|
ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW |
|
||||||
|
ZIO_FLAG_DONT_RETRY, NULL);
|
||||||
|
zio_nowait(cio);
|
||||||
|
} else {
|
||||||
|
zio_nowait(zio_vdev_child_io(czio, bp, vd,
|
||||||
|
offset, pabd, psize, ZIO_TYPE_READ,
|
||||||
|
ZIO_PRIORITY_SYNC_READ,
|
||||||
|
ZIO_FLAG_DONT_CACHE |
|
||||||
|
ZIO_FLAG_DONT_PROPAGATE |
|
||||||
|
ZIO_FLAG_DONT_RETRY |
|
||||||
|
ZIO_FLAG_CANFAIL | ZIO_FLAG_RAW |
|
||||||
|
ZIO_FLAG_SPECULATIVE |
|
||||||
|
ZIO_FLAG_OPTIONAL, NULL, NULL));
|
||||||
|
}
|
||||||
|
error = zio_wait(czio);
|
||||||
|
if (error == 0 || error == ECKSUM) {
|
||||||
|
zio_checksum_compute(czio, ck, pabd, lsize);
|
||||||
|
printf("%12s\tcksum=%llx:%llx:%llx:%llx\n",
|
||||||
|
zio_checksum_table[ck].ci_name,
|
||||||
|
(u_longlong_t)bp->blk_cksum.zc_word[0],
|
||||||
|
(u_longlong_t)bp->blk_cksum.zc_word[1],
|
||||||
|
(u_longlong_t)bp->blk_cksum.zc_word[2],
|
||||||
|
(u_longlong_t)bp->blk_cksum.zc_word[3]);
|
||||||
|
} else {
|
||||||
|
printf("error %d reading block\n", error);
|
||||||
|
}
|
||||||
|
spa_config_exit(spa, SCL_STATE, FTAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (borrowed)
|
if (borrowed)
|
||||||
abd_return_buf_copy(pabd, buf, size);
|
abd_return_buf_copy(pabd, buf, size);
|
||||||
|
|
||||||
|
|
|
@ -248,6 +248,8 @@ and, optionally,
|
||||||
.Bl -tag -compact -width "b offset"
|
.Bl -tag -compact -width "b offset"
|
||||||
.It Sy b Ar offset
|
.It Sy b Ar offset
|
||||||
Print block pointer
|
Print block pointer
|
||||||
|
.It Sy c
|
||||||
|
Calculate and display checksums
|
||||||
.It Sy d
|
.It Sy d
|
||||||
Decompress the block. Set environment variable
|
Decompress the block. Set environment variable
|
||||||
.Nm ZDB_NO_ZLE
|
.Nm ZDB_NO_ZLE
|
||||||
|
|
|
@ -106,7 +106,7 @@ tags = ['functional', 'clean_mirror']
|
||||||
|
|
||||||
[tests/functional/cli_root/zdb]
|
[tests/functional/cli_root/zdb]
|
||||||
tests = ['zdb_001_neg', 'zdb_002_pos', 'zdb_003_pos', 'zdb_004_pos',
|
tests = ['zdb_001_neg', 'zdb_002_pos', 'zdb_003_pos', 'zdb_004_pos',
|
||||||
'zdb_005_pos', 'zdb_006_pos']
|
'zdb_005_pos', 'zdb_006_pos', 'zdb_checksum']
|
||||||
pre =
|
pre =
|
||||||
post =
|
post =
|
||||||
tags = ['functional', 'cli_root', 'zdb']
|
tags = ['functional', 'cli_root', 'zdb']
|
||||||
|
|
|
@ -5,4 +5,5 @@ dist_pkgdata_SCRIPTS = \
|
||||||
zdb_003_pos.ksh \
|
zdb_003_pos.ksh \
|
||||||
zdb_004_pos.ksh \
|
zdb_004_pos.ksh \
|
||||||
zdb_005_pos.ksh \
|
zdb_005_pos.ksh \
|
||||||
zdb_006_pos.ksh
|
zdb_006_pos.ksh \
|
||||||
|
zdb_checksum.ksh
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/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) 2019 by Datto, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
. $STF_SUITE/include/libtest.shlib
|
||||||
|
|
||||||
|
#
|
||||||
|
# Description:
|
||||||
|
# zdb -c will display the same checksum as -ddddddbbbbbb
|
||||||
|
#
|
||||||
|
# Strategy:
|
||||||
|
# 1. Create a pool
|
||||||
|
# 2. Write some data to a file
|
||||||
|
# 3. Run zdb -ddddddbbbbbb against the file
|
||||||
|
# 4. Record the checksum and DVA of L0 block 0
|
||||||
|
# 5. Run zdb -R with :c flag and match the checksum
|
||||||
|
|
||||||
|
|
||||||
|
function cleanup
|
||||||
|
{
|
||||||
|
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
|
||||||
|
}
|
||||||
|
|
||||||
|
log_assert "Verify zdb -R generates the correct checksum."
|
||||||
|
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 -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \
|
||||||
|
|grep -m 1 "L0 DVA" |head -n1)
|
||||||
|
dva=$(grep -oP 'DVA\[0\]=<\K.*?(?=>)' <<< "$output")
|
||||||
|
log_note "block 0 of $init_data has a DVA of $dva"
|
||||||
|
cksum_expected=$(grep -oP '(?<=cksum=)[ A-Za-z0-9:]*' <<< "$output")
|
||||||
|
log_note "expecting cksum $cksum_expected"
|
||||||
|
output=$(zdb -R $TESTPOOL $dva:c 2> /dev/null)
|
||||||
|
result=$(grep $cksum_expected <<< "$output")
|
||||||
|
(( $? != 0 )) && log_fail "zdb -R failed to print the correct checksum"
|
||||||
|
|
||||||
|
log_pass "zdb -R generates the correct checksum"
|
Loading…
Reference in New Issue