ia64/xen-unstable

view tools/hotplug/Linux/block @ 19497:2f6ed9318c03

network-bridge: Fix do_ifup in the case of ${bridge} != ${netdev}

On RHEL5.2, ifup ${bridge} fails if ${bridge} != ${netdev},
because RHEL5.2's ifup ${bridge} runs the following sequence:

1. Search CONFIG that has the same mac address of ${bridge}.=20
ifcfg-${netdev} is found.
2. Run "ip link set dev ${netdev} up".
# ${bridge} is expected.
3. Output "Failed to bring up ${netdev}."
Because ${netdev} does not exist.

Thus, do_ifup() should not use ifup if ${bridge} != ${netdev}.

Signed-off-by: KUWAMURA Shin'ya <kuwa@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Apr 02 11:48:10 2009 +0100 (2009-04-02)
parents 4bfc67b09e9c
children 0f752c773497
line source
1 #!/bin/bash
3 dir=$(dirname "$0")
4 . "$dir/block-common.sh"
6 expand_dev() {
7 local dev
8 case $1 in
9 /*)
10 dev=$1
11 ;;
12 *)
13 dev=/dev/$1
14 ;;
15 esac
16 echo -n $dev
17 }
20 ##
21 # check_sharing device mode
22 #
23 # Check whether the device requested is already in use. To use the device in
24 # read-only mode, it may be in use in read-only mode, but may not be in use in
25 # read-write anywhere at all. To use the device in read-write mode, it must
26 # not be in use anywhere at all.
27 #
28 # Prints one of
29 #
30 # 'local': the device may not be used because it is mounted in the current
31 # (i.e. the privileged domain) in a way incompatible with the
32 # requested mode;
33 # 'guest': the device may not be used because it already mounted by a guest
34 # in a way incompatible with the requested mode; or
35 # 'ok': the device may be used.
36 #
37 check_sharing()
38 {
39 local dev="$1"
40 local mode="$2"
42 local devmm=$(device_major_minor "$dev")
43 local file
45 if [ "$mode" = 'w' ]
46 then
47 toskip="^$"
48 else
49 toskip="^[^ ]* [^ ]* [^ ]* ro[, ]"
50 fi
52 for file in $(cat /proc/mounts | grep -v "$toskip" | cut -f 1 -d ' ')
53 do
54 if [ -e "$file" ]
55 then
56 local d=$(device_major_minor "$file")
58 if [ "$d" = "$devmm" ]
59 then
60 echo 'local'
61 return
62 fi
63 fi
64 done
66 local base_path="$XENBUS_BASE_PATH/$XENBUS_TYPE"
67 for dom in $(xenstore-list "$base_path")
68 do
69 for dev in $(xenstore-list "$base_path/$dom")
70 do
71 d=$(xenstore_read_default "$base_path/$dom/$dev/physical-device" "")
73 if [ "$d" = "$devmm" ]
74 then
75 if [ "$mode" = 'w' ]
76 then
77 if ! same_vm $dom
78 then
79 echo 'guest'
80 return
81 fi
82 else
83 local m=$(xenstore_read "$base_path/$dom/$dev/mode")
84 m=$(canonicalise_mode "$m")
86 if [ "$m" = 'w' ]
87 then
88 if ! same_vm $dom
89 then
90 echo 'guest'
91 return
92 fi
93 fi
94 fi
95 fi
96 done
97 done
99 echo 'ok'
100 }
103 ##
104 # check_device_sharing dev mode
105 #
106 # Perform the sharing check for the given physical device and mode.
107 #
108 check_device_sharing()
109 {
110 local dev="$1"
111 local mode=$(canonicalise_mode "$2")
112 local result
114 if [ "x$mode" = 'x!' ]
115 then
116 return 0
117 fi
119 result=$(check_sharing "$dev" "$mode")
121 if [ "$result" != 'ok' ]
122 then
123 do_ebusy "Device $dev is mounted " "$mode" "$result"
124 fi
125 }
128 ##
129 # check_device_sharing file dev mode
130 #
131 # Perform the sharing check for the given file mounted through the given
132 # loopback interface, in the given mode.
133 #
134 check_file_sharing()
135 {
136 local file="$1"
137 local dev="$2"
138 local mode="$3"
140 result=$(check_sharing "$dev" "$mode")
142 if [ "$result" != 'ok' ]
143 then
144 do_ebusy "File $file is loopback-mounted through $dev,
145 which is mounted " "$mode" "$result"
146 fi
147 }
150 ##
151 # do_ebusy prefix mode result
152 #
153 # Helper function for check_device_sharing check_file_sharing, calling ebusy
154 # with an error message constructed from the given prefix, mode, and result
155 # from a call to check_sharing.
156 #
157 do_ebusy()
158 {
159 local prefix="$1"
160 local mode="$2"
161 local result="$3"
163 if [ "$result" = 'guest' ]
164 then
165 dom='a guest '
166 when='now'
167 else
168 dom='the privileged '
169 when='by a guest'
170 fi
172 if [ "$mode" = 'w' ]
173 then
174 m1=''
175 m2=''
176 else
177 m1='read-write '
178 m2='read-only '
179 fi
181 release_lock "block"
182 ebusy \
183 "${prefix}${m1}in ${dom}domain,
184 and so cannot be mounted ${m2}${when}."
185 }
188 t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING')
190 case "$command" in
191 add)
192 phys=$(xenstore_read_default "$XENBUS_PATH/physical-device" 'MISSING')
193 if [ "$phys" != 'MISSING' ]
194 then
195 # Depending upon the hotplug configuration, it is possible for this
196 # script to be called twice, so just bail.
197 exit 0
198 fi
200 if [ -n "$t" ]
201 then
202 p=$(xenstore_read "$XENBUS_PATH/params")
203 mode=$(xenstore_read "$XENBUS_PATH/mode")
204 fi
206 case $t in
207 phy)
208 dev=$(expand_dev $p)
209 FRONTEND_ID=$(xenstore_read "$XENBUS_PATH/frontend-id")
210 FRONTEND_UUID=$(xenstore_read_default \
211 "/local/domain/$FRONTEND_ID/vm" 'unknown')
213 if [ -L "$dev" ]
214 then
215 dev=$(readlink -f "$dev") || fatal "$dev link does not exist."
216 fi
217 test -e "$dev" || fatal "$dev does not exist."
218 test -b "$dev" || fatal "$dev is not a block device."
220 claim_lock "block"
221 check_device_sharing "$dev" "$mode"
222 write_dev "$dev"
223 release_lock "block"
224 exit 0
225 ;;
227 file)
228 # Canonicalise the file, for sharing check comparison, and the mode
229 # for ease of use here.
230 file=$(readlink -f "$p") || fatal "$p does not exist."
231 test -f "$file" || fatal "$file does not exist."
232 mode=$(canonicalise_mode "$mode")
234 claim_lock "block"
236 if [ "$mode" = 'w' ] && ! stat "$file" -c %A | grep -q w
237 then
238 release_lock "block"
239 ebusy \
240 "File $file is read-only, and so I will not
241 mount it read-write in a guest domain."
242 fi
244 loopdev=''
245 for dev in /dev/loop*
246 do
247 if [ ! -b "$dev" ]
248 then
249 continue
250 fi
252 f=$(losetup "$dev" 2>/dev/null) || f=''
254 if [ "$f" ]
255 then
256 # $dev is in use. Check sharing.
257 if [ "x$mode" = 'x!' ]
258 then
259 continue
260 fi
262 f=$(echo "$f" | sed -e 's/.*(\(.*\)).*/\1/g')
264 # $f is the filename, as read from losetup, but the loopback
265 # driver truncates filenames at 64 characters, so we need to go
266 # trawling through the store if it's longer than that. Truncation
267 # is indicated by an asterisk at the end of the filename.
268 if expr index "$f" '*' >/dev/null
269 then
270 found=""
271 for dom in $(xenstore-list "$XENBUS_BASE_PATH")
272 do
273 for domdev in $(xenstore-list "$XENBUS_BASE_PATH/$dom")
274 do
275 d=$(xenstore_read_default \
276 "$XENBUS_BASE_PATH/$dom/$domdev/node" "")
277 if [ "$d" = "$dev" ]
278 then
279 f=$(xenstore_read "$XENBUS_BASE_PATH/$dom/$domdev/params")
280 found=1
281 break 2
282 fi
283 done
284 done
286 if [ ! "$found" ]
287 then
288 # This loopback device is in use by someone else, so skip it.
289 log debug "Loopback sharing check skips device $dev."
290 continue
291 fi
292 fi
294 # Canonicalise the filename for the comparison.
296 # I have seen this readlink fails because the filename given by
297 # losetup is only the basename. This cannot happen when the loop
298 # device is set up through this script, because file is
299 # canonicalised above, but it may happen when loop devices are set
300 # up some other way. This readlink may also conceivably fail if
301 # the file backing this loop device has been removed.
303 # For maximum safety, in the case that $f does not resolve, we
304 # assume that $file and $f are in the same directory.
306 # If you create a loopback filesystem, remove it and continue to
307 # run on it, and then create another file with the same name, then
308 # this check will block that -- don't do that.
310 # If you create loop devices through some other mechanism, use
311 # relative filenames, and then use the same filename through this
312 # script, then this check will block that -- don't do that either.
314 f=$(readlink -f "$f" || echo $(dirname "$file")/$(basename "$f"))
317 if [ "$f" = "$file" ]
318 then
319 check_file_sharing "$file" "$dev" "$mode"
320 fi
321 else
322 # $dev is not in use, so we'll remember it for use later; we want
323 # to finish the sharing check first.
325 if [ "$loopdev" = '' ]
326 then
327 loopdev="$dev"
328 fi
329 fi
330 done
332 if [ "$loopdev" = '' ]
333 then
334 release_lock "block"
335 fatal 'Failed to find an unused loop device'
336 fi
338 if LANG=C losetup -h 2>&1 | grep read-only >/dev/null
339 then
340 roflag="-$mode"; roflag="${roflag#-w}"; roflag="${roflag#-!}"
341 else
342 roflag=''
343 fi
344 do_or_die losetup $roflag "$loopdev" "$file"
345 xenstore_write "$XENBUS_PATH/node" "$loopdev"
346 write_dev "$loopdev"
347 release_lock "block"
348 exit 0
349 ;;
351 "")
352 claim_lock "block"
353 success
354 release_lock "block"
355 ;;
356 esac
357 ;;
359 remove)
360 case $t in
361 phy)
362 exit 0
363 ;;
365 file)
366 node=$(xenstore_read "$XENBUS_PATH/node")
367 losetup -d "$node"
368 exit 0
369 ;;
371 "")
372 exit 0
373 ;;
374 esac
375 ;;
377 esac
379 # If we've reached here, $t is neither phy nor file, so fire a helper script.
380 [ -x /etc/xen/scripts/block-"$t" ] && \
381 /etc/xen/scripts/block-"$t" "$command" $node