#!/bin/ksh ################################################################### # zpool-spare-demo # # An experiment script to help me understand zfs/zpool better. # # Dale Sears ################################################################### ################################################################### # Set these to something reasonable for your system. # The rest of this code assumes you're not using spaces in these: ################################################################### ZPOOL=shallow DISKDIR=/home/dsk ################################################################### # Bail out if we have the ZPOOL. We don't want to break it: ################################################################### HASAPOOL=`/sbin/zpool status | /bin/grep "pool: $ZPOOL"` if [ ! -z "$HASAPOOL" ] then echo "/////////////////////////////////////////////////////////////////" echo "// WARNING: zpool \"$ZPOOL\" exists! I'm not touching it..." echo "//" echo "// WARNING: Removing this check will likely panic the system" echo "/////////////////////////////////////////////////////////////////" exit 1 fi ################################################################### # The directory where we're storing our pretend disks: ################################################################### /bin/mkdir -p $DISKDIR > /dev/null 2>&1 if [ ! -d $DISKDIR ] then echo "Uh, oh... : Could not create DISKDIR: $DISKDIR" exit 1 fi ################################################################### # NOTE: I'm using lame disk names here, just in case # DISKDIR gets set to something terrible like /dev/dsk. # If you don't understand why that would be bad, please logout. ################################################################### DISKS="$DISKDIR/disk01 \ $DISKDIR/disk02 \ $DISKDIR/disk03 \ $DISKDIR/disk04 \ $DISKDIR/disk05 \ $DISKDIR/disk06" SPARES="$DISKDIR/spare01 \ $DISKDIR/spare02" ################################################################### # We're making 64MB (the minimum size) files to use as disks: ################################################################### /usr/sbin/mkfile 64m $DISKS $SPARES ################################################################### # Start an XTerm to watch the scrub process. This may start out # very boring, with repeating a "no pools available": ################################################################### /usr/openwin/bin/xterm -T "zpool status" -geom 80x24-0+33 -e /bin/ksh \ '(while :;do zpool status $ZPOOL;sleep 2;done)' & ################################################################### # Create the zpool: ################################################################### /sbin/zpool create $ZPOOL raidz $DISKDIR/disk01 \ $DISKDIR/disk02 \ $DISKDIR/disk03 \ $DISKDIR/disk04 \ $DISKDIR/disk05 \ spare $DISKDIR/spare01 ################################################################### # Toss a rock into the pool: ################################################################### /bin/dd if=/dev/urandom of=/$ZPOOL/rock bs=8192k count=8 & MD5_BEFORE=`/usr/bin/digest -v -a md5 /$ZPOOL/rock | \ /bin/awk '{print $4}'` ################################################################### # Corrupt some data. This will not be "noticed" by zfs until the # checksum on the wasted blocks has been done, so we should still # have a good 'zpool status' after randomizing a few blocks: ################################################################### /bin/dd if=/dev/urandom of=$DISKDIR/disk01 bs=8192k count=4 conv=notrunc /sbin/zpool status ################################################################### # Check the md5 hash of the file (to show that they're the same. ################################################################### MD5_AFTER=`/usr/bin/digest -v -a md5 /$ZPOOL/rock | /bin/awk '{print $4}'` ################################################################### # Now we're going to force zfs to check the integrity of the pool. # but at this point, we've already read the entire file and we # expect to see that BOGUSMD5 is the same as MD5 before the disk # corruption: ################################################################### /sbin/zpool scrub $ZPOOL ################################################################### # Read the contents of the file (like the md5 did, but after a # scrub. The result of reading the file *after* the scrub should # be some form of spare action or resilvering of the data from # parity: ################################################################### /bin/cp /$ZPOOL/rock /$ZPOOL/rock.copy ################################################################### # Clear the checksum errors and zfs should present a clean status: ################################################################### zpool clear $ZPOOL ################################################################### # I think shrinking and randomizing the disk has been successful # in forcing the spare to kick in. In this corruption, we're not # going to preserve the size of the disk with "conv=notrunc" This # will cause zfs to use a spare: ################################################################### /bin/dd if=/dev/urandom of=$DISKDIR/disk01 bs=8192k count=2 /sbin/zpool scrub $ZPOOL ################################################################### # Let's replace a disk in the middle of all of this: ################################################################### zpool replace $ZPOOL $DISKDIR/disk01 $DISKDIR/disk06 ################################################################### # We should still have the same MD5: ################################################################### MD5_AFTER_SPARE=`/usr/bin/digest -v -a md5 /$ZPOOL/rock | /bin/awk '{print $4}'` ################################################################### # Did our data get corrupted at given points?: ################################################################### echo "MD5 before corruption: $MD5_BEFORE" echo "MD5 after corruption: $MD5_AFTER" echo "MD5 after spare : $MD5_AFTER_SPARE"