Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Dec 2016 02:00:53 +0000
From:      Liuyingdong <liuyingdong@huawei.com>
To:        freebsd xen <roger.pau@citrix.com>
Cc:        "freebsd-xen@freebsd.org" <freebsd-xen@freebsd.org>, "Zhaojun (Euler)" <zhao.zhaojun@huawei.com>, Suoben <suoben@huawei.com>, "Ouyangzhaowei (Charles)" <ouyangzhaowei@huawei.com>, chuzhaosong <chuzhaosong@huawei.com>, Wanglinkai <wanglinkai@huawei.com>
Subject:   Re: [PATCH]netfront: need release all resources after adding and removing NICs time and again
Message-ID:  <3655E9A8B903724782E1F75DCFD74E6B01229F6F11@szxema506-mbs.china.huawei.com>
In-Reply-To: <20161213142919.ulvvvwoz2da5fedw@dhcp-3-221.uk.xensource.com>
References:  <5825272C.3010704@huawei.com> <584F8F1C.6030006@huawei.com> <20161213142919.ulvvvwoz2da5fedw@dhcp-3-221.uk.xensource.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hello Roger,
	Thank you for the time and patience you devoted to reading my messages and e-mails. I really appreciate that.
	I can't use git send-email so I attach the patches directly. In the 0001 patch I introduce suspend_cancel mechanism for frontend devices and in the 0002 patch I release all resources after hot unplug NICs.

    Note: These two patches is on the base of the origin/release/10.2.0 branch and the 0002 patch is made after the 0001 patch.

-----邮件原件-----
发件人: freebsd xen [mailto:roger.pau@citrix.com] 
发送时间: 2016年12月13日 22:29
收件人: Liuyingdong
抄送: freebsd-xen@freebsd.org; Zhaojun (Euler); Suoben; Ouyangzhaowei (Charles)
主题: Re: [PATCH]netfront: need release all resources after adding and removing NICs time and again

On Tue, Dec 13, 2016 at 02:03:08PM +0800, liuyingdong wrote:
> Hello Roger,
>     I want to know how about this patch,Please let me know if you have any questions.
>     Thanks.

Hello,

Thanks for the patches! This one is looking fine, it's just that I'm a little bit busy at the moment, and there are some issues in HEAD related to Xen that I would like to fix before pushing anything new.

In any case, I see that you are sending the patches using Thunderbird, which is not ideal (MUAs tend to mangle patches). The preferred way for sending patches is using "git send-email"[0] directly. There are also several tutorials online that will help you setup git send-email correctly. If there's some reason why you can't use git send-email I would recommend that you also attach the patches directly to emails, that way they won't probably get mangled.

Roger.

[0] https://git-scm.com/docs/git-send-email

[-- Attachment #2 --]
From fc85ac7eba55a5f14f5f7d81f0e1fc7fbf6a7447 Mon Sep 17 00:00:00 2001
From: Yingdong Liu <liuyingdong@huawei.com>
Date: Tue, 13 Dec 2016 21:53:25 +0800
Subject: [PATCH] introduce suspend cancel mechanism for frontend devices

---
 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 */
-- 
1.8.3.4


[-- Attachment #3 --]
From 423a959a268b205c048489e6addeba5db449e322 Mon Sep 17 00:00:00 2001
From: Yingdong Liu <liuyingdong@huawei.com>
Date: Thu, 15 Dec 2016 09:09:16 +0800
Subject: [PATCH] [PATCH]netfront: need release all resources after adding and
 removing NICs time and again

---
 sys/dev/xen/netfront/netfront.c | 46 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index 0caaa2c..5b67e12 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -2196,6 +2196,46 @@ netfront_detach(device_t dev)
 }
 
 static void
+netif_release_rx_bufs_copy(struct netfront_info *np)
+{
+	struct mbuf *m;
+	int i, ref;
+	int busy = 0, inuse = 0;
+
+	XN_RX_LOCK(np);
+
+	for (i = 0; i < NET_RX_RING_SIZE; i++) {
+		ref = np->grant_rx_ref[i];
+
+		if (ref == GRANT_REF_INVALID)
+			continue;
+
+		inuse++;
+
+		m = np->rx_mbufs[i];
+
+		if (!gnttab_end_foreign_access_ref(ref))
+		{
+			busy++;
+			continue;
+		}
+
+		gnttab_release_grant_reference(&np->gref_rx_head, ref);
+		np->grant_rx_ref[i] = GRANT_REF_INVALID;
+		add_id_to_freelist(np->rx_mbufs, i);
+
+		m_freem(m);
+	}
+
+	if (busy)
+		device_printf(np->xbdev, "Unable to release %d of %d "
+			"inuse grant references out of %ld total.\n",
+			busy, inuse, NET_RX_RING_SIZE);
+	
+	XN_RX_UNLOCK(np);
+}
+
+static void
 netif_free(struct netfront_info *info)
 {
 	XN_LOCK(info);
@@ -2209,6 +2249,12 @@ netif_free(struct netfront_info *info)
 		info->xn_ifp = NULL;
 	}
 	ifmedia_removeall(&info->sc_media);
+	netif_release_tx_bufs(info);
+	if (info->copying_receiver)
+		netif_release_rx_bufs_copy(info);
+
+	gnttab_free_grant_references(info->gref_tx_head);
+	gnttab_free_grant_references(info->gref_rx_head);
 }
 
 static void
-- 
1.8.3.4


Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3655E9A8B903724782E1F75DCFD74E6B01229F6F11>