uvol: update to version 0.3

* genrate UCI fstab configs for each volume before first 'up'
 * remove UCI section on volume remove
 * use autofs automounter for read-only volumes
 * try umount on 'down'
 * emulate hotplug events for UBI volume up/down
 * more robust error paths

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle 2021-07-24 04:35:10 +01:00
parent 1614cdde0a
commit f4afa4189e
No known key found for this signature in database
GPG key ID: 5A8F39C31C3217CA
4 changed files with 145 additions and 34 deletions

View file

@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=uvol PKG_NAME:=uvol
PKG_VERSION:=0.2 PKG_VERSION:=0.3
PKG_RELEASE:=$(AUTORELEASE) PKG_RELEASE:=$(AUTORELEASE)
PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org> PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
@ -28,6 +28,7 @@ define Package/uvol
CATEGORY:=Utilities CATEGORY:=Utilities
SUBMENU:=Disc SUBMENU:=Disc
TITLE:=OpenWrt UBI/LVM volume abstraction TITLE:=OpenWrt UBI/LVM volume abstraction
DEPENDS:=+blockd
PKGARCH=all PKGARCH=all
endef endef
@ -63,8 +64,9 @@ define Package/autopart/install
endef endef
define Package/uvol/install define Package/uvol/install
$(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/libexec/uvol $(1)/usr/sbin $(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/libexec/uvol $(1)/usr/sbin $(1)/lib/functions
$(INSTALL_BIN) ./files/uvol.init $(1)/etc/init.d/uvol $(INSTALL_BIN) ./files/uvol.init $(1)/etc/init.d/uvol
$(INSTALL_BIN) ./files/common.sh $(1)/lib/functions/uvol.sh
$(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 $(INSTALL_BIN) ./files/uvol $(1)/usr/sbin

View file

@ -0,0 +1,66 @@
#!/bin/sh
UCI_SPOOLDIR="/var/spool/uvol"
_uvol_init_spooldir() {
[ ! -d "$(dirname "$UCI_SPOOLDIR")" ] && mkdir -p "$(dirname "$UCI_SPOOLDIR")"
mkdir -m 0700 -p "$UCI_SPOOLDIR"
}
uvol_uci_add() {
local volname="$1"
local devname="$2"
local mode="$3"
local autofs uuid uciname
uciname=${volname//-/_}
uuid="$(/sbin/block info | grep "^$2" | xargs -n 1 echo | grep "^UUID=.*")"
[ "$uuid" ] || return 22
_uvol_init_spooldir
uuid="${uuid:5}"
autofs=0
[ "$mode" = "ro" ] && autofs=1
if [ -e "${UCI_SPOOLDIR}/remove-$1" ]; then
rm "${UCI_SPOOLDIR}/remove-$1"
fi
cat >"${UCI_SPOOLDIR}/add-$1" <<EOF
set fstab.$uciname=mount
set fstab.$uciname.uuid=$uuid
set fstab.$uciname.target=/var/run/uvol/$volname
set fstab.$uciname.options=$mode
set fstab.$uciname.autofs=$autofs
set fstab.$uciname.enabled=1
commit fstab
EOF
}
uvol_uci_remove() {
local volname="$1"
local uciname
uciname=${volname//-/_}
if [ -e "${UCI_SPOOLDIR}/add-$1" ]; then
rm "${UCI_SPOOLDIR}/add-$1"
return
fi
_uvol_init_spooldir
cat >"${UCI_SPOOLDIR}/remove-$1" <<EOF
delete fstab.$uciname
commit fstab
EOF
}
uvol_uci_commit() {
local volname="$1"
if [ -e "${UCI_SPOOLDIR}/add-$1" ]; then
uci batch < "${UCI_SPOOLDIR}/add-$1"
rm "${UCI_SPOOLDIR}/add-$1"
elif [ -e "${UCI_SPOOLDIR}/remove-$1" ]; then
uci batch < "${UCI_SPOOLDIR}/remove-$1"
rm "${UCI_SPOOLDIR}/remove-$1"
fi
return $?
}

View file

@ -11,6 +11,7 @@ fi
command -v lvm >/dev/null || return 1 command -v lvm >/dev/null || return 1
. /lib/functions.sh . /lib/functions.sh
. /lib/functions/uvol.sh
. /lib/upgrade/common.sh . /lib/upgrade/common.sh
. /usr/share/libubox/jshn.sh . /usr/share/libubox/jshn.sh
@ -147,15 +148,21 @@ exportlv() {
getdev() { getdev() {
local dms dm_name local dms dm_name
existvol "$1" || return 1
exportlv "$1"
for dms in /sys/devices/virtual/block/dm-* ; do for dms in /sys/devices/virtual/block/dm-* ; do
[ "$dms" = "/sys/devices/virtual/block/dm-*" ] && break
read -r dm_name < "$dms/dm/name" read -r dm_name < "$dms/dm/name"
[ $(basename "$lv_dm_path") = "$dm_name" ] && echo "$(basename "$dms")" [ $(basename "$lv_dm_path") = "$dm_name" ] && echo "$(basename "$dms")"
done done
} }
getuserdev() {
local dms dm_name
existvol "$1" || return 1
exportlv "$1"
getdev "$@"
}
getsize() { getsize() {
exportlv "$1" exportlv "$1"
[ "$lv_size" ] && echo "$lv_size" [ "$lv_size" ] && echo "$lv_size"
@ -171,8 +178,9 @@ activatevol() {
;; ;;
*) *)
[ "$lv_active" = "active" ] && return 0 [ "$lv_active" = "active" ] && return 0
lvm_cmd lvchange -k n "$lv_full_name" || return $? uvol_uci_commit "$1"
lvm_cmd lvchange -a y "$lv_full_name" || return $? lvm_cmd lvchange -a y "$lv_full_name" || return $?
lvm_cmd lvchange -k n "$lv_full_name" || return $?
return 0 return 0
;; ;;
esac esac
@ -180,6 +188,7 @@ activatevol() {
disactivatevol() { disactivatevol() {
exportlv "$1" exportlv "$1"
local devname
[ "$lv_path" ] || return 2 [ "$lv_path" ] || return 2
case "$lv_path" in case "$lv_path" in
/dev/*/wo_*|\ /dev/*/wo_*|\
@ -188,7 +197,9 @@ disactivatevol() {
;; ;;
*) *)
[ "$lv_active" = "active" ] || return 0 [ "$lv_active" = "active" ] || return 0
lvm_cmd lvchange -a n "$lv_full_name" || return $? devname="$(getdev "$1")"
[ "$devname" ] && /sbin/block umount "$devname"
lvm_cmd lvchange -a n "$lv_full_name"
lvm_cmd lvchange -k y "$lv_full_name" || return $? lvm_cmd lvchange -k y "$lv_full_name" || return $?
return 0 return 0
;; ;;
@ -225,30 +236,41 @@ createvol() {
;; ;;
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" || return $?
ret=$? ret=$?
if [ ! $ret -eq 0 ] || [ "$lvmode" = "r" ]; then if [ ! $ret -eq 0 ] || [ "$lvmode" = "r" ]; then
return $ret return $ret
fi fi
exportlv "$1" exportlv "$1"
[ "$lv_full_name" ] || return 22 [ "$lv_full_name" ] || return 22
lvm_cmd lvchange -a y "$lv_full_name" || return 1 lvm_cmd lvchange -a y "$lv_full_name" || return $?
if [ "$lv_size" -gt $(( 100 * 1024 * 1024 )) ]; then if [ "$lv_size" -gt $(( 100 * 1024 * 1024 )) ]; then
mkfs.f2fs -f -l "$1" "$lv_path" mkfs.f2fs -f -l "$1" "$lv_path"
ret=$? ret=$?
[ $ret != 0 ] && [ $ret != 134 ] && return 1 [ $ret != 0 ] && [ $ret != 134 ] && {
lvm_cmd lvchange -a n "$lv_full_name" || return $?
return $ret
}
else else
mke2fs -F -L "$1" "$lv_path" || return 1 mke2fs -F -L "$1" "$lv_path" || {
ret=$?
lvm_cmd lvchange -a n "$lv_full_name" || return $?
return $ret
}
fi fi
lvm_cmd lvrename "$vg_name" "wp_$1" "rw_$1" uvol_uci_add "$1" "/dev/$(getdev "$1")" "rw"
exportlv "$1" lvm_cmd lvchange -a n "$lv_full_name" || return $?
lvm_cmd lvrename "$vg_name" "wp_$1" "rw_$1" || return $?
return 0 return 0
} }
removevol() { removevol() {
exportlv "$1" exportlv "$1"
[ "$lv_full_name" ] || return 2 [ "$lv_full_name" ] || return 2
lvm_cmd lvremove -y "$lv_full_name" [ "$lv_active" = "active" ] && return 16
lvm_cmd lvremove -y "$lv_full_name" || return $?
uvol_uci_remove "$1"
uvol_uci_commit "$1"
} }
updatevol() { updatevol() {
@ -257,12 +279,13 @@ updatevol() {
[ "$lv_size" -ge "$2" ] || return 27 [ "$lv_size" -ge "$2" ] || return 27
case "$lv_path" in case "$lv_path" in
/dev/*/wo_*) /dev/*/wo_*)
lvm_cmd lvchange -p rw "$lv_full_name" lvm_cmd lvchange -p rw "$lv_full_name" || return $?
lvm_cmd lvchange -a y "$lv_full_name" lvm_cmd lvchange -a y "$lv_full_name" || return $?
dd of="$lv_path" dd of="$lv_path"
lvm_cmd lvchange -a n "$lv_full_name" uvol_uci_add "$1" "/dev/$(getdev "$1")" "ro"
lvm_cmd lvchange -p r "$lv_full_name" lvm_cmd lvchange -a n "$lv_full_name" || return $?
lvm_cmd lvrename "$lv_full_name" "${lv_full_name%%/*}/ro_$1" lvm_cmd lvchange -p r "$lv_full_name" || return $?
lvm_cmd lvrename "$lv_full_name" "${lv_full_name%%/*}/ro_$1" || return $?
return 0 return 0
;; ;;
default) default)
@ -344,7 +367,7 @@ case "$cmd" in
removevol "$@" removevol "$@"
;; ;;
device) device)
getdev "$@" getuserdev "$@"
;; ;;
size) size)
getsize "$@" getsize "$@"

View file

@ -17,6 +17,8 @@ ubidev=$(ls -1 /sys/devices/virtual/ubi | head -n 1)
read -r ebsize < "/sys/devices/virtual/ubi/${ubidev}/eraseblock_size" read -r ebsize < "/sys/devices/virtual/ubi/${ubidev}/eraseblock_size"
. /lib/functions/uvol.sh
freebytes() { freebytes() {
read -r availeb < "/sys/devices/virtual/ubi/${ubidev}/avail_eraseblocks" read -r availeb < "/sys/devices/virtual/ubi/${ubidev}/avail_eraseblocks"
echo $((availeb * ebsize)) echo $((availeb * ebsize))
@ -87,9 +89,10 @@ getuserdev() {
mkubifs() { mkubifs() {
local tmp_mp local tmp_mp
tmp_mp="$(mktemp -d)" tmp_mp="$(mktemp -d)"
mount -t ubifs "$1" "$tmp_mp" mount -t ubifs "$1" "$tmp_mp" || return $?
umount "$tmp_mp" umount "$tmp_mp" || return $?
rmdir "$tmp_mp" rmdir "$tmp_mp" || return $?
return 0
} }
createvol() { createvol() {
@ -107,22 +110,33 @@ createvol() {
return 22 return 22
;; ;;
esac esac
ubimkvol "/dev/$ubidev" -N "uvol-$mode-$1" -s "$2" ubimkvol "/dev/$ubidev" -N "uvol-$mode-$1" -s "$2" || return $?
ret=$? ret=$?
[ $ret -eq 0 ] || return $ret [ $ret -eq 0 ] || return $ret
voldev="$(getdev "$@")" voldev="$(getdev "$@")"
ubiupdatevol -t "/dev/$voldev" ubiupdatevol -t "/dev/$voldev" || return $?
[ "$mode" = "wp" ] || return 0 [ "$mode" = "wp" ] || return 0
mkubifs "/dev/$voldev" mkubifs "/dev/$voldev" || return $?
ubirename "/dev/$ubidev" "uvol-wp-$1" "uvol-wd-$1" uvol_uci_add "$1" "/dev/$voldev" "rw"
ubirename "/dev/$ubidev" "uvol-wp-$1" "uvol-wd-$1" || return $?
} }
removevol() { removevol() {
local voldev local voldev volnum
voldev=$(getdev "$@") voldev=$(getdev "$@")
[ "$voldev" ] || return 2 [ "$voldev" ] || return 2
local volnum="${voldev#${ubidev}_}" vol_is_mode "$voldev" rw && return 16
vol_is_mode "$voldev" ro && return 16
volnum="${voldev#${ubidev}_}"
ubirmvol "/dev/$ubidev" -n "$volnum" || return $? ubirmvol "/dev/$ubidev" -n "$volnum" || return $?
uvol_uci_remove "$1"
uvol_uci_commit "$1"
}
block_hotplug() {
export ACTION="$1"
export DEVNAME="$2"
/sbin/block hotplug
} }
activatevol() { activatevol() {
@ -133,12 +147,15 @@ activatevol() {
vol_is_mode "$voldev" ro && return 0 vol_is_mode "$voldev" ro && return 0
vol_is_mode "$voldev" wo && return 22 vol_is_mode "$voldev" wo && return 22
vol_is_mode "$voldev" wp && return 16 vol_is_mode "$voldev" wp && return 16
uvol_uci_commit "$1"
if vol_is_mode "$voldev" rd; then if vol_is_mode "$voldev" rd; then
ubirename "/dev/$ubidev" "uvol-rd-$1" "uvol-ro-$1" ubirename "/dev/$ubidev" "uvol-rd-$1" "uvol-ro-$1" || return $?
ubiblock --create "/dev/$voldev" ubiblock --create "/dev/$voldev" || return $?
block_hotplug add "ubiblock${voldev:3}"
return 0 return 0
elif vol_is_mode "$voldev" wd; then elif vol_is_mode "$voldev" wd; then
ubirename "/dev/$ubidev" "uvol-wd-$1" "uvol-rw-$1" ubirename "/dev/$ubidev" "uvol-wd-$1" "uvol-rw-$1" || return $?
block_hotplug add "$voldev"
return 0 return 0
fi fi
} }
@ -152,12 +169,14 @@ disactivatevol() {
vol_is_mode "$voldev" wo && return 22 vol_is_mode "$voldev" wo && return 22
vol_is_mode "$voldev" wp && return 16 vol_is_mode "$voldev" wp && return 16
if vol_is_mode "$voldev" ro; then if vol_is_mode "$voldev" ro; then
[ -e "/dev/ubiblock${voldev:3}" ] || return 0 /sbin/block umount "ubiblock${voldev:3}"
ubiblock --remove "/dev/$voldev" || return $? ubiblock --remove "/dev/$voldev"
ubirename "/dev/$ubidev" "uvol-ro-$1" "uvol-rd-$1" || return $? ubirename "/dev/$ubidev" "uvol-ro-$1" "uvol-rd-$1" || return $?
return 0 return 0
elif vol_is_mode "$voldev" rw; then elif vol_is_mode "$voldev" rw; then
/sbin/block umount "$voldev"
ubirename "/dev/$ubidev" "uvol-rw-$1" "uvol-wd-$1" || return $? ubirename "/dev/$ubidev" "uvol-rw-$1" "uvol-wd-$1" || return $?
block_hotplug remove "$voldev"
return 0 return 0
fi fi
} }
@ -169,6 +188,7 @@ updatevol() {
[ "$2" ] || return 22 [ "$2" ] || return 22
vol_is_mode "$voldev" wo || return 22 vol_is_mode "$voldev" wo || return 22
ubiupdatevol -s "$2" "/dev/$voldev" - ubiupdatevol -s "$2" "/dev/$voldev" -
uvol_uci_add "$1" "/dev/$voldev" "ro"
ubirename "/dev/$ubidev" "uvol-wo-$1" "uvol-rd-$1" ubirename "/dev/$ubidev" "uvol-wo-$1" "uvol-rd-$1"
} }
@ -199,7 +219,7 @@ bootvols() {
case "$volname" in case "$volname" in
uvol-ro-*) uvol-ro-*)
voldev="/dev/ubiblock${voldev:3}" voldev="/dev/ubiblock${voldev:3}"
ubiblock --create "/dev/$voldev" ubiblock --create "/dev/$voldev" || return $?
;; ;;
*) *)
continue continue