summaryrefslogtreecommitdiff
path: root/ctdb/config/debug_locks.sh
diff options
context:
space:
mode:
Diffstat (limited to 'ctdb/config/debug_locks.sh')
-rwxr-xr-xctdb/config/debug_locks.sh90
1 files changed, 60 insertions, 30 deletions
diff --git a/ctdb/config/debug_locks.sh b/ctdb/config/debug_locks.sh
index 892889e86be..1fcb2f70d17 100755
--- a/ctdb/config/debug_locks.sh
+++ b/ctdb/config/debug_locks.sh
@@ -75,40 +75,70 @@ dump_stacks ()
done
}
+get_tdb_file_id ()
+{
+ if ! _device_inode=$(stat -c "%d:%i" "$tdb_path" 2>/dev/null) ; then
+ die "Unable to stat \"${tdb_path}\""
+ fi
+ _device="${_device_inode%%:*}"
+ _device_major=$((_device >> 8))
+ _device_minor=$((_device & 0xff))
+ _inode="${_device_inode#*:}"
+ printf '%02x:%02x:%u\n' "$_device_major" "$_device_minor" "$_inode"
+}
+
debug_via_proc_locks ()
{
- # Create sed expression to convert inodes to names.
- # Filenames don't contain dashes and we want basenames
- # shellcheck disable=SC2035
- sed_cmd=$(cd "$CTDB_DBDIR" &&
- stat -c "s#[0-9a-f]*:[0-9a-f]*:%i #%n #" *.tdb.* 2>/dev/null ;
- cd "$CTDB_DBDIR_PERSISTENT" &&
- stat -c "s#[0-9a-f]*:[0-9a-f]*:%i #%n #" *.tdb.* 2>/dev/null)
-
- # Parse /proc/locks and extract following information
- # pid process_name tdb_name offsets [W]
- out=$( get_proc "locks" |
- grep -F "POSIX ADVISORY WRITE" |
- awk '{ if($2 == "->") { print $6, $7, $8, $9, "W" } else { print $5, $6, $7, $8 } }' |
- while read pid rest ; do
- pname=$(ps -p "$pid" -o comm=)
- echo "$pid $pname $rest"
- done | sed -e "$sed_cmd" | grep '\.tdb' )
-
- if [ -n "$out" ]; then
+ # Get file ID to match relevant column in /proc/locks
+ _file_id=$(get_tdb_file_id)
+
+ # Log information from /proc/locks about the waiting process
+ _tdb=$(basename "$tdb_path")
+ _comm=$(ps -p "$lock_helper_pid" -o comm=)
+ _out=$(get_proc "locks" |
+ awk -v pid="$lock_helper_pid" \
+ -v file_id="$_file_id" \
+ -v file="$_tdb" \
+ -v comm="$_comm" \
+ '$2 == "->" &&
+ $3 == "POSIX" &&
+ $4 == "ADVISORY" &&
+ $5 == "WRITE" &&
+ $6 == pid &&
+ $7 == file_id { print $6, comm, file, $8, $9 }')
+ if [ -n "$_out" ] ; then
+ echo "Waiter:"
+ echo "$_out"
+ fi
+
+ # Parse /proc/locks and find process holding locks on $tdb_path
+ # extract following information
+ # pid process_name tdb_name offsets
+ _out=$(get_proc "locks" |
+ awk -v pid="$lock_helper_pid" \
+ -v file_id="$_file_id" \
+ -v file="$_tdb" \
+ '$2 == "POSIX" &&
+ $3 == "ADVISORY" &&
+ $4 == "WRITE" &&
+ $5 != pid &&
+ $6 == file_id { print $5, file, $7, $8 }' |
+ while read -r _pid _rest ; do
+ _pname=$(ps -p "$_pid" -o comm=)
+ echo "$_pid $_pname $_rest"
+ done)
+
+ if [ -z "$_out" ]; then
+ return
+ fi
+
# Log information about locks
- echo "$out"
-
- # Find processes that are waiting for locks
- dbs=$(echo "$out" | grep "W$" | awk '{print $3}')
- all_pids=""
- for db in $dbs ; do
- pids=$(echo "$out" | grep -v "W$" | grep "$db" | grep -v ctdbd | awk '{print $1}')
- all_pids="$all_pids $pids"
- done
+ echo "Lock holders:"
+ echo "$_out"
+
+ _pids=$(echo "$_out" | awk '{ print $1 }')
- lock_holder_pids="${lock_holder_pids:+${lock_holder_pids} }${all_pids}"
- fi
+ lock_holder_pids="${lock_holder_pids:+${lock_holder_pids} }${_pids}"
}
(