aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-04-17 22:21:38 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-27 12:51:05 -0400
commit06a3bbbe704048f4f8b08a0aea32418299c67555 (patch)
tree81f32e0f41c2049b395819cddadd68a5bfd8aa59
parent7e2ec6cfa0c831986c602f136b5c88ed4d252dfe (diff)
xen/xenbus: Add quirk to deal with misconfigured backends.
commit 3066616ce23aad5719c23a0f21f32676402cb44b upstream. A rather annoying and common case is when booting a PVonHVM guest and exposing the PV KBD and PV VFB - as broken toolstacks don't always initialize the backends correctly. Normally The HVM guest is using the VGA driver and the emulated keyboard for this (though upstream version of QEMU implements PV KBD, but still uses a VGA driver). We provide a very basic two-stage wait mechanism - where we wait for 30 seconds for all devices, and then for 270 for all them except the two mentioned. That allows us to wait for the essential devices, like network or disk for the full 6 minutes. To trigger this, put this in your guest config: vfb = [ 'vnc=1, vnclisten=0.0.0.0 ,vncunused=1'] instead of this: vnc=1 vnclisten="0.0.0.0" Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> [v3: Split delay in non-essential (30 seconds) and essential devices per Ian and Stefano suggestion] [v4: Added comments per Stefano suggestion] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/xen/xenbus/xenbus_probe_frontend.c69
1 files changed, 53 insertions, 16 deletions
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index b6a2690c9d4..560f2176aa6 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -132,7 +132,7 @@ static int read_backend_details(struct xenbus_device *xendev)
132 return xenbus_read_otherend_details(xendev, "backend-id", "backend"); 132 return xenbus_read_otherend_details(xendev, "backend-id", "backend");
133} 133}
134 134
135static int is_device_connecting(struct device *dev, void *data) 135static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential)
136{ 136{
137 struct xenbus_device *xendev = to_xenbus_device(dev); 137 struct xenbus_device *xendev = to_xenbus_device(dev);
138 struct device_driver *drv = data; 138 struct device_driver *drv = data;
@@ -149,16 +149,41 @@ static int is_device_connecting(struct device *dev, void *data)
149 if (drv && (dev->driver != drv)) 149 if (drv && (dev->driver != drv))
150 return 0; 150 return 0;
151 151
152 if (ignore_nonessential) {
153 /* With older QEMU, for PVonHVM guests the guest config files
154 * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0']
155 * which is nonsensical as there is no PV FB (there can be
156 * a PVKB) running as HVM guest. */
157
158 if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0))
159 return 0;
160
161 if ((strncmp(xendev->nodename, "device/vfb", 10) == 0))
162 return 0;
163 }
152 xendrv = to_xenbus_driver(dev->driver); 164 xendrv = to_xenbus_driver(dev->driver);
153 return (xendev->state < XenbusStateConnected || 165 return (xendev->state < XenbusStateConnected ||
154 (xendev->state == XenbusStateConnected && 166 (xendev->state == XenbusStateConnected &&
155 xendrv->is_ready && !xendrv->is_ready(xendev))); 167 xendrv->is_ready && !xendrv->is_ready(xendev)));
156} 168}
169static int essential_device_connecting(struct device *dev, void *data)
170{
171 return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */);
172}
173static int non_essential_device_connecting(struct device *dev, void *data)
174{
175 return is_device_connecting(dev, data, false);
176}
157 177
158static int exists_connecting_device(struct device_driver *drv) 178static int exists_essential_connecting_device(struct device_driver *drv)
159{ 179{
160 return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv, 180 return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
161 is_device_connecting); 181 essential_device_connecting);
182}
183static int exists_non_essential_connecting_device(struct device_driver *drv)
184{
185 return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
186 non_essential_device_connecting);
162} 187}
163 188
164static int print_device_status(struct device *dev, void *data) 189static int print_device_status(struct device *dev, void *data)
@@ -189,6 +214,23 @@ static int print_device_status(struct device *dev, void *data)
189/* We only wait for device setup after most initcalls have run. */ 214/* We only wait for device setup after most initcalls have run. */
190static int ready_to_wait_for_devices; 215static int ready_to_wait_for_devices;
191 216
217static bool wait_loop(unsigned long start, unsigned int max_delay,
218 unsigned int *seconds_waited)
219{
220 if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) {
221 if (!*seconds_waited)
222 printk(KERN_WARNING "XENBUS: Waiting for "
223 "devices to initialise: ");
224 *seconds_waited += 5;
225 printk("%us...", max_delay - *seconds_waited);
226 if (*seconds_waited == max_delay)
227 return true;
228 }
229
230 schedule_timeout_interruptible(HZ/10);
231
232 return false;
233}
192/* 234/*
193 * On a 5-minute timeout, wait for all devices currently configured. We need 235 * On a 5-minute timeout, wait for all devices currently configured. We need
194 * to do this to guarantee that the filesystems and / or network devices 236 * to do this to guarantee that the filesystems and / or network devices
@@ -212,19 +254,14 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
212 if (!ready_to_wait_for_devices || !xen_domain()) 254 if (!ready_to_wait_for_devices || !xen_domain())
213 return; 255 return;
214 256
215 while (exists_connecting_device(drv)) { 257 while (exists_non_essential_connecting_device(drv))
216 if (time_after(jiffies, start + (seconds_waited+5)*HZ)) { 258 if (wait_loop(start, 30, &seconds_waited))
217 if (!seconds_waited) 259 break;
218 printk(KERN_WARNING "XENBUS: Waiting for " 260
219 "devices to initialise: "); 261 /* Skips PVKB and PVFB check.*/
220 seconds_waited += 5; 262 while (exists_essential_connecting_device(drv))
221 printk("%us...", 300 - seconds_waited); 263 if (wait_loop(start, 270, &seconds_waited))
222 if (seconds_waited == 300) 264 break;
223 break;
224 }
225
226 schedule_timeout_interruptible(HZ/10);
227 }
228 265
229 if (seconds_waited) 266 if (seconds_waited)
230 printk("\n"); 267 printk("\n");