Skip to content

Instantly share code, notes, and snippets.

@kimono-koans
Last active May 5, 2024 01:21
Show Gist options
  • Save kimono-koans/2696a8c8eac0a6babf7b2d9b26a82f65 to your computer and use it in GitHub Desktop.
Save kimono-koans/2696a8c8eac0a6babf7b2d9b26a82f65 to your computer and use it in GitHub Desktop.
Test for ZFS corruption
#!/usr/bin/env bash
# Invocation: zfs list -H -o mountpoint | grep -v -e legacy -e none | xargs -I{} find "{}" -xdev -type f | \
# parallel -j 8 'zfs_corruption_detector "{}" 2>/dev/null | grep ERR' > report.txt
set -euf -o pipefail
#set -x
print_err() {
printf "%s\n" "$*" 1>&2
}
find_corruption() {
local file_name="$1"
local record_size="$2"
python3 -c "data = open('$file_name','rb').read($record_size); print('ERR: $file_name: Possible corruption.\n' if len(data) and data == b'\x00'*len(data) else 'INFO: $file_name: OK\n', end='')"
}
run_loop() {
for file in "$@"; do
local file_name=""
local record_size=""
local zfs_mount=""
file_name="$( readlink -e "$file" 2>/dev/null )"
if [[ -z "$file_name" ]]; then
print_err "WARN: $file_name: File name is empty! Quitting."
continue
fi
if [[ ! -r "$file_name" ]]; then
print_err "WARN: $file_name: File name is not readable! Quitting."
continue
fi
zfs_mount="$( zfs list -H -o mountpoint "$file_name" 2>/dev/null )"
if [[ -z "$zfs_mount" ]]; then
print_err "WARN: $file_name: Mount name is empty! Quitting."
continue
fi
record_size="$( zfs get recordsize -Hp -o value "$zfs_mount" 2>/dev/null )"
if [[ -z "$record_size" ]];then
print_err "WARN: $file_name: Record size is empty! Quitting."
continue
fi
find_corruption "$file_name" "$record_size"
done
}
run_loop $@
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment