Files
xen/tools/examples/block
T
emellor@leeni.uk.xensource.com d966085083 Check when using physical devices that the device is not already in use. Using
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>
2005-11-25 20:58:07 +00:00

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