]> git.ipfire.org Git - thirdparty/dracut.git/blame - modules.d/95iscsi/module-setup.sh
95iscsi: Fix network setup code for iscsi
[thirdparty/dracut.git] / modules.d / 95iscsi / module-setup.sh
CommitLineData
95d2dabc 1#!/bin/bash
95d2dabc 2
8bcfd683 3# called by dracut
95d2dabc 4check() {
29b10e65 5 local _rootdev
95d2dabc 6 # If our prerequisites are not met, fail anyways.
ebe18216 7 require_binaries iscsi-iname iscsiadm iscsid || return 1
95d2dabc
HH
8
9 # If hostonly was requested, fail the check if we are not actually
10 # booting from root.
11
b093aa2d 12 is_iscsi() {
83e0dc7a 13 local _dev=$1
cb08b013 14
b093aa2d
HH
15 [[ -L "/sys/dev/block/$_dev" ]] || return
16 cd "$(readlink -f "/sys/dev/block/$_dev")"
95d2dabc
HH
17 until [[ -d sys || -d iscsi_session ]]; do
18 cd ..
19 done
20 [[ -d iscsi_session ]]
b093aa2d 21 }
95d2dabc 22
7f347723 23 [[ $hostonly ]] || [[ $mount_needs ]] && {
b093aa2d 24 pushd . >/dev/null
33cfad0b
RM
25 for_each_host_dev_and_slaves is_iscsi
26 local _is_iscsi=$?
b093aa2d 27 popd >/dev/null
33cfad0b 28 [[ $_is_iscsi == 0 ]] || return 255
95d2dabc
HH
29 }
30 return 0
31}
32
2e34f380
HR
33get_ibft_mod() {
34 local ibft_mac=$1
cd728308 35 local iface_mac iface_mod
2e34f380 36 # Return the iSCSI offload module for a given MAC address
cd728308
HR
37 for iface_desc in $(iscsiadm -m iface | cut -f 2 -d ' '); do
38 iface_mod=${iface_desc%%,*}
39 iface_mac=${iface_desc#*,}
40 iface_mac=${iface_mac%%,*}
41 if [ "$ibft_mac" = "$iface_mac" ] ; then
42 echo $iface_mod
2e34f380
HR
43 return 0
44 fi
2e34f380
HR
45 done
46}
47
442abd16
HR
48install_ibft() {
49 # When iBFT / iscsi_boot is detected:
50 # - Use 'ip=ibft' to set up iBFT network interface
2e34f380
HR
51 # Note: bnx2i is using a different MAC address of iSCSI offloading
52 # so the 'ip=ibft' parameter must not be set
442abd16
HR
53 # - specify firmware booting cmdline parameter
54
55 for d in /sys/firmware/* ; do
2e34f380
HR
56 if [ -d ${d}/ethernet0 ] ; then
57 read ibft_mac < ${d}/ethernet0/mac
58 ibft_mod=$(get_ibft_mod $ibft_mac)
59 fi
60 if [ -z "$ibft_mod" ] && [ -d ${d}/ethernet1 ] ; then
61 read ibft_mac < ${d}/ethernet1/mac
62 ibft_mod=$(get_ibft_mod $ibft_mac)
63 fi
442abd16 64 if [ -d ${d}/initiator ] ; then
2e34f380 65 if [ ${d##*/} = "ibft" ] && [ "$ibft_mod" != "bnx2i" ] ; then
b31f3fe0 66 echo -n "rd.iscsi.ibft=1 "
442abd16
HR
67 fi
68 echo -n "rd.iscsi.firmware=1"
69 fi
70 done
71}
72
c4d8793c
HR
73install_iscsiroot() {
74 local devpath=$1
b31f3fe0 75 local scsi_path iscsi_lun session c d conn host flash
c4d8793c 76 local iscsi_session iscsi_address iscsi_port iscsi_targetname iscsi_tpgt
7b76fa92 77 local bootproto
c4d8793c
HR
78
79 scsi_path=${devpath%%/block*}
80 [ "$scsi_path" = "$devpath" ] && return 1
81 iscsi_lun=${scsi_path##*:}
82 [ "$iscsi_lun" = "$scsi_path" ] && return 1
83 session=${devpath%%/target*}
84 [ "$session" = "$devpath" ] && return 1
85 iscsi_session=${session##*/}
86 [ "$iscsi_session" = "$session" ] && return 1
b31f3fe0
DM
87 host=${session%%/session*}
88 [ "$host" = "$session" ] && return 1
89 iscsi_host=${host##*/}
90
91 for flash in ${host}/flashnode_sess-* ; do
94eccd15 92 [ ! -e "$flash/is_boot_target" ] && continue
b31f3fe0
DM
93 is_boot=$(cat $flash/is_boot_target)
94 if [ $is_boot -eq 1 ] ; then
95 # qla4xxx flashnode session; skip iBFT discovery
96 iscsi_initiator=$(cat /sys/class/iscsi_host/${iscsi_host}/initiatorname)
97 echo "rd.iscsi.initiator=${iscsi_initiator}"
98 return;
99 fi
100 done
c4d8793c
HR
101
102 for d in ${session}/* ; do
103 case $d in
104 *connection*)
105 c=${d##*/}
106 conn=${d}/iscsi_connection/${c}
107 if [ -d ${conn} ] ; then
108 iscsi_address=$(cat ${conn}/persistent_address)
109 iscsi_port=$(cat ${conn}/persistent_port)
110 fi
111 ;;
112 *session)
113 if [ -d ${d}/${iscsi_session} ] ; then
114 iscsi_initiator=$(cat ${d}/${iscsi_session}/initiatorname)
115 iscsi_targetname=$(cat ${d}/${iscsi_session}/targetname)
116 fi
117 ;;
118 esac
119 done
120
121 [ -z "$iscsi_address" ] && return
122 local_address=$(ip -o route get to $iscsi_address | sed -n 's/.*src \([0-9a-f.:]*\).*/\1/p')
123 ifname=$(ip -o route get to $iscsi_address | sed -n 's/.*dev \([^ ]*\).*/\1/p')
b31f3fe0 124
7b76fa92
KS
125 # follow ifcfg settings for boot protocol
126 for _path in \
127 "/etc/sysconfig/network-scripts/ifcfg-$ifname" \
128 "/etc/sysconfig/network/ifcfg-$ifname" \
129 ; do
130 [ -f "$_path" ] && bootproto=$(sed -n "s/BOOTPROTO='\?\([[:alpha:]]*6\?\)4\?/\1/p" "$_path")
131 done
132
b31f3fe0
DM
133 if [ $bootproto ]; then
134 printf 'ip=%s:%s ' ${ifname} ${bootproto}
135 else
136 printf 'ip=%s:static ' ${ifname}
137 fi
c4d8793c
HR
138
139 if [ -e /sys/class/net/$ifname/address ] ; then
140 ifmac=$(cat /sys/class/net/$ifname/address)
141 printf 'ifname=%s:%s ' ${ifname} ${ifmac}
142 fi
143
144 if [ -n "$iscsi_address" -a -n "$iscsi_targetname" ] ; then
145 if [ -n "$iscsi_port" -a "$iscsi_port" -eq 3260 ] ; then
146 iscsi_port=
147 fi
148 if [ -n "$iscsi_lun" -a "$iscsi_lun" -eq 0 ] ; then
149 iscsi_lun=
150 fi
151 # In IPv6 case rd.iscsi.initatior= must pass address in [] brackets
152 case "$iscsi_address" in
153 *:*)
154 iscsi_address="[$iscsi_address]"
155 ;;
156 esac
f34a2ef1
TR
157 # Must be two separate lines, so that "sort | uniq" commands later
158 # can sort out rd.iscsi.initiator= duplicates
159 echo "rd.iscsi.initiator=${iscsi_initiator}"
160 echo "netroot=iscsi:${iscsi_address}::${iscsi_port}:${iscsi_lun}:${iscsi_targetname}"
b31f3fe0 161 echo "rd.neednet=1"
c4d8793c
HR
162 fi
163 return 0
164}
165
166
167install_softiscsi() {
168 [ -d /sys/firmware/ibft ] && return 0
169
170 is_softiscsi() {
171 local _dev=$1
172 local iscsi_dev
173
174 [[ -L "/sys/dev/block/$_dev" ]] || return
175 iscsi_dev=$(cd -P /sys/dev/block/$_dev; echo $PWD)
176 install_iscsiroot $iscsi_dev
177 }
178
179 for_each_host_dev_and_slaves_all is_softiscsi || return 255
180 return 0
181}
182
8bcfd683 183# called by dracut
95d2dabc
HH
184depends() {
185 echo network rootfs-block
186}
187
8bcfd683 188# called by dracut
95d2dabc 189installkernel() {
4f9f76cd 190 local _arch=$(uname -m)
794b2d2c 191 local _funcs='iscsi_register_transport'
4f9f76cd 192
b31f3fe0 193 instmods bnx2i qla4xxx cxgb3i cxgb4i be2iscsi qedi
7929ec19 194 hostonly="" instmods iscsi_tcp iscsi_ibft crc32c iscsi_boot_sysfs
9c2a1d0d 195
794b2d2c
HH
196 if [ "$_arch" = "s390" -o "$_arch" = "s390x" ]; then
197 _s390drivers="=drivers/s390/scsi"
198 fi
199
b31f3fe0 200 dracut_instmods -o -s ${_funcs} =drivers/scsi ${_s390drivers:+"$_s390drivers"}
95d2dabc
HH
201}
202
442abd16
HR
203# called by dracut
204cmdline() {
c4d8793c
HR
205 local _iscsiconf=$(install_ibft)
206 {
207 if [ "$_iscsiconf" ] ; then
208 echo ${_iscsiconf}
209 else
210 install_softiscsi
211 fi
212 } | sort | uniq
442abd16
HR
213}
214
8bcfd683 215# called by dracut
95d2dabc 216install() {
af119460 217 inst_multiple -o iscsiuio
4aad3438 218 inst_libdir_file 'libgcc_s.so*'
ebe18216 219 inst_multiple umount iscsi-iname iscsiadm iscsid
b31f3fe0 220
b31f3fe0
DM
221 inst_multiple -o \
222 $systemdsystemunitdir/iscsid.socket \
223 $systemdsystemunitdir/iscsid.service \
224 $systemdsystemunitdir/iscsiuio.service \
225 $systemdsystemunitdir/iscsiuio.socket \
226 $systemdsystemunitdir/sockets.target.wants/iscsid.socket \
227 $systemdsystemunitdir/sockets.target.wants/iscsiuio.socket
228
5e615f4e
LR
229 if [[ $hostonly ]]; then
230 inst_dir $(/usr/bin/find /etc/iscsi)
231 else
232 inst_simple /etc/iscsi/iscsid.conf
233 fi
54e28d79
HR
234
235 # Detect iBFT and perform mandatory steps
236 if [[ $hostonly_cmdline == "yes" ]] ; then
c4d8793c
HR
237 local _iscsiconf=$(cmdline)
238 [[ $_iscsiconf ]] && printf "%s\n" "$_iscsiconf" >> "${initdir}/etc/cmdline.d/95iscsi.conf"
54e28d79
HR
239 fi
240
95d2dabc 241 inst_hook cmdline 90 "$moddir/parse-iscsiroot.sh"
eef7649e 242 inst_hook cleanup 90 "$moddir/cleanup-iscsi.sh"
552ecca6 243 inst "$moddir/iscsiroot.sh" "/sbin/iscsiroot"
0a5fd0dc
HH
244 if ! dracut_module_included "systemd"; then
245 inst "$moddir/mount-lun.sh" "/bin/mount-lun.sh"
b31f3fe0
DM
246 else
247 inst_multiple -o \
248 $systemdsystemunitdir/iscsi.service \
249 $systemdsystemunitdir/iscsid.service \
250 $systemdsystemunitdir/iscsid.socket \
251 $systemdsystemunitdir/iscsiuio.service \
252 $systemdsystemunitdir/iscsiuio.socket \
253 iscsiadm iscsid
254
255 mkdir -p "${initdir}/$systemdsystemunitdir/sockets.target.wants"
256 for i in \
9e82732d 257 iscsid.socket \
b31f3fe0
DM
258 iscsiuio.socket \
259 ; do
260 ln_r "$systemdsystemunitdir/${i}" "$systemdsystemunitdir/sockets.target.wants/${i}"
261 done
262
263 mkdir -p "${initdir}/$systemdsystemunitdir/basic.target.wants"
264 for i in \
265 iscsid.service \
266 iscsiuio.service \
267 ; do
268 ln_r "$systemdsystemunitdir/${i}" "$systemdsystemunitdir/basic.target.wants/${i}"
269 done
88820dc7
LN
270
271 # Make sure iscsid is started after dracut-cmdline and ready for the initqueue
272 mkdir -p "${initdir}/$systemdsystemunitdir/iscsid.service.d"
273 (
274 echo "[Unit]"
275 echo "After=dracut-cmdline.service"
276 echo "Before=dracut-initqueue.service"
277 ) > "${initdir}/$systemdsystemunitdir/iscsid.service.d/dracut.conf"
fca93eac
LN
278
279 # The iscsi deamon does not need to wait for any storage inside initrd
280 mkdir -p "${initdir}/$systemdsystemunitdir/iscsid.socket.d"
281 (
282 echo "[Unit]"
283 echo "DefaultDependencies=no"
284 echo "Conflicts=shutdown.target"
285 echo "Before=shutdown.target sockets.target"
286 ) > "${initdir}/$systemdsystemunitdir/iscsid.socket.d/dracut.conf"
ad906d85 287 mkdir -p "${initdir}/$systemdsystemunitdir/iscsiuio.socket.d"
fca93eac
LN
288 (
289 echo "[Unit]"
290 echo "DefaultDependencies=no"
291 echo "Conflicts=shutdown.target"
292 echo "Before=shutdown.target sockets.target"
ad906d85 293 ) > "${initdir}/$systemdsystemunitdir/iscsiuio.socket.d/dracut.conf"
fca93eac 294
0a5fd0dc 295 fi
f5753e18 296 inst_dir /var/lib/iscsi
41eba87b 297 dracut_need_initqueue
95d2dabc 298}