[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] Re: [PATCH] reset PV devices in crash kernel
On Fri, Feb 04, Olaf Hering wrote: Ping? Can this and the reset_devices patch be applied to the 2.6.18 tree? Olaf > > After triggering a crash dump in a HVM guest, the PV backend drivers > will remain in connected state. When the kdump kernel starts the PV > drivers will skip such devices. As a result, no root device is found > and the vmcore cant be saved. > > With this change all frontend devices with state XenbusStateConnected > will be reset by changing the state file to Closing/Closed/Initializing. > This will trigger a disconnect in the backend drivers. Now the frontend > drivers will find the backend drivers in state Initwait and can connect. > > Signed-off-by: Olaf Hering <olaf@xxxxxxxxx> > > --- > drivers/xen/xenbus/xenbus_comms.c | 4 + > drivers/xen/xenbus/xenbus_probe.c | 96 > ++++++++++++++++++++++++++++++++++++++ > 2 files changed, 99 insertions(+), 1 deletion(-) > > --- linux-2.6.18-xen.hg.orig/drivers/xen/xenbus/xenbus_comms.c > +++ linux-2.6.18-xen.hg/drivers/xen/xenbus/xenbus_comms.c > @@ -234,7 +234,9 @@ int xb_init_comms(void) > printk(KERN_WARNING "XENBUS response ring is not quiescent " > "(%08x:%08x): fixing up\n", > intf->rsp_cons, intf->rsp_prod); > - intf->rsp_cons = intf->rsp_prod; > + /* breaks kdump */ > + if (!reset_devices) > + intf->rsp_cons = intf->rsp_prod; > } > > if (xenbus_irq) > --- linux-2.6.18-xen.hg.orig/drivers/xen/xenbus/xenbus_probe.c > +++ linux-2.6.18-xen.hg/drivers/xen/xenbus/xenbus_probe.c > @@ -854,11 +854,107 @@ void unregister_xenstore_notifier(struct > } > EXPORT_SYMBOL_GPL(unregister_xenstore_notifier); > > +#ifdef CONFIG_CRASH_DUMP > +static DECLARE_WAIT_QUEUE_HEAD(be_state_wq); > +static int be_state; > + > +static void xenbus_reset_state_changed(struct xenbus_watch *w, const char > **v, unsigned int l) > +{ > + xenbus_scanf(XBT_NIL, v[XS_WATCH_PATH], "", "%i", &be_state); > + printk(KERN_INFO "XENBUS: %s %s", v[XS_WATCH_PATH], > xenbus_strstate(be_state)); > + wake_up(&be_state_wq); > +} > + > +static int xenbus_reset_check_final(int *st) > +{ > + return *st == XenbusStateInitialising || *st == XenbusStateInitWait; > +} > + > +static void xenbus_reset_frontend_state(char *backend, char *frontend) > +{ > + struct xenbus_watch watch; > + > + memset(&watch, 0, sizeof(watch)); > + watch.node = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/state", backend); > + if (!watch.node) > + return; > + > + watch.callback = xenbus_reset_state_changed; > + be_state = XenbusStateUnknown; > + > + printk(KERN_INFO "triggering reconnect on %s", backend); > + register_xenbus_watch(&watch); > + > + xenbus_printf(XBT_NIL, frontend, "state", "%d", XenbusStateClosing); > + wait_event_interruptible(be_state_wq, be_state == XenbusStateClosing); > + > + xenbus_printf(XBT_NIL, frontend, "state", "%d", XenbusStateClosed); > + wait_event_interruptible(be_state_wq, be_state == XenbusStateClosed); > + > + xenbus_printf(XBT_NIL, frontend, "state", "%d", > XenbusStateInitialising); > + wait_event_interruptible(be_state_wq, > xenbus_reset_check_final(&be_state)); > + > + unregister_xenbus_watch(&watch); > + printk(KERN_INFO "reconnect done on %s", backend); > + kfree(watch.node); > +} > + > +static void xenbus_reset_check_state(char *frontend) > +{ > + int state, err; > + char *backend; > + > + err = xenbus_scanf(XBT_NIL, frontend, "state", "%i", &state); > + /* frontend connected? */ > + if (err == 1 && state == XenbusStateConnected) { > + backend = xenbus_read(XBT_NIL, frontend, "backend", NULL); > + if (!backend || IS_ERR(backend)) > + return; > + err = xenbus_scanf(XBT_NIL, backend, "state", "%i", &state); > + /* backend connected? */ > + if (err == 1 && state == XenbusStateConnected) > + xenbus_reset_frontend_state(backend, frontend); > + kfree(backend); > + } > +} > + > +static void xenbus_reset_state(void) > +{ > + char *frontend; > + char **devclass, **dev; > + int devclass_n, dev_n; > + int i, j; > + > + devclass = xenbus_directory(XBT_NIL, "device", "", &devclass_n); > + if (IS_ERR(devclass)) > + return; > + > + for (i = 0; i < devclass_n; i++) { > + dev = xenbus_directory(XBT_NIL, "device", devclass[i], &dev_n); > + if (IS_ERR(dev)) > + continue; > + for (j = 0; j < dev_n; j++) { > + frontend = kasprintf(GFP_NOIO|__GFP_HIGH, > "device/%s/%s", devclass[i], dev[j]); > + if (!frontend) > + continue; > + xenbus_reset_check_state(frontend); > + kfree(frontend); > + } > + kfree(dev); > + } > + kfree(devclass); > +} > +#endif > > void xenbus_probe(void *unused) > { > BUG_ON(!is_xenstored_ready()); > > +#ifdef CONFIG_CRASH_DUMP > + /* reset devices in XenbusStateConnected state */ > + if (!is_initial_xendomain() && reset_devices) > + xenbus_reset_state(); > +#endif > /* Enumerate devices in xenstore and watch for changes. */ > xenbus_probe_devices(&xenbus_frontend); > register_xenbus_watch(&fe_watch); _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |