diff options
author | Dominique Martinet <dominique.martinet@cea.fr> | 2016-02-01 13:11:34 +0100 |
---|---|---|
committer | Dominique Martinet <dominique.martinet@cea.fr> | 2016-02-02 15:44:09 +0100 |
commit | c2670fbf77b452a81476745d9d7ad9bd20c61906 (patch) | |
tree | 23b8fd955e924a5ac7c9040102a06fdb80ff84e8 | |
parent | 69218279821137fbbc1feddce86f319616a50cbe (diff) |
review locking to unlink lock file safely
-rwxr-xr-x | kvm-wrapper.sh | 50 |
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. |