@@ -3,6 +3,7 @@ include $(XEN_ROOT)/tools/Rules.mk
# Xen script dir and scripts to go there.
XEN_SCRIPTS =
+XEN_SCRIPTS += locking.sh
XEN_SCRIPTS += block
XEN_SCRIPTS += vif-bridge
XEN_SCRIPTS += vif-ip
@@ -5,6 +5,7 @@
DIR=$(dirname "$0")
. "${DIR}/hotplugpath.sh"
+. "${DIR}/locking.sh"
PATH=${bindir}:${sbindir}:${LIBEXEC_BIN}:/bin:/usr/bin:/sbin:/usr/sbin
export PATH
@@ -52,6 +53,7 @@ case $xstatus in
available_disks="$available_disks $disk"
eval $disk=free
done
+ claim_lock block
# Mark the used vnd(4) devices as ``used''.
for disk in `sysctl hw.disknames`; do
case $disk in
@@ -67,6 +69,7 @@ case $xstatus in
break
fi
done
+ release_lock block
if [ x$device = x ] ; then
error "no available vnd device"
fi
@@ -76,7 +79,7 @@ case $xstatus in
device=$xparams
;;
esac
- physical_device=$(stat -f '%r' "$device")
+ physical_device=$(stat -L -f '%r' "$device")
xenstore-write $xpath/physical-device $physical_device
xenstore-write $xpath/hotplug-status connected
exit 0
new file mode 100644
@@ -0,0 +1,121 @@
+#
+# Copyright (c) 2005 XenSource Ltd.
+# Copyright (c) 2007 Red Hat
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; If not, see <http://www.gnu.org/licenses/>.
+#
+
+#
+# Serialisation
+#
+
+LOCK_BASEDIR=$XEN_LOCK_DIR/xen-hotplug
+
+_setlockfd()
+{
+ _lockfd=9
+ _lockfile="$LOCK_BASEDIR/$1"
+}
+
+
+claim_lock()
+{
+ mkdir -p "$LOCK_BASEDIR"
+ _setlockfd $1
+ # The locking strategy is identical to that from with-lock-ex(1)
+ # from chiark-utils, except using flock. It has the benefit of
+ # it being possible to safely remove the lockfile when done.
+ # See below for a correctness proof.
+ local stat
+ while true; do
+ eval "exec $_lockfd<> $_lockfile"
+ # we can't flock $_lockfd here, as the shell closes it on exec.
+ # Workaround by redirecting to 0 for the command, and flock 0 instead.
+ flock -v -x 0 0<& $_lockfd|| exit 1
+ local file_stat
+ local fd_stat
+ if fd_stat=$(stat -f '%d.%i' 0<&$_lockfd 2>/dev/null) && file_stat=$(stat -f '%d.%i' $_lockfile 2>/dev/null )
+ then
+ if [ "$fd_stat" = "$file_stat" ] ; then break; fi
+ fi
+ # Some versions of bash appear to be buggy if the same
+ # $_lockfile is opened repeatedly. Close the current fd here.
+ eval "exec $_lockfd<&-"
+ done
+}
+
+
+release_lock()
+{
+ _setlockfd $1
+ rm "$_lockfile"
+}
+
+# Protocol and correctness proof:
+#
+# * The lock is owned not by a process but by an open-file (informally
+# an fd). Any process with an fd onto this open-file is a
+# lockholder and may perform the various operations; such a process
+# should only do so when its co-lockholder processes expect. Ie, we
+# will treat all processes holding fds onto the open-file as acting
+# in concert and not distinguish between them.
+#
+# * You are a lockholder if
+# - You have an fd onto an open-file which
+# currently holds an exclusive flock lock on its inum
+# - and that inum is currently linked at the lockfile path
+#
+# * The rules are:
+# - No-one but a lockholder may unlink the lockfile path
+# (or otherwise cause it to stop referring to a file it
+# refers to).
+# - Anyone may open the lockfile with O_CREAT
+#
+# * The protocol for locking is:
+# - Open the file (O_CREAT)
+# - flock it
+# - fstat the fd you have open
+# - stat the lockfile path
+# - if both are equal you have the lock, otherwise try again.
+#
+# * Informal proof of exclusivity:
+# - No two open-files can hold an fcntl lock onto the same file
+# at the same time
+# - No two files can have the same name at the same time
+#
+# * Informal proof of correctness of locking protocol:
+# - After you call flock successfully no-one other than you
+# (someone with the same open-file) can stop you having
+# that flock lock.
+# - Obviously the inum you get from the fstat is fixed
+# - At the point where you call stat there are two
+# possibilities:
+# (i) the lockfile path referred to some other inum
+# in which case you have failed
+# (ii) the lockfile path referred to the same file
+# in which case at that point you were the
+# lockholder (by definition).
+#
+# * Informal proof that no-one else can steal the lock:
+# - After you call flock successfully no-one other than you
+# can stop you having that flock lock
+# - No-one other than the lockholder is permitted to stop
+# the path referring to a particular inum. So if you
+# hold the lock then only you are allowed to stop the
+# path referring to the file whose flock you hold; so
+# it will continue to refer to that file.
+# That's both the conditions for being the lockholder.
+#
+# Thus once you hold the lock at any instant, you will
+# continue to do so until you voluntarily stop doing so
+# (eg by unlinking the lockfile or closing the fd).
On NetBSD, some block device configuration requires serialisation. Introcuce locking functions (derived from the Linux version), and use them in the block script where appropriate. Signed-off-by: Manuel Bouyer <bouyer@netbsd.org> --- tools/hotplug/NetBSD/Makefile | 1 + tools/hotplug/NetBSD/block | 5 +- tools/hotplug/NetBSD/locking.sh | 121 ++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 tools/hotplug/NetBSD/locking.sh