We found problems while removing the netfront device in a guest kernel.
Here follows a first solution attempt, and comments are very welcome.
A more detailed description can be found in the commit log.
Thanks,
--
Glauber de Oliveira Costa
Red Hat Inc.
"Free as in Freedom"
# HG changeset patch
# User gcosta@xxxxxxxxxx
# Date 1163770243 18000
# Node ID 47fcd5f768fef50cba2fc6dbadc7b75de55e88a5
# Parent 822e0f23a8cb17be0457d6b030af2a4fe6c4d7de
[LINUX] netfront module not beging able to be rmmod'd
Current attempts to remove the netfront module leads to BUG()s
being triggered. It is because the call path of a module removal
is different from device detach via backend. In the former,
netfront_closing() (which unregisters the device) is never called.
Solution is to call the proper deinitialization routines in module
removal, in case they were not called before (dev->state !=
XenbusStateClosed). At this point, backend still holds gnttab entries,
and we wait for it to finish (while at be level, it frees the proper
structures and releases the entries).
Last, doing it leaves the device in state 6 in the backend. When
initializing again, we change our state to XenbusStateInitialising,
forcing the backend to see it and start init negotiation again
Signed-off-by: Glauber de Oliveira Costa <gcosta@xxxxxxxxxx>
diff -r 822e0f23a8cb -r 47fcd5f768fe
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Nov 17 07:53:00
2006 -0500
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Nov 17 08:30:43
2006 -0500
@@ -242,6 +242,10 @@ static void frontend_changed(struct xenb
case XenbusStateClosed:
xenbus_switch_state(dev, XenbusStateClosed);
+ if (be->netif) {
+ netif_disconnect(be->netif);
+ be->netif = NULL;
+ }
if (xenbus_dev_is_online(dev))
break;
/* fall through if not online */
diff -r 822e0f23a8cb -r 47fcd5f768fe
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Nov 17
07:53:00 2006 -0500
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Nov 17
08:30:43 2006 -0500
@@ -501,6 +501,11 @@ static int setup_device(struct xenbus_de
info->irq = err;
return 0;
+ /* backend will ignore this state change unless it's currently in
+ * Closed state. But then, we wan't it to reconnect, since we're now
+ * back */
+ xenbus_switch_state(dev, XenbusStateInitialising);
+
fail:
return err;
}
@@ -2014,8 +2019,21 @@ static int __devexit netfront_remove(str
static int __devexit netfront_remove(struct xenbus_device *dev)
{
struct netfront_info *info = dev->dev.driver_data;
+ unsigned long timeout = jiffies + 2*HZ;
DPRINTK("%s\n", dev->nodename);
+ if ( dev->state != XenbusStateClosed ){
+ close_netdev(info);
+ xenbus_frontend_closed(dev);
+ }
+
+ /* Give a chance for the foreing access to end in a reasonable ammount
of time
+ * if it's still happening, there is little we can do here */
+ while ( gnttab_query_foreign_access(info->rx_ring_ref) ){
+ if ( time_after(jiffies, timeout) )
+ break;
+ schedule_timeout_interruptible(HZ/10);
+ }
netif_disconnect_backend(info);
free_netdev(info->netdev);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|