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>
This commit is contained in:
parent
ee1a3654dc
commit
3d4d75c519
3 changed files with 48 additions and 33 deletions
|
@ -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)
|
ro|wo)
|
||||||
mode=r
|
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
|
||||||
|
|
|
@ -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)
|
ro|wo)
|
||||||
mode=ro
|
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 -
|
||||||
}
|
ubirename /dev/$ubidev uvol-wo-$1 uvol-ro-$1
|
||||||
|
|
||||||
getstatus() {
|
|
||||||
local voldev=$(getdev "$@")
|
|
||||||
[ "$voldev" ] || return 2
|
|
||||||
needs_ubiblock $voldev && [ ! -e "/dev/ubiblock${voldev:3}" ] && return 1
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listvols() {
|
listvols() {
|
||||||
|
|
|
@ -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…
Reference in a new issue