bin/121366: [zfs] [patch] Automatic disk scrubbing from periodic(8)

Giorgos Keramidas keramida at freebsd.org
Tue May 19 03:30:04 UTC 2009


The following reply was made to PR bin/121366; it has been noted by GNATS.

From: Giorgos Keramidas <keramida at freebsd.org>
To: bug-followup at freebsd.org
Cc:  
Subject: Re: bin/121366: [zfs] [patch] Automatic disk scrubbing from periodic(8)
Date: Tue, 19 May 2009 06:29:07 +0300

 On Mon, 18 May 2009 02:57:00 GMT, linimon at FreeBSD.org wrote:
 > Synopsis: [zfs] [patch] Automatic disk scrubbing from periodic(8)
 >
 > Responsible-Changed-From-To: freebsd-bugs->freebsd-fs
 > Responsible-Changed-By: linimon
 > Responsible-Changed-When: Mon May 18 02:56:46 UTC 2009
 > Responsible-Changed-Why: 
 > Over to maintainer(s).
 >
 > http://www.freebsd.org/cgi/query-pr.cgi?pr=121366
 
 A variation of the same idea that should auto-kick scrubbing if the
 'age' of the last scrub exceeds a configurable threshold would be nice
 too.  The _untested_ patch below is a start at implementing that:
 
     http://people.freebsd.org/~keramida/diff/zfs-scrub.periodic.diff
 
 I'll give this a few test runs and if it looks useful resubmit with the
 matching manpage updates too.
 
 %%%
 diff -r cc894c49974d etc/defaults/periodic.conf
 --- a/etc/defaults/periodic.conf	Mon May 18 10:31:18 2009 +0300
 +++ b/etc/defaults/periodic.conf	Tue May 19 06:27:09 2009 +0300
 @@ -226,6 +226,11 @@
  pkg_version=pkg_version					# Use this program
  pkg_version_index=/usr/ports/INDEX-8			# Use this index file
  
 +# 500.zfs-scrub
 +weekly_status_zfs_scrub_enable="NO"			# Scrub zfs pools
 +weekly_status_zfs_scrub_auto="NO"			# Auto-scrub old pools
 +weekly_status_zfs_scrub_max_age="1728000"		# Scrub age in seconds
 +
  # 999.local
  weekly_local="/etc/weekly.local"			# Local scripts
  
 diff -r cc894c49974d etc/periodic/weekly/500.zfs-scrub
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
 +++ b/etc/periodic/weekly/500.zfs-scrub	Tue May 19 06:27:09 2009 +0300
 @@ -0,0 +1,131 @@
 +#!/bin/sh
 +#
 +# $FreeBSD$
 +#
 +# Report the last time a zfs pool was scrubbed and if auto-scrubbing is
 +# enabled, kick off a 'zfs scrub' run for pools that were checked too
 +# far in the past.
 +#
 +
 +# 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
 +
 +# scrubdate
 +#	Find the time since the Epoch of the last pool scrub for all
 +#	active zfs pools (0=never, -1=running now).
 +scrubdate()
 +{
 +    for pool in $(/sbin/zpool list -H -o name) ; do
 +	/sbin/zpool status "${pool}" |
 +	while read line ; do
 +	    case "${line}" in
 +		scrub:\ scrub\ completed*|scrub:\ resilver\ completed*)
 +		    # Extract date from zpool output and convert to epoch.
 +		    date=$(echo $line | sed 's/^scrub: .* on //')
 +		    date=$(date -jn -f '%+' "$date" '+%s')
 +		    ;;
 +
 +		scrub:\ scrub\ in\ progress*|scrub:\ resilver\ in\ progress*)
 +		    # Scrub or resilver is running now.
 +		    date='-1'
 +		;;
 +
 +		scrub:\ none\ requested)
 +		    # Pool has never been scrubed or resilvered.
 +		    date='0'
 +		    ;;
 +	    esac
 +	    echo "${date} ${pool}"
 +	done
 +    done
 +}
 +
 +# scrubpool POOL TIME
 +#	Kick off a scrub of zfs pool `POOL' if the `TIME' of its last
 +#	scrub is too old and auto-scrubbing is enabled.
 +scrubpool()
 +{
 +    local _pool="$1"
 +    local _time="$2"
 +
 +    case "${weekly_status_zfs_scrub_auto}" in
 +	[Yy][Ee][Ss])
 +	    case "${weekly_status_zfs_scrub_max_age}" in
 +		[0-9]*)
 +		    ;;
 +		*)
 +		    echo '$weekly_status_zfs_scrub_max_age is not set' \
 +			'properly - see periodic.conf(5)'
 +		    ;;
 +	    esac
 +	    now=$(date '+%s')
 +	    age=$(( "${now}" - "${_time}" ))
 +	    if [ -z "${age}" ]; then
 +		echo "Cannot find scrub age for pool ${_pool} -" \
 +		    "forcing a scrub run"
 +		zfs scrub "${_pool}"
 +		return $?
 +	    fi
 +	    if [ "${age}" -gt "${weekly_status_zfs_scrub_max_age}" ]; then
 +		echo "Last scrub for pool ${_pool} was ${age} seconds ago."
 +		echo "Starting automatic scrub run."
 +		zfs scrub "${_pool}"
 +		return $?
 +	    fi
 +	    ;;
 +
 +	[Nn][Oo])
 +	    return 0
 +	    ;;
 +
 +	*)
 +	    echo '$weekly_zfs_scrub_auto is not set properly - ' \
 +	    'see periodic.conf(5)'
 +	    return 1
 +	    ;;
 +    esac
 +}
 +
 +rc=0
 +case "$weekly_zfs_scrub_enable" in
 +    [Yy][Ee][Ss])
 +	havepools=1
 +	scrubdate | sort -n | \
 +	while read date pool ; do
 +	    havepools=1
 +	    echo ""
 +	    case ${date} in
 +		-1)
 +		    echo "Scrub or resilver is running for pool $pool:"
 +		    /sbin/zpool status ${pool}
 +		    status=$?
 +		    [ ${status} -ne 0 ] && rc=${status}
 +		    ;;
 +
 +		0)
 +		    scrubpool ${pool} ${time}
 +		    status=$?
 +		    [ ${status} -ne 0 ] && rc=${status}
 +		    ;;
 +	    esac
 +	done
 +	if [ ${havepools} -eq 0 ]; then
 +	    echo '$weekly_zfs_scrub_enable is set' \
 +		'but no zfs pools have been created'
 +	    rc=2
 +	fi
 +	;;
 +
 +    [Nn][Oo])
 +	;;
 +
 +    *)
 +	echo '$weekly_zfs_scrub_enable is not set properly - ' \
 +	    'see periodic.conf(5)'
 +	;;
 +esac
 +exit $rc
 %%%


More information about the freebsd-fs mailing list