diff mbox series

uqmi: use UUCP-style locking on control device

Message ID X71W5653orf/JarU@makrotopia.org
State Under Review
Delegated to: Daniel Golle
Headers show
Series uqmi: use UUCP-style locking on control device | expand

Commit Message

Daniel Golle Nov. 24, 2020, 6:54 p.m. UTC
Use UUCP-style locking to avoid interfering with running commands, eg.
by running 'ifup wwan' while 'ifdown wwan' has not completed yet,
multiple parallel instances of uqmi would occur and mess things up.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 package/network/utils/uqmi/Makefile           |   2 +-
 .../utils/uqmi/files/lib/netifd/proto/qmi.sh  | 107 +++++++++++-------
 2 files changed, 68 insertions(+), 41 deletions(-)
diff mbox series

Patch

diff --git a/package/network/utils/uqmi/Makefile b/package/network/utils/uqmi/Makefile
index 68958a3729..da54ba0f46 100644
--- a/package/network/utils/uqmi/Makefile
+++ b/package/network/utils/uqmi/Makefile
@@ -1,7 +1,7 @@ 
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=uqmi
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 
 PKG_SOURCE_PROTO:=git
 PKG_SOURCE_URL=$(PROJECT_GIT)/project/uqmi.git
diff --git a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh
index a6c785eb56..f8e64371ae 100755
--- a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh
+++ b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh
@@ -28,16 +28,19 @@  proto_qmi_init_config() {
 	proto_config_add_defaults
 }
 
-proto_qmi_setup() {
+qmi_setup() {
 	local interface="$1"
+	local device="$2"
 	local dataformat connstat plmn_mode mcc mnc
-	local device apn auth username password pincode delay modes pdptype
+	local apn auth username password pincode delay modes pdptype
 	local profile dhcp dhcpv6 autoconnect plmn timeout mtu $PROTO_DEFAULT_OPTIONS
 	local ip4table ip6table
 	local cid_4 pdh_4 cid_6 pdh_6
 	local ip_6 ip_prefix_length gateway_6 dns1_6 dns2_6
 
-	json_get_vars device apn auth username password pincode delay modes
+	flock -x 1000 || return -1000
+
+	json_get_vars apn auth username password pincode delay modes
 	json_get_vars pdptype profile dhcp dhcpv6 autoconnect plmn ip4table
 	json_get_vars ip6table timeout mtu $PROTO_DEFAULT_OPTIONS
 
@@ -45,35 +48,8 @@  proto_qmi_setup() {
 
 	[ "$metric" = "" ] && metric="0"
 
-	[ -n "$ctl_device" ] && device=$ctl_device
-
-	[ -n "$device" ] || {
-		echo "No control device specified"
-		proto_notify_error "$interface" NO_DEVICE
-		proto_set_available "$interface" 0
-		return 1
-	}
-
 	[ -n "$delay" ] && sleep "$delay"
 
-	device="$(readlink -f $device)"
-	[ -c "$device" ] || {
-		echo "The specified control device does not exist"
-		proto_notify_error "$interface" NO_DEVICE
-		proto_set_available "$interface" 0
-		return 1
-	}
-
-	devname="$(basename "$device")"
-	devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
-	ifname="$( ls "$devpath"/net )"
-	[ -n "$ifname" ] || {
-		echo "The interface could not be found."
-		proto_notify_error "$interface" NO_IFACE
-		proto_set_available "$interface" 0
-		return 1
-	}
-
 	[ -n "$mtu" ] && {
 		echo "Setting MTU to $mtu"
 		/sbin/ip link set dev $ifname mtu $mtu
@@ -409,9 +385,50 @@  proto_qmi_setup() {
 	}
 }
 
+proto_qmi_setup() {
+	local device lock ret
+	json_get_vars device
+
+	[ -n "$ctl_device" ] && device=$ctl_device
+
+	[ -n "$device" ] || {
+		echo "No control device specified"
+		proto_notify_error "$interface" NO_DEVICE
+		proto_set_available "$interface" 0
+		return 1
+	}
+
+	device="$(readlink -f $device)"
+	[ -c "$device" ] || {
+		echo "The specified control device does not exist"
+		proto_notify_error "$interface" NO_DEVICE
+		proto_set_available "$interface" 0
+		return 1
+	}
+
+	devname="$(basename "$device")"
+	devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
+	ifname="$( ls "$devpath"/net )"
+	[ -n "$ifname" ] || {
+		echo "The interface could not be found."
+		proto_notify_error "$interface" NO_IFACE
+		proto_set_available "$interface" 0
+		return 1
+	}
+	lock="/var/lock/..LCK.$(basename "$device")"
+	{
+		qmi_setup "$1" "$device"
+	} 1000>"$lock"
+	ret=$?
+	[ "$ret" != "-1000" ] && rm "$lock"
+	echo "exited with code $ret"
+	return $ret
+}
+
 qmi_wds_stop() {
-	local cid="$1"
-	local pdh="$2"
+	local device="$1"
+	local cid="$2"
+	local pdh="$3"
 
 	[ -n "$cid" ] || return
 
@@ -428,23 +445,33 @@  qmi_wds_stop() {
 		--release-client-id wds > /dev/null 2>&1
 }
 
+qmi_wds_stop_all() {
+	local device="$1"
+	flock -x 1000 || return -1000
+	json_load "$(ubus call network.interface.$interface status)"
+	json_select data
+	json_get_vars cid_4 pdh_4 cid_6 pdh_6
+	qmi_wds_stop "$device" "$cid_4" "$pdh_4"
+	qmi_wds_stop "$device" "$cid_6" "$pdh_6"
+}
+
 proto_qmi_teardown() {
 	local interface="$1"
 
-	local device cid_4 pdh_4 cid_6 pdh_6
+	local device lock cid_4 pdh_4 cid_6 pdh_6
 	json_get_vars device
 
 	[ -n "$ctl_device" ] && device=$ctl_device
 
-	echo "Stopping network $interface"
-
-	json_load "$(ubus call network.interface.$interface status)"
-	json_select data
-	json_get_vars cid_4 pdh_4 cid_6 pdh_6
+	device="$(readlink -f $device)"
 
-	qmi_wds_stop "$cid_4" "$pdh_4"
-	qmi_wds_stop "$cid_6" "$pdh_6"
+	echo "Stopping network $interface"
 
+	lock="/var/lock/..LCK.$(basename "$device")"
+	{
+		qmi_wds_stop_all "$device"
+	} 1000>"$lock"
+	[ "$?" != "-1000" ] && rm "$lock"
 	proto_init_update "*" 0
 	proto_send_update "$interface"
 }