summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominique Martinet <dominique.martinet@cea.fr>2016-02-01 13:11:34 +0100
committerDominique Martinet <dominique.martinet@cea.fr>2016-02-02 15:44:09 +0100
commitc2670fbf77b452a81476745d9d7ad9bd20c61906 (patch)
tree23b8fd955e924a5ac7c9040102a06fdb80ff84e8
parent69218279821137fbbc1feddce86f319616a50cbe (diff)
review locking to unlink lock file safely
-rwxr-xr-xkvm-wrapper.sh50
1 files changed, 44 insertions, 6 deletions
diff --git a/kvm-wrapper.sh b/kvm-wrapper.sh
index b5ab56c..e60609d 100755
--- a/kvm-wrapper.sh
+++ b/kvm-wrapper.sh
@@ -176,6 +176,46 @@ function random_mac ()
|| echo -n $MACADDR
}
+# stores FD in global variable LOCKFD_${VARIANT}
+# the lock will automatically be released when shell exits,
+# but calling unlock lets us unlink lock file safely
+function lock ()
+{
+ local VARIANT="$1"
+ local LOCKFILE="/tmp/kvm-wrapper-$VARIANT.lock"
+ local LOCKFD
+
+ while :; do
+ exec {LOCKFD}<>"$LOCKFILE"
+ flock ${LOCKFD}
+
+ # Check if file has changed since opening
+ # if it has, drop lock and try again
+ FD_INO=$(stat -c "%i" -L "/proc/$$/fd/${LOCKFD}")
+ FILE_INO=$(stat -c "%i" "${LOCKFILE}" 2>/dev/null)
+
+ [[ "$FD_INO" == "$FILE_INO" ]] && break
+
+ exec {LOCKFD}<&-
+ done
+
+ eval "export LOCKFD_${VARIANT}=${LOCKFD}"
+}
+
+function unlock ()
+{
+ local VARIANT="$1"
+ local LOCKFILE="/tmp/kvm-wrapper-$VARIANT.lock"
+ local LOCKFD
+
+ # remove lockfile then close (unlock) fd
+ rm -f "$LOCKFILE"
+
+ eval "LOCKFD=\$LOCKFD_${VARIANT}"
+ eval "exec $LOCKFD<&-"
+ eval "unset LOCKFD_${VARIANT}"
+}
+
# cluster helpers
hash_string ()
{
@@ -474,8 +514,7 @@ function sriov()
[[ "$DEVDIR" = "inval" ]] && fail_exit "could not find device for $BR"
# following is racy, lock through.
- exec {FLOCK}<>/tmp/kvm-wrapper-$BR.lock
- flock ${FLOCK}
+ lock "$BR"
if [[ -e "$DEVDIR/sriov_numvfs" && ! -e "$DEVDIR/virtfn0" ]]; then
# arbitrary number: create all vfs available
@@ -488,18 +527,17 @@ function sriov()
[[ -e /sys/bus/pci/drivers/vfio-pci/$PCIDOMAIN ]] || break
PCIDOMAIN=inval
done
- [[ $PCIDOMAIN = inval ]] && fail_exit "no vfio virtfn available for $BR"
+ [[ $PCIDOMAIN = inval ]] && { unlock "$BR"; fail_exit "no vfio virtfn available for $BR"; }
VFNUM=${VIRTFN##*virtfn}
# hack - register everything to pci-stub first so we can tell appart which are used or not
local PCIVENDOR="$(cat "/sys/bus/pci/devices/$PCIDOMAIN/vendor" |sed 's/^0x//')"
PCIVENDOR+=" $(cat "/sys/bus/pci/devices/$PCIDOMAIN/device" |sed 's/^0x//')"
- echo "$PCIVENDOR" > "/sys/bus/pci/drivers/pci-stub/new_id" || fail_exit "couldn't add new_id (pci-stub)"
+ echo "$PCIVENDOR" > "/sys/bus/pci/drivers/pci-stub/new_id" || { unlock "$BR"; fail_exit "couldn't add new_id (pci-stub)"; }
pci_vfiofy "$PCIDOMAIN"
- # unlock, can't unlink file though..
- exec {FLOCK}<&-
+ unlock "$BR"
}
# Change perms. Meant to run forked.