ia64/xen-unstable
changeset 8196:485871ff1d39
Fix the block-sharing check for physical devices by using a lock to serialise
the check, reading from the store rather than /sys, and checking whether the
VM for apparently-conflicting uses is actually the same (i.e. this is a
migration or a reboot in progress).
This fixes recent failures in 12_block_attach_shared_domU and recloses bug #331.
This fix includes particularly skanky path slicing inside xenbus_probe, which
it would be nice to remove very soon.
The loopback device check still suffers from the problem that filenames over
64 characters long are truncated.
Signed-off-by: Ewan Mellor <ewan@xensource.com>
the check, reading from the store rather than /sys, and checking whether the
VM for apparently-conflicting uses is actually the same (i.e. this is a
migration or a reboot in progress).
This fixes recent failures in 12_block_attach_shared_domU and recloses bug #331.
This fix includes particularly skanky path slicing inside xenbus_probe, which
it would be nice to remove very soon.
The loopback device check still suffers from the problem that filenames over
64 characters long are truncated.
Signed-off-by: Ewan Mellor <ewan@xensource.com>
author | emellor@leeni.uk.xensource.com |
---|---|
date | Fri Dec 02 15:48:44 2005 +0000 (2005-12-02) |
parents | df011cae33e9 |
children | 30eb074a560a |
files | linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c tools/examples/block |
line diff
1.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Dec 02 15:39:13 2005 +0000 1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Dec 02 15:48:44 2005 +0000 1.3 @@ -59,6 +59,8 @@ extern struct semaphore xenwatch_mutex; 1.4 1.5 #define streq(a, b) (strcmp((a), (b)) == 0) 1.6 1.7 +static char *kasprintf(const char *fmt, ...); 1.8 + 1.9 static struct notifier_block *xenstore_chain; 1.10 1.11 /* If something in array of ids matches this device, return it. */ 1.12 @@ -226,8 +228,11 @@ static int xenbus_hotplug_backend(struct 1.13 int num_envp, char *buffer, int buffer_size) 1.14 { 1.15 struct xenbus_device *xdev; 1.16 + struct xenbus_driver *drv = NULL; 1.17 int i = 0; 1.18 int length = 0; 1.19 + char *basepath_end; 1.20 + char *frontend_id; 1.21 1.22 DPRINTK(""); 1.23 1.24 @@ -238,6 +243,9 @@ static int xenbus_hotplug_backend(struct 1.25 if (xdev == NULL) 1.26 return -ENODEV; 1.27 1.28 + if (dev->driver) 1.29 + drv = to_xenbus_driver(dev->driver); 1.30 + 1.31 /* stuff we want to pass to /sbin/hotplug */ 1.32 add_hotplug_env_var(envp, num_envp, &i, 1.33 buffer, buffer_size, &length, 1.34 @@ -247,6 +255,25 @@ static int xenbus_hotplug_backend(struct 1.35 buffer, buffer_size, &length, 1.36 "XENBUS_PATH=%s", xdev->nodename); 1.37 1.38 + add_hotplug_env_var(envp, num_envp, &i, 1.39 + buffer, buffer_size, &length, 1.40 + "XENBUS_BASE_PATH=%s", xdev->nodename); 1.41 + 1.42 + basepath_end = strrchr(envp[i - 1], '/'); 1.43 + length -= strlen(basepath_end); 1.44 + *basepath_end = '\0'; 1.45 + basepath_end = strrchr(envp[i - 1], '/'); 1.46 + length -= strlen(basepath_end); 1.47 + *basepath_end = '\0'; 1.48 + 1.49 + basepath_end++; 1.50 + frontend_id = kmalloc(strlen(basepath_end) + 1, GFP_KERNEL); 1.51 + strcpy(frontend_id, basepath_end); 1.52 + add_hotplug_env_var(envp, num_envp, &i, 1.53 + buffer, buffer_size, &length, 1.54 + "XENBUS_FRONTEND_ID=%s", frontend_id); 1.55 + kfree(frontend_id); 1.56 + 1.57 /* terminate, set to next free slot, shrink available space */ 1.58 envp[i] = NULL; 1.59 envp = &envp[i]; 1.60 @@ -254,9 +281,9 @@ static int xenbus_hotplug_backend(struct 1.61 buffer = &buffer[length]; 1.62 buffer_size -= length; 1.63 1.64 - if (dev->driver && to_xenbus_driver(dev->driver)->hotplug) 1.65 - return to_xenbus_driver(dev->driver)->hotplug 1.66 - (xdev, envp, num_envp, buffer, buffer_size); 1.67 + if (drv && drv->hotplug) 1.68 + return drv->hotplug(xdev, envp, num_envp, buffer, 1.69 + buffer_size); 1.70 1.71 return 0; 1.72 }
2.1 --- a/tools/examples/block Fri Dec 02 15:39:13 2005 +0000 2.2 +++ b/tools/examples/block Fri Dec 02 15:48:44 2005 +0000 2.3 @@ -89,39 +89,54 @@ check_sharing() 2.4 fi 2.5 done 2.6 2.7 -## 2.8 -## XXX SMH: the below causes live migration on localhost to fail sometimes 2.9 -## since the source domain may still appear to be using a local device. 2.10 -## For now simply comment it out - a proper fix will come in due course. 2.11 + for dom in $(xenstore-list "$XENBUS_BASE_PATH") 2.12 + do 2.13 + for dev in $(xenstore-list "$XENBUS_BASE_PATH/$dom") 2.14 + do 2.15 + d=$(xenstore_read_default \ 2.16 + "$XENBUS_BASE_PATH/$dom/$dev/physical-device" "") 2.17 2.18 -# for file in /sys/devices/xen-backend/*/physical_device 2.19 -# do 2.20 -# if [ -e "$file" ] # Cope with no devices, i.e. the * above did not expand. 2.21 -# then 2.22 -# local d=$(cat "$file") 2.23 -# if [ "$d" == "$devmm" ] 2.24 -# then 2.25 -# if [ "$mode" == 'w' ] 2.26 -# then 2.27 -# echo 'guest' 2.28 -# return 2.29 -# else 2.30 -# local m=$(cat "${file/physical_device/mode}") 2.31 + if [ "$d" == "$devmm" ] 2.32 + then 2.33 + if [ "$mode" == 'w' ] 2.34 + then 2.35 + if ! same_vm $dom 2.36 + then 2.37 + echo 'guest' 2.38 + return 2.39 + fi 2.40 + else 2.41 + local m=$(xenstore_read "$XENBUS_BASE_PATH/$dom/$dev/mode") 2.42 + m=$(canonicalise_mode "$m") 2.43 2.44 -# if expr index "$m" 'w' >/dev/null 2.45 -# then 2.46 -# echo 'guest' 2.47 -# return 2.48 -# fi 2.49 -# fi 2.50 -# fi 2.51 -# fi 2.52 -# done 2.53 + if [ "$m" == 'w' ] 2.54 + then 2.55 + if ! same_vm $dom 2.56 + then 2.57 + echo 'guest' 2.58 + return 2.59 + fi 2.60 + fi 2.61 + fi 2.62 + fi 2.63 + done 2.64 + done 2.65 2.66 echo 'ok' 2.67 } 2.68 2.69 2.70 +same_vm() 2.71 +{ 2.72 + local thisdom="$XENBUS_FRONTEND_ID" 2.73 + local otherdom="$1" 2.74 + local thisvm=$(xenstore-read "/local/domain/$thisdom/vm") 2.75 + local othervm=$(xenstore-read "/local/domain/otherdom/vm") 2.76 + 2.77 + return [ "$thisvm" == "$othervm" ] 2.78 +} 2.79 + 2.80 + 2.81 ## 2.82 # check_device_sharing dev mode 2.83 # 2.84 @@ -200,6 +215,7 @@ do_ebusy() 2.85 m2='read-only ' 2.86 fi 2.87 2.88 + release_lock "block" 2.89 ebusy \ 2.90 "${prefix}${m1}in ${dom}domain, 2.91 and so cannot be mounted ${m2}${when}." 2.92 @@ -224,8 +240,10 @@ case "$command" in 2.93 case $t in 2.94 phy) 2.95 dev=$(expand_dev $p) 2.96 + claim_lock "block" 2.97 check_device_sharing "$dev" "$mode" 2.98 write_dev "$dev" 2.99 + release_lock "block" 2.100 exit 0 2.101 ;; 2.102 2.103 @@ -235,68 +253,62 @@ case "$command" in 2.104 file=$(readlink -f "$p") 2.105 mode=$(canonicalise_mode "$mode") 2.106 2.107 + claim_lock "block" 2.108 + 2.109 if [ "$mode" == 'w' ] && ! stat "$file" -c %A | grep -q w 2.110 then 2.111 + release_lock "block" 2.112 ebusy \ 2.113 "File $file is read-only, and so I will not 2.114 mount it read-write in a guest domain." 2.115 fi 2.116 2.117 + loopdev='' 2.118 + for dev in /dev/loop* 2.119 + do 2.120 + if [ ! -b "$dev" ] 2.121 + then 2.122 + continue 2.123 + fi 2.124 2.125 - while true 2.126 - do 2.127 - loopdev='' 2.128 - for dev in /dev/loop* 2.129 - do 2.130 - if [ ! -b "$dev" ] 2.131 + f=$(losetup "$dev" 2>/dev/null) || f='()' 2.132 + f=$(echo "$f" | sed -e 's/.*(\(.*\)).*/\1/g') 2.133 + 2.134 + if [ "$f" ] 2.135 + then 2.136 + # $dev is in use. Check sharing. 2.137 + if [ "$mode" == '!' ] 2.138 then 2.139 continue 2.140 fi 2.141 2.142 - f=$(losetup "$dev" 2>/dev/null) || f='()' 2.143 - f=$(echo "$f" | sed -e 's/.*(\(.*\)).*/\1/g') 2.144 + f=$(readlink -f "$f") 2.145 2.146 - log err "$file $f $dev" 2.147 - 2.148 - if [ "$f" ] 2.149 + if [ "$f" == "$file" ] 2.150 then 2.151 - # $dev is in use. Check sharing. 2.152 - if [ "$mode" == '!' ] 2.153 - then 2.154 - continue 2.155 - fi 2.156 - 2.157 - f=$(readlink -f "$f") 2.158 + check_file_sharing "$file" "$dev" "$mode" 2.159 + fi 2.160 + else 2.161 + # $dev is not in use, so we'll remember it for use later; we want 2.162 + # to finish the sharing check first. 2.163 2.164 - if [ "$f" == "$file" ] 2.165 - then 2.166 - check_file_sharing "$file" "$dev" "$mode" 2.167 - fi 2.168 - else 2.169 - # $dev is not in use, so we'll remember it for use later; we want 2.170 - # to finish the sharing check first. 2.171 - 2.172 - if [ "$loopdev" == '' ] 2.173 - then 2.174 - loopdev="$dev" 2.175 - fi 2.176 + if [ "$loopdev" == '' ] 2.177 + then 2.178 + loopdev="$dev" 2.179 fi 2.180 - done 2.181 + fi 2.182 + done 2.183 2.184 - if [ "$loopdev" == '' ] 2.185 - then 2.186 - fatal 'Failed to find an unused loop device' 2.187 - fi 2.188 - if losetup "$loopdev" "$file" 2.189 - then 2.190 - log err "mapped $file using $loopdev" 2.191 - xenstore_write "$XENBUS_PATH/node" "$loopdev" 2.192 - write_dev "$loopdev" 2.193 - exit 0 2.194 - else 2.195 - log err "losetup $loopdev $file failed, retry" 2.196 - fi 2.197 - done 2.198 + if [ "$loopdev" == '' ] 2.199 + then 2.200 + fatal 'Failed to find an unused loop device' 2.201 + fi 2.202 + 2.203 + do_or_die losetup "$loopdev" "$file" 2.204 + xenstore_write "$XENBUS_PATH/node" "$loopdev" 2.205 + write_dev "$loopdev" 2.206 + release_lock "block" 2.207 + exit 0 2.208 ;; 2.209 esac 2.210 ;;