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