Skip to content

Commit

Permalink
os-helpers: fs: replace wait4file w/ inotifywait
Browse files Browse the repository at this point in the history
Previously, scripts that required a file that is created asynchronously,
such as the by-state links created by a udev rule, would busy loop until
the file existed using wait4file(), part of os-helpers-fs.

This is time consuming and inefficient, as the minimum wait time adds
latency to the following operations. Instead, use inotifywait to receive
an event from the kernel when the relevant file or path is modified to
prevent unnecessary resource usage and busy waiting.

Change-type: patch
Signed-off-by: Joseph Kogut <[email protected]>
  • Loading branch information
jakogut committed Mar 24, 2023
1 parent ead4a8f commit 1c7244e
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@ fsuuidsinit_enabled() {
return 1
fi

# Wait for balena by-state symlinks to come up
# We only wait for resin-rootA here as we use it right away
# but we in fact assume the other symlinks are created as well
# wait4file does $2 loops of 100ms, therefore use 10 * roottimeout
timeout=${bootparam_roottimeout:-5}
if ! wait4file "/dev/disk/by-state/resin-rootA" "$((timeout * 10))"; then
if ! ls /dev/disk/by-state/* \
&& ! inotifywait -r /dev \
--include 'disk/by-state/resin-+(boot|data|root[AB]|state)$' \
--timeout "${timeout}"; then
error "Timeout while waiting for resin-root partition to be detected"
return 1
fi
Expand Down
7 changes: 5 additions & 2 deletions meta-balena-common/recipes-core/initrdscripts/files/machineid
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ machineid_enabled() {
machineid_run() {
# Mount the state partition - that's where we store the machine_id
state_partition_path="$(get_state_path_from_label "resin-state")"
if ! wait4file "$state_partition_path" "300"; then
if [ ! -e "${state_partition_path}" ] \
&& ! inotifywait -r /dev \
--include "${state_partition_path#/dev/}" \
--timeout 30; then
error "Timeout while waiting for resin-state partition to be detected."
error "Not able to mount resin-state, machine-id will not be persistent."
return
return
fi

info "Binding machine-id from ${state_partition_path}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ resindataexpander_enabled() {
datadev=$(lsblk "/dev/${datapartdev}" -d -n -o PKNAME)
pttype=$(get_part_table_type "/dev/${datadev}")

if ! wait4file "$datapart" "300"; then
error "Timeout while waiting for data partition to be detected. Data partition expansion will not be tried."
if [ ! -e "${datapart}" ] \
&& ! inotifywait -r /dev \
--include "${datapart#/dev/}" \
--timeout 30; then
error "Timeout while waiting for data partition to be detected." \
"Data partition expansion will not be tried."
return 1
fi

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${BALENA_COREBASE}/COPYING.Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"

DEPENDS = "time-native"
RDEPENDS:${PN}-fs = "e2fsprogs-tune2fs mtools parted bash util-linux-fdisk"
RDEPENDS:${PN}-fs = "e2fsprogs-tune2fs mtools parted bash util-linux-fdisk inotify-tools"
RDEPENDS:${PN}-fs:append = "${@bb.utils.contains('MACHINE_FEATURES','raid',' mdadm','',d)}"
RDEPENDS:${PN}-tpm2 = "libtss2-tcti-device tpm2-tools"
RDEPENDS:${PN}-config = "bash"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,6 @@ if [ -f "/usr/libexec/os-helpers-logging" ]; then
. /usr/libexec/os-helpers-logging
fi

# Wait for a file to appear with loop count limit.
# Use-case example: wait for udev to create a filesystem symlink.
# Arguments:
# 1 - target path
# 2 - number of loops (each loop sleeps for 100ms)
wait4file() {
_lpath="$1"
_lloops="$2"

while [ ! -e "$_lpath" ]; do
if [ "$_lloops" -gt 0 ]; then
sleep 0.1
_lloops=$((_lloops-1))
else
return 1
fi
done
return 0
}

# Output the UUID for the specified block device.
# Arguments:
# 1 - Target block device
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@

set -e

TIMEOUT_LOOPS=300 # ~ 100ms/loop * 300loops = 30000ms = 30s

#
# Help message
#
Expand Down Expand Up @@ -103,7 +101,10 @@ if [ ! -d "$target_mountpoint" ]; then
echo "ERROR: Target mountpoint $target_mountpoint not found."
exit 1
fi
if ! wait4file "$target_path" "$TIMEOUT_LOOPS"; then
if [ ! -e "${target_path}" ] \
&& ! inotifywait -r /dev \
--include "${target_path#/dev/}" \
--timeout 30; then
echo "ERROR: Timeout while waiting for $target_path to come up."
exit 1
fi
Expand Down

0 comments on commit 1c7244e

Please sign in to comment.