uvol: some improvements
* use lvm --reportformat json * add 'list' and 'align' commands * add help output Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
parent
231d40053b
commit
a4b034cf68
|
@ -1,15 +1,23 @@
|
|||
#!/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/upgrade/common.sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
export_bootdevice
|
||||
[ "$BOOTDEV_MAJOR" ] || return 1
|
||||
export_partdevice rootdev 0
|
||||
[ "$rootdev" ] || return 1
|
||||
LVM_SUPPRESS_FD_WARNINGS=1
|
||||
|
||||
case "$rootdev" in
|
||||
mtd*|\
|
||||
|
@ -18,93 +26,157 @@ case "$rootdev" in
|
|||
return 1
|
||||
esac
|
||||
|
||||
lvs() {
|
||||
lvm_cmd() {
|
||||
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 "$@"
|
||||
shift
|
||||
LVM_SUPPRESS_FD_WARNINGS=1 lvm "$cmd" "$@"
|
||||
}
|
||||
|
||||
pvvars() {
|
||||
case "${1:5}" in
|
||||
"$rootdev"*)
|
||||
partdev="$1"
|
||||
vgname="$2"
|
||||
;;
|
||||
esac
|
||||
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() {
|
||||
echo $((vgfs * vgbs * 1024))
|
||||
echo $(($vg_free_count * $vg_extent_size * 1024))
|
||||
}
|
||||
|
||||
totalbytes() {
|
||||
echo $((vgts * vgbs * 1024))
|
||||
echo $(($vg_extent_count * $vg_extent_size * 1024))
|
||||
}
|
||||
|
||||
existvol() {
|
||||
[ "$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 $?
|
||||
}
|
||||
|
||||
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() {
|
||||
existvol "$1" || return 1
|
||||
readlink /dev/$(getlvname "$1")
|
||||
exportlv "$1"
|
||||
echo $lv_dm_path
|
||||
}
|
||||
|
||||
getsize() {
|
||||
lvs lvdisplay lvvars "$1"
|
||||
[ "$lvsize" ] && echo $lvsize
|
||||
exportlv "$1"
|
||||
[ "$lv_size" ] && echo $lv_size
|
||||
}
|
||||
|
||||
activatevol() {
|
||||
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a y "$(getlvname "$1")"
|
||||
exportlv "$1"
|
||||
lvm_cmd lvchange -a y "$lv_full_name"
|
||||
}
|
||||
|
||||
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() {
|
||||
lvs lvdisplay lvvars "$1"
|
||||
[ "$lvsize" ] || return 2
|
||||
exportlv "$1"
|
||||
[ "$lv_full_name" ] || return 2
|
||||
existvol "$1" || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
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
|
||||
ro)
|
||||
mode=r
|
||||
|
@ -117,53 +189,82 @@ createvol() {
|
|||
;;
|
||||
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=$?
|
||||
if [ ! $ret -eq 0 ] || [ "$mode" = "r" ]; then
|
||||
return $ret
|
||||
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
|
||||
mke2fs -F -L "$1" $lvpath || return 1
|
||||
mke2fs -F -L "$1" "$lv_path" || return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
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() {
|
||||
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_*)
|
||||
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -p r ${lvpath:5}
|
||||
lvm_cmd lvchange -p r "$lv_full_name"
|
||||
;;
|
||||
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
|
||||
align)
|
||||
echo "$vg_extent_size"
|
||||
;;
|
||||
free)
|
||||
freebytes
|
||||
;;
|
||||
total)
|
||||
totalbytes
|
||||
;;
|
||||
list)
|
||||
listvols "$@"
|
||||
;;
|
||||
create)
|
||||
createvol "$@"
|
||||
;;
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
#!/bin/sh
|
||||
|
||||
cmd="$1"
|
||||
shift
|
||||
|
||||
if [ "$cmd" = "name" ]; then
|
||||
echo "UBI"
|
||||
return 0
|
||||
fi
|
||||
|
||||
test -e /sys/class/ubi/version || return 0
|
||||
read ubiver < /sys/class/ubi/version
|
||||
[ "$ubiver" = "1" ] || return 1
|
||||
|
@ -65,8 +73,8 @@ getuserdev() {
|
|||
}
|
||||
|
||||
createvol() {
|
||||
local mode
|
||||
local existdev=$(getdev "$1")
|
||||
local mode ret
|
||||
local existdev=$(getdev "$@")
|
||||
[ "$existdev" ] && return 17
|
||||
case "$3" in
|
||||
ro)
|
||||
|
@ -80,6 +88,9 @@ createvol() {
|
|||
;;
|
||||
esac
|
||||
ubimkvol /dev/$ubidev -N "uvol-$mode-$1" -s "$2"
|
||||
ret=$?
|
||||
[ $ret -eq 0 ] || return $ret
|
||||
ubiupdatevol -t /dev/$(getdev "$@")
|
||||
}
|
||||
|
||||
removevol() {
|
||||
|
@ -120,15 +131,37 @@ getstatus() {
|
|||
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
|
||||
align)
|
||||
echo "$ebsize"
|
||||
;;
|
||||
free)
|
||||
freebytes
|
||||
;;
|
||||
total)
|
||||
totalbytes
|
||||
;;
|
||||
list)
|
||||
listvols "$@"
|
||||
;;
|
||||
create)
|
||||
createvol "$@"
|
||||
;;
|
||||
|
|
|
@ -1,9 +1,52 @@
|
|||
#!/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=
|
||||
backends_tried=
|
||||
|
||||
for backend in /usr/libexec/uvol/*.sh; do
|
||||
total=$($backend total)
|
||||
backends_tried="$backends_tried $($backend name)"
|
||||
[ "$total" ] && uvol_backend=$backend
|
||||
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 "$@"
|
||||
|
|
Loading…
Reference in New Issue