diff --git a/debian/tree/zfsutils-linux/usr/lib/zfs-linux/scrub b/debian/tree/zfsutils-linux/usr/lib/zfs-linux/scrub index 38f071a..f18c6e8 100755 --- a/debian/tree/zfsutils-linux/usr/lib/zfs-linux/scrub +++ b/debian/tree/zfsutils-linux/usr/lib/zfs-linux/scrub @@ -1,12 +1,45 @@ #!/bin/sh -eu -# Scrub all healthy pools that are not already scrubbing. +# directly exit successfully when zfs module is not loaded +if ! [ -d /sys/module/zfs ]; then + exit 0 +fi + +# [auto] / enable / disable +PROPERTY_NAME="org.debian:periodic-scrub" + +get_property () { + # Detect the ${PROPERTY_NAME} property on a given pool. + # We are abusing user-defined properties on the root dataset, + # since they're not available on pools https://github.com/openzfs/zfs/pull/11680 + # TODO: use zpool user-defined property when such feature is available. + pool="$1" + zfs get -H -o value "${PROPERTY_NAME}" "${pool}" 2>/dev/null || return 1 +} + +scrub_if_not_scrub_in_progress () { + pool="$1" + if ! zpool status "${pool}" | grep -q "scrub in progress"; then + # Ignore errors and continue with scrubbing other pools. + zpool scrub "${pool}" || true + fi +} + +# Scrub all healthy pools that are not already scrubbing as per their configs. zpool list -H -o health,name 2>&1 | \ - awk 'BEGIN {FS="\t"} {if ($1 ~ /^ONLINE/) print $2}' | \ + awk -F'\t' '$1 == "ONLINE" {print $2}' | \ while read pool do - if ! zpool status "$pool" | grep -q "scrub in progress" - then - zpool scrub "$pool" + # read user-defined config + ret=$(get_property "${pool}") + if [ $? -ne 0 ] || [ "disable" = "${ret}" ]; then + : + elif [ "-" = "${ret}" ] || [ "auto" = "${ret}" ] || [ "enable" = "${ret}" ]; then + scrub_if_not_scrub_in_progress "${pool}" + else + cat > /dev/stderr </dev/null || return 1 +} + +trim_if_not_already_trimming () { + pool="$1" + if ! zpool status "${pool}" | grep -q "trimming"; then + # Ignore errors (i.e. HDD pools), + # and continue with trimming other pools. + zpool trim "${pool}" || true + fi +} + +zpool_is_nvme_only () { + zpool=$1 + # get a list of devices attached to the specified zpool + zpool list -vHPL "${zpool}" | + awk -F'\t' '$2 ~ /^\/dev\// { + if($2 !~ /^\/dev\/nvme/) + exit 1 + }' +} + +# TRIM all healthy pools that are not already trimming as per their configs. +zpool list -H -o health,name 2>&1 | \ + awk -F'\t' '$1 == "ONLINE" {print $2}' | \ +while read pool +do + # read user-defined config + ret=$(get_property "${pool}") + if [ $? -ne 0 ] || [ "disable" = "${ret}" ]; then + : + elif [ "enable" = "${ret}" ]; then + trim_if_not_already_trimming "${pool}" + elif [ "-" = "${ret}" ] || [ "auto" = "${ret}" ]; then + if zpool_is_nvme_only "${pool}"; then + trim_if_not_already_trimming "${pool}" + fi + else + cat > /dev/stderr <