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

Stefan Moeding sm at kill-9.net
Tue Mar 4 20:10:02 UTC 2008


>Number:         121366
>Category:       bin
>Synopsis:       [zfs] [patch] Automatic disk scrubbing from periodic(8)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 04 20:10:01 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Stefan Moeding
>Release:        FreeBSD 7.0-STABLE i386
>Organization:
>Environment:
System: FreeBSD elan.setuid.de 7.0-STABLE FreeBSD 7.0-STABLE #23: Sat Mar  1 14:17:18 CET 2008 root at elan.setuid.de:/usr/obj/usr/src/sys/ELAN i386
>Description:

The ZFS Best Practices Guide recommends disk scrubbing on a regular
basis.  The attached file fits into the periodic(8) framework to start
a weekly scrub.  It will look at all pools and choose one of them on a
round-robin basis depending on the date of the last scrub/resilver
unless there is already a scrub or resilver running.

The script should probably be installed to run at the end the weekly
schedule to avoid I/O contention from scrubbing and other weekly scripts.

The new periodic(8) switch 'weekly_zfs_scrubbing_enable' is introduced.

One drawback: ZFS seems to forget the time of a scrub/resilver when
shutting down.  On machines with regular reboots and multiple pools
the script will probably pick the same pool every time.

>How-To-Repeat:

>Fix:

#!/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

scrubdate() {
    # Echo lines with timestamp (0=never, -1=running)
    # of last scrub/resilver and pool name to stdout.
    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")
                    echo $date $pool
                    ;;
                scrub:\ scrub\ in\ progress*|scrub:\ resilver\ in\ progress*)
                    # Scrub or resilver is running
                    echo -1 $pool
                    ;;
                scrub:\ none\ requested)
                    # Pool has never been scrubed or resilvered
                    echo 0 $pool
                    ;;
            esac
        done
    done
}

case "$weekly_zfs_scrubbing_enable" in
    [Yy][Ee][Ss])
        line=$(scrubdate | sort -n | head -1)

        if [ -n "$line" ]; then
            date=$(echo $line | cut -d" " -f1)
            pool=$(echo $line | cut -d" " -f2)

            echo ""
            case "$date" in
                -1)
                    echo "Scrub or resilver is running for pool $pool:"
                    /sbin/zpool status $pool
                    rc=1
                    ;;
                *)
                    echo "Starting scrub for pool $pool:"
                    /sbin/zpool scrub $pool
                    rc=$?
                    ;;
            esac
        else
            echo '$weekly_zfs_scrubbing_enable is set' \
                 'but no zfs pools have been created'
            rc=2
        fi;;
    *)  rc=0;;
esac

exit $rc
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list