#!/bin/sh . /etc/initrd.d/00-common.sh . /etc/initrd.d/00-fsdev.sh . /etc/initrd.d/00-devmgr.sh is_zfs() { # Note: this only works after zfs_real_root_init # (thus, only after real_root_init) [ "${USE_ZFS}" = "1" ] && return 0 return 1 } # This piece of information can be used by external # functions to return the default filesystem type # for zfs members. zfs_member_fstype() { echo "zfs_member" } is_zfs_fstype() { local fstype="${1}" [ "${fstype}" = "$(zfs_member_fstype)" ] && return 0 return 1 } zfs_real_root_init() { case "${REAL_ROOT}" in ZFS=*) ZFS_POOL=${REAL_ROOT#*=} ZFS_POOL=${ZFS_POOL%%/*} USE_ZFS=1 ;; ZFS) USE_ZFS=1 ;; esac # Verify that zfs support has been compiled in if [ "${USE_ZFS}" = "1" ]; then for i in /sbin/zfs /sbin/zpool; do if [ ! -x "${i}" ]; then USE_ZFS=0 bad_msg 'Aborting use of zfs because ${i} not found!' break fi done fi } # This helper function is to be called using _call_func_timeout. This # works around the inability of busybox modprobe to handle complex # module dependencies. This also enables us to wait a reasonable # amount of time until /dev/zfs appears. wait_for_zfs() { while [ ! -c /dev/zfs ]; do modprobe zfs 2> /dev/null; done; } _call_func_timeout() { local func=$1 timeout=$2 pid watcher ( ${func} ) & pid=$! ( sleep ${timeout} && kill -HUP ${pid} ) 2>/dev/null & watcher=$! if wait ${pid} 2>/dev/null; then kill -HUP $watcher 2> /dev/null wait $watcher 2>/dev/null return 1 fi return 0 } zfs_start_volumes() { # is ZFS enabled? is_zfs || return 0 # Avoid race involving asynchronous module loading if _call_func_timeout wait_for_zfs 5; then bad_msg "Cannot import ZFS pool because /dev/zfs is missing" elif [ -z "${ZFS_POOL}" ]; then good_msg "Importing ZFS pools" zpool import -N -a ${ZPOOL_FORCE} if [ "${?}" = "0" ]; then good_msg "Importing ZFS pools succeeded" else bad_msg "Imported ZFS pools failed" fi else local pools=$(zpool list -H -o name ${ZFS_POOL} 2>&1) if [ "${pools}" = "${ZFS_POOL}" ]; then good_msg "ZFS pool ${ZFS_POOL} already imported." if [ -n "${CRYPT_ROOTS}" ] || [ -n "${CRYPT_SWAPS}" ]; then good_msg "LUKS detected. Reimporting ${ZFS_POOL}" zpool export -f "${ZFS_POOL}" zpool import -N ${ZPOOL_FORCE} "${ZFS_POOL}" fi else good_msg "Importing ZFS pool ${ZFS_POOL}" zpool import -N ${ZPOOL_FORCE} "${ZFS_POOL}" if [ "${?}" = "0" ]; then good_msg "Import of ${ZFS_POOL} succeeded" else bad_msg "Import of ${ZFS_POOL} failed" fi fi fi is_udev && udevadm settle } # Initialize the zfs root filesystem device and # tweak ${REAL_ROOT}. In addition, set ${ZFS_POOL} # for later use. # Return 0 if initialization is successful. zfs_rootdev_init() { local root_dev="${REAL_ROOT#*=}" ZFS_POOL="${root_dev%%/*}" if [ "${root_dev}" != "ZFS" ]; then local ztype=$(zfs get type -o value -H "${root_dev}") if [ "${ztype}" = "filesystem" ]; then REAL_ROOT="${root_dev}" good_msg "Detected zfs root: ${REAL_ROOT}" return 0 else bad_msg "${root_dev} is not a zfs filesystem" return 1 fi fi local bootfs=$(zpool list -H -o bootfs) [ "${bootfs}" = "-" ] && return 1 for i in ${bootfs}; do if zfs get type "${i}" > /dev/null; then REAL_ROOT="${i}" good_msg "Detected zfs bootfs root: ${REAL_ROOT}" return 0 fi done return 1 } zfs_get_real_root_mount_flags() { local flags=rw,zfsutil local zmtype=$(zfs get -H -o value mountpoint "${REAL_ROOT}") [ "${zmtype}" = "legacy" ] && flags=rw echo "${flags}" }