564 lines
18 KiB
Bash
Executable File
564 lines
18 KiB
Bash
Executable File
#!/bin/sh -e
|
|
|
|
# Copyright 2012 Slawomir Wojciech Wojtczak (vermaden). All rights reserved.
|
|
# Copyright 2012 Bryan Drewery (bdrewery). All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that 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.
|
|
|
|
unset LC_ALL
|
|
unset LANG
|
|
PATH=${PATH}:/bin:/usr/bin:/sbin:/usr/sbin
|
|
|
|
if [ $( uname -r | cut -d '.' -f1 ) -lt 8 ]
|
|
then
|
|
echo "ERROR: beadm works on FreeBSD 8.0 or later"
|
|
exit 1
|
|
fi
|
|
|
|
__usage() {
|
|
local NAME=${0##*/}
|
|
echo "usage:"
|
|
echo " ${NAME} subcommand cmd_options"
|
|
echo
|
|
echo " subcommands:"
|
|
echo
|
|
echo " ${NAME} activate beName"
|
|
echo " ${NAME} create [-e nonActiveBe | -e beName@snapshot] beName"
|
|
echo " ${NAME} create beName@snapshot"
|
|
echo " ${NAME} destroy [-F] beName | beName@snapshot"
|
|
echo " ${NAME} list [-S]"
|
|
echo " ${NAME} mount"
|
|
echo " ${NAME} mount beName [mountpoint]"
|
|
echo " ${NAME} umount | unmount [-f] beName"
|
|
echo " ${NAME} rename origBeName newBeName"
|
|
exit 1
|
|
}
|
|
|
|
# check if boot environment exists
|
|
__be_exist() { # 1=DATASET
|
|
if ! zfs list -H -o name ${1} 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: Boot environment '${1##*/}' does not exist"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# check if argument is a snapshot
|
|
__be_snapshot() { # 1=DATASET/SNAPSHOT
|
|
echo "${1}" | grep -q "@"
|
|
}
|
|
|
|
# create new boot environment
|
|
__be_new() { # 1=SOURCE 2=TARGET
|
|
local SOURCE=$( echo ${1} | cut -d '@' -f 1 )
|
|
if __be_snapshot ${1}
|
|
then
|
|
local SNAPSHOT=$( echo ${1} | cut -d '@' -f 2 )
|
|
zfs list -r -H -t filesystem -o name ${SOURCE} \
|
|
| while read FS
|
|
do
|
|
if ! zfs list -H -o name ${FS}@${SNAPSHOT} 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: Child snapshot '${FS}@${SNAPSHOT}' does not exists"
|
|
exit 1
|
|
fi
|
|
done
|
|
else
|
|
if zfs list -H -o name ${1}@${2##*/} 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: Snapshot '${1}@${2##*/}' already exists"
|
|
exit 1
|
|
fi
|
|
FMT=$( date "+%Y-%m-%d-%H:%M:%S" ) # NEW #
|
|
if ! zfs snapshot -r ${1}@${FMT} 1> /dev/null 2> /dev/null # NEW #
|
|
# if ! zfs snapshot -r ${1}@${2##*/} 1> /dev/null 2> /dev/null # old #
|
|
then
|
|
echo "ERROR: Cannot create snapshot '${1}@${FMT}'" # NEW #
|
|
# echo "ERROR: Cannot create snapshot '${1}@${2##*/}'" # old #
|
|
exit 1
|
|
fi
|
|
fi
|
|
zfs list -H -o name -r ${SOURCE} \
|
|
| while read FS
|
|
do
|
|
local OPTS=""
|
|
while read NAME PROPERTY VALUE
|
|
do
|
|
local OPTS="-o ${PROPERTY}=${VALUE} ${OPTS}"
|
|
done << EOF
|
|
$( zfs get -o name,property,value -s local,received -H all ${FS} | grep -v -E "canmount" )
|
|
EOF
|
|
DATASET=$( echo ${FS} | awk '{print $1}' | sed -E s/"^${POOL}\/ROOT\/${SOURCE##*/}"/"${POOL}\/ROOT\/${2##*/}"/g )
|
|
if [ "${OPTS}" = "-o = " ]
|
|
then
|
|
local OPTS=""
|
|
fi
|
|
if __be_snapshot ${1}
|
|
then
|
|
zfs clone -o canmount=off ${OPTS} ${FS}@${1##*@} ${DATASET}
|
|
else
|
|
# zfs clone -o canmount=off ${OPTS} ${FS}@${2##*/} ${DATASET} # old #
|
|
zfs clone -o canmount=off ${OPTS} ${FS}@${FMT} ${DATASET} # NEW #
|
|
fi
|
|
done
|
|
echo "Created successfully"
|
|
}
|
|
|
|
ROOTFS=$( mount | awk '/ \/ / {print $1}' )
|
|
|
|
if echo ${ROOTFS} | grep -q -m 1 -E "^/dev/"
|
|
then
|
|
echo "ERROR: This system does not boot from ZFS pool"
|
|
exit 1
|
|
fi
|
|
|
|
POOL=$( echo ${ROOTFS} | awk -F '/' '{print $1}' )
|
|
|
|
if ! zfs list ${POOL}/ROOT 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: This system is not configured for boot environments"
|
|
exit 1
|
|
fi
|
|
|
|
BOOTFS=$( zpool list -H -o bootfs ${POOL} )
|
|
|
|
case ${1} in
|
|
|
|
(list) # --------------------------------------------------------------------
|
|
if [ ${#} -ne 1 -a "${2}" != "-S" ]
|
|
then
|
|
__usage
|
|
fi
|
|
BENAME_STARTS_WITH="${POOL}/ROOT"
|
|
LIST=$( zfs list -o name,used,mountpoint,creation -s creation -H -d 1 -r ${POOL}/ROOT | grep -E "^${POOL}/ROOT/" )
|
|
WIDTH_CREATION=$( echo "${LIST}" | awk '{print $5}' | wc -L )
|
|
WIDTH_NAME=$( echo "${LIST}" | awk '{print $1}' | wc -L )
|
|
WIDTH_NAME=$(( ${WIDTH_NAME} - ${#BENAME_STARTS_WITH} - 1 ))
|
|
printf "%-${WIDTH_NAME}s %-6s %-10s %6s %6s %s\n" \
|
|
BE Active Mountpoint Space Policy Created
|
|
echo "${LIST}" \
|
|
| while read NAME USED MOUNTPOINT Y m d H M
|
|
do
|
|
TOTAL=0
|
|
NAME=${NAME##*/}
|
|
ACTIVE=''
|
|
if [ "${BENAME_STARTS_WITH}/${NAME}" = "${ROOTFS}" ]
|
|
then
|
|
ACTIVE="${ACTIVE}N"
|
|
fi
|
|
if [ "${BENAME_STARTS_WITH}/${NAME}" = "${BOOTFS}" ]
|
|
then
|
|
ACTIVE="${ACTIVE}R"
|
|
fi
|
|
if [ -z "${ACTIVE}" ]
|
|
then
|
|
ACTIVE="-"
|
|
fi
|
|
case ${ACTIVE} in
|
|
(N|NR) MOUNT="/" ;;
|
|
(*) MOUNT="-" ;;
|
|
esac
|
|
if [ "${2}" = "-S" ]
|
|
then
|
|
USED_ALL=$( zfs list -H -t all -o name,used )
|
|
while read I
|
|
do
|
|
USED=$( echo "${USED_ALL}" | grep -m 1 -E "^${I}" | awk '{print $2}' )
|
|
if [ ${USED} = "0" ]
|
|
then
|
|
continue
|
|
fi
|
|
case "${USED}" in
|
|
(*K) USED=$( echo "${USED} * 10" | sed s/K// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100 )) ;;
|
|
(*M) USED=$( echo "${USED} * 10" | sed s/M// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000 )) ;;
|
|
(*G) USED=$( echo "${USED} * 10" | sed s/G// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000000 )) ;;
|
|
(*T) USED=$( echo "${USED} * 10" | sed s/T// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000000000 )) ;;
|
|
(*P) USED=$( echo "${USED} * 10" | sed s/P// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000000000000 )) ;;
|
|
(*E) USED=$( echo "${USED} * 10" | sed s/E// | bc | cut -d '.' -f 1 ); USED=$(( ${USED} * 100000000000000000 )) ;;
|
|
# 100000000000000000 is maximum that is supported by $(( ))
|
|
(*Z) USED=$( echo "${USED} * 10000000000000000000" | sed s/Z// | bc ) ;;
|
|
esac
|
|
TOTAL=$(( $( echo ${USED} | cut -d '.' -f 1 ) + ${TOTAL} ))
|
|
done << EOF
|
|
$( zfs list -H -t all -o name,origin -r "${BENAME_STARTS_WITH}/${NAME}" | tr '\t' '\n' | grep -v "^-$" )
|
|
EOF
|
|
RANGE=$( echo ${TOTAL} | cut -d . -f 1 )
|
|
case $( echo "${RANGE}" | wc -c | tr -c -d '[0-9]\n' ) in
|
|
(5|6|7) TOTAL="$( echo ${TOTAL} / 1000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )K" ;;
|
|
(8|9|10) TOTAL="$( echo ${TOTAL} / 1000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )M" ;;
|
|
(11|12|13) TOTAL="$( echo ${TOTAL} / 1000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )G" ;;
|
|
(14|15|16) TOTAL="$( echo ${TOTAL} / 1000000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )T" ;;
|
|
(17|18|19) TOTAL="$( echo ${TOTAL} / 1000000000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )P" ;;
|
|
(20|21|22) TOTAL="$( echo ${TOTAL} / 1000000000000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )E" ;;
|
|
(23|24|25) TOTAL="$( echo ${TOTAL} / 1000000000000000000000 | bc -l | grep -m 1 -o -E "[0-9]*\.[0-9]{1}" )Z" ;;
|
|
esac
|
|
else
|
|
TOTAL=${USED}
|
|
fi
|
|
printf "%-${WIDTH_NAME}s %-6s %-10s %6s %-6s " ${NAME} ${ACTIVE} ${MOUNT} ${TOTAL} "static"
|
|
date -j -f "%a %b %d %H:%M %Y" "${Y} ${m} ${d} ${H} ${M}" +"%Y-%m-%d %H:%M"
|
|
done
|
|
;;
|
|
|
|
(create) # ------------------------------------------------------------------
|
|
case ${#} in
|
|
(4)
|
|
if ! [ ${2} = "-e" ]
|
|
then
|
|
__usage
|
|
fi
|
|
__be_exist ${POOL}/ROOT/${3}
|
|
if zfs list -H -o name ${POOL}/ROOT/${4} 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: Boot environment '${4}' already exists"
|
|
exit 1
|
|
fi
|
|
__be_new ${POOL}/ROOT/${3} ${POOL}/ROOT/${4}
|
|
;;
|
|
(2)
|
|
if __be_snapshot ${2}
|
|
then
|
|
if ! zfs snapshot -r ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: Cannot create '${2}' recursive snapshot"
|
|
exit 1
|
|
fi
|
|
echo "Created successfully"
|
|
else
|
|
__be_new ${ROOTFS} ${POOL}/ROOT/${2}
|
|
fi
|
|
;;
|
|
(*)
|
|
__usage
|
|
;;
|
|
esac
|
|
;;
|
|
|
|
(activate) # ----------------------------------------------------------------
|
|
if [ ${#} -ne 2 ]
|
|
then
|
|
__usage
|
|
fi
|
|
__be_exist ${POOL}/ROOT/${2}
|
|
if [ "${BOOTFS}" = "${POOL}/ROOT/${2}" ]
|
|
then
|
|
echo "Already activated"
|
|
exit 0
|
|
else
|
|
if mount | grep -E "^${POOL}/ROOT/${2} " 1> /dev/null 2> /dev/null
|
|
then
|
|
MNT=$( mount | grep -E "^${POOL}/ROOT/${2} " | awk '{print $3}' )
|
|
if [ "${MNT}" != "/" ]
|
|
then
|
|
echo "ERROR: The '${2}' is mounted at '${MNT}'"
|
|
echo "ERROR: Cannot activate mounted boot environment"
|
|
exit 1
|
|
fi
|
|
fi
|
|
if [ "${ROOTFS}" != "${POOL}/ROOT/${2}" ]
|
|
then
|
|
TMPMNT="/tmp/BE"
|
|
if ! mkdir -p ${TMPMNT}
|
|
then
|
|
echo "ERROR: Cannot create '${TMPMNT}' directory"
|
|
exit 1
|
|
fi
|
|
MOUNT=0
|
|
while read FS MNT
|
|
do
|
|
if [ "${FS}" = "${POOL}/ROOT/${2}" ]
|
|
then
|
|
MOUNT=${MNT}
|
|
fi
|
|
done << EOF
|
|
$( mount -p | awk '{print $1 " " $2}' )
|
|
EOF
|
|
if [ ${MOUNT} -eq 0 ]
|
|
then
|
|
zfs set canmount=noauto ${POOL}/ROOT/${2}
|
|
zfs set mountpoint=${TMPMNT} ${POOL}/ROOT/${2}
|
|
zfs mount ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null
|
|
else
|
|
TMPMNT=${MOUNT}
|
|
fi
|
|
cp /boot/zfs/zpool.cache ${TMPMNT}/boot/zfs/zpool.cache
|
|
LOADER_CONFIGS=${TMPMNT}/boot/loader.conf
|
|
if [ -f ${TMPMNT}/boot/loader.conf.local ]
|
|
then
|
|
LOADER_CONFIGS="${LOADER_CONFIGS} ${TMPMNT}/boot/loader.conf.local"
|
|
fi
|
|
sed -i '' -E s/"^vfs.root.mountfrom=.*$"/"vfs.root.mountfrom=\"zfs:${POOL}\/ROOT\/${2##*/}\""/g ${LOADER_CONFIGS} 2> /dev/null
|
|
if [ ${MOUNT} -eq 0 ]
|
|
then
|
|
zfs umount ${POOL}/ROOT/${2}
|
|
zfs set mountpoint=legacy ${POOL}/ROOT/${2}
|
|
fi
|
|
fi
|
|
if ! zpool set bootfs=${POOL}/ROOT/${2} ${POOL} 2> /dev/null
|
|
then
|
|
echo "ERROR: Failed to activate '${POOL}/ROOT/${2}'"
|
|
exit 1
|
|
fi
|
|
fi
|
|
# disable automatic mount on all inactive datasets
|
|
zfs list -H -o name -r ${POOL}/ROOT \
|
|
| grep -v "${POOL}/ROOT/${2}" \
|
|
| while read I
|
|
do
|
|
zfs set canmount=noauto ${I}
|
|
done
|
|
# enable automatic mount for active BE and promote it
|
|
zfs list -H -o name,origin -t filesystem -r ${POOL}/ROOT/${2} \
|
|
| while read I ORIGIN
|
|
do
|
|
zfs set canmount=on ${I}
|
|
if [ ${ORIGIN} != "-" ]
|
|
then
|
|
zfs promote ${I}
|
|
fi
|
|
done
|
|
echo "Activated successfully"
|
|
;;
|
|
|
|
(destroy) # -----------------------------------------------------------------
|
|
case ${#} in
|
|
(2)
|
|
echo "Are you sure you want to destroy '${2}'?"
|
|
echo -n "This action cannot be undone (y/[n]): "
|
|
read CHOICE
|
|
DESTROY=${2}
|
|
;;
|
|
(3)
|
|
if [ "${2}" != "-F" ]
|
|
then
|
|
__usage
|
|
fi
|
|
CHOICE=Y
|
|
DESTROY=${3}
|
|
;;
|
|
(*)
|
|
__usage
|
|
;;
|
|
esac
|
|
__be_exist ${POOL}/ROOT/${DESTROY}
|
|
if [ "${BOOTFS}" = "${POOL}/ROOT/${DESTROY}" ]
|
|
then
|
|
echo "ERROR: '${POOL}/ROOT/${2}' is current active boot environment"
|
|
exit 1
|
|
fi
|
|
case ${CHOICE} in
|
|
(Y|y|[Yy][Ee][Ss])
|
|
# delete snapshot or delete boot environment
|
|
if __be_snapshot ${POOL}/ROOT/${DESTROY}
|
|
then
|
|
# destroy desired snapshot
|
|
if ! zfs destroy -r ${POOL}/ROOT/${DESTROY} 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: Snapshot '${2}' is origin for other boot environment(s)"
|
|
exit 1
|
|
fi
|
|
else
|
|
# promote clones dependent on snapshots used by destroyed boot environment
|
|
zfs list -H -t all -o name,origin \
|
|
| while read NAME ORIGIN
|
|
do
|
|
if echo "${ORIGIN}" | grep -q -E "${POOL}/ROOT/${DESTROY}(/.*@|@)" 2> /dev/null
|
|
then
|
|
zfs promote ${NAME}
|
|
fi
|
|
done
|
|
# get origins used by destroyed boot environment
|
|
ORIGINS=$( zfs list -H -t all -o origin -r ${POOL}/ROOT/${DESTROY} | grep -v '^-$' )
|
|
# destroy boot environment
|
|
zfs destroy -r ${POOL}/ROOT/${DESTROY}
|
|
# destroy origins used by destroyed boot environment
|
|
echo "${ORIGINS}" \
|
|
| while read I
|
|
do
|
|
zfs destroy ${I}
|
|
done
|
|
fi
|
|
echo "Destroyed successfully"
|
|
;;
|
|
(*)
|
|
echo "'${DESTROY}' has not been destroyed"
|
|
;;
|
|
esac
|
|
;;
|
|
|
|
(rename) # ------------------------------------------------------------------
|
|
if [ ${#} -ne 3 ]
|
|
then
|
|
__usage
|
|
fi
|
|
__be_exist ${POOL}/ROOT/${2}
|
|
if [ "${BOOTFS}" = "${POOL}/ROOT/${2}" ]
|
|
then
|
|
echo "ERROR: Renaming the active BE is not supported"
|
|
exit 1
|
|
fi
|
|
if zfs list -H -o name ${POOL}/ROOT/${3} 2> /dev/null
|
|
then
|
|
echo "ERROR: Boot environment '${3}' already exists"
|
|
exit 1
|
|
fi
|
|
zfs rename ${POOL}/ROOT/${2} ${POOL}/ROOT/${3}
|
|
echo "Renamed successfully"
|
|
;;
|
|
|
|
(mount) # -------------------------------------------------------------------
|
|
COMPLETE=1
|
|
if [ ${#} -eq 1 -o ${#} -eq 2 ]
|
|
then
|
|
if [ ${2} ]
|
|
then
|
|
BE=${2}
|
|
else
|
|
zfs list -H -o name -d 1 -r ${POOL}/ROOT \
|
|
| grep "${POOL}/ROOT/" \
|
|
| while read NAME
|
|
do
|
|
NAME=${NAME##*/}
|
|
if mount | grep -E "^${POOL}/ROOT/${NAME}" 1> /dev/null 2> /dev/null
|
|
then
|
|
echo ${NAME}
|
|
mount \
|
|
| grep -E "^${POOL}/ROOT/${NAME}" \
|
|
| awk '{print $1 " " $3}' \
|
|
| column -t \
|
|
| awk '{print " " $0}'
|
|
echo
|
|
fi
|
|
done
|
|
exit 0
|
|
fi
|
|
elif [ ${#} -eq 3 ]
|
|
then
|
|
BE=${2}
|
|
TARGET=${3}
|
|
else
|
|
__usage
|
|
fi
|
|
__be_exist "${POOL}/ROOT/${BE}"
|
|
if mount | grep -E "^${POOL}/ROOT/${BE} " 1> /dev/null 2> /dev/null
|
|
then
|
|
MNT=$( mount | grep -E "^${POOL}/ROOT/${BE} " | awk '{print $3}' )
|
|
echo "The '${BE}' is already mounted at '${MNT}'"
|
|
exit 1
|
|
fi
|
|
if ! [ ${3} ]
|
|
then
|
|
TARGET=$( mktemp -d /tmp/tmp.XXXXXX )
|
|
mkdir -p ${TARGET}
|
|
fi
|
|
if ! mount -t zfs ${POOL}/ROOT/${BE} ${TARGET}
|
|
then
|
|
echo "ERROR: Cannot mount '${POOL}/ROOT/${BE}' at '${TARGET}' mountpoint"
|
|
exit 1
|
|
fi
|
|
PREFIX=$( echo ${POOL}/ROOT/${BE}/ | sed 's/\//\\\//g' )
|
|
zfs list -H -o name,mountpoint -r ${POOL}/ROOT/${BE} \
|
|
| grep -v "legacy$" \
|
|
| sort -n \
|
|
| grep -E "^${POOL}/ROOT/${BE}/" \
|
|
| while read FS MOUNTPOINT
|
|
do
|
|
if [ "{FS}" != "${POOL}/ROOT/${BE}" ]
|
|
then
|
|
INHERIT=$( zfs get -H -o source mountpoint ${FS} )
|
|
if [ "${INHERIT}" = "local" ]
|
|
then
|
|
if [ "${MOUNTPOINT}" = "legacy" ]
|
|
then
|
|
continue
|
|
else
|
|
MOUNTPOINT=$( echo "${FS}" | sed s/"${PREFIX}"//g )
|
|
MOUNTPOINT="/${MOUNTPOINT}"
|
|
fi
|
|
fi
|
|
fi
|
|
if ! mkdir -p ${TARGET}${MOUNTPOINT} 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: Cannot create '${TARGET}${MOUNTPOINT}' mountpoint"
|
|
exit 1
|
|
fi
|
|
if ! mount -t zfs ${FS} ${TARGET}${MOUNTPOINT} 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: Cannot mount '${FS}' at '${TARGET}${MOUNTPOINT}' mountpoint"
|
|
COMPLETE=0
|
|
fi
|
|
done
|
|
if [ ${COMPLETE} -eq 0 ]
|
|
then
|
|
echo "Partially mounted"
|
|
else
|
|
echo "Mounted successfully on '${TARGET}'"
|
|
fi
|
|
;;
|
|
|
|
(umount|unmount) # ------------------------------------------------------------------
|
|
COMPLETE=1
|
|
if [ ${#} -eq 2 ]
|
|
then
|
|
BE=${2}
|
|
elif [ ${#} -eq 3 ]
|
|
then
|
|
BE=${3}
|
|
if [ "${2}" = "-f" ]
|
|
then
|
|
OPTS="-f"
|
|
else
|
|
__usage
|
|
fi
|
|
else
|
|
__usage
|
|
fi
|
|
__be_exist "$POOL/ROOT/$BE"
|
|
if ! mount | grep -E "^${POOL}/ROOT/${BE} " 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "The '${BE}' is not mounted"
|
|
exit 1
|
|
fi
|
|
mount \
|
|
| grep "^${POOL}/ROOT/${BE}" \
|
|
| awk '{print $1}' \
|
|
| sort -n -r \
|
|
| while read FS
|
|
do
|
|
if ! umount ${OPTS} ${FS} 1> /dev/null 2> /dev/null
|
|
then
|
|
echo "ERROR: Cannot umount '${FS}' dataset"
|
|
COMPLETE=0
|
|
fi
|
|
done
|
|
if [ ${COMPLETE} -eq 0 ]
|
|
then
|
|
echo "Partially unmounted"
|
|
else
|
|
echo "Unmounted successfully"
|
|
fi
|
|
;;
|
|
|
|
(*) # -----------------------------------------------------------------------
|
|
__usage
|
|
;;
|
|
|
|
esac
|