[PATCH] introduce frontend suspend_cancel mechanism

liuyingdong liuyingdong at huawei.com
Tue Dec 13 13:51:38 UTC 2016


Hello Roger,
     I introduce frontend suspend_cancel mechanism.If there are something need to be modified please let me know, thanks.
     On the base of the origin/release/10.2.0 branch, I make a patch file as fellows:

Signed-off-by: Yingdong Liu<liuyingdong at huawei.com>

 sys/dev/xen/blkfront/blkfront.c | 13 +++++++++++
 sys/dev/xen/control/control.c   |  9 ++++++-
 sys/dev/xen/netfront/netfront.c | 52 ++++++++++++++++++++++++++++++-----------
 sys/x86/xen/hvm.c               | 16 ++++++++-----
 sys/xen/xenbus/xenbusb.c        | 45 ++++++++++++++++++++++-------------
 sys/xen/xenbus/xenbusvar.h      |  4 ++++
 6 files changed, 102 insertions(+), 37 deletions(-)

diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c
index a71251d..8d7c32a 100644
--- a/sys/dev/xen/blkfront/blkfront.c
+++ b/sys/dev/xen/blkfront/blkfront.c
@@ -68,6 +68,8 @@ __FBSDID("$FreeBSD$");

 #include "xenbus_if.h"

+static int blkfront_suspend_cancelled = 0;
+
 /*--------------------------- Forward Declarations ---------------------------*/
 static void xbd_closing(device_t);
 static void xbd_startio(struct xbd_softc *sc);
@@ -1417,10 +1419,21 @@ xbd_suspend(device_t dev)
 	return (retval);
 }

+void xbd_set_suspend_cancel(void)
+{
+	blkfront_suspend_cancelled = 1;
+}
+
 static int
 xbd_resume(device_t dev)
 {
 	struct xbd_softc *sc = device_get_softc(dev);
+	
+	if(blkfront_suspend_cancelled == 1) {
+		sc->xbd_state = XBD_STATE_CONNECTED;
+		blkfront_suspend_cancelled = 0;
+		return (0);
+	}

 	DPRINTK("xbd_resume: %s\n", xenbus_get_node(dev));

diff --git a/sys/dev/xen/control/control.c b/sys/dev/xen/control/control.c
index bc0609d..b500100 100644
--- a/sys/dev/xen/control/control.c
+++ b/sys/dev/xen/control/control.c
@@ -400,7 +400,9 @@ xctrl_suspend()
 	/*
 	 * Reset grant table info.
 	 */
-	gnttab_resume();
+	if(suspend_cancelled == 0) {
+		gnttab_resume();
+	}

 #ifdef SMP
 	if (smp_started && !CPU_EMPTY(&cpu_suspend_map)) {
@@ -416,6 +418,11 @@ xctrl_suspend()
 	 * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or
 	 * similar.
 	 */
+	if(suspend_cancelled == 1) {
+		xenbusb_set_suspend_cancel();
+		xbd_set_suspend_cancel();
+		xn_set_suspend_cancel();
+	}
 	mtx_lock(&Giant);
 	DEVICE_RESUME(root_bus);
 	mtx_unlock(&Giant);
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index d89c0e0..0caaa2c 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -98,6 +98,8 @@ __FBSDID("$FreeBSD$");
 #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
 #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)

+static int netfront_suspend_cancelled = 0;
+
 #if __FreeBSD_version >= 700000
 /*
  * Should the driver do LRO on the RX end
@@ -192,6 +194,10 @@ static int xennet_get_responses(struct netfront_info *np,
 	struct netfront_rx_info *rinfo, RING_IDX rp, RING_IDX *cons,
 	struct mbuf **list, int *pages_flipped_p);

+#ifdef INET
+static void netfront_send_fake_arp(device_t dev, struct netfront_info *info);
+#endif
+
 #define virt_to_mfn(x) (vtomach(x) >> PAGE_SHIFT)

 #define INVALID_P2M_ENTRY (~0UL)
@@ -493,6 +499,11 @@ netfront_suspend(device_t dev)
 	return (0);
 }

+void xn_set_suspend_cancel(void)
+{
+	netfront_suspend_cancelled = 1;
+}
+
 /**
  * We are reconnecting to the backend, due to a suspend/resume, or a backend
  * driver restart.  We tear down our netif structure and recreate it, but
@@ -504,6 +515,19 @@ netfront_resume(device_t dev)
 {
 	struct netfront_info *info = device_get_softc(dev);

+	if(netfront_suspend_cancelled == 1) {
+		info->xn_resume = true;
+		XN_RX_LOCK(info);
+		XN_TX_LOCK(info);
+		netfront_carrier_on(info);
+		XN_TX_UNLOCK(info);
+		XN_RX_UNLOCK(info);
+#ifdef INET
+		netfront_send_fake_arp(dev, info);
+#endif
+		netfront_suspend_cancelled = 0;
+		return (0);
+	}
 	info->xn_resume = true;
 	netif_disconnect_backend(info);
 	return (0);
@@ -2108,26 +2132,26 @@ create_netdev(device_t dev)
 	
 	/* Set up ifnet structure */
 	ifp = np->xn_ifp = if_alloc(IFT_ETHER);
-    	ifp->if_softc = np;
-    	if_initname(ifp, "xn",  device_get_unit(dev));
-    	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-    	ifp->if_ioctl = xn_ioctl;
-    	ifp->if_output = ether_output;
-    	ifp->if_start = xn_start;
+	ifp->if_softc = np;
+	if_initname(ifp, "xn",  device_get_unit(dev));
+	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	ifp->if_ioctl = xn_ioctl;
+	ifp->if_output = ether_output;
+	ifp->if_start = xn_start;
 #ifdef notyet
-    	ifp->if_watchdog = xn_watchdog;
+	ifp->if_watchdog = xn_watchdog;
 #endif
-    	ifp->if_init = xn_ifinit;
-    	ifp->if_snd.ifq_maxlen = NET_TX_RING_SIZE - 1;
-	
-    	ifp->if_hwassist = XN_CSUM_FEATURES;
-    	ifp->if_capabilities = IFCAP_HWCSUM;
+	ifp->if_init = xn_ifinit;
+	ifp->if_snd.ifq_maxlen = NET_TX_RING_SIZE - 1;
+
+	ifp->if_hwassist = XN_CSUM_FEATURES;
+	ifp->if_capabilities = IFCAP_HWCSUM;
 	ifp->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
 	ifp->if_hw_tsomaxsegcount = MAX_TX_REQ_FRAGS;
 	ifp->if_hw_tsomaxsegsize = PAGE_SIZE;
 	
-    	ether_ifattach(ifp, np->mac);
-    	callout_init(&np->xn_stat_ch, CALLOUT_MPSAFE);
+	ether_ifattach(ifp, np->mac);
+	callout_init(&np->xn_stat_ch, CALLOUT_MPSAFE);
 	netfront_carrier_off(np);

 	return (0);
diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c
index c386953..1c2ba9d 100644
--- a/sys/x86/xen/hvm.c
+++ b/sys/x86/xen/hvm.c
@@ -517,10 +517,9 @@ xen_hvm_init(enum xen_hvm_init_type init_type)
 	int error;
 	int i;

-	if (init_type == XEN_HVM_INIT_CANCELLED_SUSPEND)
-		return;
-
-	error = xen_hvm_init_hypercall_stubs();
+	if (init_type != XEN_HVM_INIT_CANCELLED_SUSPEND) {
+		error = xen_hvm_init_hypercall_stubs();
+	}

 	switch (init_type) {
 	case XEN_HVM_INIT_COLD:
@@ -541,13 +540,17 @@ xen_hvm_init(enum xen_hvm_init_type init_type)
 		CPU_FOREACH(i)
 			DPCPU_ID_SET(i, vcpu_info, NULL);
 		break;
+	case XEN_HVM_INIT_CANCELLED_SUSPEND:
+		break;
 	default:
 		panic("Unsupported HVM initialization type");
 	}

 	xen_vector_callback_enabled = 0;
 	xen_domain_type = XEN_HVM_DOMAIN;
-	xen_hvm_init_shared_info_page();
+	if (init_type != XEN_HVM_INIT_CANCELLED_SUSPEND) {
+		xen_hvm_init_shared_info_page();
+	}
 	xen_hvm_set_callback(NULL);
 	xen_hvm_disable_emulated_devices();
 }
@@ -565,7 +568,8 @@ xen_hvm_resume(bool suspend_cancelled)
 	    XEN_HVM_INIT_CANCELLED_SUSPEND : XEN_HVM_INIT_RESUME);

 	/* Register vcpu_info area for CPU#0. */
-	xen_hvm_cpu_init();
+	if(!suspend_cancelled)
+		xen_hvm_cpu_init();
 }

 static void
diff --git a/sys/xen/xenbus/xenbusb.c b/sys/xen/xenbus/xenbusb.c
index 1f84795..cce83cd 100644
--- a/sys/xen/xenbus/xenbusb.c
+++ b/sys/xen/xenbus/xenbusb.c
@@ -75,6 +75,8 @@ __FBSDID("$FreeBSD$");
 #include <xen/xenbus/xenbusb.h>
 #include <xen/xenbus/xenbusvar.h>

+static int xenbusb_suspend_cancelled = 0;
+
 /*------------------------- Private Functions --------------------------------*/
 /**
  * \brief Deallocate XenBus device instance variables.
@@ -776,6 +778,11 @@ xenbusb_attach(device_t dev, char *bus_node, u_int id_components)
 	return (0);
 }

+void xenbusb_set_suspend_cancel(void)
+{
+	xenbusb_suspend_cancelled = 1;
+}
+
 int
 xenbusb_resume(device_t dev)
 {
@@ -793,29 +800,32 @@ xenbusb_resume(device_t dev)
 			if (device_get_state(kids[i]) == DS_NOTPRESENT)
 				continue;

-			ivars = device_get_ivars(kids[i]);
+			if(xenbusb_suspend_cancelled == 0) {
+				ivars = device_get_ivars(kids[i]);

-			xs_unregister_watch(&ivars->xd_otherend_watch);
-			xenbus_set_state(kids[i], XenbusStateInitialising);
+				xs_unregister_watch(&ivars->xd_otherend_watch);
+				xenbus_set_state(kids[i], XenbusStateInitialising);

-			/*
-			 * Find the new backend details and
-			 * re-register our watch.
-			 */
-			error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
-			if (error)
-				return (error);
+				/*
+				 * Find the new backend details and
+				 * re-register our watch.
+				 */
+				error = XENBUSB_GET_OTHEREND_NODE(dev, ivars);
+				if (error)
+					return (error);

-			statepath = malloc(ivars->xd_otherend_path_len
-			    + strlen("/state") + 1, M_XENBUS, M_WAITOK);
-			sprintf(statepath, "%s/state", ivars->xd_otherend_path);
+				statepath = malloc(ivars->xd_otherend_path_len
+				    + strlen("/state") + 1, M_XENBUS, M_WAITOK);
+				sprintf(statepath, "%s/state", ivars->xd_otherend_path);

-			free(ivars->xd_otherend_watch.node, M_XENBUS);
-			ivars->xd_otherend_watch.node = statepath;
+				free(ivars->xd_otherend_watch.node, M_XENBUS);
+				ivars->xd_otherend_watch.node = statepath;
+			}

 			DEVICE_RESUME(kids[i]);

-			xs_register_watch(&ivars->xd_otherend_watch);
+			if(xenbusb_suspend_cancelled == 0)
+				xs_register_watch(&ivars->xd_otherend_watch);
 #if 0
 			/*
 			 * Can't do this yet since we are running in
@@ -834,6 +844,9 @@ xenbusb_resume(device_t dev)
 		free(kids, M_TEMP);
 	}

+	if(xenbusb_suspend_cancelled == 1)
+		xenbusb_suspend_cancelled = 0;
+	
 	return (0);
 }

diff --git a/sys/xen/xenbus/xenbusvar.h b/sys/xen/xenbus/xenbusvar.h
index ab5d01f..aff3b60 100644
--- a/sys/xen/xenbus/xenbusvar.h
+++ b/sys/xen/xenbus/xenbusvar.h
@@ -272,4 +272,8 @@ void xenbus_localend_changed(device_t dev, const char *path);

 #include "xenbus_if.h"

+void xenbusb_set_suspend_cancel(void);
+void xbd_set_suspend_cancel(void);
+void xn_set_suspend_cancel(void);
+
 #endif /* _XEN_XENBUS_XENBUSVAR_H */





More information about the freebsd-xen mailing list