uvol: emmit ubus events and bring up volumes on boot

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 <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle 2021-04-17 19:16:18 +01:00
parent e6f5e2cc62
commit fc01307d7a
No known key found for this signature in database
GPG Key ID: 5A8F39C31C3217CA
5 changed files with 172 additions and 28 deletions

View File

@ -63,10 +63,11 @@ define Package/autopart/install
endef endef
define Package/uvol/install define Package/uvol/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/libexec/uvol $(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/libexec/uvol $(1)/usr/sbin
$(INSTALL_BIN) ./files/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/ubi.sh $(1)/usr/libexec/uvol/20-ubi.sh
$(INSTALL_BIN) ./files/lvm.sh $(1)/usr/libexec/uvol/50-lvm.sh $(INSTALL_BIN) ./files/lvm.sh $(1)/usr/libexec/uvol/50-lvm.sh
$(INSTALL_BIN) ./files/uvol $(1)/usr/sbin
endef endef
$(eval $(call BuildPackage,autopart)) $(eval $(call BuildPackage,autopart))

View File

@ -30,6 +30,7 @@ lvm_cmd() {
local cmd="$1" local cmd="$1"
shift shift
LVM_SUPPRESS_FD_WARNINGS=1 lvm "$cmd" "$@" LVM_SUPPRESS_FD_WARNINGS=1 lvm "$cmd" "$@"
return $?
} }
pvs() { pvs() {
@ -109,19 +110,23 @@ exportvg() {
done done
} }
lv_active=
lv_name=
lv_full_name= lv_full_name=
lv_path= lv_path=
lv_dm_path= lv_dm_path=
lv_size= lv_size=
exportlv() { exportlv() {
local reports rep lv lvs local reports rep lv lvs
lv_active=
lv_name=
lv_full_name= lv_full_name=
lv_path= lv_path=
lv_dm_path= lv_dm_path=
lv_size= lv_size=
json_init 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_select report
json_get_keys reports json_get_keys reports
for rep in $reports; do for rep in $reports; do
@ -130,7 +135,7 @@ exportlv() {
json_get_keys lvs json_get_keys lvs
for lv in $lvs; do for lv in $lvs; do
json_select "$lv" 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} lv_size=${lv_size%B}
json_select .. json_select ..
break break
@ -153,12 +158,17 @@ getsize() {
activatevol() { activatevol() {
exportlv "$1" exportlv "$1"
[ "$lv_path" ] || return 2
case "$lv_path" in case "$lv_path" in
/dev/*/wo_*) /dev/*/wo_*|\
/dev/*/wp_*)
return 22 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 return 0
;; ;;
esac esac
@ -166,7 +176,20 @@ activatevol() {
disactivatevol() { disactivatevol() {
exportlv "$1" 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() { getstatus() {
@ -192,14 +215,14 @@ createvol() {
;; ;;
rw) rw)
lvmode=rw lvmode=rw
mode=rw mode=wp
;; ;;
*) *)
return 22 return 22
;; ;;
esac 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=$? ret=$?
if [ ! $ret -eq 0 ] || [ "$lvmode" = "r" ]; then if [ ! $ret -eq 0 ] || [ "$lvmode" = "r" ]; then
return $ret return $ret
@ -212,6 +235,9 @@ createvol() {
else else
mke2fs -F -L "$1" "$lv_path" || return 1 mke2fs -F -L "$1" "$lv_path" || return 1
fi 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 return 0
} }
@ -219,6 +245,7 @@ removevol() {
exportlv "$1" exportlv "$1"
[ "$lv_full_name" ] || return 2 [ "$lv_full_name" ] || return 2
lvm_cmd lvremove -y "$lv_full_name" 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() { updatevol() {
@ -231,6 +258,7 @@ updatevol() {
dd of=$lv_path dd of=$lv_path
lvm_cmd lvchange -p r "$lv_full_name" lvm_cmd lvchange -p r "$lv_full_name"
lvm_cmd lvrename "$lv_full_name" "${lv_full_name%%/*}/ro_$1" 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 return 0
;; ;;
default) default)
@ -264,6 +292,29 @@ listvols() {
done 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 exportpv
exportvg exportvg
@ -277,6 +328,9 @@ case "$cmd" in
total) total)
totalbytes totalbytes
;; ;;
boot)
boot
;;
list) list)
listvols "$@" listvols "$@"
;; ;;

View File

@ -31,8 +31,15 @@ getdev() {
local voldir volname devname local voldir volname devname
for voldir in /sys/devices/virtual/ubi/${ubidev}/${ubidev}_*; do for voldir in /sys/devices/virtual/ubi/${ubidev}/${ubidev}_*; do
read volname < "${voldir}/name" read volname < "${voldir}/name"
[ "$volname" = "uvol-ro-$1" ] || [ "$volname" = "uvol-wp-$1" ] || [ "$volname" = "uvol-rw-$1" ] || [ "$volname" = "uvol-wo-$1" ] || continue case "$volname" in
basename "$voldir" uvol-[rw][owpd]-$1)
basename "$voldir"
break
;;
*)
continue
;;
esac
done done
} }
@ -51,7 +58,9 @@ vol_is_mode() {
getstatus() { getstatus() {
local voldev=$(getdev "$@") local voldev=$(getdev "$@")
[ "$voldev" ] || return 2 [ "$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 vol_is_mode $voldev ro && [ ! -e "/dev/ubiblock${voldev:3}" ] && return 1
return 0 return 0
} }
@ -73,10 +82,17 @@ getuserdev() {
fi fi
} }
mkubifs() {
local tmp_mp=$(mktemp -d)
mount -t ubifs $1 $tmp_mp
umount $tmp_mp
rmdir $tmp_mp
}
createvol() { createvol() {
local mode ret local mode ret
local existdev=$(getdev "$@") local voldev=$(getdev "$@")
[ "$existdev" ] && return 17 [ "$voldev" ] && return 17
case "$3" in case "$3" in
ro|wo) ro|wo)
mode=wo mode=wo
@ -91,37 +107,61 @@ createvol() {
ubimkvol /dev/$ubidev -N "uvol-$mode-$1" -s "$2" ubimkvol /dev/$ubidev -N "uvol-$mode-$1" -s "$2"
ret=$? ret=$?
[ $ret -eq 0 ] || return $ret [ $ret -eq 0 ] || return $ret
ubiupdatevol -t /dev/$(getdev "$@") voldev=$(getdev "$@")
ubiupdatevol -t /dev/$voldev
[ "$mode" = "wp" ] || return 0 [ "$mode" = "wp" ] || return 0
local tmp_mp=$(mktemp -d) mkubifs /dev/$voldev
mount -t ubifs /dev/$(getdev "$@") $tmp_mp
umount $tmp_mp
rmdir $tmp_mp
ubirename /dev/$ubidev uvol-wp-$1 uvol-rw-$1 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() { removevol() {
local voldev=$(getdev "$@") local voldev=$(getdev "$@")
local evdata
[ "$voldev" ] || return 2 [ "$voldev" ] || return 2
local volnum=${voldev#${ubidev}_} 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() { activatevol() {
local voldev=$(getdev "$@") local voldev=$(getdev "$@")
[ "$voldev" ] || return 2 [ "$voldev" ] || return 2
vol_is_mode $voldev wo || return 1 vol_is_mode $voldev rw && return 0
vol_is_mode $voldev ro || return 0 vol_is_mode $voldev wo && return 22
[ -e "/dev/ubiblock${voldev:3}" ] && return 0 vol_is_mode $voldev wp && return 16
ubiblock --create /dev/$voldev 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() { disactivatevol() {
local voldev=$(getdev "$@") local voldev=$(getdev "$@")
[ "$voldev" ] || return 2 [ "$voldev" ] || return 2
vol_is_mode $voldev ro || return 0 vol_is_mode $voldev wo && return 22
[ -e "/dev/ubiblock${voldev:3}" ] || return 0 vol_is_mode $voldev wp && return 16
ubiblock --remove /dev/$voldev 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() { updatevol() {
@ -131,6 +171,8 @@ updatevol() {
vol_is_mode $voldev wo || return 22 vol_is_mode $voldev wo || return 22
ubiupdatevol -s $2 /dev/$voldev - ubiupdatevol -s $2 /dev/$voldev -
ubirename /dev/$ubidev uvol-wo-$1 uvol-ro-$1 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() { listvols() {
@ -138,7 +180,7 @@ listvols() {
for voldir in /sys/devices/virtual/ubi/${ubidev}/${ubidev}_*; do for voldir in /sys/devices/virtual/ubi/${ubidev}/${ubidev}_*; do
read volname < $voldir/name read volname < $voldir/name
case "$volname" in case "$volname" in
uvol-r[wo]*) uvol-[rw][wod]*)
read volsize < $voldir/data_bytes read volsize < $voldir/data_bytes
;; ;;
*) *)
@ -151,6 +193,31 @@ listvols() {
done 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 case "$cmd" in
align) align)
echo "$ebsize" echo "$ebsize"
@ -161,6 +228,9 @@ case "$cmd" in
total) total)
totalbytes totalbytes
;; ;;
boot)
bootvols
;;
list) list)
listvols "$@" listvols "$@"
;; ;;

View File

@ -11,6 +11,7 @@ uvol storage volume manager
syntax: uvol command ... syntax: uvol command ...
commands: commands:
boot get active volumes ready (called on boot)
free show number of bytes available free show number of bytes available
total show total number of bytes total show total number of bytes
align show sector size in bytes align show sector size in bytes

View File

@ -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
}