mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
a device from two guests, or from dom 0 and a guest, can destroy the filesystem, and this check prevents that. This should ensure that the xm tests 11_block_attach_shared_dom0 and 12_block_attach_shared_domU should pass. Closes bug #331. Devices may be shared only if all uses are read-only. If anyone has read-write access to a device, then no sharing is allowed. The mode in the config file may now have an exclamation mark appended, to indicate that devices may be shared (i.e. that this new check should be bypassed). This supports some network block devices, but is clearly dangerous and should only be used when you know what you are doing. The mode specified in the config file is now written explicitly to the store, To implement this, the blkback driver has been changed to create two entries in /sys describing each device in use. This means that we can determine which devices are in use without crawling through the store. The physical-device node has been changed to give the major and minor of the device, separated by a colon. This means that we do not need to pack these numbers into one, removing the restriction to 8 bit minors that we had in place before. The mode specified in the config file is now written explicitly to the store, rather than using the presence or absence of a read-only node. This supports the write-sharing override above. If the device is in use, a new hotplug status of "busy" is written to the store, and a message is written to a new hotplug-error node. Xend uses these things for diagnosis. The block scripts do not need to handle online or offline events, so this support has been removed. These scripts can be called twice, depending upon the hotplug config, so they now identify the second run and do not attempt to set up the device again. The device directories in the store are cleaned out before new details are written there. This prevents stale information from messing up block device hotplugging. This will be one cause of "blkback: changing physical device not supported" messages. Signed-off-by: Ewan Mellor <ewan@xensource.com>
164 lines
3.2 KiB
Bash
164 lines
3.2 KiB
Bash
#!/bin/sh
|
|
|
|
dir=$(dirname "$0")
|
|
. "$dir/block-common.sh"
|
|
|
|
expand_dev() {
|
|
local dev
|
|
case $1 in
|
|
/*)
|
|
dev=$1
|
|
;;
|
|
*)
|
|
dev=/dev/$1
|
|
;;
|
|
esac
|
|
echo -n $dev
|
|
}
|
|
|
|
|
|
##
|
|
# check_sharing device device_major_minor writable
|
|
#
|
|
# Check whether the device requested is already in use. To use the device in
|
|
# read-only mode, it may be in use in read-only mode, but may not be in use in
|
|
# read-write anywhere at all. To use the device in read-write mode, it must
|
|
# not be in use anywhere at all.
|
|
#
|
|
check_sharing()
|
|
{
|
|
|
|
local dev="$1"
|
|
local devmm="$2"
|
|
local writable="$3"
|
|
local file
|
|
|
|
if [ "$writable" ]
|
|
then
|
|
toskip="^$"
|
|
else
|
|
toskip="^[^ ]* [^ ]* [^ ]* ro "
|
|
fi
|
|
|
|
for file in $(cat /proc/mounts | grep -v "$toskip" | cut -f 1 -d ' ')
|
|
do
|
|
if [ -e "$file" ]
|
|
then
|
|
local d=$(device_major_minor "$file")
|
|
|
|
if [ "$d" == "$devmm" ]
|
|
then
|
|
if [ "$writable" ]
|
|
then
|
|
m1=""
|
|
m2=""
|
|
else
|
|
m1="read-write "
|
|
m2="read-only "
|
|
fi
|
|
|
|
ebusy \
|
|
"Device $dev is mounted ${m1}in the privileged domain,
|
|
and so cannot be mounted ${m2}by a guest."
|
|
fi
|
|
fi
|
|
done
|
|
|
|
for file in /sys/devices/xen-backend/*/physical_device
|
|
do
|
|
if [ -e "$file" ] # Cope with no devices, i.e. the * above did not expand.
|
|
then
|
|
local d=$(cat "$file")
|
|
if [ "$d" == "$devmm" ]
|
|
then
|
|
if [ "$writable" ]
|
|
then
|
|
ebusy \
|
|
"Device $dev is already mounted in a guest domain, and so
|
|
cannot be mounted read-write now."
|
|
else
|
|
local m=$(cat "${file/physical_device/mode}")
|
|
|
|
if expr index "$m" 'w' >/dev/null
|
|
then
|
|
ebusy \
|
|
"Device $dev is already mounted read-write in a guest domain,
|
|
and so cannot be mounted read-only again."
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
check_device_sharing()
|
|
{
|
|
local dev="$1"
|
|
local devmm=$(device_major_minor "$dev")
|
|
local mode=$(xenstore_read "$XENBUS_PATH/mode")
|
|
|
|
if ! expr index "$mode" 'w' >/dev/null
|
|
then
|
|
# No w implies read-only use; sharing with writers must be prevented.
|
|
check_sharing "$dev" "$devmm" ""
|
|
elif ! expr index "$mode" '!' >/dev/null
|
|
then
|
|
# No exclamation mark implies all sharing must be prevented.
|
|
check_sharing "$dev" "$devmm" 1
|
|
fi
|
|
}
|
|
|
|
|
|
t=$(xenstore_read_default "$XENBUS_PATH/type" "MISSING")
|
|
|
|
case "$command" in
|
|
add)
|
|
phys=$(xenstore_read_default "$XENBUS_PATH/physical-device" "MISSING")
|
|
if [ "$phys" != "MISSING" ]
|
|
then
|
|
# Depending upon the hotplug configuration, it is possible for this
|
|
# script to be called twice, so just bail.
|
|
exit 0
|
|
fi
|
|
p=$(xenstore_read "$XENBUS_PATH/params")
|
|
case $t in
|
|
phy)
|
|
dev=$(expand_dev $p)
|
|
check_device_sharing "$dev"
|
|
write_dev "$dev"
|
|
exit 0
|
|
;;
|
|
|
|
file)
|
|
for dev in /dev/loop* ; do
|
|
if losetup $dev $p; then
|
|
write_dev "$dev"
|
|
exit 0
|
|
fi
|
|
done
|
|
exit 1
|
|
;;
|
|
esac
|
|
;;
|
|
|
|
remove)
|
|
case $t in
|
|
phy)
|
|
exit 0
|
|
;;
|
|
|
|
file)
|
|
node=$(xenstore_read "$XENBUS_PATH/node")
|
|
losetup -d $node
|
|
exit 0
|
|
;;
|
|
esac
|
|
;;
|
|
|
|
esac
|
|
|
|
# If we've reached here, $t is neither phy nor file, so fire a helper script.
|
|
[ -x /etc/xen/scripts/block-"$t" ] && \
|
|
/etc/xen/scripts/block-"$t" "$command" $node
|