Skip to content

Commit

Permalink
Add display of checksums to zdb -R
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Kjeld Schouten <[email protected]>
Signed-off-by: Paul Zuchowski <[email protected]>
Closes #9607
  • Loading branch information
PaulZ-98 authored and behlendorf committed Nov 27, 2019
1 parent 0c46813 commit 894f669
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 4 deletions.
60 changes: 58 additions & 2 deletions cmd/zdb/zdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +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.
*/

#include <stdio.h>
Expand Down Expand Up @@ -6340,15 +6341,14 @@ zdb_vdev_lookup(vdev_t *vdev, const char *path)
* size - Amount of data to read, in hex, in bytes
* flags - A string of characters specifying options
* b: Decode a blkptr at given offset within block
* *c: Calculate and display checksums
* c: Calculate and display checksums
* d: Decompress data before dumping
* e: Byteswap data before dumping
* g: Display data as a gang block header
* i: Display as an indirect block
* p: Do I/O to physical offset
* r: Dump raw data to stdout
*
* * = not yet implemented
*/
static void
zdb_read_block(char *thing, spa_t *spa)
Expand Down Expand Up @@ -6566,6 +6566,62 @@ zdb_read_block(char *thing, spa_t *spa)
else
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)
abd_return_buf_copy(pabd, buf, size);

Expand Down
2 changes: 2 additions & 0 deletions man/man8/zdb.8
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ and, optionally,
.Bl -tag -compact -width "b offset"
.It Sy b Ar offset
Print block pointer
.It Sy c
Calculate and display checksums
.It Sy d
Decompress the block. Set environment variable
.Nm ZDB_NO_ZLE
Expand Down
2 changes: 1 addition & 1 deletion tests/runfiles/common.run
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ 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_005_pos', 'zdb_006_pos', 'zdb_checksum']
pre =
post =
tags = ['functional', 'cli_root', 'zdb']
Expand Down
3 changes: 2 additions & 1 deletion tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ dist_pkgdata_SCRIPTS = \
zdb_003_pos.ksh \
zdb_004_pos.ksh \
zdb_005_pos.ksh \
zdb_006_pos.ksh
zdb_006_pos.ksh \
zdb_checksum.ksh
64 changes: 64 additions & 0 deletions tests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit 894f669

Please sign in to comment.