├── LICENSE ├── README.md └── bclonecheck.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 0x5c 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zfs-bclonecheck 2 | Small script to check for bcloned files on a ZFS pool 3 | 4 | > [!IMPORTANT] 5 | > This script requires a version of zdb that can dump the BRT. See https://github.com/openzfs/zfs/pull/15541 6 | 7 | > [!WARNING] 8 | > This script (and zfs as a whole) can only report bcloned files that still have at least two instances (original+copy, two or more copies, ...). 9 | > Files were only one instance or less exists could have been bcloned at some point in the past and not be reported. 10 | 11 | > [!NOTE] 12 | > If you use this script to identify files potentially affected by https://github.com/openzfs/zfs/issues/15526, be aware that the bug has since been reproduced on both 2.2.1 (where bclone is default-disabled) and 2.1.x where bclone did not exist; it seems the corruption bug was preëxisting and only made easier to hit by bclone. 13 | 14 | ## Usage 15 | 16 | ``` 17 | bclonecheck.sh [-C] ZPOOL 18 | ``` 19 | 20 | Dumps the list of files that have been bcloned. Both the original and copy will be in the list. 21 | 22 | Add `-C` to prevent removal of the created temporary directory, and print its path. Can be useful to see the list of DVAs affected. 23 | 24 | -------------------------------------------------------------------------------- /bclonecheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$1" = "-C" ]; then 4 | NOCLEAN=1 5 | shift 6 | fi 7 | 8 | errmsg() { 9 | printf '\033[91m%s\033[0m\n' "$1" 10 | exit 1 11 | } 12 | 13 | cleanup() { 14 | if [ -z "$NOCLEAN" ]; then 15 | rm -r "$tempdir" 16 | else 17 | printf "\nTemporary directory: %s\n" "$tempdir" 18 | fi 19 | 20 | } 21 | 22 | [ -n "$1" ] || errmsg "You must give a pool name!" 23 | zpool="$1" 24 | 25 | # Check the pool exists 26 | zpool status "$zpool" > /dev/null 2>&1 || errmsg "Invalid pool name: $zpool" 27 | 28 | # Check that zdb is capable of dumping the BRT 29 | zdb -h 2>&1 | grep -q -- '-T --brt-stats' || \ 30 | errmsg "Your version of zdb must have the -T/--brt-stats option!" 31 | 32 | # Must be root! 33 | [ "$(id -u)" -ne 0 ] && errmsg "$0: must be run as root!" 34 | 35 | tempdir="$(mktemp -d)" 36 | 37 | trap cleanup INT TERM 38 | 39 | # Dump the BRT, write DVAs to file 40 | # TODO: Can DVAs start with hex digits? how many digits? 41 | zdb -TTT "$zpool" | grep -Po '^[0-9a-f]+:[0-9a-f]+(?=\s)' > "${tempdir}/dvas.txt" || { 42 | echo "BRT empty. There are no bcloned files in the pool."; 43 | cleanup; 44 | exit 0 45 | } 46 | 47 | set -e 48 | 49 | # Dump pool blocks, filter for L0 blocks and match on dumped DVAs, get filepath for each 50 | zdb -bbb -vvv "$zpool" | grep 'level 0' | grep -wf "${tempdir}/dvas.txt" | \ 51 | cut -d' ' -f2,4 | xargs -n2 zfs_ids_to_path -v "$zpool" | column -ts: -N DATASET,PATH -l2 52 | 53 | cleanup 54 | --------------------------------------------------------------------------------