Merge pull request #16078 from ja-pa/fix-email
[feed/packages.git] / utils / uvol / files / lvm.sh
1 #!/bin/sh
2
3 cmd="$1"
4 shift
5
6 if [ "$cmd" = "name" ]; then
7 echo "LVM"
8 return 0
9 fi
10
11 command -v lvm >/dev/null || return 1
12
13 . /lib/functions.sh
14 . /lib/functions/uvol.sh
15 . /lib/upgrade/common.sh
16 . /usr/share/libubox/jshn.sh
17
18 export_bootdevice
19 [ "$BOOTDEV_MAJOR" ] || return 1
20 export_partdevice rootdev 0
21 [ "$rootdev" ] || return 1
22
23 case "$rootdev" in
24 mtd*|\
25 ram*|\
26 ubi*)
27 return 1
28 esac
29
30 lvm_cmd() {
31 local cmd="$1"
32 shift
33 LVM_SUPPRESS_FD_WARNINGS=1 lvm "$cmd" "$@"
34 return $?
35 }
36
37 pvs() {
38 lvm_cmd pvs --reportformat json --units b "$@"
39 }
40
41 vgs() {
42 lvm_cmd vgs --reportformat json --units b "$@"
43 }
44
45 lvs() {
46 lvm_cmd lvs --reportformat json --units b "$@"
47 }
48
49 freebytes() {
50 echo $((vg_free_count * vg_extent_size))
51 }
52
53 totalbytes() {
54 echo $((vg_extent_count * vg_extent_size))
55 }
56
57 existvol() {
58 [ "$1" ] || return 1
59 test -e "/dev/$vg_name/ro_$1" || test -e "/dev/$vg_name/rw_$1"
60 return $?
61 }
62
63 vg_name=
64 exportpv() {
65 local reports rep pv pvs
66 vg_name=
67 json_init
68 json_load "$(pvs -o vg_name -S "pv_name=~^/dev/$rootdev.*\$")"
69 json_select report
70 json_get_keys reports
71 for rep in $reports; do
72 json_select "$rep"
73 json_select pv
74 json_get_keys pvs
75 for pv in $pvs; do
76 json_select "$pv"
77 json_get_vars vg_name
78 json_select ..
79 break
80 done
81 json_select ..
82 break
83 done
84 }
85
86 vg_extent_size=
87 vg_extent_count=
88 vg_free_count=
89 exportvg() {
90 local reports rep vg vgs
91 vg_extent_size=
92 vg_extent_count=
93 vg_free_count=
94 json_init
95 json_load "$(vgs -o vg_extent_size,vg_extent_count,vg_free_count -S "vg_name=$vg_name")"
96 json_select report
97 json_get_keys reports
98 for rep in $reports; do
99 json_select "$rep"
100 json_select vg
101 json_get_keys vgs
102 for vg in $vgs; do
103 json_select "$vg"
104 json_get_vars vg_extent_size vg_extent_count vg_free_count
105 vg_extent_size=${vg_extent_size%B}
106 json_select ..
107 break
108 done
109 json_select ..
110 break
111 done
112 }
113
114 lv_active=
115 lv_name=
116 lv_full_name=
117 lv_path=
118 lv_dm_path=
119 lv_size=
120 exportlv() {
121 local reports rep lv lvs
122 lv_active=
123 lv_name=
124 lv_full_name=
125 lv_path=
126 lv_dm_path=
127 lv_size=
128 json_init
129
130 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")"
131 json_select report
132 json_get_keys reports
133 for rep in $reports; do
134 json_select "$rep"
135 json_select lv
136 json_get_keys lvs
137 for lv in $lvs; do
138 json_select "$lv"
139 json_get_vars lv_active lv_name lv_full_name lv_size lv_path lv_dm_path
140 lv_size=${lv_size%B}
141 json_select ..
142 break
143 done
144 json_select ..
145 break
146 done
147 }
148
149 getdev() {
150 local dms dm_name
151
152 for dms in /sys/devices/virtual/block/dm-* ; do
153 [ "$dms" = "/sys/devices/virtual/block/dm-*" ] && break
154 read -r dm_name < "$dms/dm/name"
155 [ $(basename "$lv_dm_path") = "$dm_name" ] && echo "$(basename "$dms")"
156 done
157 }
158
159 getuserdev() {
160 local dms dm_name
161 existvol "$1" || return 1
162 exportlv "$1"
163 getdev "$@"
164 }
165
166 getsize() {
167 exportlv "$1"
168 [ "$lv_size" ] && echo "$lv_size"
169 }
170
171 activatevol() {
172 exportlv "$1"
173 [ "$lv_path" ] || return 2
174 case "$lv_path" in
175 /dev/*/wo_*|\
176 /dev/*/wp_*)
177 return 22
178 ;;
179 *)
180 [ "$lv_active" = "active" ] && return 0
181 uvol_uci_commit "$1"
182 lvm_cmd lvchange -a y "$lv_full_name" || return $?
183 lvm_cmd lvchange -k n "$lv_full_name" || return $?
184 return 0
185 ;;
186 esac
187 }
188
189 disactivatevol() {
190 exportlv "$1"
191 local devname
192 [ "$lv_path" ] || return 2
193 case "$lv_path" in
194 /dev/*/wo_*|\
195 /dev/*/wp_*)
196 return 22
197 ;;
198 *)
199 [ "$lv_active" = "active" ] || return 0
200 devname="$(getdev "$1")"
201 [ "$devname" ] && /sbin/block umount "$devname"
202 lvm_cmd lvchange -a n "$lv_full_name"
203 lvm_cmd lvchange -k y "$lv_full_name" || return $?
204 return 0
205 ;;
206 esac
207 }
208
209 getstatus() {
210 exportlv "$1"
211 [ "$lv_full_name" ] || return 2
212 existvol "$1" || return 1
213 return 0
214 }
215
216 createvol() {
217 local mode lvmode ret
218 local volsize=$(($2))
219 [ "$volsize" ] || return 22
220 exportlv "$1"
221 [ "$lv_size" ] && return 17
222 size_ext=$((volsize / vg_extent_size))
223 [ $((size_ext * vg_extent_size)) -lt $volsize ] && size_ext=$((size_ext + 1))
224
225 case "$3" in
226 ro|wo)
227 lvmode=r
228 mode=wo
229 ;;
230 rw)
231 lvmode=rw
232 mode=wp
233 ;;
234 *)
235 return 22
236 ;;
237 esac
238
239 lvm_cmd lvcreate -p "$lvmode" -a n -y -W n -Z n -n "${mode}_$1" -l "$size_ext" "$vg_name" || return $?
240 ret=$?
241 if [ ! $ret -eq 0 ] || [ "$lvmode" = "r" ]; then
242 return $ret
243 fi
244 exportlv "$1"
245 [ "$lv_full_name" ] || return 22
246 lvm_cmd lvchange -a y "$lv_full_name" || return $?
247 if [ "$lv_size" -gt $(( 100 * 1024 * 1024 )) ]; then
248 mkfs.f2fs -f -l "$1" "$lv_path"
249 ret=$?
250 [ $ret != 0 ] && [ $ret != 134 ] && {
251 lvm_cmd lvchange -a n "$lv_full_name" || return $?
252 return $ret
253 }
254 else
255 mke2fs -F -L "$1" "$lv_path" || {
256 ret=$?
257 lvm_cmd lvchange -a n "$lv_full_name" || return $?
258 return $ret
259 }
260 fi
261 uvol_uci_add "$1" "/dev/$(getdev "$1")" "rw"
262 lvm_cmd lvchange -a n "$lv_full_name" || return $?
263 lvm_cmd lvrename "$vg_name" "wp_$1" "rw_$1" || return $?
264 return 0
265 }
266
267 removevol() {
268 exportlv "$1"
269 [ "$lv_full_name" ] || return 2
270 [ "$lv_active" = "active" ] && return 16
271 lvm_cmd lvremove -y "$lv_full_name" || return $?
272 uvol_uci_remove "$1"
273 uvol_uci_commit "$1"
274 }
275
276 updatevol() {
277 exportlv "$1"
278 [ "$lv_full_name" ] || return 2
279 [ "$lv_size" -ge "$2" ] || return 27
280 case "$lv_path" in
281 /dev/*/wo_*)
282 lvm_cmd lvchange -p rw "$lv_full_name" || return $?
283 lvm_cmd lvchange -a y "$lv_full_name" || return $?
284 dd of="$lv_path"
285 uvol_uci_add "$1" "/dev/$(getdev "$1")" "ro"
286 lvm_cmd lvchange -a n "$lv_full_name" || return $?
287 lvm_cmd lvchange -p r "$lv_full_name" || return $?
288 lvm_cmd lvrename "$lv_full_name" "${lv_full_name%%/*}/ro_$1" || return $?
289 return 0
290 ;;
291 default)
292 return 22
293 ;;
294 esac
295 }
296
297 listvols() {
298 local reports rep lv lvs lv_name lv_size lv_mode volname
299 volname=${1:-.*}
300 json_init
301 json_load "$(lvs -o lv_name,lv_size -S "lv_name=~^[rw][owp]_$volname\$ && vg_name=$vg_name")"
302 json_select report
303 json_get_keys reports
304 for rep in $reports; do
305 json_select "$rep"
306 json_select lv
307 json_get_keys lvs
308 for lv in $lvs; do
309 json_select "$lv"
310 json_get_vars lv_name lv_size
311 lv_mode="${lv_name:0:2}"
312 lv_name="${lv_name:3}"
313 lv_size=${lv_size%B}
314 echo "$lv_name $lv_mode $lv_size"
315 json_select ..
316 done
317 json_select ..
318 break
319 done
320 }
321
322 boot() {
323 local reports rep lv lvs lv_name lv_dm_path lv_mode volname
324 json_init
325 json_load "$(lvs -o lv_name,lv_dm_path -S "lv_name=~^[rw][ow]_.*\$ && vg_name=$vg_name && lv_active=active")"
326 json_select report
327 json_get_keys reports
328 for rep in $reports; do
329 json_select "$rep"
330 json_select lv
331 json_get_keys lvs
332 for lv in $lvs; do
333 json_select "$lv"
334 json_get_vars lv_name lv_dm_path
335 lv_mode="${lv_name:0:2}"
336 lv_name="${lv_name:3}"
337 json_select ..
338 done
339 json_select ..
340 break
341 done
342 }
343
344 exportpv
345 exportvg
346
347 case "$cmd" in
348 align)
349 echo "$vg_extent_size"
350 ;;
351 free)
352 freebytes
353 ;;
354 total)
355 totalbytes
356 ;;
357 boot)
358 boot
359 ;;
360 list)
361 listvols "$@"
362 ;;
363 create)
364 createvol "$@"
365 ;;
366 remove)
367 removevol "$@"
368 ;;
369 device)
370 getuserdev "$@"
371 ;;
372 size)
373 getsize "$@"
374 ;;
375 up)
376 activatevol "$@"
377 ;;
378 down)
379 disactivatevol "$@"
380 ;;
381 status)
382 getstatus "$@"
383 ;;
384 write)
385 updatevol "$@"
386 ;;
387 *)
388 echo "unknown command"
389 return 1
390 ;;
391 esac