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.

367 lines
6.9 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. return $?
  27. }
  28. pvs() {
  29. lvm_cmd pvs --reportformat json --units b "$@"
  30. }
  31. vgs() {
  32. lvm_cmd vgs --reportformat json --units b "$@"
  33. }
  34. lvs() {
  35. lvm_cmd lvs --reportformat json --units b "$@"
  36. }
  37. freebytes() {
  38. echo $((vg_free_count * vg_extent_size * 1024))
  39. }
  40. totalbytes() {
  41. echo $((vg_extent_count * vg_extent_size * 1024))
  42. }
  43. existvol() {
  44. [ "$1" ] || return 1
  45. test -e "/dev/$vg_name/ro_$1" || test -e "/dev/$vg_name/rw_$1"
  46. return $?
  47. }
  48. vg_name=
  49. exportpv() {
  50. local reports rep pv pvs
  51. vg_name=
  52. json_init
  53. json_load "$(pvs -o vg_name -S "pv_name=~^/dev/$rootdev.*\$")"
  54. json_select report
  55. json_get_keys reports
  56. for rep in $reports; do
  57. json_select "$rep"
  58. json_select pv
  59. json_get_keys pvs
  60. for pv in $pvs; do
  61. json_select "$pv"
  62. json_get_vars vg_name
  63. json_select ..
  64. break
  65. done
  66. json_select ..
  67. break
  68. done
  69. }
  70. vg_extent_size=
  71. vg_extent_count=
  72. vg_free_count=
  73. exportvg() {
  74. local reports rep vg vgs
  75. vg_extent_size=
  76. vg_extent_count=
  77. vg_free_count=
  78. json_init
  79. json_load "$(vgs -o vg_extent_size,vg_extent_count,vg_free_count -S "vg_name=$vg_name")"
  80. json_select report
  81. json_get_keys reports
  82. for rep in $reports; do
  83. json_select "$rep"
  84. json_select vg
  85. json_get_keys vgs
  86. for vg in $vgs; do
  87. json_select "$vg"
  88. json_get_vars vg_extent_size vg_extent_count vg_free_count
  89. vg_extent_size=${vg_extent_size%B}
  90. json_select ..
  91. break
  92. done
  93. json_select ..
  94. break
  95. done
  96. }
  97. lv_active=
  98. lv_name=
  99. lv_full_name=
  100. lv_path=
  101. lv_dm_path=
  102. lv_size=
  103. exportlv() {
  104. local reports rep lv lvs
  105. lv_active=
  106. lv_name=
  107. lv_full_name=
  108. lv_path=
  109. lv_dm_path=
  110. lv_size=
  111. json_init
  112. json_load "$(lvs -o lv_active,lv_name,lv_full_name,lv_size,lv_path,lv_dm_path -S "lv_name=~^[rw][owp]_$1\$ && vg_name=$vg_name")"
  113. json_select report
  114. json_get_keys reports
  115. for rep in $reports; do
  116. json_select "$rep"
  117. json_select lv
  118. json_get_keys lvs
  119. for lv in $lvs; do
  120. json_select "$lv"
  121. json_get_vars lv_active lv_name lv_full_name lv_size lv_path lv_dm_path
  122. lv_size=${lv_size%B}
  123. json_select ..
  124. break
  125. done
  126. json_select ..
  127. break
  128. done
  129. }
  130. getdev() {
  131. existvol "$1" || return 1
  132. exportlv "$1"
  133. echo "$lv_dm_path"
  134. }
  135. getsize() {
  136. exportlv "$1"
  137. [ "$lv_size" ] && echo "$lv_size"
  138. }
  139. activatevol() {
  140. exportlv "$1"
  141. [ "$lv_path" ] || return 2
  142. case "$lv_path" in
  143. /dev/*/wo_*|\
  144. /dev/*/wp_*)
  145. return 22
  146. ;;
  147. *)
  148. [ "$lv_active" = "active" ] && return 0
  149. lvm_cmd lvchange -k n "$lv_full_name" || return $?
  150. lvm_cmd lvchange -a y "$lv_full_name" || return $?
  151. ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"${lv_name:0:2}\", \"device\": \"$lv_dm_path\"}"
  152. return 0
  153. ;;
  154. esac
  155. }
  156. disactivatevol() {
  157. exportlv "$1"
  158. [ "$lv_path" ] || return 2
  159. case "$lv_path" in
  160. /dev/*/wo_*|\
  161. /dev/*/wp_*)
  162. return 22
  163. ;;
  164. *)
  165. [ "$lv_active" = "active" ] || return 0
  166. lvm_cmd lvchange -a n "$lv_full_name" || return $?
  167. lvm_cmd lvchange -k y "$lv_full_name" || return $?
  168. ubus send block.volume "{\"name\": \"$1\", \"action\": \"down\", \"mode\": \"${lv_name:0:2}\", \"device\": \"$lv_dm_path\"}"
  169. return 0
  170. ;;
  171. esac
  172. }
  173. getstatus() {
  174. exportlv "$1"
  175. [ "$lv_full_name" ] || return 2
  176. existvol "$1" || return 1
  177. return 0
  178. }
  179. createvol() {
  180. local mode lvmode ret
  181. local volsize=$(($2))
  182. [ "$volsize" ] || return 22
  183. exportlv "$1"
  184. [ "$lv_size" ] && return 17
  185. size_ext=$((volsize / vg_extent_size))
  186. [ $((size_ext * vg_extent_size)) -lt $volsize ] && size_ext=$((size_ext + 1))
  187. case "$3" in
  188. ro|wo)
  189. lvmode=r
  190. mode=wo
  191. ;;
  192. rw)
  193. lvmode=rw
  194. mode=wp
  195. ;;
  196. *)
  197. return 22
  198. ;;
  199. esac
  200. lvm_cmd lvcreate -p "$lvmode" -a n -y -W n -Z n -n "${mode}_$1" -l "$size_ext" "$vg_name"
  201. ret=$?
  202. if [ ! $ret -eq 0 ] || [ "$lvmode" = "r" ]; then
  203. return $ret
  204. fi
  205. exportlv "$1"
  206. [ "$lv_full_name" ] || return 22
  207. lvm_cmd lvchange -a y "$lv_full_name" || return 1
  208. if [ "$lv_size" -gt $(( 100 * 1024 * 1024 )) ]; then
  209. mkfs.f2fs -f -l "$1" "$lv_path"
  210. ret=$?
  211. [ $ret != 0 ] && [ $ret != 134 ] && return 1
  212. else
  213. mke2fs -F -L "$1" "$lv_path" || return 1
  214. fi
  215. lvm_cmd lvrename "$vg_name" "wp_$1" "rw_$1"
  216. exportlv "$1"
  217. ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"${lv_name:0:2}\", \"device\": \"$lv_dm_path\"}"
  218. return 0
  219. }
  220. removevol() {
  221. exportlv "$1"
  222. [ "$lv_full_name" ] || return 2
  223. lvm_cmd lvremove -y "$lv_full_name"
  224. ubus send block.volume "{\"name\": \"$1\", \"action\": \"down\", \"mode\": \"${lv_name:0:2}\", \"device\": \"$lv_dm_path\"}"
  225. }
  226. updatevol() {
  227. exportlv "$1"
  228. [ "$lv_full_name" ] || return 2
  229. [ "$lv_size" -ge "$2" ] || return 27
  230. case "$lv_path" in
  231. /dev/*/wo_*)
  232. lvm_cmd lvchange -a y -p rw "$lv_full_name"
  233. dd of="$lv_path"
  234. lvm_cmd lvchange -p r "$lv_full_name"
  235. lvm_cmd lvrename "$lv_full_name" "${lv_full_name%%/*}/ro_$1"
  236. ubus send block.volume "{\"name\": \"$1\", \"action\": \"up\", \"mode\": \"ro\", \"device\": \"$(getdev "$@")\"}"
  237. return 0
  238. ;;
  239. default)
  240. return 22
  241. ;;
  242. esac
  243. }
  244. listvols() {
  245. local reports rep lv lvs lv_name lv_size lv_mode volname
  246. volname=${1:-.*}
  247. json_init
  248. json_load "$(lvs -o lv_name,lv_size -S "lv_name=~^[rw][owp]_$volname\$ && vg_name=$vg_name")"
  249. json_select report
  250. json_get_keys reports
  251. for rep in $reports; do
  252. json_select "$rep"
  253. json_select lv
  254. json_get_keys lvs
  255. for lv in $lvs; do
  256. json_select "$lv"
  257. json_get_vars lv_name lv_size
  258. lv_mode="${lv_name:0:2}"
  259. lv_name="${lv_name:3}"
  260. lv_size=${lv_size%B}
  261. echo "$lv_name $lv_mode $lv_size"
  262. json_select ..
  263. done
  264. json_select ..
  265. break
  266. done
  267. }
  268. boot() {
  269. local reports rep lv lvs lv_name lv_dm_path lv_mode volname
  270. json_init
  271. json_load "$(lvs -o lv_name,lv_dm_path -S "lv_name=~^[rw][ow]_.*\$ && vg_name=$vg_name && lv_active=active")"
  272. json_select report
  273. json_get_keys reports
  274. for rep in $reports; do
  275. json_select "$rep"
  276. json_select lv
  277. json_get_keys lvs
  278. for lv in $lvs; do
  279. json_select "$lv"
  280. json_get_vars lv_name lv_dm_path
  281. lv_mode="${lv_name:0:2}"
  282. lv_name="${lv_name:3}"
  283. ubus send block.volume "{\"name\": \"$lv_name\", \"action\": \"up\", \"mode\": \"$lv_mode\", \"device\": \"$lv_dm_path\"}"
  284. json_select ..
  285. done
  286. json_select ..
  287. break
  288. done
  289. }
  290. exportpv
  291. exportvg
  292. case "$cmd" in
  293. align)
  294. echo "$vg_extent_size"
  295. ;;
  296. free)
  297. freebytes
  298. ;;
  299. total)
  300. totalbytes
  301. ;;
  302. boot)
  303. boot
  304. ;;
  305. list)
  306. listvols "$@"
  307. ;;
  308. create)
  309. createvol "$@"
  310. ;;
  311. remove)
  312. removevol "$@"
  313. ;;
  314. device)
  315. getdev "$@"
  316. ;;
  317. size)
  318. getsize "$@"
  319. ;;
  320. up)
  321. activatevol "$@"
  322. ;;
  323. down)
  324. disactivatevol "$@"
  325. ;;
  326. status)
  327. getstatus "$@"
  328. ;;
  329. write)
  330. updatevol "$@"
  331. ;;
  332. *)
  333. echo "unknown command"
  334. return 1
  335. ;;
  336. esac