Skip to content

Commit ca44b94

Browse files
committed
kickstart: Rewrite block devices detection
Instead of having a whitelist of block device types you can try to guess if it is possible to scan partitions. The same code is used in systemd. Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
1 parent 13a27fb commit ca44b94

File tree

1 file changed

+90
-36
lines changed

1 file changed

+90
-36
lines changed

features/kickstart/data/bin/kickstart

Lines changed: 90 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
. shell-error
1010
. shell-quote
1111
. shell-args
12+
. shell-var
13+
14+
. initrd-sh-functions
1215

1316
. "$0-sh-storage"
1417
. "$0-sh-installation"
@@ -145,62 +148,113 @@ KS_ORDERS=(
145148
9200000000:shutdown
146149
)
147150

148-
get_device_type()
151+
# Based on systemd code.
152+
# https://github.com/systemd/systemd/blob/main/src/shared/blockdev-util.c#L359
153+
ks_valid_block_device()
149154
{
150-
local id="$1"; shift
151-
local block=
152-
local maj type
153-
154-
while read -r maj type; do
155-
if [ -n "$block" ] && [ "$id" = "$maj" ]; then
156-
echo "$type"
157-
return 0
158-
fi
155+
local syspath="$1"
156+
local attr
159157

160-
[ "$maj $type" != 'Block devices:' ] ||
161-
block=1
162-
done </proc/devices
163-
return 1
158+
[ -e "$syspath" ] ||
159+
return 1
160+
161+
# With https://github.com/torvalds/linux/commit/a4217c6740dc64a3eb6815868a9260825e8c68c6 (v6.10,
162+
# backported to v6.6+), the partscan status is directly exposed as
163+
# 'partscan' sysattr.
164+
if [ -r "$syspath/partscan" ]; then
165+
readline attr "$syspath/partscan"
166+
167+
shell_var_is_yes "$attr" ||
168+
return 1
169+
return 0
170+
fi
171+
172+
# For loopback block device, especially for v5.19 or newer. Even if this
173+
# is enabled, we also need to check GENHD_FL_NO_PART flag through
174+
# 'ext_range' and 'capability' sysfs attributes below.
175+
if [ -r "$syspath/loop/partscan" ]; then
176+
readline attr "$syspath/loop/partscan"
177+
178+
shell_var_is_yes "$attr" ||
179+
return 1
180+
fi
181+
182+
# With https://github.com/torvalds/linux/commit/1ebe2e5f9d68e94c524aba876f27b945669a7879 (v5.17),
183+
# we can check the flag from 'ext_range' sysfs attribute directly.
184+
#
185+
# If the ext_range file doesn't exist then we are most likely looking at
186+
# a partition block device, not the whole block device. And that means
187+
# we have no partition scanning on for it (we do for its parent, but not
188+
# for the partition itself).
189+
[ -r "$syspath/ext_range" ] ||
190+
return 1
191+
192+
readline attr "$syspath/ext_range"
193+
194+
# The value should be always positive, but the kernel uses '%d'
195+
# for the attribute.
196+
shell_var_is_number "$attr" ||
197+
return 1
198+
199+
# With https://github.com/torvalds/linux/commit/e81cd5a983bb35dabd38ee472cf3fea1c63e0f23 (v6.3),
200+
# the 'capability' sysfs attribute is deprecated, hence we cannot check
201+
# flags from it.
202+
if [ -r "$syspath/capability" ]; then
203+
# With https://github.com/torvalds/linux/commit/430cc5d3ab4d0ba0bd011cfbb0035e46ba92920c (v5.17),
204+
# the value of GENHD_FL_NO_PART is changed from 0x0200 to 0x0004
205+
local GENHD_FL_NO_PART_v5_17=$(( 0x0200 ))
206+
local GENHD_FL_NO_PART_v6_3=$(( 0x0004 ))
207+
208+
readline attr "$f/capability"
209+
210+
# If one of the NO_PART flags is set, part scanning is
211+
# definitely off.
212+
shell_var_is_number "$attr" &&
213+
[ "$(( $attr & ( $GENHD_FL_NO_PART_v5_17 | $GENHD_FL_NO_PART_v6_3 ) ))" -eq 0 ] ||
214+
return 1
215+
fi
216+
217+
# Otherwise, assume part scanning is on.
218+
return 0
164219
}
165220

166221
ks_block_devices()
167222
{
168-
local retval="$1"; shift
169-
local f dev
170-
local maj min
171-
local blocktype
223+
local retval="$1"
224+
local majmin dev
172225
local exclude=','
173226

174-
for f in $(findmnt -lno SOURCE | sed -n -e 's,^/dev/,,p'); do
175-
dev="$(readlink -f "/sys/class/block/$f")"
176-
dev="${dev%/$f}"
177-
dev="${dev##*/}"
178-
exclude="$exclude$dev,"
227+
for majmin in $(findmnt -lno MAJ:MIN |sed -e '/^ *0:.*/d' |sort -u); do
228+
dev="$(readlink -f "/sys/dev/block/$majmin")" ||
229+
continue
230+
[ -z "${dev##*/virtual/block/*}" ] ||
231+
dev="${dev%/*}"
232+
exclude="${exclude}${majmin},"
179233
done
180234

181235
set --
182236

183-
for f in $(set +f; printf '%s\n' /sys/block/*); do
184-
[ -e "$f" ] ||
237+
for majmin in $(set +f && cd /sys/dev/block && printf '%s\n' * |sort -nt:); do
238+
[ -n "${exclude##*,$majmin,*}" ] ||
185239
continue
186240

187-
maj=
188-
min=
189-
IFS=: read -r maj min < "$f/dev"
190-
blocktype="$(get_device_type "$maj")"
191-
192-
case "$blocktype" in
193-
sd|virtblk|mmc|blkext)
194-
;;
195-
*)
241+
case "$majmin" in
242+
# 0 - Unnamed devices (e.g. non-device mounts)
243+
# 1 block - RAM disk
244+
# 4 block - Aliases for dynamically allocated major
245+
# devices to be used when its not possible to
246+
# create the real device nodes because the
247+
# root filesystem is mounted read-only.
248+
0:*|1:*|4:*)
196249
continue
197250
;;
198251
esac
199252

200-
[ -n "${exclude##*,${f##*/},*}" ] ||
253+
ks_valid_block_device "/sys/dev/block/$majmin" ||
201254
continue
202255

203-
set -- "$@" "${f##*/}"
256+
dev="$(readlink -f "/sys/dev/block/$majmin")"
257+
set -- "$@" "${dev##*/}"
204258
done
205259

206260
eval "$retval=\"\$*\""

0 commit comments

Comments
 (0)