Port-xen archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: xen-backend
Manuel Bouyer wrote:
On Sun, May 25, 2008 at 05:56:33PM +0200, Christoph Egger wrote:
I think, it is best to start with a (stupid) question:
When launching a PV guest with one disk and no vif,
what is the successful code-path from "xm create"
to the guest kernels boot message ?
Somewhere in between must be obviously the error.
I turned on all dom0 xen debug messages and all
what I get are debug messages from the xenbus_xs.c
From what I remeber, xm (or xend) creates the new domain's memory space
and loads it with the kernel, and create the new domain's entries (both
frontend and backend) in xenstore. Writing the backend values to xenstore
should trigger a call to *xenbus_create in backend drivers.
This will set a watch on the corresponding frontend entries, and switch the
backend state to XenbusStateInitWait. This should wakeup xenbackendd
which calls the scripts for the corresponding backends. The script
does whatever config is needed and writes to the store the informations for
the backend, and write the backend's "hotplug-status" entry to
"connected". I think writing hotplug-status is what cause xm or xend to
unpause the domU, which starts booting.
When I fill up src/sys/arch/xen/xenbus/xenbus_probe.c with debug code
(see attached diff), then *xenbus_create is called in backend drivers
and things go fine.
But without the debug code, *xenbus_create is never called and backend
state stays in XenbusStateInitialising.
What could be going on? Is there a timing problem? Is there a signal
delivery bug? Is there a gcc bug?
Christoph
--- xenbus_probe.c 2008-05-27 00:43:27.000000000 +0200
+++ xenbus_probe.c.new 2008-05-27 00:09:54.000000000 +0200
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.20 2008/04/16 18:41:48 cegger
Exp $");
-#if 0
+#if 1
#define DPRINTK(fmt, args...) \
printf("xenbus_probe (%s:%d) " fmt ".\n", __func__, __LINE__, ##args)
#else
@@ -105,6 +105,8 @@ xenbus_attach(device_t parent, device_t
void
xenbus_backend_register(struct xenbus_backend_driver *xbakd)
{
+printf("%s: check A\n", __func__);
+
SLIST_INSERT_HEAD(&xenbus_backend_driver_list, xbakd, xbakd_entries);
}
@@ -115,6 +117,7 @@ read_otherend_details(struct xenbus_devi
int err;
char *val, *ep;
+printf("%s: check A\n", __func__);
err = xenbus_read(NULL, xendev->xbusd_path, id_node, NULL, &val);
if (err) {
printf("reading other end details %s from %s\n",
@@ -124,6 +127,7 @@ read_otherend_details(struct xenbus_devi
id_node, xendev->xbusd_path);
return err;
}
+printf("%s: check B\n", __func__);
xendev->xbusd_otherend_id = strtoul(val, &ep, 10);
if (val[0] == '\0' || *ep != '\0') {
printf("reading other end details %s from %s: %s is not a
number\n", id_node, xendev->xbusd_path, val);
@@ -134,6 +138,7 @@ read_otherend_details(struct xenbus_devi
return EFTYPE;
}
free(val, M_DEVBUF);
+printf("%s: check C\n", __func__);
err = xenbus_read(NULL, xendev->xbusd_path, path_node, NULL, &val);
if (err) {
printf("reading other end details %s from %s (%d)\n",
@@ -143,6 +148,7 @@ read_otherend_details(struct xenbus_devi
path_node, xendev->xbusd_path);
return err;
}
+printf("%s: check D\n", __func__);
DPRINTK("read_otherend_details: read %s/%s returned %s\n",
xendev->xbusd_path, path_node, val);
xendev->xbusd_otherend = val;
@@ -157,12 +163,14 @@ read_otherend_details(struct xenbus_devi
return ENOENT;
}
+printf("%s: check E\n", __func__);
return 0;
}
static int
read_backend_details(struct xenbus_device *xendev)
{
+printf("%s: check A\n", __func__);
return read_otherend_details(xendev, "backend-id", "backend");
}
@@ -170,6 +178,7 @@ read_backend_details(struct xenbus_devic
static int
read_frontend_details(struct xenbus_device *xendev)
{
+printf("%s: check A\n", __func__);
return read_otherend_details(xendev, "frontend-id", "frontend");
}
@@ -186,11 +195,14 @@ free_otherend_details(struct xenbus_devi
static void
free_otherend_watch(struct xenbus_device *dev)
{
+printf("%s: check A\n", __func__);
if (dev->xbusd_otherend_watch.node) {
+printf("%s: check B\n", __func__);
unregister_xenbus_watch(&dev->xbusd_otherend_watch);
free(dev->xbusd_otherend_watch.node, M_DEVBUF);
dev->xbusd_otherend_watch.node = NULL;
}
+printf("%s: check C\n", __func__);
}
static void
@@ -200,6 +212,8 @@ otherend_changed(struct xenbus_watch *wa
struct xenbus_device *xdev = watch->xbw_dev;
XenbusState state;
+printf("%s: check A\n", __func__);
+
/* Protect us against watches firing on old details when the otherend
details change, say immediately after a resume. */
if (!xdev->xbusd_otherend ||
@@ -209,6 +223,7 @@ otherend_changed(struct xenbus_watch *wa
return;
}
+printf("%s: check B\n", __func__);
state = xenbus_read_driver_state(xdev->xbusd_otherend);
DPRINTK("state is %d, %s, %s",
@@ -235,15 +250,18 @@ otherend_changed(struct xenbus_watch *wa
xenbus_free_device(xdev);
return;
}
+printf("%s: check C\n", __func__);
if (xdev->xbusd_otherend_changed)
xdev->xbusd_otherend_changed(
(xdev->xbusd_type == XENBUS_BACKEND_DEVICE) ?
xdev->xbusd_u.b.b_cookie : xdev->xbusd_u.f.f_dev, state);
+printf("%s: check D\n", __func__);
}
static int
talk_to_otherend(struct xenbus_device *dev)
{
+printf("%s: check A\n", __func__);
free_otherend_watch(dev);
return xenbus_watch_path2(dev, dev->xbusd_otherend, "state",
@@ -256,10 +274,12 @@ xenbus_lookup_device_path(const char *pa
{
struct xenbus_device *xbusd;
+printf("%s: check A\n", __func__);
SLIST_FOREACH(xbusd, &xenbus_device_list, xbusd_entries) {
if (strcmp(xbusd->xbusd_path, path) == 0)
return xbusd;
}
+printf("%s: check B\n", __func__);
return NULL;
}
@@ -275,12 +295,14 @@ xenbus_probe_device_type(const char *pat
struct xenbusdev_attach_args xa;
char *ep;
+printf("%s: check A\n", __func__);
DPRINTK("probe %s type %s", path, type);
err = xenbus_directory(NULL, path, "", &dir_n, &dir);
DPRINTK("directory err %d dir_n %d", err, dir_n);
if (err)
return err;
+printf("%s: check B\n", __func__);
for (i = 0; i < dir_n; i++) {
/*
* add size of path to size of xenbus_device. xenbus_device
@@ -356,6 +378,7 @@ xenbus_probe_device_type(const char *pat
xbusd, xbusd_entries);
talk_to_otherend(xbusd);
}
+printf("%s: check C\n", __func__);
free(dir, M_DEVBUF);
return err;
}
@@ -365,7 +388,9 @@ xenbus_print(void *aux, const char *pnp)
{
struct xenbusdev_attach_args *xa = aux;
+printf("%s: check A\n", __func__);
if (pnp) {
+printf("%s: check B\n", __func__);
if (strcmp(xa->xa_type, "vbd") == 0)
aprint_normal("xbd");
else if (strcmp(xa->xa_type, "vif") == 0)
@@ -374,6 +399,7 @@ xenbus_print(void *aux, const char *pnp)
aprint_normal("unknown type %s", xa->xa_type);
aprint_normal(" at %s", pnp);
}
+printf("%s: check C\n", __func__);
aprint_normal(" id %d", xa->xa_id);
return(UNCONF);
}
@@ -386,18 +412,21 @@ xenbus_probe_frontends(void)
unsigned int i, dir_n;
char path[30];
+printf("%s: check A\n", __func__);
DPRINTK("probe device");
err = xenbus_directory(NULL, "device", "", &dir_n, &dir);
DPRINTK("directory err %d dir_n %d", err, dir_n);
if (err)
return err;
+printf("%s: check B\n", __func__);
for (i = 0; i < dir_n; i++) {
snprintf(path, sizeof(path), "device/%s", dir[i]);
err = xenbus_probe_device_type(path, dir[i], NULL);
if (err)
break;
}
+printf("%s: check C\n", __func__);
free(dir, M_DEVBUF);
return err;
}
@@ -411,12 +440,14 @@ xenbus_probe_backends(void)
char path[30];
struct xenbus_backend_driver *xbakd;
+printf("%s: check A\n", __func__);
DPRINTK("probe backend");
err = xenbus_directory(NULL, "backend", "", &dirt_n, &dirt);
DPRINTK("directory err %d dirt_n %d", err, dirt_n);
if (err)
return err;
+printf("%s: check B\n", __func__);
for (type = 0; type < dirt_n; type++) {
SLIST_FOREACH(xbakd, &xenbus_backend_driver_list,
xbakd_entries) {
@@ -443,6 +474,7 @@ xenbus_probe_backends(void)
}
free(dirid, M_DEVBUF);
}
+printf("%s: check C\n", __func__);
free(dirt, M_DEVBUF);
return err;
}
@@ -450,6 +482,7 @@ xenbus_probe_backends(void)
int
xenbus_free_device(struct xenbus_device *xbusd)
{
+printf("%s: check A\n", __func__);
KASSERT(xenbus_lookup_device_path(xbusd->xbusd_path) == xbusd);
SLIST_REMOVE(&xenbus_device_list, xbusd, xenbus_device, xbusd_entries);
free_otherend_watch(xbusd);
@@ -463,6 +496,7 @@ static void
frontend_changed(struct xenbus_watch *watch,
const char **vec, unsigned int len)
{
+printf("%s: check A\n", __func__);
DPRINTK("frontend_changed %s\n", vec[XS_WATCH_PATH]);
xenbus_probe_frontends();
}
@@ -471,6 +505,7 @@ static void
backend_changed(struct xenbus_watch *watch,
const char **vec, unsigned int len)
{
+printf("%s: check A\n", __func__);
DPRINTK("backend_changed %s\n", vec[XS_WATCH_PATH]);
xenbus_probe_backends();
}
@@ -487,12 +522,17 @@ int xenstored_ready = 0;
void
xenbus_probe(void *unused)
{
+printf("%s: check A\n", __func__);
+
KASSERT((xenstored_ready > 0));
+printf("%s: check B\n", __func__);
/* Enumerate devices in xenstore. */
xenbus_probe_frontends();
+printf("%s: check C\n", __func__);
xenbus_probe_backends();
+printf("%s: check D\n", __func__);
/* Watch for changes. */
fe_watch.node = malloc(strlen("device" + 1), M_DEVBUF, M_NOWAIT);
strcpy(fe_watch.node, "device");
@@ -504,6 +544,7 @@ xenbus_probe(void *unused)
register_xenbus_watch(&be_watch);
shutdown_xenbus_setup();
+printf("%s: check E\n", __func__);
/* Notify others that xenstore is up */
//notifier_call_chain(&xenstore_chain, 0, NULL);
}
@@ -513,6 +554,7 @@ xenbus_probe_init(void *unused)
{
int err = 0, dom0;
+printf("%s: check A\n", __func__);
DPRINTK("");
SLIST_INIT(&xenbus_device_list);
@@ -522,6 +564,7 @@ xenbus_probe_init(void *unused)
*/
dom0 = (xen_start_info.store_evtchn == 0);
if (dom0) {
+printf("%s: check B1\n", __func__);
#if defined(DOM0OPS)
vaddr_t page;
paddr_t ma;
@@ -548,16 +591,20 @@ xenbus_probe_init(void *unused)
panic("can't register xenstore event");
xen_start_info.store_evtchn = op.u.alloc_unbound.port;
+printf("%s: check B2\n", __func__);
/* And finally publish the above info in /kern/xen */
xenbus_kernfs_init();
#else /* DOM0OPS */
+printf("%s: check B3\n", __func__);
return ; /* can't get a working xenstore in this case */
#endif /* DOM0OPS */
}
+printf("%s: check C\n", __func__);
/* register event handler */
xb_init_comms(xenbus_sc);
+printf("%s: check D\n", __func__);
/* Initialize the interface to xenstore. */
err = xs_init();
if (err) {
@@ -565,24 +612,30 @@ xenbus_probe_init(void *unused)
kthread_exit(err);
}
+printf("%s: check E\n", __func__);
if (!dom0) {
+printf("%s: check E1\n", __func__);
xenstored_ready = 1;
xenbus_probe(NULL);
}
+printf("%s: check F\n", __func__);
DPRINTK("done");
config_pending_decr();
#ifdef DOM0OPS
if (dom0) {
int s;
+printf("%s: check F1\n", __func__);
s = spltty();
while (xenstored_ready == 0) {
tsleep(&xenstored_ready, PRIBIO, "xsready", 0);
xenbus_probe(NULL);
}
splx(s);
+printf("%s: check F2\n", __func__);
}
#endif
+printf("%s: check G\n", __func__);
kthread_exit(0);
}
Home |
Main Index |
Thread Index |
Old Index