Add some more file layout output, triggered by -v
With one -v, the block type (parity or data) is printed (matching the ASCII-art version); with two -v, the offset into the file is also printed. This also updates the man page, and adds some simple test scripts. Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Sean Fagan <sean.fagan@klarasystems.com> Signed-off-by: Sean Fagan <sean.fagan@klarasystems.com> Closes #18470
This commit is contained in:
+42
-10
@@ -2802,18 +2802,18 @@ print_file_layout_raidz(vdev_t *vd, blkptr_t *bp, uint64_t file_offset,
|
||||
vd->vdev_children, vdrz->vd_nparity);
|
||||
raidz_row_t *rr = rm->rm_row[0];
|
||||
|
||||
if (!dump_opt['H']) {
|
||||
int last_disk = vd->vdev_children - 1;
|
||||
/*
|
||||
* Account for out of order disks in raidz1.
|
||||
* For now just reverse them back and adjust for it later.
|
||||
*/
|
||||
if (rr->rr_firstdatacol == 1 && (zio.io_offset & (1ULL << 20))) {
|
||||
if (rr->rr_firstdatacol == 1 &&
|
||||
(zio.io_offset & (1ULL << 20))) {
|
||||
uint64_t devidx = rr->rr_col[0].rc_devidx;
|
||||
rr->rr_col[0].rc_devidx = rr->rr_col[1].rc_devidx;
|
||||
rr->rr_col[1].rc_devidx = devidx;
|
||||
}
|
||||
|
||||
if (!dump_opt['H']) {
|
||||
int last_disk = vd->vdev_children - 1;
|
||||
int first_disk = rr->rr_col[0].rc_devidx;
|
||||
|
||||
(void) printf("%12llx", (u_longlong_t)file_offset);
|
||||
@@ -2843,23 +2843,49 @@ print_file_layout_raidz(vdev_t *vd, blkptr_t *bp, uint64_t file_offset,
|
||||
static uint64_t next_offset = 0;
|
||||
|
||||
if (next_offset != file_offset) {
|
||||
(void) printf("skip hole\t-\t%llx\n",
|
||||
(u_longlong_t)((file_offset - next_offset) >>
|
||||
vd->vdev_ashift));
|
||||
(void) printf("skip hole\t-\t\t%lld\n",
|
||||
(u_longlong_t)((file_offset - next_offset) / 512));
|
||||
}
|
||||
next_offset = file_offset + BP_GET_LSIZE(bp);
|
||||
uint64_t tmp_offset = file_offset;
|
||||
|
||||
|
||||
for (int c = 0; c < rr->rr_cols; c++) {
|
||||
boolean_t pcol = c < rr->rr_firstdatacol;
|
||||
raidz_col_t *rc = &rr->rr_col[c];
|
||||
char *path = vd->vdev_child[rc->rc_devidx]->vdev_path;
|
||||
// c < rr->rr_firstdatacol
|
||||
|
||||
if (rc->rc_size == 0)
|
||||
continue;
|
||||
(void) printf("%s\t%llu\t%d\n",
|
||||
(void) printf("%s\t\t%llu\t%d",
|
||||
zfs_basename(path),
|
||||
(u_longlong_t)(rc->rc_offset +
|
||||
VDEV_LABEL_START_SIZE)/512,
|
||||
(int)rc->rc_size/512);
|
||||
if (dump_opt['v']) {
|
||||
char label = pcol ? 'P' : 'D';
|
||||
int num;
|
||||
|
||||
if (c < 2) {
|
||||
num = 0;
|
||||
} else {
|
||||
num = pcol ? c :
|
||||
(c - rr->rr_firstdatacol);
|
||||
}
|
||||
printf("\t%c%d", label, num);
|
||||
if (dump_opt['v'] > 1) {
|
||||
unsigned long long off;
|
||||
if (pcol)
|
||||
off = file_offset;
|
||||
else
|
||||
off = tmp_offset;
|
||||
off = off / 512ULL;
|
||||
printf("\t%llu", off);
|
||||
}
|
||||
}
|
||||
if (!pcol)
|
||||
tmp_offset += rc->rc_size;
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2989,7 +3015,12 @@ dump_indirect_layout(dnode_t *dn)
|
||||
* Start layout with a header
|
||||
*/
|
||||
if (dump_opt['H']) {
|
||||
(void) printf("DISK\t\tLBA\t\tCOUNT\n");
|
||||
(void) printf("DISK\t\t\tLBA\tCOUNT");
|
||||
if (dump_opt['v'])
|
||||
(void) printf("\tTYPE");
|
||||
if (dump_opt['v'] > 1)
|
||||
(void) printf("\tOFFSET");
|
||||
printf("\n");
|
||||
} else {
|
||||
char diskhdr[16];
|
||||
|
||||
@@ -10519,6 +10550,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (dump_opt['f'] && os != NULL) {
|
||||
dump_opt['v'] = verbose;
|
||||
dump_file_data_layout(os);
|
||||
} else if (dump_opt['B']) {
|
||||
dump_backup(target, objset_id,
|
||||
|
||||
+6
-1
@@ -284,10 +284,15 @@ Decode and display block from an embedded block pointer specified by the
|
||||
arguments.
|
||||
.It Fl f , -file-layout
|
||||
Display the file layout of an object for the disks of a raidz vdev.
|
||||
Numeric values in the disply are hexadecimal.
|
||||
With
|
||||
.Fl H ,
|
||||
the output is in scripted mode for easy parsing, with all values
|
||||
being presented as 512 byte blocks.
|
||||
being presented as 512 byte blocks in decimal; with
|
||||
.Fl v ,
|
||||
the block type (parity or data) is displayed; with
|
||||
.Fl vv ,
|
||||
the offset into the file for each block is also printed.
|
||||
Only a single top-level raidz vdev is supported.
|
||||
.It Fl h , -history
|
||||
Display pool history similar to
|
||||
|
||||
@@ -173,9 +173,10 @@ tests = ['zdb_002_pos', 'zdb_003_pos', 'zdb_004_pos', 'zdb_005_pos',
|
||||
'zdb_006_pos', 'zdb_args_neg', 'zdb_args_pos',
|
||||
'zdb_block_size_histogram', 'zdb_checksum', 'zdb_decompress',
|
||||
'zdb_display_block', 'zdb_encrypted', 'zdb_encrypted_raw',
|
||||
'zdb_label_checksum', 'zdb_object_range_neg', 'zdb_object_range_pos',
|
||||
'zdb_objset_id', 'zdb_decompress_zstd', 'zdb_recover', 'zdb_recover_2',
|
||||
'zdb_backup', 'zdb_tunables']
|
||||
'zdb_file_layout_001', 'zdb_file_layout_002', 'zdb_file_layout_003',
|
||||
'zdb_file_layout_neg', 'zdb_label_checksum', 'zdb_object_range_neg',
|
||||
'zdb_object_range_pos', 'zdb_objset_id', 'zdb_decompress_zstd',
|
||||
'zdb_recover', 'zdb_recover_2', 'zdb_backup', 'zdb_tunables']
|
||||
pre =
|
||||
post =
|
||||
tags = ['functional', 'cli_root', 'zdb']
|
||||
|
||||
@@ -650,6 +650,10 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/cli_root/zdb/zdb_encrypted.ksh \
|
||||
functional/cli_root/zdb/zdb_encrypted_raw.ksh \
|
||||
functional/cli_root/zdb/zdb_label_checksum.ksh \
|
||||
functional/cli_root/zdb/zdb_file_layout_001.ksh \
|
||||
functional/cli_root/zdb/zdb_file_layout_002.ksh \
|
||||
functional/cli_root/zdb/zdb_file_layout_003.ksh \
|
||||
functional/cli_root/zdb/zdb_file_layout_neg.ksh \
|
||||
functional/cli_root/zdb/zdb_object_range_neg.ksh \
|
||||
functional/cli_root/zdb/zdb_object_range_pos.ksh \
|
||||
functional/cli_root/zdb/zdb_objset_id.ksh \
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/ksh
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
|
||||
#
|
||||
# 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.
|
||||
# Copyright (c) 2026, Klara Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# Description:
|
||||
# zdb -fHv <dataset> <objnum> will display block
|
||||
# layouts for the object.
|
||||
#
|
||||
# Strategery:
|
||||
# 1. Create a RAIDZ1 pool, set compression to none
|
||||
# 2. Create a file filled with random data
|
||||
# 3. Get the inode number of the file
|
||||
# 4. Run zdb -fHv <pool>/ <inum> & extract file
|
||||
# 5. Compare real file and extracted file.
|
||||
|
||||
DATA=/$TESTPOOL1/random.bin
|
||||
BLOCKS=$(( $RANDOM % 16 ))
|
||||
COMPARE=/tmp/compare.$$
|
||||
|
||||
function cleanup
|
||||
{
|
||||
destroy_pool $TESTPOOL1
|
||||
rm -f $TESTDIR/file?.bin $COMPARE
|
||||
}
|
||||
|
||||
log_assert "Verify zdb -fHv displays correct offsets"
|
||||
log_onexit cleanup
|
||||
|
||||
# 1. Create a RAIDZ1 pool
|
||||
log_must mkdir -p $TESTDIR
|
||||
for file in 1 2 3 4 5
|
||||
do
|
||||
rm -f $TESTDIR/file${file}.bin
|
||||
touch $TESTDIR/file${file}.bin
|
||||
log_must truncate -s 128m $TESTDIR/file${file}.bin
|
||||
done
|
||||
|
||||
log_must zpool create -O compression=off -O recordsize=16K $TESTPOOL1 raidz1 $TESTDIR/file[12345].bin
|
||||
zfs get compression,recordsize $TESTPOOL1
|
||||
# 2. Create a file with random data
|
||||
log_must rm -f $DATA
|
||||
log_must dd if=/dev/urandom of=${DATA} bs=16k count=${BLOCKS} > /dev/null 2>&1
|
||||
log_must zpool sync $TESTPOOL1
|
||||
|
||||
# 3. Get the inode number of the file
|
||||
INUM=$(ls -li $DATA | cut -f1 -d ' ')
|
||||
|
||||
# 4. Extract the contents of the file using dd
|
||||
rm -f $COMPARE
|
||||
log_must touch ${COMPARE}
|
||||
log_must zdb -fHv $TESTPOOL1/ ${INUM} | grep 'D.$' |
|
||||
while read file offset count rest
|
||||
do
|
||||
log_must sh -c "dd if=$TESTDIR/${file} bs=512 skip=${offset} count=${count} >> ${COMPARE}"
|
||||
done
|
||||
|
||||
# 5. Compare files
|
||||
log_must cmp ${COMPARE} ${DATA}
|
||||
|
||||
log_pass "'zdb -fHv' works as expected."
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/ksh
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
|
||||
#
|
||||
# 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.
|
||||
# Copyright (c) 2026, Klara Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# Description:
|
||||
# zdb -fHv <dataset> <objnum> will display block
|
||||
# layouts for the object.
|
||||
#
|
||||
# Strategery:
|
||||
# 1. Create a RAIDZ2 pool, set compression to none
|
||||
# 2. Create a file filled with random data
|
||||
# 3. Get the inode number of the file
|
||||
# 4. Run zdb -fHv <pool>/ <inum> & extract file
|
||||
# 5. Compare real file and extracted file.
|
||||
|
||||
DATA=/$TESTPOOL1/random.bin
|
||||
BLOCKS=$(( $RANDOM % 16 ))
|
||||
COMPARE=/tmp/compare.$$
|
||||
|
||||
function cleanup
|
||||
{
|
||||
destroy_pool $TESTPOOL1
|
||||
rm -f $TESTDIR/file?.bin $COMPARE
|
||||
}
|
||||
|
||||
log_assert "Verify zdb -fHv displays correct offsets"
|
||||
log_onexit cleanup
|
||||
|
||||
# 1. Create a RAIDZ1 pool
|
||||
log_must mkdir -p $TESTDIR
|
||||
for file in 1 2 3 4 5 6
|
||||
do
|
||||
rm -f $TESTDIR/file${file}.bin
|
||||
touch $TESTDIR/file${file}.bin
|
||||
log_must truncate -s 128m $TESTDIR/file${file}.bin
|
||||
done
|
||||
|
||||
log_must zpool create -O compression=off -O recordsize=16K $TESTPOOL1 raidz2 $TESTDIR/file[123456].bin
|
||||
zfs get compression,recordsize $TESTPOOL1
|
||||
# 2. Create a file with random data
|
||||
log_must rm -f $DATA
|
||||
log_must dd if=/dev/urandom of=${DATA} bs=16k count=${BLOCKS} > /dev/null 2>&1
|
||||
log_must zpool sync $TESTPOOL1
|
||||
|
||||
# 3. Get the inode number of the file
|
||||
INUM=$(ls -li $DATA | cut -f1 -d ' ')
|
||||
|
||||
# 4. Extract the contents of the file using dd
|
||||
rm -f $COMPARE
|
||||
log_must touch ${COMPARE}
|
||||
log_must zdb -fHv $TESTPOOL1/ ${INUM} | grep 'D.$' |
|
||||
while read file offset count rest
|
||||
do
|
||||
log_must sh -c "dd if=$TESTDIR/${file} bs=512 skip=${offset} count=${count} >> ${COMPARE}"
|
||||
done
|
||||
|
||||
# 5. Compare files
|
||||
log_must cmp ${COMPARE} ${DATA}
|
||||
|
||||
log_pass "'zdb -fHv' works as expected."
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/ksh
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
|
||||
#
|
||||
# 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.
|
||||
# Copyright (c) 2026, Klara Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# Description:
|
||||
# zdb -fHv <dataset> <objnum> will display block
|
||||
# layouts for the object.
|
||||
#
|
||||
# Strategery:
|
||||
# 1. Create a RAIDZ3 pool, set compression to none
|
||||
# 2. Create a file filled with random data
|
||||
# 3. Get the inode number of the file
|
||||
# 4. Run zdb -fHv <pool>/ <inum> & extract file
|
||||
# 5. Compare real file and extracted file.
|
||||
|
||||
DATA=/$TESTPOOL1/random.bin
|
||||
BLOCKS=$(( $RANDOM % 16 ))
|
||||
COMPARE=/tmp/compare.$$
|
||||
|
||||
function cleanup
|
||||
{
|
||||
destroy_pool $TESTPOOL1
|
||||
rm -f $TESTDIR/file?.bin $COMPARE
|
||||
}
|
||||
|
||||
log_assert "Verify zdb -fHv displays correct offsets"
|
||||
log_onexit cleanup
|
||||
|
||||
# 1. Create a RAIDZ1 pool
|
||||
log_must mkdir -p $TESTDIR
|
||||
for file in 1 2 3 4 5 6 7
|
||||
do
|
||||
rm -f $TESTDIR/file${file}.bin
|
||||
touch $TESTDIR/file${file}.bin
|
||||
log_must truncate -s 128m $TESTDIR/file${file}.bin
|
||||
done
|
||||
|
||||
log_must zpool create -O compression=off -O recordsize=16K $TESTPOOL1 raidz3 $TESTDIR/file[123456].bin
|
||||
zfs get compression,recordsize $TESTPOOL1
|
||||
# 2. Create a file with random data
|
||||
log_must rm -f $DATA
|
||||
log_must dd if=/dev/urandom of=${DATA} bs=16k count=${BLOCKS} > /dev/null 2>&1
|
||||
log_must zpool sync $TESTPOOL1
|
||||
|
||||
# 3. Get the inode number of the file
|
||||
INUM=$(ls -li $DATA | cut -f1 -d ' ')
|
||||
|
||||
# 4. Extract the contents of the file using dd
|
||||
rm -f $COMPARE
|
||||
log_must touch ${COMPARE}
|
||||
log_must zdb -fHv $TESTPOOL1/ ${INUM} | grep 'D.$' |
|
||||
while read file offset count rest
|
||||
do
|
||||
log_must sh -c "dd if=$TESTDIR/${file} bs=512 skip=${offset} count=${count} >> ${COMPARE}"
|
||||
done
|
||||
|
||||
# 5. Compare files
|
||||
log_must cmp ${COMPARE} ${DATA}
|
||||
|
||||
log_pass "'zdb -fHv' works as expected."
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/bin/ksh
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
|
||||
#
|
||||
# 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.
|
||||
# Copyright (c) 2026, Klara Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# Description:
|
||||
# Ensure zdb -f only works on raidz
|
||||
#
|
||||
# Strategery:
|
||||
# 1. Create a pool with one disk
|
||||
# 2. Create a file
|
||||
# 3. Get the inode number of the file
|
||||
# 4. Run zdb -f
|
||||
# 5. Confirm failure status
|
||||
|
||||
function cleanup
|
||||
{
|
||||
destroy_pool $TESTPOOL1
|
||||
rm -f $TESTDIR/file1.bin
|
||||
}
|
||||
|
||||
log_assert "Verify zdb -f fails on non-raidz pool"
|
||||
log_onexit cleanup
|
||||
|
||||
# 1. Create a RAIDZ1 pool
|
||||
log_must mkdir -p $TESTDIR
|
||||
touch $TESTDIR/file1.bin
|
||||
log_must truncate -s 128m $TESTDIR/file1.bin
|
||||
log_must zpool create -f $TESTPOOL1 $TESTDIR/file1.bin
|
||||
|
||||
# 2. Create a file
|
||||
log_must touch /$TESTPOOL1/file.txt
|
||||
|
||||
# 3. Get the inode number of the file
|
||||
INUM=$(ls -li /$TESTDIR/file1.txt | cut -f1 -d ' ')
|
||||
|
||||
# 4. Run zdb -f
|
||||
log_mustnot zdb -f $TESTDIR/ $INUM
|
||||
|
||||
log_pass "'zdb -f' fails on non-raidz as expected."
|
||||
Reference in New Issue
Block a user