c7420318e2
Getting loop device backing file path was broken: ${NAME%p*} for not-partitioned devices will cut the actual device name. Use full name instead. This probably breaks handling partitioned devices, but such devices should not appear in a directory flagged to be ignored (VM images) QubesOS/qubes-issues#3084
171 lines
4.4 KiB
Bash
Executable File
171 lines
4.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
shopt -s nullglob
|
|
|
|
|
|
export LC_CTYPE=en_US.UTF-8
|
|
NAME=${DEVNAME#/dev/}
|
|
DESC="`echo "${ID_MODEL} (${ID_FS_LABEL})" | iconv -f utf8 -t ascii//TRANSLIT`"
|
|
SIZE=$[ $(cat /sys/$DEVPATH/size) * 512 ]
|
|
MODE=w
|
|
QDB_KEY="/qubes-block-devices/$NAME"
|
|
|
|
xs_remove() {
|
|
if is_attached /sys$DEVPATH; then
|
|
return 0
|
|
fi
|
|
|
|
if qubesdb-read -q "$QDB_KEY/desc" >/dev/null; then
|
|
qubesdb-rm "$QDB_KEY/"
|
|
qubesdb-write /qubes-block-devices ''
|
|
fi
|
|
}
|
|
|
|
is_used() {
|
|
local sys_devpath=$1
|
|
local devname=$(grep ^DEVNAME= $sys_devpath/uevent | cut -f 2 -d =)
|
|
# mounted; or enabled swap
|
|
if lsblk -dnr -o MOUNTPOINT "/dev/$devname" | grep -q .; then
|
|
return 0
|
|
fi
|
|
# part of other device-mapper
|
|
if [ -n "`ls -A $sys_devpath/holders 2> /dev/null`" ]; then
|
|
return 0
|
|
fi
|
|
# open device-mapper device
|
|
if [ -f "$sys_devpath/dm/name" ] && \
|
|
/sbin/dmsetup info "$(cat $sys_devpath/dm/name)" |\
|
|
grep -q "^Open count:.*[1-9]"; then
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
refresh_another() {
|
|
# launch this script for other device
|
|
local devpath=$1
|
|
local launch_env=$(udevadm info -q all -x -p "$devpath" \
|
|
| grep ^E: | cut -d ' ' -f 2- | tr ' ' ':')
|
|
env -i PATH=$PATH $launch_env $0
|
|
}
|
|
|
|
# communicate with xenstored through socket in dom0
|
|
# trying to access xenstore before xenstored is started, hang forever (in
|
|
# non-killable state), so better fail ('-s' in VM if /proc/xen isn't mounted
|
|
# yet) than hang dom0 boot
|
|
if [ ! -r /proc/xen/capabilities ] || grep -q control_d /proc/xen/capabilities; then
|
|
XENSTORE_LS="xenstore-ls -s"
|
|
else
|
|
XENSTORE_LS="xenstore-ls"
|
|
fi
|
|
is_attached() {
|
|
dev_hex=$(stat -c %t:%T /dev/$(basename $1))
|
|
if [ -z "$dev_hex" -o "$dev_hex" = "0:0" ]; then
|
|
return 1
|
|
fi
|
|
$XENSTORE_LS backend/vbd | grep -q "physical-device = \"$dev_hex\""
|
|
}
|
|
|
|
# update info about parent devices, if any:
|
|
if [ -f /sys$DEVPATH/partition ]; then
|
|
parent=$(dirname $(readlink -f /sys$DEVPATH))
|
|
refresh_another /$(realpath --relative-to=/sys $parent)
|
|
# if parent device is already attached, skip its partitions
|
|
if is_attached $parent; then
|
|
xs_remove
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# and underlying devices of device-mapper (if any)
|
|
for dev in /sys$DEVPATH/slaves/*; do
|
|
refresh_another /$(realpath --relative-to=/sys $dev)
|
|
done
|
|
|
|
# cache slave devices for remove event
|
|
if [ -n "$DM_NAME" ]; then
|
|
ls -1 /sys$DEVPATH/slaves/ > /var/run/qubes/block-slave-cache-$NAME
|
|
fi
|
|
|
|
# then take care of this device:
|
|
|
|
# udev rules already excluded this device:
|
|
|
|
if [ "$DM_UDEV_DISABLE_DISK_RULES_FLAG" = "1" ]; then
|
|
xs_remove
|
|
exit 0
|
|
fi
|
|
|
|
# device itself is already used
|
|
if is_used /sys$DEVPATH; then
|
|
xs_remove
|
|
exit 0
|
|
fi
|
|
|
|
# or one of its partitions is used
|
|
# or already attached (prevent attaching both device and its partition(s) at
|
|
# the same time)
|
|
for part in /sys$DEVPATH/$NAME*; do
|
|
if [ -d $part ]; then
|
|
if is_used $part || is_attached $part; then
|
|
xs_remove
|
|
exit 0
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# or "empty" loop device
|
|
if [ "$MAJOR" -eq 7 -a ! -d /sys/$DEVPATH/loop ]; then
|
|
xs_remove
|
|
exit 0
|
|
fi
|
|
|
|
# ... and loop devices from excluded directories
|
|
if [[ "$NAME" = 'loop'* ]]; then
|
|
backing_file=$(cat /sys/block/${NAME}/loop/backing_file)
|
|
if [ -n "$backing_file" ]; then
|
|
dir_to_check=$(dirname "$backing_file")
|
|
while [ "$dir_to_check" != "/" -a "$dir_to_check" != "." ]; do
|
|
if [ -e "$dir_to_check/.qubes-exclude-block-devices" ]; then
|
|
xs_remove
|
|
exit 0
|
|
fi
|
|
dir_to_check=$(dirname "$dir_to_check")
|
|
done
|
|
fi
|
|
fi
|
|
|
|
# Check if device is read-only
|
|
if [ "`cat /sys/$DEVPATH/ro`" -eq 1 ]; then
|
|
MODE=r
|
|
fi
|
|
|
|
# Special case for CD
|
|
if [ "$ID_TYPE" = "cd" ]; then
|
|
if [ "$ID_CDROM_MEDIA" != "1" ]; then
|
|
# Hide empty cdrom drive
|
|
xs_remove
|
|
exit 0
|
|
fi
|
|
MODE=r
|
|
fi
|
|
|
|
# Special description for loop devices
|
|
if [ -d /sys/$DEVPATH/loop ]; then
|
|
DESC=$(cat /sys/$DEVPATH/loop/backing_file)
|
|
fi
|
|
# and for device-mapper
|
|
if [ -n "$DM_NAME" ]; then
|
|
DESC="$DM_NAME"
|
|
fi
|
|
|
|
# The last one is meant to trigger watches
|
|
qubesdb-write \
|
|
"$QDB_KEY/desc" "$DESC" \
|
|
"$QDB_KEY/size" "$SIZE" \
|
|
"$QDB_KEY/mode" "$MODE" \
|
|
/qubes-block-devices ''
|
|
|
|
# Make sure that block backend is loaded
|
|
/sbin/modprobe xen-blkback 2> /dev/null || /sbin/modprobe blkbk
|