Index: stable/8/tools/tools/zfsboottest/Makefile =================================================================== --- stable/8/tools/tools/zfsboottest/Makefile (nonexistent) +++ stable/8/tools/tools/zfsboottest/Makefile (revision 229761) @@ -0,0 +1,29 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../sys/boot/zfs ${.CURDIR}/../../../sys/cddl/boot/zfs + +BINDIR?= /usr/bin +SCRIPTSDIR?= /usr/bin + +PROG= zfsboottest +SCRIPTS= zfsboottest.sh +SCRIPTSNAME= zfsboottest.sh +NO_MAN= + +CFLAGS= -O1 \ + -I${.CURDIR}/../../../sys/boot/zfs \ + -I${.CURDIR}/../../../sys/cddl/boot/zfs \ + -I. \ + -fdiagnostics-show-option \ + -W -Wextra -Wno-sign-compare -Wno-unused-parameter \ + -Werror +LDFLAGS+=-lmd + +.if ${MACHINE_ARCH} == "amd64" +beforedepend zfsboottest.o: machine +CLEANFILES+= machine +machine: + ln -sf ${.CURDIR}/../../../sys/i386/include machine +.endif + +.include Property changes on: stable/8/tools/tools/zfsboottest/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/8/tools/tools/zfsboottest/zfsboottest.c =================================================================== --- stable/8/tools/tools/zfsboottest/zfsboottest.c (nonexistent) +++ stable/8/tools/tools/zfsboottest/zfsboottest.c (revision 229761) @@ -0,0 +1,182 @@ +/*- + * Copyright (c) 2010 Doug Rabson + * Copyright (c) 2011 Andriy Gapon + * Copyright (c) 2011 Pawel Jakub Dawidek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NBBY 8 + +void +pager_output(const char *line) +{ + + fprintf(stderr, "%s", line); +} + +#define ZFS_TEST +#define printf(...) fprintf(stderr, __VA_ARGS__) +#include "zfsimpl.c" +#undef printf + +static int +vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes) +{ + int fd = *(int *)priv; + + if (pread(fd, buf, bytes, off) != bytes) + return (-1); + return (0); +} + +static int +zfs_read(spa_t *spa, dnode_phys_t *dn, void *buf, size_t size, off_t off) +{ + const znode_phys_t *zp = (const znode_phys_t *) dn->dn_bonus; + size_t n; + int rc; + + n = size; + if (off + n > zp->zp_size) + n = zp->zp_size - off; + + rc = dnode_read(spa, dn, off, buf, n); + if (rc != 0) + return (-rc); + + return (n); +} + +int +main(int argc, char** argv) +{ + char buf[512], hash[33]; + MD5_CTX ctx; + struct stat sb; + dnode_phys_t dn; + spa_t *spa; + off_t off; + ssize_t n; + int i, failures, *fd; + + zfs_init(); + if (argc == 1) { + static char *av[] = { + "zfsboottest", + "/dev/gpt/system0", + "/dev/gpt/system1", + "-", + "/boot/zfsloader", + "/boot/support.4th", + "/boot/kernel/kernel", + NULL, + }; + argc = sizeof(av) / sizeof(av[0]) - 1; + argv = av; + } + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-") == 0) + break; + } + fd = malloc(sizeof(fd[0]) * (i - 1)); + if (fd == NULL) + errx(1, "Unable to allocate memory."); + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-") == 0) + break; + fd[i - 1] = open(argv[i], O_RDONLY); + if (fd[i - 1] == -1) { + warn("open(%s) failed", argv[i]); + continue; + } + if (vdev_probe(vdev_read, &fd[i - 1], NULL) != 0) { + warnx("vdev_probe(%s) failed", argv[i]); + close(fd[i - 1]); + } + } + spa_all_status(); + + spa = STAILQ_FIRST(&zfs_pools); + if (spa == NULL) { + fprintf(stderr, "no pools\n"); + exit(1); + } + + if (zfs_mount_pool(spa)) { + fprintf(stderr, "can't mount pool\n"); + exit(1); + } + + printf("\n"); + for (++i, failures = 0; i < argc; i++) { + if (zfs_lookup(spa, argv[i], &dn)) { + fprintf(stderr, "%s: can't lookup\n", argv[i]); + failures++; + continue; + } + + if (zfs_dnode_stat(spa, &dn, &sb)) { + fprintf(stderr, "%s: can't stat\n", argv[i]); + failures++; + continue; + } + + off = 0; + MD5Init(&ctx); + do { + n = sb.st_size - off; + n = n > sizeof(buf) ? sizeof(buf) : n; + n = zfs_read(spa, &dn, buf, n, off); + if (n < 0) { + fprintf(stderr, "%s: zfs_read failed\n", + argv[i]); + failures++; + break; + } + MD5Update(&ctx, buf, n); + off += n; + } while (off < sb.st_size); + if (off < sb.st_size) + continue; + MD5End(&ctx, hash); + printf("%s %s\n", hash, argv[i]); + } + + return (failures == 0 ? 0 : 1); +} Property changes on: stable/8/tools/tools/zfsboottest/zfsboottest.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/8/tools/tools/zfsboottest/zfsboottest.sh =================================================================== --- stable/8/tools/tools/zfsboottest/zfsboottest.sh (nonexistent) +++ stable/8/tools/tools/zfsboottest/zfsboottest.sh (revision 229761) @@ -0,0 +1,130 @@ +#!/bin/sh +# +# Copyright (c) 2011 Pawel Jakub Dawidek +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ + +if [ $# -ne 1 ]; then + echo "usage: zfsboottest.sh " >&2 + exit 1 +fi + +which -s zfsboottest +if [ $? -eq 0 ]; then + zfsboottest="zfsboottest" +else + if [ ! -x "/usr/src/tools/tools/zfsboottest/zfsboottest" ]; then + echo "Unable to find \"zfsboottest\" utility." >&2 + exit 1 + fi + zfsboottest="/usr/src/tools/tools/zfsboottest/zfsboottest" +fi + +startdir="/boot" + +pool="${1}" +zpool list "${pool}" >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "No such pool \"${pool}\"." >&2 + exit 1 +fi +bootfs=`zpool get bootfs "${pool}" | tail -1 | awk '{print $3}'` +if [ "${bootfs}" = "-" ]; then + echo "The \"bootfs\" property is not configured for pool \"${pool}\"." >&2 + exit 1 +fi +# Dataset's mountpoint property should be set to 'legacy'. +if [ "`zfs get -H -o value mountpoint ${bootfs}`" != "legacy" ]; then + echo "The \"mountpoint\" property of dataset \"${bootfs}\" should be set to \"legacy\"." >&2 + exit 1 +fi +mountpoint=`df -t zfs "${bootfs}" 2>/dev/null | tail -1 | awk '{print $6}'` +if [ -z "${mountpoint}" ]; then + echo "The \"${bootfs}\" dataset is not mounted." >&2 + exit 1 +fi +if [ ! -d "${mountpoint}${startdir}" ]; then + echo "The \"${mountpoint}${startdir}\" directory doesn't exist." >&2 + exit 1 +fi +# To be able to mount root ZFS file system we need either /etc/fstab entry +# or vfs.root.mountfrom variable set in /boot/loader.conf. +egrep -q '^'"${bootfs}"'[[:space:]]+/[[:space:]]+zfs[[:space:]]+' "${mountpoint}/etc/fstab" 2>/dev/null +if [ $? -ne 0 ]; then + egrep -q 'vfs.root.mountfrom="?'"${bootfs}"'"?[[:space:]]*$' "${mountpoint}/boot/loader.conf" 2>/dev/null + if [ $? -ne 0 ]; then + echo "To be able to boot from \"${bootfs}\", you need to declare" >&2 + echo "\"${bootfs}\" as being root file system in ${mountpoint}/etc/fstab" >&2 + echo "or add \"vfs.root.mountfrom\" variable set to \"${bootfs}\" to" >&2 + echo "${mountpoint}/boot/loader.conf." >&2 + exit 1 + fi +fi +vdevs="" +for vdev in `zpool status "${pool}" | grep ONLINE | awk '{print $1}'`; do + vdev="/dev/${vdev#/dev/}" + if [ -c "${vdev}" ]; then + if [ -z "${vdevs}" ]; then + vdevs="${vdev}" + else + vdevs="${vdevs} ${vdev}" + fi + fi +done + +list0=`mktemp /tmp/zfsboottest.XXXXXXXXXX` +if [ $? -ne 0 ]; then + echo "Unable to create temporary file." >&2 + exit 1 +fi +list1=`mktemp /tmp/zfsboottest.XXXXXXXXXX` +if [ $? -ne 0 ]; then + echo "Unable to create temporary file." >&2 + rm -f "${list0}" + exit 1 +fi + +echo "zfsboottest.sh is reading all the files in ${mountpoint}${startdir} using" +echo "boot code and using file system code." +echo "It calculates MD5 checksums for all the files and will compare them." +echo "If all files can be properly read using boot code, it is very likely you" +echo "will be able to boot from \"${pool}\" pool>:> Good luck!" +echo + +"${zfsboottest}" ${vdevs} - `find "${mountpoint}${startdir}" -type f | sed "s@^${mountpoint}@@"` | egrep '^[0-9a-z]{32} /' | sort -k 2 >"${list0}" +find "${mountpoint}${startdir}" -type f | xargs md5 -r | sed "s@ ${mountpoint}@ @" | egrep '^[0-9a-z]{32} /' | sort -k 2 >"${list1}" + +diff -u "${list0}" "${list1}" +ec=$? + +rm -f "${list0}" "${list1}" + +if [ $? -ne 0 ]; then + echo >&2 + echo "You may not be able to boot." >&2 + exit 1 +fi + +echo "OK" Property changes on: stable/8/tools/tools/zfsboottest/zfsboottest.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/8/tools/tools =================================================================== --- stable/8/tools/tools (revision 229760) +++ stable/8/tools/tools (revision 229761) Property changes on: stable/8/tools/tools ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/tools/tools:r225608-225609,226611-226612 Index: stable/8/tools =================================================================== --- stable/8/tools (revision 229760) +++ stable/8/tools (revision 229761) Property changes on: stable/8/tools ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/tools:r225608-225609,226611-226612