diff --git a/etc/periodic/daily/800.scrub-zfs b/etc/periodic/daily/800.scrub-zfs new file mode 100755 index 000000000000..8c0ece79cb4c --- /dev/null +++ b/etc/periodic/daily/800.scrub-zfs @@ -0,0 +1,86 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# If there is a global system configuration file, suck it in. +# +if [ -r /etc/defaults/periodic.conf ] +then + . /etc/defaults/periodic.conf + source_periodic_confs +fi + +: ${daily_scrub_zfs_default_threshold=30} + +case "$daily_scrub_zfs_enable" in + [Yy][Ee][Ss]) + echo + echo 'Scrubbing of zfs pools:' + + if [ -z "${daily_scrub_zfs_pools}" ]; then + daily_scrub_zfs_pools="$(zpool list -H -o name)" + fi + + for pool in ${daily_scrub_zfs_pools}; do + # sanity check + zpool list ${pool} >/dev/null 2>&1 + if [ $? -ne 0 ]; then + echo " WARNING: pool '${pool}' specified in" + echo " '/etc/periodic.conf:daily_scrub_zfs_pools'" + echo " does not exist" + continue + fi + + # successful only if there is at least one pool to scrub + rc=0 + + # determine how many days shall be between scrubs + eval _pool_threshold=\${daily_scrub_zfs_${pool}_threshold} + if [ -z "${_pool_threshold}" ];then + _pool_threshold=${daily_scrub_zfs_default_threshold} + fi + + _last_scrub=$(zpool history ${pool} | \ + egrep "^[0-9\.\:\-]{19} zpool scrub ${pool}\$" | tail -1 |\ + cut -d ' ' -f 1) + if [ -z "${_last_scrub}" ]; then + # creation time of the pool if no scrub was done + _last_scrub=$(zpool history ${pool} | \ + sed -ne '2s/ .*$//p') + fi + + # Now minus last scrub (both in seconds) converted to days. + _scrub_diff=$(expr -e \( $(date +%s) - \ + $(date -j -f %F.%T ${_last_scrub} +%s) \) / 60 / 60 / 24) + if [ ${_scrub_diff} -le ${_pool_threshold} ]; then + echo " skipping scrubbing of pool '${pool}':" + echo " last scrubbing is ${_scrub_diff} days ago, threshold is set to ${_pool_threshold} days" + continue + fi + + _status="$(zpool status ${pool} | grep scrub:)" + case "${_status}" in + *"scrub in progress"*) + echo " scrubbing of pool '${pool}' already in progress, skipping:" + ;; + *"none requested"*) + echo " starting first scrubbing (after reboot) of pool '${pool}':" + zpool scrub ${pool} + ;; + *) + echo " starting scrubbing of pool '${pool}':" + zpool scrub ${pool} + ;; + esac + + echo " consult 'zpool status ${pool}' for the result" + done + ;; + + *) + rc=0 + ;; +esac + +exit $rc diff --git a/share/man/man5/periodic.conf.5 b/share/man/man5/periodic.conf.5 index 2052a1b48801..7947a59626c3 100644 --- a/share/man/man5/periodic.conf.5 +++ b/share/man/man5/periodic.conf.5 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 12, 2007 +.Dd June 15, 2010 .Dt PERIODIC.CONF 5 .Os .Sh NAME @@ -611,6 +611,25 @@ when .Va daily_queuerun_enable is set to .Dq Li YES . +.It Va daily_scrub_zfs_enable +.Pq Vt bool +Set to +.Dq Li YES +if you want to run a zfs scrub periodically. +.It Va daily_scrub_zfs_pools +.Pq Vt str +A space separated list of names of zfs pools to scrub. +If the list is empty or not set, all zfs pools are scrubbed. +.It Va daily_scrub_zfs_default_threshold +.Pq Vt int +Number of days between a scrub if no pool-specific threshold is set. +The default value if no value is set is 30. +.It Va daily_scrub_zfs_ Ns Ao Ar poolname Ac Ns Va _threshold +.Pq Vt int +The same as +.Va daily_scrub_zfs_default_threshold +but specific to the pool +.Va Ns Ao Ar poolname Ac Ns . .It Va daily_local .Pq Vt str Set to a list of extra scripts that should be run after all other