Browse Source

uvol: some improvements

* use lvm --reportformat json
 * add 'list' and 'align' commands
 * add help output

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
lilik-openwrt-22.03
Daniel Golle 4 years ago
parent
commit
a4b034cf68
No known key found for this signature in database GPG Key ID: 5A8F39C31C3217CA
3 changed files with 252 additions and 75 deletions
  1. +172
    -71
      utils/uvol/files/lvm.sh
  2. +37
    -4
      utils/uvol/files/ubi.sh
  3. +43
    -0
      utils/uvol/files/uvol

+ 172
- 71
utils/uvol/files/lvm.sh View File

@ -1,15 +1,23 @@
#!/bin/sh #!/bin/sh
command -v lvm || return 1
cmd="$1"
shift
if [ "$cmd" = "name" ]; then
echo "LVM"
return 0
fi
command -v lvm >/dev/null || return 1
. /lib/functions.sh . /lib/functions.sh
. /lib/upgrade/common.sh . /lib/upgrade/common.sh
. /usr/share/libubox/jshn.sh
export_bootdevice export_bootdevice
[ "$BOOTDEV_MAJOR" ] || return 1 [ "$BOOTDEV_MAJOR" ] || return 1
export_partdevice rootdev 0 export_partdevice rootdev 0
[ "$rootdev" ] || return 1 [ "$rootdev" ] || return 1
LVM_SUPPRESS_FD_WARNINGS=1
case "$rootdev" in case "$rootdev" in
mtd*|\ mtd*|\
@ -18,93 +26,157 @@ case "$rootdev" in
return 1 return 1
esac esac
lvs() {
lvm_cmd() {
local cmd="$1" local cmd="$1"
local cb="$2"
local param="${3:+-S vg_name=${vgname} -S lv_name=~^r[ow]_$3\$}"
local oIFS="$IFS"
IFS=" "
set -- $(LVM_SUPPRESS_FD_WARNINGS=1 $cmd -c $param)
[ "$1" ] || {
IFS="$oIFS"
return 1
}
IFS=":"
set -- $1
IFS="$oIFS"
$cb "$@"
}
pvvars() {
case "${1:5}" in
"$rootdev"*)
partdev="$1"
vgname="$2"
;;
esac
shift
LVM_SUPPRESS_FD_WARNINGS=1 lvm "$cmd" "$@"
}
pvs() {
lvm_cmd pvs --reportformat json --units b "$@"
} }
vgvars() {
[ "$1" = "$vgname" ] || return
vgbs="${13}"
vgts="${14}"
vgus="${15}"
vgfs="${16}"
vgs() {
lvm_cmd vgs --reportformat json --units b "$@"
} }
lvvars() {
lvpath="$1"
lvsize=$(( 512 * $7 ))
lvs() {
lvm_cmd vgs --reportformat json --units b "$@"
} }
freebytes() { freebytes() {
echo $((vgfs * vgbs * 1024))
echo $(($vg_free_count * $vg_extent_size * 1024))
} }
totalbytes() { totalbytes() {
echo $((vgts * vgbs * 1024))
echo $(($vg_extent_count * $vg_extent_size * 1024))
} }
existvol() { existvol() {
[ "$1" ] || return 1 [ "$1" ] || return 1
test -e "/dev/$vgname/ro_$1" || test -e "/dev/$vgname/rw_$1"
test -e "/dev/$vg_name/ro_$1" || test -e "/dev/$vg_name/rw_$1"
return $? return $?
} }
getlvname() {
lvs lvdisplay lvvars "$1"
vg_name=
exportpv() {
local reports rep pv pvs
vg_name=
json_init
json_load "$(pvs -o vg_name -S "pv_name=~^/dev/$rootdev.*\$")"
json_select report
json_get_keys reports
for rep in $reports; do
json_select "$rep"
json_select pv
json_get_keys pvs
for pv in $pvs; do
json_select "$pv"
json_get_vars vg_name
json_select ..
break
done
json_select ..
break
done
}
[ "$lvpath" ] && echo ${lvpath:5}
vg_extent_size=
vg_extent_count=
vg_free_count=
exportvg() {
local reports rep vg vgs
vg_extent_size=
vg_extent_count=
vg_free_count=
json_init
json_load "$(vgs -o vg_extent_size,vg_extent_count,vg_free_count -S "vg_name=$vg_name")"
json_select report
json_get_keys reports
for rep in $reports; do
json_select "$rep"
json_select vg
json_get_keys vgs
for vg in $vgs; do
json_select "$vg"
json_get_vars vg_extent_size vg_extent_count vg_free_count
vg_extent_size=${vg_extent_size%B}
json_select ..
break
done
json_select ..
break
done
}
lv_full_name=
lv_path=
lv_dm_path=
lv_size=
exportlv() {
local reports rep lv lvs
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=~^r[ow]_$1\$ && vg_name=$vg_name")"
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_full_name lv_size lv_path lv_dm_path
lv_size=${lv_size%B}
json_select ..
break
done
json_select ..
break
done
} }
getdev() { getdev() {
existvol "$1" || return 1 existvol "$1" || return 1
readlink /dev/$(getlvname "$1")
exportlv "$1"
echo $lv_dm_path
} }
getsize() { getsize() {
lvs lvdisplay lvvars "$1"
[ "$lvsize" ] && echo $lvsize
exportlv "$1"
[ "$lv_size" ] && echo $lv_size
} }
activatevol() { activatevol() {
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a y "$(getlvname "$1")"
exportlv "$1"
lvm_cmd lvchange -a y "$lv_full_name"
} }
disactivatevol() { disactivatevol() {
existvol "$1" || return 1
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a n "$(getlvname "$1")"
exportlv "$1"
lvm_cmd lvchange -a n "$lv_full_name"
} }
getstatus() { getstatus() {
lvs lvdisplay lvvars "$1"
[ "$lvsize" ] || return 2
exportlv "$1"
[ "$lv_full_name" ] || return 2
existvol "$1" || return 1 existvol "$1" || return 1
return 0 return 0
} }
createvol() { createvol() {
local mode ret lvname
local mode ret
local volsize=$(($2))
[ "$volsize" ] || return 22
exportlv "$1"
[ "$lv_size" ] && return 17
size_ext=$((volsize / vg_extent_size))
[ $((size_ext * vg_extent_size)) -lt $volsize ] && size_ext=$((size_ext + 1))
case "$3" in case "$3" in
ro) ro)
mode=r mode=r
@ -117,53 +189,82 @@ createvol() {
;; ;;
esac esac
LVM_SUPPRESS_FD_WARNINGS=1 lvcreate -p $mode -a n -y -W n -Z n -n "${3}_${1}" -L "$2" $vgname
lvm_cmd lvcreate -p $mode -a n -y -W n -Z n -n "${3}_${1}" -l "$size_ext" $vg_name
ret=$? ret=$?
if [ ! $ret -eq 0 ] || [ "$mode" = "r" ]; then if [ ! $ret -eq 0 ] || [ "$mode" = "r" ]; then
return $ret return $ret
fi fi
lvs lvdisplay lvvars "$1"
[ "$lvpath" ] || return 22
lvname=${lvpath:5}
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a y /dev/$lvname || return 1
if [ $lvsize -gt $(( 100 * 1024 * 1024 )) ]; then
mkfs.f2fs -f -l "$1" $lvpath || return 1
exportlv "$1"
[ "$lv_full_name" ] || return 22
lvm_cmd lvchange -a y "$lv_full_name" || return 1
if [ $lv_size -gt $(( 100 * 1024 * 1024 )) ]; then
mkfs.f2fs -f -l "$1" "$lv_path" || return 1
else else
mke2fs -F -L "$1" $lvpath || return 1
mke2fs -F -L "$1" "$lv_path" || return 1
fi fi
return 0 return 0
} }
removevol() { removevol() {
local lvname="$(getlvname "$1")"
[ "$lvname" ] || return 2
LVM_SUPPRESS_FD_WARNINGS=1 lvremove -y "$(getlvname "$1")"
exportlv "$1"
[ "$lv_full_name" ] || return 2
lvm_cmd lvremove -y "$lv_full_name"
} }
updatevol() { updatevol() {
lvs lvdisplay lvvars "$1"
[ "$lvpath" ] || return 2
[ $lvsize -ge $2 ] || return 27
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a y -p rw ${lvpath:5}
dd of=$lvpath
case "$lvpath" in
exportlv "$1"
[ "$lv_full_name" ] || return 2
[ $lv_size -ge $2 ] || return 27
lvm_cmd lvchange -a y -p rw "$lv_full_name"
dd of=$lv_path
case "$lv_path" in
/dev/*/ro_*) /dev/*/ro_*)
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -p r ${lvpath:5}
lvm_cmd lvchange -p r "$lv_full_name"
;; ;;
esac esac
} }
lvs pvdisplay pvvars
lvs vgdisplay vgvars
cmd="$1"
shift
listvols() {
local reports rep lv lvs lv_name lv_size lv_mode volname
volname=${1:-.*}
json_init
json_load "$(lvs -o lv_name,lv_size -S "lv_name=~^r[ow]_$volname\$ && vg_name=$vg_name")"
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_size
lv_mode="${lv_name:0:2}"
lv_name="${lv_name:3}"
lv_size=${lv_size%B}
echo "$lv_name $lv_mode $lv_size"
json_select ..
done
json_select ..
break
done
}
exportpv
exportvg
case "$cmd" in case "$cmd" in
align)
echo "$vg_extent_size"
;;
free) free)
freebytes freebytes
;; ;;
total) total)
totalbytes totalbytes
;; ;;
list)
listvols "$@"
;;
create) create)
createvol "$@" createvol "$@"
;; ;;


+ 37
- 4
utils/uvol/files/ubi.sh View File

@ -1,5 +1,13 @@
#!/bin/sh #!/bin/sh
cmd="$1"
shift
if [ "$cmd" = "name" ]; then
echo "UBI"
return 0
fi
test -e /sys/class/ubi/version || return 0 test -e /sys/class/ubi/version || return 0
read ubiver < /sys/class/ubi/version read ubiver < /sys/class/ubi/version
[ "$ubiver" = "1" ] || return 1 [ "$ubiver" = "1" ] || return 1
@ -65,8 +73,8 @@ getuserdev() {
} }
createvol() { createvol() {
local mode
local existdev=$(getdev "$1")
local mode ret
local existdev=$(getdev "$@")
[ "$existdev" ] && return 17 [ "$existdev" ] && return 17
case "$3" in case "$3" in
ro) ro)
@ -80,6 +88,9 @@ createvol() {
;; ;;
esac esac
ubimkvol /dev/$ubidev -N "uvol-$mode-$1" -s "$2" ubimkvol /dev/$ubidev -N "uvol-$mode-$1" -s "$2"
ret=$?
[ $ret -eq 0 ] || return $ret
ubiupdatevol -t /dev/$(getdev "$@")
} }
removevol() { removevol() {
@ -120,15 +131,37 @@ getstatus() {
return 0 return 0
} }
cmd="$1"
shift
listvols() {
local volname volmode volsize
for voldir in /sys/devices/virtual/ubi/${ubidev}/${ubidev}_*; do
read volname < $voldir/name
case "$volname" in
uvol-r[wo]*)
read volsize < $voldir/data_bytes
;;
*)
continue
;;
esac
volmode=${volname:5:2}
volname=${volname:8}
echo "$volname $volmode $volsize"
done
}
case "$cmd" in case "$cmd" in
align)
echo "$ebsize"
;;
free) free)
freebytes freebytes
;; ;;
total) total)
totalbytes totalbytes
;; ;;
list)
listvols "$@"
;;
create) create)
createvol "$@" createvol "$@"
;; ;;


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

@ -1,9 +1,52 @@
#!/bin/sh #!/bin/sh
# uvol prototype
# 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*)
# * add atomic batch processing for use by container/package manager
if [ -z "$1" ]; then cat <<EOF
uvol storage volume manager
syntax: uvol command ...
commands:
free show number of bytes available
total show total number of bytes
align show sector size in bytes
list [volname] list volumes
create volname type size create new volume
type: 'ro' or 'rw'
size: in bytes
remove volname delete volume
device volname show block device for mounting
size volname show size of volume
up volname get volume ready for mounting
down volname take volume down after unmounting
status volname return status of volume
return code: 0 - volume is ready for use
1 - volume is not ready for use
2 - volume doesn'y exist
write volname size write to volume from stdin, size in bytes
EOF
return 22
fi
uvol_backend= uvol_backend=
backends_tried=
for backend in /usr/libexec/uvol/*.sh; do for backend in /usr/libexec/uvol/*.sh; do
total=$($backend total) total=$($backend total)
backends_tried="$backends_tried $($backend name)"
[ "$total" ] && uvol_backend=$backend [ "$total" ] && uvol_backend=$backend
done done
if [ -z "$uvol_backend" ]; then
echo "No backend available. (tried:$backends_tried)"
echo "To setup devices with block storage install 'autopart'."
return 2
fi
flock -x /tmp/run/uvol.lock $uvol_backend "$@" flock -x /tmp/run/uvol.lock $uvol_backend "$@"

Loading…
Cancel
Save