Browse Source

uvol: make volume creation atomic

Make sure filesystem is ready when volume becomes available.
Use 'write-once' as initial state for read-only volumes, only allow
writing to volumes in that state and transision to 'read-only' once
write has completed.
Also fix a typo which prevented 'list' command from working with LVM.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
lilik-openwrt-22.03
Daniel Golle 4 years ago
parent
commit
3d4d75c519
No known key found for this signature in database GPG Key ID: 5A8F39C31C3217CA
3 changed files with 48 additions and 33 deletions
  1. +27
    -12
      utils/uvol/files/lvm.sh
  2. +21
    -19
      utils/uvol/files/ubi.sh
  3. +0
    -2
      utils/uvol/files/uvol

+ 27
- 12
utils/uvol/files/lvm.sh View File

@ -41,7 +41,7 @@ vgs() {
} }
lvs() { lvs() {
lvm_cmd vgs --reportformat json --units b "$@"
lvm_cmd lvs --reportformat json --units b "$@"
} }
freebytes() { freebytes() {
@ -121,7 +121,7 @@ exportlv() {
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=~^r[ow]_$1\$ && vg_name=$vg_name")"
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_select report json_select report
json_get_keys reports json_get_keys reports
for rep in $reports; do for rep in $reports; do
@ -153,7 +153,15 @@ getsize() {
activatevol() { activatevol() {
exportlv "$1" exportlv "$1"
lvm_cmd lvchange -a y "$lv_full_name"
case "$lv_path" in
/dev/*/wo_*)
return 22
;;
*)
lvm_cmd lvchange -a y "$lv_full_name"
return 0
;;
esac
} }
disactivatevol() { disactivatevol() {
@ -169,7 +177,7 @@ getstatus() {
} }
createvol() { createvol() {
local mode ret
local mode lvmode ret
local volsize=$(($2)) local volsize=$(($2))
[ "$volsize" ] || return 22 [ "$volsize" ] || return 22
exportlv "$1" exportlv "$1"
@ -178,10 +186,12 @@ createvol() {
[ $((size_ext * vg_extent_size)) -lt $volsize ] && size_ext=$((size_ext + 1)) [ $((size_ext * vg_extent_size)) -lt $volsize ] && size_ext=$((size_ext + 1))
case "$3" in case "$3" in
ro)
mode=r
ro|wo)
lvmode=r
mode=wo
;; ;;
rw) rw)
lvmode=rw
mode=rw mode=rw
;; ;;
*) *)
@ -189,9 +199,9 @@ createvol() {
;; ;;
esac esac
lvm_cmd lvcreate -p $mode -a n -y -W n -Z n -n "${3}_${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 ] || [ "$mode" = "r" ]; then
if [ ! $ret -eq 0 ] || [ "$lvmode" = "r" ]; then
return $ret return $ret
fi fi
exportlv "$1" exportlv "$1"
@ -215,11 +225,16 @@ updatevol() {
exportlv "$1" exportlv "$1"
[ "$lv_full_name" ] || return 2 [ "$lv_full_name" ] || return 2
[ $lv_size -ge $2 ] || return 27 [ $lv_size -ge $2 ] || return 27
lvm_cmd lvchange -a y -p rw "$lv_full_name"
dd of=$lv_path
case "$lv_path" in case "$lv_path" in
/dev/*/ro_*)
/dev/*/wo_*)
lvm_cmd lvchange -a y -p rw "$lv_full_name"
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"
return 0
;;
default)
return 22
;; ;;
esac esac
} }
@ -228,7 +243,7 @@ listvols() {
local reports rep lv lvs lv_name lv_size lv_mode volname local reports rep lv lvs lv_name lv_size lv_mode volname
volname=${1:-.*} volname=${1:-.*}
json_init json_init
json_load "$(lvs -o lv_name,lv_size -S "lv_name=~^r[ow]_$volname\$ && vg_name=$vg_name")"
json_load "$(lvs -o lv_name,lv_size -S "lv_name=~^[rw][ow]_$volname\$ && 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


+ 21
- 19
utils/uvol/files/ubi.sh View File

@ -31,17 +31,17 @@ 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-rw-$1" ] || continue
[ "$volname" = "uvol-ro-$1" ] || [ "$volname" = "uvol-wp-$1" ] || [ "$volname" = "uvol-rw-$1" ] || [ "$volname" = "uvol-wo-$1" ] || continue
basename "$voldir" basename "$voldir"
done done
} }
needs_ubiblock() {
vol_is_mode() {
local voldev="$1" local voldev="$1"
local volname local volname
read volname < "/sys/devices/virtual/ubi/${ubidev}/${voldev}/name" read volname < "/sys/devices/virtual/ubi/${ubidev}/${voldev}/name"
case "$volname" in case "$volname" in
uvol-ro-*)
uvol-$2-*)
return 0 return 0
;; ;;
esac esac
@ -51,7 +51,8 @@ needs_ubiblock() {
getstatus() { getstatus() {
local voldev=$(getdev "$@") local voldev=$(getdev "$@")
[ "$voldev" ] || return 2 [ "$voldev" ] || return 2
needs_ubiblock $voldev && [ ! -e "/dev/ubiblock${voldev:3}" ] && return 1
vol_is_mode $voldev wo && return 1
vol_is_mode $voldev ro && [ ! -e "/dev/ubiblock${voldev:3}" ] && return 1
return 0 return 0
} }
@ -65,9 +66,9 @@ getsize() {
getuserdev() { getuserdev() {
local voldev=$(getdev "$@") local voldev=$(getdev "$@")
[ "$voldev" ] || return 2 [ "$voldev" ] || return 2
if needs_ubiblock $voldev ; then
if vol_is_mode $voldev ro ; then
echo "/dev/ubiblock${voldev:3}" echo "/dev/ubiblock${voldev:3}"
else
elif vol_is_mode $voldev rw ; then
echo "/dev/$voldev" echo "/dev/$voldev"
fi fi
} }
@ -77,11 +78,11 @@ createvol() {
local existdev=$(getdev "$@") local existdev=$(getdev "$@")
[ "$existdev" ] && return 17 [ "$existdev" ] && return 17
case "$3" in case "$3" in
ro)
mode=ro
ro|wo)
mode=wo
;; ;;
rw) rw)
mode=rw
mode=wp
;; ;;
*) *)
return 22 return 22
@ -91,6 +92,12 @@ createvol() {
ret=$? ret=$?
[ $ret -eq 0 ] || return $ret [ $ret -eq 0 ] || return $ret
ubiupdatevol -t /dev/$(getdev "$@") ubiupdatevol -t /dev/$(getdev "$@")
[ "$mode" = "wp" ] || return 0
local tmp_mp=$(mktemp -d)
mount -t ubifs /dev/$(getdev "$@") $tmp_mp
umount $tmp_mp
rmdir $tmp_mp
ubirename /dev/$ubidev uvol-wp-$1 uvol-rw-$1
} }
removevol() { removevol() {
@ -103,7 +110,8 @@ removevol() {
activatevol() { activatevol() {
local voldev=$(getdev "$@") local voldev=$(getdev "$@")
[ "$voldev" ] || return 2 [ "$voldev" ] || return 2
needs_ubiblock $voldev || return 0
vol_is_mode $voldev wo || return 1
vol_is_mode $voldev ro || return 0
[ -e "/dev/ubiblock${voldev:3}" ] && return 0 [ -e "/dev/ubiblock${voldev:3}" ] && return 0
ubiblock --create /dev/$voldev ubiblock --create /dev/$voldev
} }
@ -111,7 +119,7 @@ activatevol() {
disactivatevol() { disactivatevol() {
local voldev=$(getdev "$@") local voldev=$(getdev "$@")
[ "$voldev" ] || return 2 [ "$voldev" ] || return 2
needs_ubiblock $voldev || return 0
vol_is_mode $voldev ro || return 0
[ -e "/dev/ubiblock${voldev:3}" ] || return 0 [ -e "/dev/ubiblock${voldev:3}" ] || return 0
ubiblock --remove /dev/$voldev ubiblock --remove /dev/$voldev
} }
@ -120,15 +128,9 @@ updatevol() {
local voldev=$(getdev "$@") local voldev=$(getdev "$@")
[ "$voldev" ] || return 2 [ "$voldev" ] || return 2
[ "$2" ] || return 22 [ "$2" ] || return 22
needs_ubiblock $voldev || return 22
vol_is_mode $voldev wo || return 22
ubiupdatevol -s $2 /dev/$voldev - ubiupdatevol -s $2 /dev/$voldev -
}
getstatus() {
local voldev=$(getdev "$@")
[ "$voldev" ] || return 2
needs_ubiblock $voldev && [ ! -e "/dev/ubiblock${voldev:3}" ] && return 1
return 0
ubirename /dev/$ubidev uvol-wo-$1 uvol-ro-$1
} }
listvols() { listvols() {


+ 0
- 2
utils/uvol/files/uvol View File

@ -2,8 +2,6 @@
# uvol prototype # uvol prototype
# future development roadmap (aka. to-do): # future development roadmap (aka. to-do):
# * atomic create using temp volnames
# * create read-only volumes as 'write-once', introduce 'pending' state until written
# * re-implement in C (use libubox, execve lvm/ubi*) # * re-implement in C (use libubox, execve lvm/ubi*)
# * add atomic batch processing for use by container/package manager # * add atomic batch processing for use by container/package manager


Loading…
Cancel
Save