External storage sometimes not mounted on /srv after (re)boot

Note: “SW bugs discussion” is a first approximation to a category for this problem. Some other category may turn out to be more appropriate.

After setting up external storage on a USB stick and starting to use this for LXC and pakon, I’m seeing that sometimes the USB stick is not mounted at /srv after a reboot. when this happens, it seems to be necessary to re-seat the USB device before it is again recognized on a subsequent reboot. This has undesired effects for LXC and for pakon.

LXC startup fails, as the relevant configuration and resources in /srv/lxc are missing. This at least prevents unwanted activity on the emmc device.

On the other hand, pakon creates resources in /srv (on the emmc device) so that there are now two copies of its persistent data.

I’ve not been able to establish yet whether the observed problem is specific to certain brands of USB flash, or to flash rather than USB-connected spinning rust, or is due to some race condition, or what.

I think it would be good to have some indication in persistent state (eg: some new file in /etc/config, manipulated by UCI) that external storage had been set up, which would be probed during startup of packages such as LXC or pakon, so that these would avoid starting unless the storage they needed were on some non-root file system.

On reflection, it seems to me that /etc/config/fstab has all the necessary state already, so no new config file would be needed.

Relevant init scripts would simply need to test for an enabled stanza in the fstab config which referred to /srv as the target, and fail if such was found AND /srv was not a mount point.

I’ll look at this and try to suggest code.

Something like this would allow packages which use /srv to check for trouble before starting:

--- /etc/init.d/srv	2018-08-14 19:32:35.000000000 +0100
+++ ./srv	2018-09-12 15:40:35.365860642 +0100
@@ -2,9 +2,56 @@
 
 START=40
 STOP=90
+EXTRA_COMMANDS='status'
+EXTRA_HELP="	status	Show service status and fail if not valid"
+
+status_mounted() {
+	while read bearer point fstype options rest; do
+		[ "$point" = "/srv" ] || continue
+		return 0
+		break
+	done < /proc/mounts
+	return 1
+}
+
+mount_configured() {
+	for item in $(uci show fstab | while IFS='=' read tag val; do [ "$val" = "mount" ] || continue; echo $tag; done); do
+		enabled="$(uci -q get $item.enabled)"
+		target="$(uci -q get $item.target)"
+		case "$enabled" in
+			1|yes|on) ;;
+			*) continue ;;
+		esac
+		[ "$target" = "/srv" ] || continue
+		return 0
+		break
+	done
+	return 1
+}
 
 status() {
-        return 0
+	if status_mounted; then
+		rc=0
+		if [ -t 0 ]; then
+			echo "/srv: mounted [OK]"
+			if mount_configured; then
+				echo "/srv: configured [OK]"
+			else
+				echo "/srv: not configured [OK]"
+			fi
+		fi
+	elif mount_configured; then
+		rc=1
+		if [ -t 0 ]; then
+			echo "/srv: configured but not mounted [ERROR]"
+		fi
+	else
+		rc=0
+		if [ -t 0 ]; then
+			echo "/srv: neither configured nor mounted [OK]"
+		fi
+	fi
+        return $rc
 }
 
 die() {
1 Like

Corresponding change in any dependent pckage might be like this:

--- /etc/init.d/pakon-monitor	2018-08-14 19:10:24.000000000 +0100
+++ ./pakon-monitor	2018-09-13 14:16:28.250857368 +0100
@@ -5,6 +5,7 @@
 STOP=10
 
 start_service() {
+if [ ! -e /etc/init.d/srv ] || /etc/init.d/srv status; then
   [ ! -f /var/lib/pakon.db ] && [ -f /srv/pakon/pakon.db.xz ] && /usr/bin/xz -c -d /srv/pakon/pakon.db.xz > /var/lib/pakon.db
   /usr/bin/sqlite3 /var/lib/pakon.db "pragma integrity_check" >/dev/null || rm -f /var/lib/pakon.db
   #sqlite3 integrity_check returns 0 even if the file has zero size...
@@ -16,11 +17,14 @@
   procd_set_param command /usr/libexec/pakon-light/pakon-monitor.py
   procd_set_param respawn ${respawn_threshold:-600} ${respawn_timeout:-5} ${respawn_retry:-5}
   procd_close_instance
+fi
 }
 
 stop_service() {
+if [ ! -e /etc/init.d/srv ] || /etc/init.d/srv status; then
   mkdir -p /srv/suricata
   [ -f /var/lib/pakon.db ] && /usr/libexec/pakon-light/backup_sqlite.sh /var/lib/pakon.db /srv/pakon/pakon.db.xz 
+fi
 }
 
 reload_service() {