Register a non-enumerating watch for type qdisk when XEN_DATAPATH_ONLY

From: Tim Smith <tim.smith@citrix.com>

The watch for everything of type qdisk results in a large number of
events, particularly when activating a lot of disks on a guest. Then
each of those events causes a complete enumeration of the entire bus,
which is an ever-increasing load on the Xenstore implementation.

Instead, register a watch which does not perform this complete enumeration.
---
 hw/xen/xen-bus.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index 19f20c6608..5dbc42ae64 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -423,6 +423,15 @@ static void xen_bus_backend_changed(void *opaque)
     xen_bus_cleanup(xenbus);
 }
 
+#ifdef CONFIG_XEN_DATAPATH_ONLY
+static void xen_bus_backend_changed_noenumerate(void *opaque)
+{
+    XenBus *xenbus = opaque;
+
+    xen_bus_cleanup(xenbus);
+}
+#endif /* CONFIG_XEN_DATAPATH_ONLY */
+
 static void xen_bus_unrealize(BusState *bus)
 {
     XenBus *xenbus = XEN_BUS(bus);
@@ -485,9 +494,17 @@ static void xen_bus_realize(BusState *bus, Error **errp)
 
     for (i = 0; i < xenbus->backend_types; i++) {
         char *node = g_strdup_printf("backend/%s", type[i]);
-
+        XenWatchHandler handler = xen_bus_backend_changed;
+#ifdef CONFIG_XEN_DATAPATH_ONLY
+        /* If it's type "qdisk", set up a type watch which won't enumerate the entire bus
+		   so that when we add a couple of hundred disks to a guest it doesn't start taking 20
+		   minutes to get a disk attached and make the xenstore process eat all the CPU. */
+        if (!strcmp(type[i], "qdisk")) {
+            handler = xen_bus_backend_changed_noenumerate;
+        }
+#endif /* CONFIG_XEN_DATAPATH_ONLY */
         xenbus->backend_watch[i] =
-            xen_bus_add_watch(xenbus, node, key, xen_bus_backend_changed,
+            xen_bus_add_watch(xenbus, node, key, handler,
                               &local_err);
         if (local_err) {
             /* This need not be treated as a hard error so don't propagate */
