blob: 0b2a8a3e60c3fdebd2ba85f772d6563041e83c83 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
#!/bin/sh
count_zvols() {
if [ -z "$zvols" ]; then
echo 0
else
echo "$zvols" | wc -l
fi
}
filter_out_zvols_with_links() {
echo "$zvols" | tr ' ' '+' | while read -r zvol; do
if ! [ -L "/dev/zvol/$zvol" ]; then
echo "$zvol"
fi
done | tr '+' ' '
}
filter_out_deleted_zvols() {
OIFS="$IFS"
IFS="
"
# shellcheck disable=SC2086
zfs list -H -o name $zvols 2>/dev/null
IFS="$OIFS"
}
list_zvols() {
read -r default_volmode < /sys/module/zfs/parameters/zvol_volmode
zfs list -t volume -H -o \
name,volmode,receive_resume_token,redact_snaps,keystatus |
while IFS=" " read -r name volmode token redacted keystatus; do # IFS=\t here!
# /dev links are not created for zvols with volmode = "none",
# redacted zvols, or encrypted zvols for which the key has not
# been loaded.
[ "$volmode" = "none" ] && continue
[ "$volmode" = "default" ] && [ "$default_volmode" = "3" ] &&
continue
[ "$redacted" = "-" ] || continue
[ "$keystatus" = "unavailable" ] && continue
# We also ignore partially received zvols if it is
# not an incremental receive, as those won't even have a block
# device minor node created yet.
if [ "$token" != "-" ]; then
# Incremental receives create an invisible clone that
# is not automatically displayed by zfs list.
if ! zfs list "$name/%recv" >/dev/null 2>&1; then
continue
fi
fi
echo "$name"
done
}
zvols=$(list_zvols)
zvols_count=$(count_zvols)
if [ "$zvols_count" -eq 0 ]; then
echo "No zvols found, nothing to do."
exit 0
fi
echo "Testing $zvols_count zvol links"
outer_loop=0
while [ "$outer_loop" -lt 20 ]; do
outer_loop=$((outer_loop + 1))
old_zvols_count=$(count_zvols)
inner_loop=0
while [ "$inner_loop" -lt 30 ]; do
inner_loop=$((inner_loop + 1))
zvols="$(filter_out_zvols_with_links)"
zvols_count=$(count_zvols)
if [ "$zvols_count" -eq 0 ]; then
echo "All zvol links are now present."
exit 0
fi
sleep 1
done
echo "Still waiting on $zvols_count zvol links ..."
#
# Although zvols should normally not be deleted at boot time,
# if that is the case then their links will be missing and
# we would stall.
#
if [ "$old_zvols_count" -eq "$zvols_count" ]; then
echo "No progress since last loop."
echo "Checking if any zvols were deleted."
zvols=$(filter_out_deleted_zvols)
zvols_count=$(count_zvols)
if [ "$old_zvols_count" -ne "$zvols_count" ]; then
echo "$((old_zvols_count - zvols_count)) zvol(s) deleted."
fi
if [ "$zvols_count" -ne 0 ]; then
echo "Remaining zvols:"
echo "$zvols"
else
echo "All zvol links are now present."
exit 0
fi
fi
#
# zvol_count made some progress - let's stay in this loop.
#
if [ "$old_zvols_count" -gt "$zvols_count" ]; then
outer_loop=$((outer_loop - 1))
fi
done
echo "Timed out waiting on zvol links"
exit 1
|