Skip to content

Commit 91f2c59

Browse files
committed
kvm: fix SharedMountPoint heartbeat when pool path is a subdirectory of a mount
kvmsmpheartbeat.sh required the pool path itself to be a mount point (mountpoint -q). A SharedMountPoint pool is "a file system path local to each server" and is commonly a subdirectory of a mounted clustered or parallel filesystem (e.g. /data01/vol01 on IBM Storage Scale mounted at /data01). For such pools every heartbeat write failed. - add is_on_mounted_fs(): the path must reside on a mounted filesystem other than / (findmnt -T, fallback df -P). Use it for both the initial check and the /proc/mounts check in front of deleteVMs, so relaxing the first check cannot lead to deleteVMs (kill -9) being run on every write. - check_hbLog: 'expr' exits with 1 when the result is 0, so a heartbeat read in the same second it was written reported the host as DEAD. Validate the timestamp and use shell arithmetic instead. - remove the temporary heartbeat file when the script is interrupted (e.g. killed on timeout). Fixes #14326
1 parent 2974af8 commit 91f2c59

1 file changed

Lines changed: 29 additions & 13 deletions

File tree

‎scripts/vm/hypervisor/kvm/kvmsmpheartbeat.sh‎

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,23 @@ if [ ! -d "$MountPoint" ]; then
8080
exit 1
8181
fi
8282

83-
# If the 'mountpoint' utility is available, ensure this is an actual mount
84-
if command -v mountpoint >/dev/null 2>&1; then
85-
if ! mountpoint -q "$MountPoint"; then
86-
echo "Mount point is not a mounted filesystem: $MountPoint" >&2
87-
exit 1
83+
# Returns 0 if the given path resides on a mounted filesystem other than the
84+
# root filesystem. A SharedMountPoint path does not need to be a mount point
85+
# itself, it may be a subdirectory of a mounted (e.g. clustered) filesystem.
86+
is_on_mounted_fs() {
87+
local target
88+
if command -v findmnt >/dev/null 2>&1; then
89+
target=$(findmnt -n -o TARGET -T "$1" 2>/dev/null)
90+
else
91+
target=$(df -P "$1" 2>/dev/null | awk 'NR==2 {print $6}')
8892
fi
93+
[ -n "$target" ] && [ "$target" != "/" ]
94+
}
95+
96+
# Ensure the path is on a mounted filesystem (not the local root filesystem)
97+
if ! is_on_mounted_fs "$MountPoint"; then
98+
echo "Mount point is not on a mounted filesystem: $MountPoint" >&2
99+
exit 1
89100
fi
90101

91102
# Ensure the mount point is writable
@@ -112,8 +123,8 @@ deleteVMs() {
112123
done
113124
}
114125

115-
#checking is there the mount point present under $MountPoint?
116-
if grep -q "^[^ ]\+ $MountPoint " /proc/mounts
126+
#checking is the filesystem of $MountPoint mounted?
127+
if is_on_mounted_fs "$MountPoint"
117128
then
118129
# mount exists; nothing to do here; keep for compatibility with original flow
119130
:
@@ -146,6 +157,9 @@ write_hbLog() {
146157
timestamp=$(date +%s)
147158
# Write atomically to avoid partial writes (write to tmp then mv)
148159
tmpfile="${hbFile}.$$"
160+
# remove the temporary file if the script is interrupted (e.g. on timeout)
161+
trap 'rm -f "$tmpfile"' EXIT
162+
trap 'exit 1' INT TERM
149163
printf "%s\n" "$timestamp" > "$tmpfile" 2>/dev/null
150164
if [ $? -ne 0 ]; then
151165
printf "Failed to write heartbeat to $tmpfile" >&2
@@ -168,12 +182,14 @@ check_hbLog() {
168182
hb_diff=999998
169183
return 1
170184
fi
171-
diff=`expr $now - $hb 2>/dev/null`
172-
if [ $? -ne 0 ]
173-
then
174-
hb_diff=999997
175-
return 1
176-
fi
185+
# note: 'expr' exits with 1 when the result is 0, so use shell arithmetic
186+
case "$hb" in
187+
''|*[!0-9]*)
188+
hb_diff=999997
189+
return 1
190+
;;
191+
esac
192+
diff=$((now - hb))
177193
if [ -z "$interval" ]; then
178194
# if no interval provided, consider 0 as success
179195
if [ $diff -gt 0 ]; then

0 commit comments

Comments
 (0)