aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/zdb/zdb.c60
-rw-r--r--man/man8/zdb.82
-rw-r--r--tests/runfiles/common.run2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am3
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh64
5 files changed, 127 insertions, 4 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index 81c9eaf8c..2d35bd0f9 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -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>
@@ -6340,7 +6341,7 @@ name:
* 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
@@ -6348,7 +6349,6 @@ name:
* 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)
@@ -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);
diff --git a/man/man8/zdb.8 b/man/man8/zdb.8
index 50f600252..55689a994 100644
--- a/man/man8/zdb.8
+++ b/man/man8/zdb.8
@@ -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
diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run
index d6d3874f6..943bb6b71 100644
--- a/tests/runfiles/common.run
+++ b/tests/runfiles/common.run
@@ -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']
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am
index d37bcf607..0c4de2b25 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am
@@ -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
diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh
new file mode 100755
index 000000000..9bc3603d4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zdb/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"