diff --git a/scripts/common.sh.in b/scripts/common.sh.in index ae1c5cf09e..a6586f4aa9 100644 --- a/scripts/common.sh.in +++ b/scripts/common.sh.in @@ -288,34 +288,61 @@ check_loop_utils() { # -# Find and return an unused loopback device. +# Find and return an unused loop device. A new /dev/loopN node will be +# created if required. The kernel loop driver will automatically register +# the minor as long as it's less than /sys/module/loop/parameters/max_loop. # unused_loop_device() { - for DEVICE in `ls -1 /dev/loop[0-9]* 2>/dev/null`; do - ${LOSETUP} ${DEVICE} &>/dev/null - if [ $? -ne 0 ]; then - echo ${DEVICE} - return - fi - done + local DEVICE=`${LOSETUP} -f` + local MAX_LOOP_PATH="/sys/module/loop/parameters/max_loop" + local MAX_LOOP; - die "Error: Unable to find unused loopback device" + # An existing /dev/loopN device was available. + if [ -n "${DEVICE}" ]; then + echo "${DEVICE}" + return 0 + fi + + # Create a new /dev/loopN provided we are not at MAX_LOOP. + if [ -f "${MAX_LOOP_PATH}" ]; then + MAX_LOOP=`cat /sys/module/loop/parameters/max_loop` + if [ ${MAX_LOOP} -eq 0 ]; then + MAX_LOOP=255 + fi + + for (( i=0; i<=${MAX_LOOP}; i++ )); do + DEVICE="/dev/loop$i" + + if [ -b "${DEVICE}" ]; then + continue + else + mknod -m660 "${DEVICE}" b 7 $i + chown root.disk "${DEVICE}" + chmod 666 "${DEVICE}" + + echo "${DEVICE}" + return 0 + fi + done + fi + + die "Error: Unable to create new loopback device" } # # This can be slightly dangerous because the loop devices we are # cleaning up may not be ours. However, if the devices are currently # in use we will not be able to remove them, and we only remove -# devices which include 'zpool' in the name. So any damage we might -# do should be limited to other zfs related testing. +# devices which include 'zpool' or 'deleted' in the name. So any +# damage we might do should be limited to other zfs related testing. # cleanup_loop_devices() { local TMP_FILE=`mktemp` ${LOSETUP} -a | tr -d '()' >${TMP_FILE} ${AWK} -F":" -v losetup="$LOSETUP" \ - '/zpool/ { system("losetup -d "$1) }' ${TMP_FILE} - ${AWK} -F" " '/zpool/ { system("rm -f "$3) }' ${TMP_FILE} + '/zpool/ || /deleted/ { system("losetup -d "$1) }' ${TMP_FILE} + ${AWK} -F" " '/zpool/ || /deleted/ { system("rm -f "$3) }' ${TMP_FILE} rm -f ${TMP_FILE} }