ia64/xen-unstable

view tools/examples/block @ 8964:8946b6dcd49e

Fix x86_64 Xen build.

event_callback_cs and failsafe_callback_cs are x86_32 only.

Signed-off-by: Ian Campbell <Ian.Campbell@XenSource.com>
author Ian.Campbell@xensource.com
date Wed Feb 22 17:26:39 2006 +0000 (2006-02-22)
parents 5f574f9cb4bd
children b2d3117cc7ed
line source
1 #!/bin/sh
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 # canonicalise_mode mode
22 #
23 # Takes the given mode, which may be r, w, ro, rw, w!, or rw!, or variations
24 # thereof, and canonicalises them to one of
25 #
26 # 'r': perform checks for a new read-only mount;
27 # 'w': perform checks for a read-write mount; or
28 # '!': perform no checks at all.
29 #
30 canonicalise_mode()
31 {
32 local mode="$1"
34 if ! expr index "$mode" 'w' >/dev/null
35 then
36 echo 'r'
37 elif ! expr index "$mode" '!' >/dev/null
38 then
39 echo 'w'
40 else
41 echo '!'
42 fi
43 }
46 ##
47 # check_sharing device mode
48 #
49 # Check whether the device requested is already in use. To use the device in
50 # read-only mode, it may be in use in read-only mode, but may not be in use in
51 # read-write anywhere at all. To use the device in read-write mode, it must
52 # not be in use anywhere at all.
53 #
54 # Prints one of
55 #
56 # 'local': the device may not be used because it is mounted in the current
57 # (i.e. the privileged domain) in a way incompatible with the
58 # requested mode;
59 # 'guest': the device may not be used because it already mounted by a guest
60 # in a way incompatible with the requested mode; or
61 # 'ok': the device may be used.
62 #
63 check_sharing()
64 {
65 local dev="$1"
66 local mode="$2"
68 local devmm=$(device_major_minor "$dev")
69 local file
71 if [ "$mode" == 'w' ]
72 then
73 toskip="^$"
74 else
75 toskip="^[^ ]* [^ ]* [^ ]* ro "
76 fi
78 for file in $(cat /proc/mounts | grep -v "$toskip" | cut -f 1 -d ' ')
79 do
80 if [ -e "$file" ]
81 then
82 local d=$(device_major_minor "$file")
84 if [ "$d" == "$devmm" ]
85 then
86 echo 'local'
87 return
88 fi
89 fi
90 done
92 local base_path="$XENBUS_BASE_PATH/$XENBUS_TYPE"
93 for dom in $(xenstore-list "$base_path")
94 do
95 for dev in $(xenstore-list "$base_path/$dom")
96 do
97 d=$(xenstore_read_default "$base_path/$dom/$dev/physical-device" "")
99 if [ "$d" == "$devmm" ]
100 then
101 if [ "$mode" == 'w' ]
102 then
103 if ! same_vm $dom
104 then
105 echo 'guest'
106 return
107 fi
108 else
109 local m=$(xenstore_read "$base_path/$dom/$dev/mode")
110 m=$(canonicalise_mode "$m")
112 if [ "$m" == 'w' ]
113 then
114 if ! same_vm $dom
115 then
116 echo 'guest'
117 return
118 fi
119 fi
120 fi
121 fi
122 done
123 done
125 echo 'ok'
126 }
129 same_vm()
130 {
131 local otherdom="$1"
132 local othervm=$(xenstore-read "/local/domain/$otherdom/vm")
134 [ "$FRONTEND_UUID" == "$othervm" ]
135 }
138 ##
139 # check_device_sharing dev mode
140 #
141 # Perform the sharing check for the given physical device and mode.
142 #
143 check_device_sharing()
144 {
145 local dev="$1"
146 local mode=$(canonicalise_mode "$2")
147 local result
149 if [ "$mode" == '!' ]
150 then
151 return 0
152 fi
154 result=$(check_sharing "$dev" "$mode")
156 if [ "$result" != 'ok' ]
157 then
158 do_ebusy "Device $dev is mounted " "$mode" "$result"
159 fi
160 }
163 ##
164 # check_device_sharing file dev mode
165 #
166 # Perform the sharing check for the given file mounted through the given
167 # loopback interface, in the given mode.
168 #
169 check_file_sharing()
170 {
171 local file="$1"
172 local dev="$2"
173 local mode="$3"
175 result=$(check_sharing "$dev" "$mode")
177 if [ "$result" != 'ok' ]
178 then
179 do_ebusy "File $file is loopback-mounted through $dev,
180 which is mounted " "$mode" "$result"
181 fi
182 }
185 ##
186 # do_ebusy prefix mode result
187 #
188 # Helper function for check_device_sharing check_file_sharing, calling ebusy
189 # with an error message constructed from the given prefix, mode, and result
190 # from a call to check_sharing.
191 #
192 do_ebusy()
193 {
194 local prefix="$1"
195 local mode="$2"
196 local result="$3"
198 if [ "$result" == 'guest' ]
199 then
200 dom='a guest '
201 when='now'
202 else
203 dom='the privileged '
204 when='by a guest'
205 fi
207 if [ "$mode" == 'w' ]
208 then
209 m1=''
210 m2=''
211 else
212 m1='read-write '
213 m2='read-only '
214 fi
216 release_lock "block"
217 ebusy \
218 "${prefix}${m1}in ${dom}domain,
219 and so cannot be mounted ${m2}${when}."
220 }
223 t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING')
225 case "$command" in
226 add)
227 phys=$(xenstore_read_default "$XENBUS_PATH/physical-device" 'MISSING')
228 if [ "$phys" != 'MISSING' ]
229 then
230 # Depending upon the hotplug configuration, it is possible for this
231 # script to be called twice, so just bail.
232 exit 0
233 fi
235 p=$(xenstore_read "$XENBUS_PATH/params")
236 mode=$(xenstore_read "$XENBUS_PATH/mode")
238 case $t in
239 phy)
240 dev=$(expand_dev $p)
241 FRONTEND_ID=$(xenstore_read "$XENBUS_PATH/frontend-id")
242 FRONTEND_UUID=$(xenstore_read_default \
243 "/local/domain/$FRONTEND_ID/vm" 'unknown')
244 claim_lock "block"
245 check_device_sharing "$dev" "$mode"
246 write_dev "$dev"
247 release_lock "block"
248 exit 0
249 ;;
251 file)
252 # Canonicalise the file, for sharing check comparison, and the mode
253 # for ease of use here.
254 file=$(readlink -f "$p") || fatal "$p does not exist."
255 mode=$(canonicalise_mode "$mode")
257 claim_lock "block"
259 if [ "$mode" == 'w' ] && ! stat "$file" -c %A | grep -q w
260 then
261 release_lock "block"
262 ebusy \
263 "File $file is read-only, and so I will not
264 mount it read-write in a guest domain."
265 fi
267 loopdev=''
268 for dev in /dev/loop*
269 do
270 if [ ! -b "$dev" ]
271 then
272 continue
273 fi
275 f=$(losetup "$dev" 2>/dev/null) || f=''
277 if [ "$f" ]
278 then
279 # $dev is in use. Check sharing.
280 if [ "$mode" == '!' ]
281 then
282 continue
283 fi
285 f=$(echo "$f" | sed -e 's/.*(\(.*\)).*/\1/g')
287 # $f is the filename, as read from losetup, but the loopback
288 # driver truncates filenames at 64 characters, so we need to go
289 # trawling through the store if it's longer than that. Truncation
290 # is indicated by an asterisk at the end of the filename.
291 if expr index "$f" '*' >/dev/null
292 then
293 found=""
294 for dom in $(xenstore-list "$XENBUS_BASE_PATH")
295 do
296 for domdev in $(xenstore-list "$XENBUS_BASE_PATH/$dom")
297 do
298 d=$(xenstore_read_default \
299 "$XENBUS_BASE_PATH/$dom/$domdev/node" "")
300 if [ "$d" == "$dev" ]
301 then
302 f=$(xenstore_read "$XENBUS_BASE_PATH/$dom/$domdev/params")
303 found=1
304 break 2
305 fi
306 done
307 done
309 if [ ! "$found" ]
310 then
311 # This loopback device is in use by someone else, so skip it.
312 log debug "Loopback sharing check skips device $dev."
313 continue
314 fi
315 fi
317 f=$(readlink -f "$f")
319 if [ "$f" == "$file" ]
320 then
321 check_file_sharing "$file" "$dev" "$mode"
322 fi
323 else
324 # $dev is not in use, so we'll remember it for use later; we want
325 # to finish the sharing check first.
327 if [ "$loopdev" == '' ]
328 then
329 loopdev="$dev"
330 fi
331 fi
332 done
334 if [ "$loopdev" == '' ]
335 then
336 fatal 'Failed to find an unused loop device'
337 fi
339 do_or_die losetup "$loopdev" "$file"
340 xenstore_write "$XENBUS_PATH/node" "$loopdev"
341 write_dev "$loopdev"
342 release_lock "block"
343 exit 0
344 ;;
345 esac
346 ;;
348 remove)
349 case $t in
350 phy)
351 exit 0
352 ;;
354 file)
355 node=$(xenstore_read "$XENBUS_PATH/node")
356 losetup -d "$node"
357 exit 0
358 ;;
359 esac
360 ;;
362 esac
364 # If we've reached here, $t is neither phy nor file, so fire a helper script.
365 [ -x /etc/xen/scripts/block-"$t" ] && \
366 /etc/xen/scripts/block-"$t" "$command" $node