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
|
#!/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"
|
shift
|
||||||
local param="${3:+-S vg_name=${vgname} -S lv_name=~^r[ow]_$3\$}"
|
LVM_SUPPRESS_FD_WARNINGS=1 lvm "$cmd" "$@"
|
||||||
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() {
|
pvs() {
|
||||||
case "${1:5}" in
|
lvm_cmd pvs --reportformat json --units b "$@"
|
||||||
"$rootdev"*)
|
|
||||||
partdev="$1"
|
|
||||||
vgname="$2"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vgvars() {
|
vgs() {
|
||||||
[ "$1" = "$vgname" ] || return
|
lvm_cmd vgs --reportformat json --units b "$@"
|
||||||
vgbs="${13}"
|
|
||||||
vgts="${14}"
|
|
||||||
vgus="${15}"
|
|
||||||
vgfs="${16}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lvvars() {
|
lvs() {
|
||||||
lvpath="$1"
|
lvm_cmd vgs --reportformat json --units b "$@"
|
||||||
lvsize=$(( 512 * $7 ))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
vg_name=
|
||||||
lvs lvdisplay lvvars "$1"
|
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"
|
exportlv "$1"
|
||||||
[ "$lvsize" ] && echo $lvsize
|
[ "$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
|
exportlv "$1"
|
||||||
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a n "$(getlvname "$1")"
|
lvm_cmd lvchange -a n "$lv_full_name"
|
||||||
}
|
}
|
||||||
|
|
||||||
getstatus() {
|
getstatus() {
|
||||||
lvs lvdisplay lvvars "$1"
|
exportlv "$1"
|
||||||
[ "$lvsize" ] || return 2
|
[ "$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"
|
exportlv "$1"
|
||||||
[ "$lvpath" ] || return 22
|
[ "$lv_full_name" ] || return 22
|
||||||
lvname=${lvpath:5}
|
lvm_cmd lvchange -a y "$lv_full_name" || return 1
|
||||||
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a y /dev/$lvname || return 1
|
if [ $lv_size -gt $(( 100 * 1024 * 1024 )) ]; then
|
||||||
if [ $lvsize -gt $(( 100 * 1024 * 1024 )) ]; then
|
mkfs.f2fs -f -l "$1" "$lv_path" || return 1
|
||||||
mkfs.f2fs -f -l "$1" $lvpath || 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")"
|
exportlv "$1"
|
||||||
[ "$lvname" ] || return 2
|
[ "$lv_full_name" ] || return 2
|
||||||
LVM_SUPPRESS_FD_WARNINGS=1 lvremove -y "$(getlvname "$1")"
|
lvm_cmd lvremove -y "$lv_full_name"
|
||||||
}
|
}
|
||||||
|
|
||||||
updatevol() {
|
updatevol() {
|
||||||
lvs lvdisplay lvvars "$1"
|
exportlv "$1"
|
||||||
[ "$lvpath" ] || return 2
|
[ "$lv_full_name" ] || return 2
|
||||||
[ $lvsize -ge $2 ] || return 27
|
[ $lv_size -ge $2 ] || return 27
|
||||||
LVM_SUPPRESS_FD_WARNINGS=1 lvchange -a y -p rw ${lvpath:5}
|
lvm_cmd lvchange -a y -p rw "$lv_full_name"
|
||||||
dd of=$lvpath
|
dd of=$lv_path
|
||||||
case "$lvpath" in
|
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
|
listvols() {
|
||||||
lvs vgdisplay vgvars
|
local reports rep lv lvs lv_name lv_size lv_mode volname
|
||||||
cmd="$1"
|
volname=${1:-.*}
|
||||||
shift
|
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 "$@"
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -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 mode ret
|
||||||
local existdev=$(getdev "$1")
|
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"
|
listvols() {
|
||||||
shift
|
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 "$@"
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -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…
Reference in New Issue