uvol: emmit ubus events and bring up volumes on boot
authorDaniel Golle <redacted>
Sat, 17 Apr 2021 18:16:18 +0000 (19:16 +0100)
committerDaniel Golle <redacted>
Sat, 17 Apr 2021 23:41:35 +0000 (00:41 +0100)
Emmit ubus events when volumes come up/down.
Make sure volume state is always well defined by introducing
additional state 'write-prepare' (wp) during mkfs.
Add init scripts to bring up volumes at boot.

Signed-off-by: Daniel Golle <redacted>
utils/uvol/Makefile
utils/uvol/files/lvm.sh
utils/uvol/files/ubi.sh
utils/uvol/files/uvol
utils/uvol/files/uvol.init [new file with mode: 0644]

index 64fb0238dadb942268dbf152f4103b0cf7ec682a..f470e51431f3084576fe3f196026d9c67de44da1 100644 (file)
@@ -63,10 +63,11 @@ define Package/autopart/install
 endef
 
 define Package/uvol/install
-       $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/libexec/uvol
-       $(INSTALL_BIN) ./files/uvol $(1)/usr/sbin
+       $(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/libexec/uvol $(1)/usr/sbin
+       $(INSTALL_BIN) ./files/uvol.init $(1)/etc/init.d/uvol
        $(INSTALL_BIN) ./files/ubi.sh $(1)/usr/libexec/uvol/20-ubi.sh
        $(INSTALL_BIN) ./files/lvm.sh $(1)/usr/libexec/uvol/50-lvm.sh
+       $(INSTALL_BIN) ./files/uvol $(1)/usr/sbin
 endef
 
 $(eval $(call BuildPackage,autopart))
index 158ab1c83deac14807dc87e562f641bc705d0bf3..4a20f628d19cad29501b798b8113b21cc5989d4a 100644 (file)
@@ -30,6 +30,7 @@ lvm_cmd() {
        local cmd="$1"
        shift
        LVM_SUPPRESS_FD_WARNINGS=1 lvm "$cmd" "$@"
+       return $?
 }
 
 pvs() {
@@ -109,19 +110,23 @@ exportvg() {
        done
 }
 
+lv_active=
+lv_name=
 lv_full_name=
 lv_path=
 lv_dm_path=
 lv_size=
 exportlv() {
        local reports rep lv lvs
+       lv_active=
+       lv_name=
        lv_full_name=
        lv_path=
        lv_dm_path=
        lv_size=
        json_init
 
-       json_load "$(lvs -o lv_full_name,lv_size,lv_path,lv_dm_path -S "lv_name=~^[rw][ow]_$1\$ && vg_name=$vg_name")"
+       json_load "$(lvs -o lv_active,lv_name,lv_full_name,lv_size,lv_path,lv_dm_path -S "lv_name=~^[rw][owp]_$1\$ && vg_name=$vg_name")"
        json_select report
        json_get_keys reports
        for rep in $reports; do
@@ -130,7 +135,7 @@ exportlv() {
                json_get_keys lvs
                for lv in $lvs; do
                        json_select "$lv"
-                       json_get_vars lv_full_name lv_size lv_path lv_dm_path
+                       json_get_vars lv_active lv_name lv_full_name lv_size lv_path lv_dm_path
                        lv_size=${lv_size%B}
                        json_select ..
                        break
@@ -153,12 +158,17 @@ getsize() {
 
 activatevol() {
        exportlv "$1"
+       [ "$lv_path" ] || return 2
        case "$lv_path" in
-               /dev/*/wo_*)
+               /dev/*/wo_*|\
+               /dev/*/wp_*)
                        return 22
                        ;;
                *)
-                       lvm_cmd lvchange -a y "$lv_full_name"
+                       [ "$lv_active" = "active" ] && return 0
+                       lvm_cmd lvchange -a y "$lv_full_name" || return $?
+                       lvm_cmd lvchange -k n "$lv_full_name" || return $?
+                       ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"${lv_name:0:2}\", \"device\": \"$lv_dm_path\"}"
                        return 0
                        ;;
        esac
@@ -166,7 +176,20 @@ activatevol() {
 
 disactivatevol() {
        exportlv "$1"
-       lvm_cmd lvchange -a n "$lv_full_name"
+       [ "$lv_path" ] || return 2
+       case "$lv_path" in
+               /dev/*/wo_*|\
+               /dev/*/wp_*)
+                       return 22
+                       ;;
+               *)
+                       [ "$lv_active" = "active" ] || return 0
+                       lvm_cmd lvchange -a n "$lv_full_name" || return $?
+                       lvm_cmd lvchange -k y "$lv_full_name" || return $?
+                       ubus send block.volume "{\"name\": \"$1\", \"action\": \"down\", \"mode\": \"${lv_name:0:2}\", \"device\": \"$lv_dm_path\"}"
+                       return 0
+                       ;;
+       esac
 }
 
 getstatus() {
@@ -192,14 +215,14 @@ createvol() {
                        ;;
                rw)
                        lvmode=rw
-                       mode=rw
+                       mode=wp
                        ;;
                *)
                        return 22
                        ;;
        esac
 
-       lvm_cmd lvcreate -p $lvmode -a n -y -W n -Z n -n "${mode}_${1}" -l "$size_ext" $vg_name
+       lvm_cmd lvcreate -p $lvmode -a n -y -W n -Z n -n "${mode}_$1" -l "$size_ext" $vg_name
        ret=$?
        if [ ! $ret -eq 0 ] || [ "$lvmode" = "r" ]; then
                return $ret
@@ -212,6 +235,9 @@ createvol() {
        else
                mke2fs -F -L "$1" "$lv_path" || return 1
        fi
+       lvm_cmd lvrename "$vg_name" "wp_$1" "rw_$1"
+       exportlv "$1"
+       ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"${lv_name:0:2}\", \"device\": \"$lv_dm_path\"}"
        return 0
 }
 
@@ -219,6 +245,7 @@ removevol() {
        exportlv "$1"
        [ "$lv_full_name" ] || return 2
        lvm_cmd lvremove -y "$lv_full_name"
+       ubus send block.volume "{\"name\": \"$1\", \"action\": \"down\", \"mode\": \"${lv_name:0:2}\", \"device\": \"$lv_dm_path\"}"
 }
 
 updatevol() {
@@ -231,6 +258,7 @@ updatevol() {
                        dd of=$lv_path
                        lvm_cmd lvchange -p r "$lv_full_name"
                        lvm_cmd lvrename "$lv_full_name" "${lv_full_name%%/*}/ro_$1"
+                       ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"ro\", \"device\": \"$(getdev "$@")\"}"
                        return 0
                        ;;
                default)
@@ -264,6 +292,29 @@ listvols() {
        done
 }
 
+boot() {
+       local reports rep lv lvs lv_name lv_dm_path lv_mode volname
+       json_init
+       json_load "$(lvs -o lv_name,lv_dm_path -S "lv_name=~^[rw][ow]_.*\$ && vg_name=$vg_name && lv_active=active")"
+       json_select report
+       json_get_keys reports
+       for rep in $reports; do
+               json_select "$rep"
+               json_select lv
+               json_get_keys lvs
+               for lv in $lvs; do
+                       json_select "$lv"
+                       json_get_vars lv_name lv_dm_path
+                       lv_mode="${lv_name:0:2}"
+                       lv_name="${lv_name:3}"
+                       ubus send block.volume "{\"name\": \"$lv_name\", \"action\": \"up\", \"mode\": \"$lv_mode\", \"device\": \"$lv_dm_path\"}"
+                       json_select ..
+               done
+               json_select ..
+               break
+       done
+}
+
 exportpv
 exportvg
 
@@ -277,6 +328,9 @@ case "$cmd" in
        total)
                totalbytes
                ;;
+       boot)
+               boot
+               ;;
        list)
                listvols "$@"
                ;;
index 7851a98df486d7ecde93fa4d76aecde80db53fb3..0a1b73093cb432b11111b0847de79e3b17470127 100644 (file)
@@ -31,8 +31,15 @@ getdev() {
        local voldir volname devname
        for voldir in /sys/devices/virtual/ubi/${ubidev}/${ubidev}_*; do
                read volname < "${voldir}/name"
-               [ "$volname" = "uvol-ro-$1" ] || [ "$volname" = "uvol-wp-$1" ] || [ "$volname" = "uvol-rw-$1" ] || [ "$volname" = "uvol-wo-$1" ] || continue
-               basename "$voldir"
+               case "$volname" in
+                       uvol-[rw][owpd]-$1)
+                               basename "$voldir"
+                               break
+                               ;;
+                       *)
+                               continue
+                               ;;
+               esac
        done
 }
 
@@ -51,7 +58,9 @@ vol_is_mode() {
 getstatus() {
        local voldev=$(getdev "$@")
        [ "$voldev" ] || return 2
-       vol_is_mode $voldev wo && return 1
+       vol_is_mode $voldev wo && return 22
+       vol_is_mode $voldev wp && return 16
+       vol_is_mode $voldev wd && return 1
        vol_is_mode $voldev ro && [ ! -e "/dev/ubiblock${voldev:3}" ] && return 1
        return 0
 }
@@ -73,10 +82,17 @@ getuserdev() {
        fi
 }
 
+mkubifs() {
+       local tmp_mp=$(mktemp -d)
+       mount -t ubifs $1 $tmp_mp
+       umount $tmp_mp
+       rmdir $tmp_mp
+}
+
 createvol() {
        local mode ret
-       local existdev=$(getdev "$@")
-       [ "$existdev" ] && return 17
+       local voldev=$(getdev "$@")
+       [ "$voldev" ] && return 17
        case "$3" in
                ro|wo)
                        mode=wo
@@ -91,37 +107,61 @@ createvol() {
        ubimkvol /dev/$ubidev -N "uvol-$mode-$1" -s "$2"
        ret=$?
        [ $ret -eq 0 ] || return $ret
-       ubiupdatevol -t /dev/$(getdev "$@")
+       voldev=$(getdev "$@")
+       ubiupdatevol -t /dev/$voldev
        [ "$mode" = "wp" ] || return 0
-       local tmp_mp=$(mktemp -d)
-       mount -t ubifs /dev/$(getdev "$@") $tmp_mp
-       umount $tmp_mp
-       rmdir $tmp_mp
+       mkubifs /dev/$voldev
        ubirename /dev/$ubidev uvol-wp-$1 uvol-rw-$1
+       ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"rw\", \"fstype\": \"ubifs\", \"device\": \"/dev/$voldev\"}"
 }
 
 removevol() {
        local voldev=$(getdev "$@")
+       local evdata
        [ "$voldev" ] || return 2
        local volnum=${voldev#${ubidev}_}
-       ubirmvol /dev/$ubidev -n $volnum
+       if vol_is_mode $voldev rw ; then
+               evdata="{\"name\": \"$1\", \"action\": \"down\", \"device\": \"/dev/$voldev\"}"
+       elif vol_is_mode $voldev ro ; then
+               evdata="{\"name\": \"$1\", \"action\": \"down\", \"device\": \"/dev/ubiblock${voldev:3}\"}"
+       fi
+       ubirmvol /dev/$ubidev -n $volnum || return $?
+       ubus send block.volume "$evdata"
 }
 
 activatevol() {
        local voldev=$(getdev "$@")
        [ "$voldev" ] || return 2
-       vol_is_mode $voldev wo || return 1
-       vol_is_mode $voldev ro || return 0
-       [ -e "/dev/ubiblock${voldev:3}" ] && return 0
-       ubiblock --create /dev/$voldev
+       vol_is_mode $voldev rw && return 0
+       vol_is_mode $voldev wo && return 22
+       vol_is_mode $voldev wp && return 16
+       if vol_is_mode $voldev ro; then
+               [ -e "/dev/ubiblock${voldev:3}" ] && return 0
+               ubiblock --create /dev/$voldev
+               ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"ro\", \"device\": \"/dev/ubiblock${voldev:3}\"}"
+               return 0
+       elif vol_is_mode $voldev wd; then
+               ubirename /dev/$ubidev uvol-wd-$1 uvol-rw-$1
+               ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"rw\", \"fstype\": \"ubifs\", \"device\": \"/dev/$voldev\"}"
+               return 0
+       fi
 }
 
 disactivatevol() {
        local voldev=$(getdev "$@")
        [ "$voldev" ] || return 2
-       vol_is_mode $voldev ro || return 0
-       [ -e "/dev/ubiblock${voldev:3}" ] || return 0
-       ubiblock --remove /dev/$voldev
+       vol_is_mode $voldev wo && return 22
+       vol_is_mode $voldev wp && return 16
+       if vol_is_mode $voldev ro; then
+               [ -e "/dev/ubiblock${voldev:3}" ] || return 0
+               ubiblock --remove /dev/$voldev || return $?
+               ubus send block.volume "{\"name\": \"$1\", \"action\": \"down\", \"mode\": \"ro\", \"device\": \"/dev/ubiblock${voldev:3}\"}"
+               return 0
+       elif vol_is_mode $voldev rw; then
+               ubirename /dev/$ubidev uvol-rw-$1 uvol-wd-$1 || return $?
+               ubus send block.volume "{\"name\": \"$1\", \"action\": \"down\", \"mode\": \"rw\", \"device\": \"/dev/$voldev\"}"
+               return 0
+       fi
 }
 
 updatevol() {
@@ -131,6 +171,8 @@ updatevol() {
        vol_is_mode $voldev wo || return 22
        ubiupdatevol -s $2 /dev/$voldev -
        ubirename /dev/$ubidev uvol-wo-$1 uvol-ro-$1
+       ubiblock --create /dev/$voldev
+       ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"ro\", \"device\": \"/dev/ubiblock${voldev:3}\"}"
 }
 
 listvols() {
@@ -138,7 +180,7 @@ listvols() {
        for voldir in /sys/devices/virtual/ubi/${ubidev}/${ubidev}_*; do
                read volname < $voldir/name
                case "$volname" in
-                       uvol-r[wo]*)
+                       uvol-[rw][wod]*)
                                read volsize < $voldir/data_bytes
                                ;;
                        *)
@@ -151,6 +193,31 @@ listvols() {
        done
 }
 
+bootvols() {
+       local volname volmode volsize voldev fstype
+       for voldir in /sys/devices/virtual/ubi/${ubidev}/${ubidev}_*; do
+               read volname < $voldir/name
+               voldev=$(basename $voldir)
+               fstype=
+               case "$volname" in
+                       uvol-ro-*)
+                               voldev="/dev/ubiblock${voldev:3}"
+                               ubiblock --create /dev/$voldev
+                               ;;
+                       uvol-rw-*)
+                               voldev="/dev/$voldev"
+                               fstype="ubifs"
+                               ;;
+                       *)
+                               continue
+                               ;;
+               esac
+               volmode=${volname:5:2}
+               volname=${volname:8}
+               ubus send block.volume "{\"name\": \"$volname\", \"action\": \"up\", \"mode\": \"$volmode\",${fstype:+ \"fstype\": \"$fstype\", }\"device\": \"$voldev\"}"
+       done
+}
+
 case "$cmd" in
        align)
                echo "$ebsize"
@@ -161,6 +228,9 @@ case "$cmd" in
        total)
                totalbytes
                ;;
+       boot)
+               bootvols
+               ;;
        list)
                listvols "$@"
                ;;
index 0fea88f38ce7d4fde7f78dbb77916b3be90422f3..a095b3efff386a8d1be55073b05a223a06a4f55b 100644 (file)
@@ -11,6 +11,7 @@ uvol storage volume manager
 syntax: uvol command ...
 
 commands:
+  boot                         get active volumes ready (called on boot)
   free                         show number of bytes available
   total                                show total number of bytes
   align                                show sector size in bytes
diff --git a/utils/uvol/files/uvol.init b/utils/uvol/files/uvol.init
new file mode 100644 (file)
index 0000000..7c290d7
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh /etc/rc.common
+
+START=99
+USE_PROCD=1
+NAME=uvol
+PROG=/usr/sbin/uvol
+
+start_service() {
+       [ "${__BOOT_UVOL}" = "1" ] || return 0
+       procd_open_instance "$NAME"
+       procd_set_param command "$PROG" boot
+       procd_close_instance
+}
+
+boot() {
+       __BOOT_UVOL=1
+       start
+}
git clone https://git.99rst.org/PROJECT