blob: d3307b98b82811c217c2af572af90b0be1fdac9b (
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
|
#!/bin/bash
# called by dracut
check() {
# If our prerequisites are not met, fail anyways.
require_binaries iscsi-iname iscsiadm iscsid || return 1
require_kernel_modules iscsi_tcp || return 1
# If hostonly was requested, fail the check if we are not actually
# booting from root.
[[ $hostonly ]] || [[ $mount_needs ]] && {
pushd . > /dev/null
for_each_host_dev_and_slaves block_is_iscsi
local _is_iscsi=$?
popd > /dev/null || exit
[[ $_is_iscsi == 0 ]] || return 255
}
return 0
}
get_ibft_mod() {
local ibft_mac=$1
local iface_mac iface_mod
# Return the iSCSI offload module for a given MAC address
for iface_desc in $(iscsiadm -m iface | cut -f 2 -d ' '); do
iface_mod=${iface_desc%%,*}
iface_mac=${iface_desc#*,}
iface_mac=${iface_mac%%,*}
if [ "$ibft_mac" = "$iface_mac" ]; then
echo "$iface_mod"
return 0
fi
done
}
install_ibft() {
# When iBFT / iscsi_boot is detected:
# - Use 'ip=ibft' to set up iBFT network interface
# Note: bnx2i is using a different MAC address of iSCSI offloading
# so the 'ip=ibft' parameter must not be set
# - specify firmware booting cmdline parameter
for d in /sys/firmware/*; do
if [ -d "${d}"/ethernet0 ]; then
read -r ibft_mac < "${d}"/ethernet0/mac
ibft_mod=$(get_ibft_mod "$ibft_mac")
fi
if [ -z "$ibft_mod" ] && [ -d "${d}"/ethernet1 ]; then
read -r ibft_mac < "${d}"/ethernet1/mac
ibft_mod=$(get_ibft_mod "$ibft_mac")
fi
if [ -d "${d}"/initiator ]; then
if [ "${d##*/}" = "ibft" ] && [ "$ibft_mod" != "bnx2i" ]; then
echo -n "rd.iscsi.ibft=1 "
fi
echo -n "rd.iscsi.firmware=1 "
fi
done
}
install_iscsiroot() {
local devpath=$1
local scsi_path iscsi_lun session c d conn host flash
local iscsi_session iscsi_address iscsi_port iscsi_targetname
scsi_path=${devpath%%/block*}
[ "$scsi_path" = "$devpath" ] && return 1
iscsi_lun=${scsi_path##*:}
[ "$iscsi_lun" = "$scsi_path" ] && return 1
session=${devpath%%/target*}
[ "$session" = "$devpath" ] && return 1
iscsi_session=${session##*/}
[ "$iscsi_session" = "$session" ] && return 1
host=${session%%/session*}
[ "$host" = "$session" ] && return 1
iscsi_host=${host##*/}
for flash in "${host}"/flashnode_sess-*; do
[ -f "$flash" ] || continue
[ ! -e "$flash/is_boot_target" ] && continue
read -r is_boot < "$flash"/is_boot_target
if [ "$is_boot" -eq 1 ]; then
# qla4xxx flashnode session; skip iBFT discovery
read -r iscsi_initiator < /sys/class/iscsi_host/"${iscsi_host}"/initiatorname
echo "rd.iscsi.initiator=${iscsi_initiator}"
return
fi
done
for d in "${session}"/*; do
case $d in
*connection*)
c=${d##*/}
conn=${d}/iscsi_connection/${c}
if [ -d "${conn}" ]; then
read -r iscsi_address < "${conn}"/persistent_address
read -r iscsi_port < "${conn}"/persistent_port
fi
;;
*session)
if [ -d "${d}"/"${iscsi_session}" ]; then
read -r iscsi_initiator < "${d}"/"${iscsi_session}"/initiatorname
read -r iscsi_targetname < "${d}"/"${iscsi_session}"/targetname
fi
;;
esac
done
[ -z "$iscsi_address" ] && return
ip_params_for_remote_addr "$iscsi_address"
if [ -n "$iscsi_address" ] && [ -n "$iscsi_targetname" ]; then
if [ -n "$iscsi_port" ] && [ "$iscsi_port" -eq 3260 ]; then
iscsi_port=
fi
if [ -n "$iscsi_lun" ] && [ "$iscsi_lun" -eq 0 ]; then
iscsi_lun=
fi
# In IPv6 case rd.iscsi.initatior= must pass address in [] brackets
case "$iscsi_address" in
*:*)
iscsi_address="[$iscsi_address]"
;;
esac
# Must be two separate lines, so that "sort | uniq" commands later
# can sort out rd.iscsi.initiator= duplicates
echo "rd.iscsi.initiator=${iscsi_initiator}"
echo "netroot=iscsi:${iscsi_address}::${iscsi_port}:${iscsi_lun}:${iscsi_targetname}"
echo "rd.neednet=1"
fi
return 0
}
install_softiscsi() {
[ -d /sys/firmware/ibft ] && return 0
# shellcheck disable=SC2317 # called later by for_each_host_dev_and_slaves
is_softiscsi() {
local _dev=$1
local iscsi_dev
[[ -L "/sys/dev/block/$_dev" ]] || return
iscsi_dev=$(
cd -P /sys/dev/block/"$_dev" || exit
echo "$PWD"
)
install_iscsiroot "$iscsi_dev"
}
for_each_host_dev_and_slaves_all is_softiscsi || return 255
return 0
}
# called by dracut
depends() {
echo network rootfs-block
}
# called by dracut
installkernel() {
local _arch=${DRACUT_ARCH:-$(uname -m)}
local _funcs='iscsi_register_transport'
instmods bnx2i qla4xxx cxgb3i cxgb4i be2iscsi qedi
hostonly="" instmods iscsi_tcp iscsi_ibft crc32c iscsi_boot_sysfs 8021q
if [ "$_arch" = "s390" ] || [ "$_arch" = "s390x" ]; then
_s390drivers="=drivers/s390/scsi"
fi
dracut_instmods -o -s ${_funcs} =drivers/scsi ${_s390drivers:+"$_s390drivers"}
}
# called by dracut
cmdline() {
local _iscsiconf
_iscsiconf=$(install_ibft)
{
if [ "$_iscsiconf" ]; then
echo "${_iscsiconf}"
else
install_softiscsi
fi
} | sort | uniq
}
# called by dracut
install() {
inst_multiple -o iscsiuio
inst_libdir_file 'libgcc_s.so*'
inst_multiple umount iscsi-iname iscsiadm iscsid
inst_binary sort
inst_multiple -o \
"$systemdsystemunitdir"/iscsid.socket \
"$systemdsystemunitdir"/iscsid.service \
"$systemdsystemunitdir"/iscsiuio.service \
"$systemdsystemunitdir"/iscsiuio.socket \
"$systemdsystemunitdir"/sockets.target.wants/iscsid.socket \
"$systemdsystemunitdir"/sockets.target.wants/iscsiuio.socket
inst_simple /etc/iscsi/iscsid.conf
if [[ $hostonly ]]; then
inst_simple /etc/iscsi/initiatorname.iscsi
fi
# Detect iBFT and perform mandatory steps
if [[ $hostonly_cmdline == "yes" ]]; then
local _iscsiconf
_iscsiconf=$(cmdline)
[[ $_iscsiconf ]] && printf "%s\n" "$_iscsiconf" >> "${initdir}/etc/cmdline.d/95iscsi.conf"
fi
inst_hook cmdline 90 "$moddir/parse-iscsiroot.sh"
inst_hook cleanup 90 "$moddir/cleanup-iscsi.sh"
inst "$moddir/iscsiroot.sh" "/sbin/iscsiroot"
if ! dracut_module_included "systemd"; then
inst "$moddir/mount-lun.sh" "/bin/mount-lun.sh"
else
inst_multiple -o \
"$systemdsystemunitdir"/iscsi.service \
"$systemdsystemunitdir"/iscsi-init.service \
"$systemdsystemunitdir"/iscsid.service \
"$systemdsystemunitdir"/iscsid.socket \
"$systemdsystemunitdir"/iscsiuio.service \
"$systemdsystemunitdir"/iscsiuio.socket \
iscsiadm iscsid
for i in \
iscsid.socket \
iscsiuio.socket; do
$SYSTEMCTL -q --root "$initdir" enable "$i"
done
mkdir -p "${initdir}/$systemdsystemunitdir/iscsid.service.d"
{
echo "[Unit]"
echo "DefaultDependencies=no"
echo "Conflicts=shutdown.target"
echo "Before=shutdown.target"
} > "${initdir}/$systemdsystemunitdir/iscsid.service.d/dracut.conf"
mkdir -p "${initdir}/$systemdsystemunitdir/iscsid.socket.d"
{
echo "[Unit]"
echo "DefaultDependencies=no"
echo "Conflicts=shutdown.target"
echo "Before=shutdown.target sockets.target"
} > "${initdir}/$systemdsystemunitdir/iscsid.socket.d/dracut.conf"
mkdir -p "${initdir}/$systemdsystemunitdir/iscsiuio.service.d"
{
echo "[Unit]"
echo "DefaultDependencies=no"
echo "Conflicts=shutdown.target"
echo "Before=shutdown.target"
} > "${initdir}/$systemdsystemunitdir/iscsiuio.service.d/dracut.conf"
mkdir -p "${initdir}/$systemdsystemunitdir/iscsiuio.socket.d"
{
echo "[Unit]"
echo "DefaultDependencies=no"
echo "Conflicts=shutdown.target"
echo "Before=shutdown.target sockets.target"
} > "${initdir}/$systemdsystemunitdir/iscsiuio.socket.d/dracut.conf"
# Fedora 34 iscsid requires iscsi-shutdown.service
# which would terminate all iSCSI connections on switch root
cat > "${initdir}/$systemdsystemunitdir/iscsi-shutdown.service" << EOF
[Unit]
Description=Dummy iscsi-shutdown.service for the initrd
Documentation=man:iscsid(8) man:iscsiadm(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-remount-fs.service network.target iscsid.service iscsiuio.service
Before=remote-fs-pre.target
[Service]
Type=oneshot
RemainAfterExit=false
ExecStart=-/usr/bin/true
EOF
fi
inst_dir /var/lib/iscsi
mkdir -p "${initdir}/var/lib/iscsi/nodes"
# Fedora 34 iscsid wants a non-empty /var/lib/iscsi/nodes directory
: > "${initdir}/var/lib/iscsi/nodes/.dracut"
dracut_need_initqueue
}
|