summaryrefslogtreecommitdiff
path: root/ctdb
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2021-01-04 13:35:11 +1100
committerAmitay Isaacs <amitay@samba.org>2021-05-28 06:46:29 +0000
commitdd5972b69916fa08b114193d644faf3ae58c550b (patch)
treeab03d72982b30536908ce266332a05adb97cbd51 /ctdb
parente62ae53ef6d04016e3a3453380c9add3ce888e3c (diff)
downloadsamba-dd5972b69916fa08b114193d644faf3ae58c550b.tar.gz
ctdb-scripts: Simplify logic in debug_via_proc_locks()
The path of the TDB is known, so calculate the file ID (device number + inode number) from it and use this to directly filter /proc/locks to find processes holding locks. Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com>
Diffstat (limited to 'ctdb')
-rwxr-xr-xctdb/config/debug_locks.sh90
-rw-r--r--ctdb/tests/UNIT/eventscripts/scripts/debug_locks.sh21
-rwxr-xr-xctdb/tests/UNIT/eventscripts/stubs/stat18
3 files changed, 89 insertions, 40 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}"
}
(
diff --git a/ctdb/tests/UNIT/eventscripts/scripts/debug_locks.sh b/ctdb/tests/UNIT/eventscripts/scripts/debug_locks.sh
index d9c3df76d57..162dc21b2ac 100644
--- a/ctdb/tests/UNIT/eventscripts/scripts/debug_locks.sh
+++ b/ctdb/tests/UNIT/eventscripts/scripts/debug_locks.sh
@@ -168,25 +168,26 @@ EOF
'
_db="locking.tdb.${FAKE_CTDB_PNN}"
- _pids=''
+ if [ -n "$_helper_lock" ] ; then
+ read -r _ _ _ _ _pid _ _start _end <<EOF
+$_helper_lock
+EOF
+ _out="Waiter:${_nl}"
+ _out="${_out}${_pid} ctdb_lock_helpe ${_db} ${_start} ${_end}"
+ fi
+
# fake lock info
+ _pids=''
+ _out="${_out:+${_out}${_nl}}Lock holders:"
while read -r _ _ _ _pid _ _start _end ; do
_comm="smbd"
- _out="${_out:+${_out}${_nl}}"
+ _out="${_out}${_nl}"
_out="${_out}${_pid} smbd ${_db} ${_start} ${_end}"
_pids="${_pids:+${_pids} }${_pid}"
done <<EOF
$_holder_lock
EOF
- if [ -n "$_helper_lock" ] ; then
- read -r _ _ _ _ _pid _ _start _end <<EOF
-$_helper_lock
-EOF
- _out="${_out}${_nl}"
- _out="${_out}${_pid} ctdb_lock_helpe ${_db} ${_start} ${_end} W"
- fi
-
# fake stack traces
for _pid in $_pids ; do
_comm="smbd"
diff --git a/ctdb/tests/UNIT/eventscripts/stubs/stat b/ctdb/tests/UNIT/eventscripts/stubs/stat
index 04c654883d2..71508f6795d 100755
--- a/ctdb/tests/UNIT/eventscripts/stubs/stat
+++ b/ctdb/tests/UNIT/eventscripts/stubs/stat
@@ -16,6 +16,19 @@ while getopts "c:h:?" opt ; do
done
shift $((OPTIND - 1))
+fake_device_id ()
+{
+ _path="$1"
+
+ _t=$(echo "$FAKE_FILE_ID_MAP" |
+ awk -v path="${_path}" '$1 == path { print $2 }')
+ _major_minor="${_t%:*}"
+ _major="0x${_major_minor%:*}"
+ _minor="0x${_major_minor#*:}"
+ _device_id=$((_major * 256 + _minor))
+ echo "$_device_id"
+}
+
fake_inode ()
{
_path="$1"
@@ -40,6 +53,11 @@ if [ -n "$format" ] ; then
inode=$(fake_inode "$path")
echo "s#[0-9a-f]*:[0-9a-f]*:${inode} #${f} #"
;;
+ "%d:%i")
+ device_id=$(fake_device_id "$path")
+ inode=$(fake_inode "$path")
+ echo "${device_id}:${inode}"
+ ;;
*)
echo "Unsupported format \"${format}\""
usage