1#!/bin/sh 2# 3# Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26# 27 28if [ $# -ne 1 ]; then 29 echo "usage: zfsboottest.sh <pool>" >&2 30 exit 1 31fi 32 33which -s zfsboottest 34if [ $? -eq 0 ]; then 35 zfsboottest="zfsboottest" 36else 37 if [ ! -x "/usr/src/tools/tools/zfsboottest/zfsboottest" ]; then 38 echo "Unable to find \"zfsboottest\" utility." >&2 39 exit 1 40 fi 41 zfsboottest="/usr/src/tools/tools/zfsboottest/zfsboottest" 42fi 43 44startdir="/boot" 45 46pool="${1}" 47zpool list "${pool}" >/dev/null 2>&1 48if [ $? -ne 0 ]; then 49 echo "No such pool \"${pool}\"." >&2 50 exit 1 51fi 52bootfs=`zpool get bootfs "${pool}" | tail -1 | awk '{print $3}'` 53if [ "${bootfs}" = "-" ]; then 54 bootfs="${pool}" 55fi 56mountpoint=`df -t zfs "${bootfs}" 2>/dev/null | tail -1 | awk '{print $6}'` 57if [ -z "${mountpoint}" ]; then 58 echo "The \"${bootfs}\" dataset is not mounted." >&2 59 exit 1 60fi 61if [ ! -d "${mountpoint}${startdir}" ]; then 62 echo "The \"${mountpoint}${startdir}\" directory doesn't exist." >&2 63 exit 1 64fi 65vdevs="" 66for vdev in `zpool status "${pool}" | grep ONLINE | awk '{print $1}'`; do 67 vdev="/dev/${vdev#/dev/}" 68 if [ -c "${vdev}" ]; then 69 if [ -z "${vdevs}" ]; then 70 vdevs="${vdev}" 71 else 72 vdevs="${vdevs} ${vdev}" 73 fi 74 fi 75done 76 77list0=`mktemp /tmp/zfsboottest.XXXXXXXXXX` 78if [ $? -ne 0 ]; then 79 echo "Unable to create temporary file." >&2 80 exit 1 81fi 82list1=`mktemp /tmp/zfsboottest.XXXXXXXXXX` 83if [ $? -ne 0 ]; then 84 echo "Unable to create temporary file." >&2 85 rm -f "${list0}" 86 exit 1 87fi 88 89echo "zfsboottest.sh is reading all the files in ${mountpoint}${startdir} using" 90echo "boot code and using file system code." 91echo "It calculates MD5 checksums for all the files and will compare them." 92echo "If all files can be properly read using boot code, it is very likely you" 93echo "will be able to boot from \"${pool}\" pool>:> Good luck!" 94echo 95 96"${zfsboottest}" ${vdevs} - `find "${mountpoint}${startdir}" -type f | sed "s@^${mountpoint}@@"` | egrep '^[0-9a-z]{32} /' | sort -k 2 >"${list0}" 97find "${mountpoint}${startdir}" -type f | xargs md5 -r | sed "s@ ${mountpoint}@ @" | egrep '^[0-9a-z]{32} /' | sort -k 2 >"${list1}" 98 99diff -u "${list0}" "${list1}" 100ec=$? 101 102rm -f "${list0}" "${list1}" 103 104if [ $? -ne 0 ]; then 105 echo >&2 106 echo "You may not be able to boot." >&2 107 exit 1 108fi 109 110echo "OK" 111