Files
xen/tools/hotplug/Linux/locking.sh
T
Olaf Hering 5622adc372 hotplug/Linux: close lockfd after lock attempt
When a HVM guest is shutdown some of the 'remove' events can not claim
the lock for some reason. Instead they try to grab the lock in a busy
loop, until udev reaps the xen-hotplug-cleanup helper.
After analyzing the resulting logfile its not obvious what the cause is.
The only explanation is that bash (?) gets confused if the same lockfd
is opened again and again. Closing it in each iteration seem to fix the
issue.

This was observed with sles11sp2 (bash 3.2) and 4.2 xend.

Signed-off-by: Olaf Hering <olaf@aepfle.de>
Acked-by: Ian Campbell <Ian.campbell@citrix.com>
[ ijc -- added the comment ]
Committed-by: Ian Campbell <ian.campbell@citrix.com>
2012-10-18 09:35:01 +01:00

133 lines
4.8 KiB
Bash

#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# Serialisation
#
LOCK_BASEDIR=/var/run/xen-hotplug
_setlockfd()
{
local i
for ((i = 0; i < ${#_lockdict}; i++))
do [ -z "${_lockdict[$i]}" -o "${_lockdict[$i]}" = "$1" ] && break
done
_lockdict[$i]="$1"
let _lockfd=200+i
_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 rightfile
while true; do
eval "exec $_lockfd>>$_lockfile"
flock -x $_lockfd || return $?
# We can't just stat /dev/stdin or /proc/self/fd/$_lockfd or
# use bash's test -ef because those all go through what is
# actually a synthetic symlink in /proc and we aren't
# guaranteed that our stat(2) won't lose the race with an
# rm(1) between reading the synthetic link and traversing the
# file system to find the inum. Perl is very fast so use that.
rightfile=$( perl -e '
open STDIN, "<&'$_lockfd'" or die $!;
my $fd_inum = (stat STDIN)[1]; die $! unless defined $fd_inum;
my $file_inum = (stat $ARGV[0])[1];
print "y\n" if $fd_inum eq $file_inum;
' "$_lockfile" )
if [ x$rightfile = xy ]; then break; 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).