Add flock(2) locking for the map
authorBryn M. Reeves <bmr@redhat.com>
Wed, 23 Jan 2013 11:44:03 +0000 (11:44 +0000)
committerBryn M. Reeves <bmr@redhat.com>
Wed, 23 Jan 2013 11:44:03 +0000 (11:44 +0000)
Since multiple administrators as well as udev may be running the
script concurrently use flock(2)-based locking to protect the
database from concurrent updates.

Acquire an exclusive flock lock on /var/lock/blkdevalias for any
operation that modifies the map file. Acquire a shared lock for
all read-only operations.

blkdevalias

index 5cbfea9..3704876 100755 (executable)
@@ -40,7 +40,10 @@ BA_CONF_DIR="/etc/blkdevalias"
 BA_DEV_PATH="oracleasm/disks"
 BA_MAP_PATH="${BA_CONF_DIR}/blkdevalias.map"
 BA_CONF_PATH="${BA_CONF_DIR}/blkdevalias.conf"
-BA_LOCK="/var/lock/blkdevalias"
+BA_LOCK_PATH="/var/lock/blkdevalias"
+
+# locking
+BA_LOCK_FD=9
 
 # user and group - only used if loading with a blank configuration file.
 BA_USER="$BA_DEFAULT_USER"
@@ -54,6 +57,7 @@ BA_BASENAME="/bin/basename"
 BA_DMSETUP="/sbin/dmsetup"
 BA_GETENT="/usr/bin/getent"
 BA_CHOWN="/bin/chown"
+BA_FLOCK="/usr/bin/flock"
 BA_SUDO="/usr/bin/sudo"
 BA_SED="/bin/sed"
 BA_ID="/usr/bin/id"
@@ -505,32 +509,85 @@ ba_map () {
     echo "BA_MODE=$BA_MODE"
 }
 
+ba_lock_map () {
+    local _MODE _FLAG
+    _MODE="$1"
+    _FLAG="-s" # shared by default
+    if [ "$_MODE" == "exclusive" ]; then
+        _FLAG="-x"
+    fi
+    _debug "$FUNCNAME: locking $BA_LOCK_PATH on" \
+        "fd $BA_LOCK_FD with mode: $_MODE"
+    $BA_FLOCK -n $BA_LOCK_FD -x &>/dev/null
+}
+
+ba_unlock_map () {
+    _debug "$FUNCNAME: unlocking $BA_LOCK_PATH on fd $BA_LOCK_FD"
+    $BA_FLOCK -n $BA_LOCK_FD -u &>/dev/null
+}
+
 # no point optimizing this out for configure
 ba_load_wwid_map
+_debug "ba_main: dispatching command \"$@\""
 case "$1" in
     configure)
         ba_configure
         ;;
     create*)
-        ba_createdisk "$2" "$3"
+        (
+            # lock exclusive
+            ba_lock_map exclusive
+            ba_createdisk "$2" "$3"
+            ba_unlock_map
+        ) 9> $BA_LOCK_PATH
         ;;
     delete*)
-        ba_deletedisk "$2"
+        (
+            # lock exclusive
+            ba_lock_map exclusive
+            ba_deletedisk "$2"
+            ba_unlock_map
+        ) 9> $BA_LOCK_PATH
         ;;
     list*)
-        ba_list_disks
+        (
+            # lock shared
+            ba_lock_map shared
+            ba_list_disks
+            ba_unlock_map
+        ) 9> $BA_LOCK_PATH
         ;;
     query*)
-        ba_querydisk "$2" "$3"
+        (
+            # lock shared
+            ba_lock_map shared
+            ba_querydisk "$2" "$3"
+            ba_unlock_map
+        ) 9> $BA_LOCK_PATH
         ;;
     scan*)
-        ba_scandisks "$2"
+        (
+            # lock shared
+            ba_lock_map shared
+            ba_scandisks "$2"
+            ba_unlock_map
+        ) 9> $BA_LOCK_PATH
         ;;
     refresh*)
-        ba_refresh_alias "$2"
+        (
+            # lock shared
+            ba_lock_map shared
+            ba_refresh_alias "$2"
+            ba_unlock_map
+        ) 9> $BA_LOCK_PATH
         ;;
     map)
-        ba_map "$2"
+        (
+            # lock shared
+            ba_lock_map shared
+            ba_map "$2"
+            ba_unlock_map
+        ) 9> $BA_LOCK_PATH
         ;;
     *)
         ba_usage "\n{configure|createdisk|deletedisk|listdisks|scandisks|querydisk|map}"