aboutsummaryrefslogtreecommitdiffstats
path: root/tools/hotplug
diff options
context:
space:
mode:
authorZhigang Wang <zhigang.x.wang@oracle.com>2012-07-04 15:46:14 +0100
committerZhigang Wang <zhigang.x.wang@oracle.com>2012-07-04 15:46:14 +0100
commit827fbaa64b1c3540edd202fe393896a6c4775a80 (patch)
treee71bcbe3075fd95993098f70dfd320614a1bd4fa /tools/hotplug
parente7e8937625f5a62f8f15a0dcf98546113446675e (diff)
downloadxen-827fbaa64b1c3540edd202fe393896a6c4775a80.tar.gz
xen-827fbaa64b1c3540edd202fe393896a6c4775a80.tar.bz2
xen-827fbaa64b1c3540edd202fe393896a6c4775a80.zip
hotplug/Linux: use flock based locking
In the normal case of a single domain booting with one disk, the disk hotplug script will fire once. In this case taking out the lock will never cause a sleep because there's no other concurrent invocations. If a domain has 4 disks configured, then the hotplug script will fire 4 times, all 4 invocations at pretty much the same time. If there is even a little load on the system, the locking function in the shell script will sleep for a few seconds - as many as 5 seconds, or potentially even time out & fail completely. If say 4 or even more domains each with 4 disks start up at once, that's 16 invocations of the hotplug script running at once. There will be a lot of sleep's done & because of the very coarse 1 second granularity the delay can add up significantly. The change to using flock() removes the arbitrary 1 second sleep, so the very instant once hotplug script finishes, another can start & there is no repeated attempts & failures to lock which would add more delay. In addition the current locking implementation would allow two processes get the lock simultaneously if one decided the other had timed out. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Zhigang Wang <zhigang.x.wang@oracle.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> Committed-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'tools/hotplug')
-rw-r--r--tools/hotplug/Linux/locking.sh93
1 files changed, 16 insertions, 77 deletions
diff --git a/tools/hotplug/Linux/locking.sh b/tools/hotplug/Linux/locking.sh
index e233c4763a..e7f61b8afe 100644
--- a/tools/hotplug/Linux/locking.sh
+++ b/tools/hotplug/Linux/locking.sh
@@ -1,5 +1,6 @@
#
# 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
@@ -19,92 +20,30 @@
# Serialisation
#
-LOCK_SLEEPTIME=1
-LOCK_SPINNING_RETRIES=5
-LOCK_RETRIES=100
LOCK_BASEDIR=/var/run/xen-hotplug
-
-claim_lock()
-{
- local lockdir="$LOCK_BASEDIR/$1"
- mkdir -p "$LOCK_BASEDIR"
- _claim_lock "$lockdir"
-}
-
-
-release_lock()
+_setlockfd()
{
- _release_lock "$LOCK_BASEDIR/$1"
+ 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
}
-# This function will be redefined in xen-hotplug-common.sh.
-sigerr() {
- exit 1
-}
-
-
-_claim_lock()
-{
- local lockdir="$1"
- local owner=$(_lock_owner "$lockdir")
- local retries=0
-
- while [ $retries -lt $LOCK_RETRIES ]
- do
- mkdir "$lockdir" 2>/dev/null && trap "_release_lock $lockdir; sigerr" ERR &&
- _update_lock_info "$lockdir" && return
-
- local new_owner=$(_lock_owner "$lockdir")
- if [ "$new_owner" != "$owner" ]
- then
- owner="$new_owner"
- retries=0
- else
- local pid=$(echo $owner | cut -d : -f 1)
- if [ -n "$pid" -a "$pid" != "unknown" -a ! -f "/proc/$pid/status" ]
- then
- _release_lock $lockdir
- fi
- fi
-
- if [ $retries -gt $LOCK_SPINNING_RETRIES ]
- then
- sleep $LOCK_SLEEPTIME
- else
- sleep 0
- fi
- retries=$(($retries + 1))
- done
- _steal_lock "$lockdir"
-}
-
-
-_release_lock()
-{
- trap sigerr ERR
- rm -rf "$1" 2>/dev/null || true
-}
-
-
-_steal_lock()
-{
- local lockdir="$1"
- local owner=$(cat "$lockdir/owner" 2>/dev/null || echo "unknown")
- log err "Forced to steal lock on $lockdir from $owner!"
- _release_lock "$lockdir"
- _claim_lock "$lockdir"
-}
-
-
-_lock_owner()
+claim_lock()
{
- cat "$1/owner" 2>/dev/null || echo "unknown"
+ mkdir -p "$LOCK_BASEDIR"
+ _setlockfd $1
+ eval "exec $_lockfd>>$LOCK_BASEDIR/$1"
+ flock -x $_lockfd
}
-_update_lock_info()
+release_lock()
{
- echo "$$: $0" >"$1/owner"
+ _setlockfd $1
+ flock -u $_lockfd
}