2019-07-18 01:33:05 +03:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
count_zvols() {
|
|
|
|
if [ -z "$zvols" ]; then
|
|
|
|
echo 0
|
|
|
|
else
|
|
|
|
echo "$zvols" | wc -l
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
filter_out_zvols_with_links() {
|
|
|
|
while read -r zvol; do
|
|
|
|
if [ ! -L "/dev/zvol/$zvol" ]; then
|
|
|
|
echo "$zvol"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
filter_out_deleted_zvols() {
|
|
|
|
while read -r zvol; do
|
|
|
|
if zfs list "$zvol" >/dev/null 2>&1; then
|
|
|
|
echo "$zvol"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
list_zvols() {
|
2019-09-03 21:29:52 +03:00
|
|
|
zfs list -t volume -H -o name,volmode,receive_resume_token |
|
|
|
|
while read -r zvol_line; do
|
2019-07-18 01:33:05 +03:00
|
|
|
name=$(echo "$zvol_line" | awk '{print $1}')
|
|
|
|
volmode=$(echo "$zvol_line" | awk '{print $2}')
|
2019-09-03 21:29:52 +03:00
|
|
|
token=$(echo "$zvol_line" | awk '{print $3}')
|
|
|
|
#
|
2019-07-18 01:33:05 +03:00
|
|
|
# /dev links are not created for zvols with volmode = "none".
|
2019-09-03 21:29:52 +03:00
|
|
|
#
|
|
|
|
[ "$volmode" = "none" ] && continue
|
|
|
|
#
|
|
|
|
# We also 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"
|
2019-07-18 01:33:05 +03:00
|
|
|
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="$(echo "$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=$(echo "$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
|
|
|
|
done
|
|
|
|
|
|
|
|
echo "Timed out waiting on zvol links"
|
|
|
|
exit 1
|