You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

311 lines
5.0 KiB

  1. #!/bin/sh
  2. cmd="$1"
  3. shift
  4. if [ "$cmd" = "name" ]; then
  5. echo "LVM"
  6. return 0
  7. fi
  8. command -v lvm >/dev/null || return 1
  9. . /lib/functions.sh
  10. . /lib/upgrade/common.sh
  11. . /usr/share/libubox/jshn.sh
  12. export_bootdevice
  13. [ "$BOOTDEV_MAJOR" ] || return 1
  14. export_partdevice rootdev 0
  15. [ "$rootdev" ] || return 1
  16. case "$rootdev" in
  17. mtd*|\
  18. ram*|\
  19. ubi*)
  20. return 1
  21. esac
  22. lvm_cmd() {
  23. local cmd="$1"
  24. shift
  25. LVM_SUPPRESS_FD_WARNINGS=1 lvm "$cmd" "$@"
  26. }
  27. pvs() {
  28. lvm_cmd pvs --reportformat json --units b "$@"
  29. }
  30. vgs() {
  31. lvm_cmd vgs --reportformat json --units b "$@"
  32. }
  33. lvs() {
  34. lvm_cmd lvs --reportformat json --units b "$@"
  35. }
  36. freebytes() {
  37. echo $(($vg_free_count * $vg_extent_size * 1024))
  38. }
  39. totalbytes() {
  40. echo $(($vg_extent_count * $vg_extent_size * 1024))
  41. }
  42. existvol() {
  43. [ "$1" ] || return 1
  44. test -e "/dev/$vg_name/ro_$1" || test -e "/dev/$vg_name/rw_$1"
  45. return $?
  46. }
  47. vg_name=
  48. exportpv() {
  49. local reports rep pv pvs
  50. vg_name=
  51. json_init
  52. json_load "$(pvs -o vg_name -S "pv_name=~^/dev/$rootdev.*\$")"
  53. json_select report
  54. json_get_keys reports
  55. for rep in $reports; do
  56. json_select "$rep"
  57. json_select pv
  58. json_get_keys pvs
  59. for pv in $pvs; do
  60. json_select "$pv"
  61. json_get_vars vg_name
  62. json_select ..
  63. break
  64. done
  65. json_select ..
  66. break
  67. done
  68. }
  69. vg_extent_size=
  70. vg_extent_count=
  71. vg_free_count=
  72. exportvg() {
  73. local reports rep vg vgs
  74. vg_extent_size=
  75. vg_extent_count=
  76. vg_free_count=
  77. json_init
  78. json_load "$(vgs -o vg_extent_size,vg_extent_count,vg_free_count -S "vg_name=$vg_name")"
  79. json_select report
  80. json_get_keys reports
  81. for rep in $reports; do
  82. json_select "$rep"
  83. json_select vg
  84. json_get_keys vgs
  85. for vg in $vgs; do
  86. json_select "$vg"
  87. json_get_vars vg_extent_size vg_extent_count vg_free_count
  88. vg_extent_size=${vg_extent_size%B}
  89. json_select ..
  90. break
  91. done
  92. json_select ..
  93. break
  94. done
  95. }
  96. lv_full_name=
  97. lv_path=
  98. lv_dm_path=
  99. lv_size=
  100. exportlv() {
  101. local reports rep lv lvs
  102. lv_full_name=
  103. lv_path=
  104. lv_dm_path=
  105. lv_size=
  106. json_init
  107. json_load "$(lvs -o lv_full_name,lv_size,lv_path,lv_dm_path -S "lv_name=~^[rw][ow]_$1\$ && vg_name=$vg_name")"
  108. json_select report
  109. json_get_keys reports
  110. for rep in $reports; do
  111. json_select "$rep"
  112. json_select lv
  113. json_get_keys lvs
  114. for lv in $lvs; do
  115. json_select "$lv"
  116. json_get_vars lv_full_name lv_size lv_path lv_dm_path
  117. lv_size=${lv_size%B}
  118. json_select ..
  119. break
  120. done
  121. json_select ..
  122. break
  123. done
  124. }
  125. getdev() {
  126. existvol "$1" || return 1
  127. exportlv "$1"
  128. echo $lv_dm_path
  129. }
  130. getsize() {
  131. exportlv "$1"
  132. [ "$lv_size" ] && echo $lv_size
  133. }
  134. activatevol() {
  135. exportlv "$1"
  136. case "$lv_path" in
  137. /dev/*/wo_*)
  138. return 22
  139. ;;
  140. *)
  141. lvm_cmd lvchange -a y "$lv_full_name"
  142. return 0
  143. ;;
  144. esac
  145. }
  146. disactivatevol() {
  147. exportlv "$1"
  148. lvm_cmd lvchange -a n "$lv_full_name"
  149. }
  150. getstatus() {
  151. exportlv "$1"
  152. [ "$lv_full_name" ] || return 2
  153. existvol "$1" || return 1
  154. return 0
  155. }
  156. createvol() {
  157. local mode lvmode ret
  158. local volsize=$(($2))
  159. [ "$volsize" ] || return 22
  160. exportlv "$1"
  161. [ "$lv_size" ] && return 17
  162. size_ext=$((volsize / vg_extent_size))
  163. [ $((size_ext * vg_extent_size)) -lt $volsize ] && size_ext=$((size_ext + 1))
  164. case "$3" in
  165. ro|wo)
  166. lvmode=r
  167. mode=wo
  168. ;;
  169. rw)
  170. lvmode=rw
  171. mode=rw
  172. ;;
  173. *)
  174. return 22
  175. ;;
  176. esac
  177. lvm_cmd lvcreate -p $lvmode -a n -y -W n -Z n -n "${mode}_${1}" -l "$size_ext" $vg_name
  178. ret=$?
  179. if [ ! $ret -eq 0 ] || [ "$lvmode" = "r" ]; then
  180. return $ret
  181. fi
  182. exportlv "$1"
  183. [ "$lv_full_name" ] || return 22
  184. lvm_cmd lvchange -a y "$lv_full_name" || return 1
  185. if [ $lv_size -gt $(( 100 * 1024 * 1024 )) ]; then
  186. mkfs.f2fs -f -l "$1" "$lv_path" || return 1
  187. else
  188. mke2fs -F -L "$1" "$lv_path" || return 1
  189. fi
  190. return 0
  191. }
  192. removevol() {
  193. exportlv "$1"
  194. [ "$lv_full_name" ] || return 2
  195. lvm_cmd lvremove -y "$lv_full_name"
  196. }
  197. updatevol() {
  198. exportlv "$1"
  199. [ "$lv_full_name" ] || return 2
  200. [ $lv_size -ge $2 ] || return 27
  201. case "$lv_path" in
  202. /dev/*/wo_*)
  203. lvm_cmd lvchange -a y -p rw "$lv_full_name"
  204. dd of=$lv_path
  205. lvm_cmd lvchange -p r "$lv_full_name"
  206. lvm_cmd lvrename "$lv_full_name" "${lv_full_name%%/*}/ro_$1"
  207. return 0
  208. ;;
  209. default)
  210. return 22
  211. ;;
  212. esac
  213. }
  214. listvols() {
  215. local reports rep lv lvs lv_name lv_size lv_mode volname
  216. volname=${1:-.*}
  217. json_init
  218. json_load "$(lvs -o lv_name,lv_size -S "lv_name=~^[rw][ow]_$volname\$ && vg_name=$vg_name")"
  219. json_select report
  220. json_get_keys reports
  221. for rep in $reports; do
  222. json_select "$rep"
  223. json_select lv
  224. json_get_keys lvs
  225. for lv in $lvs; do
  226. json_select "$lv"
  227. json_get_vars lv_name lv_size
  228. lv_mode="${lv_name:0:2}"
  229. lv_name="${lv_name:3}"
  230. lv_size=${lv_size%B}
  231. echo "$lv_name $lv_mode $lv_size"
  232. json_select ..
  233. done
  234. json_select ..
  235. break
  236. done
  237. }
  238. exportpv
  239. exportvg
  240. case "$cmd" in
  241. align)
  242. echo "$vg_extent_size"
  243. ;;
  244. free)
  245. freebytes
  246. ;;
  247. total)
  248. totalbytes
  249. ;;
  250. list)
  251. listvols "$@"
  252. ;;
  253. create)
  254. createvol "$@"
  255. ;;
  256. remove)
  257. removevol "$@"
  258. ;;
  259. device)
  260. getdev "$@"
  261. ;;
  262. size)
  263. getsize "$@"
  264. ;;
  265. up)
  266. activatevol "$@"
  267. ;;
  268. down)
  269. disactivatevol "$@"
  270. ;;
  271. status)
  272. getstatus "$@"
  273. ;;
  274. write)
  275. updatevol "$@"
  276. ;;
  277. *)
  278. echo "unknown command"
  279. return 1
  280. ;;
  281. esac