Blame SOURCES/0001-vhost-fix-IOTLB-pool-out-of-memory-handling.patch

a6040a
From 37771844a05c7b0a7b039dcae1b4b0a69b4acced Mon Sep 17 00:00:00 2001
a6040a
From: Maxime Coquelin <maxime.coquelin@redhat.com>
a6040a
Date: Mon, 5 Feb 2018 16:04:56 +0100
a6040a
Subject: [PATCH] vhost: fix IOTLB pool out-of-memory handling
a6040a
a6040a
In the unlikely case the IOTLB memory pool runs out of memory,
a6040a
an issue may happen if all entries are used by the IOTLB cache,
a6040a
and an IOTLB miss happen. If the iotlb pending list is empty,
a6040a
then no memory is freed and allocation fails a second time.
a6040a
a6040a
This patch fixes this by doing an IOTLB cache random evict if
a6040a
the IOTLB pending list is empty, ensuring the second allocation
a6040a
try will succeed.
a6040a
a6040a
In the same spirit, the opposite is done when inserting an
a6040a
IOTLB entry in the IOTLB cache fails due to out of memory. In
a6040a
this case, the IOTLB pending is flushed if the IOTLB cache is
a6040a
empty to ensure the new entry can be inserted.
a6040a
a6040a
Fixes: d012d1f293f4 ("vhost: add IOTLB helper functions")
a6040a
Fixes: f72c2ad63aeb ("vhost: add pending IOTLB miss request list and helpers")
a6040a
Cc: stable@dpdk.org
a6040a
a6040a
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
a6040a
---
a6040a
 lib/librte_vhost/iotlb.c | 18 +++++++++++++-----
a6040a
 1 file changed, 13 insertions(+), 5 deletions(-)
a6040a
a6040a
diff --git a/lib/librte_vhost/iotlb.c b/lib/librte_vhost/iotlb.c
a6040a
index b74cc6a78..72cd27df8 100644
a6040a
--- a/lib/librte_vhost/iotlb.c
a6040a
+++ b/lib/librte_vhost/iotlb.c
a6040a
@@ -50,6 +50,9 @@ struct vhost_iotlb_entry {
a6040a
 
a6040a
 #define IOTLB_CACHE_SIZE 2048
a6040a
 
a6040a
+static void
a6040a
+vhost_user_iotlb_cache_random_evict(struct vhost_virtqueue *vq);
a6040a
+
a6040a
 static void
a6040a
 vhost_user_iotlb_pending_remove_all(struct vhost_virtqueue *vq)
a6040a
 {
a6040a
@@ -95,9 +98,11 @@ vhost_user_iotlb_pending_insert(struct vhost_virtqueue *vq,
a6040a
 
a6040a
 	ret = rte_mempool_get(vq->iotlb_pool, (void **)&node);
a6040a
 	if (ret) {
a6040a
-		RTE_LOG(INFO, VHOST_CONFIG,
a6040a
-				"IOTLB pool empty, clear pending misses\n");
a6040a
-		vhost_user_iotlb_pending_remove_all(vq);
a6040a
+		RTE_LOG(DEBUG, VHOST_CONFIG, "IOTLB pool empty, clear entries\n");
a6040a
+		if (!TAILQ_EMPTY(&vq->iotlb_pending_list))
a6040a
+			vhost_user_iotlb_pending_remove_all(vq);
a6040a
+		else
a6040a
+			vhost_user_iotlb_cache_random_evict(vq);
a6040a
 		ret = rte_mempool_get(vq->iotlb_pool, (void **)&node);
a6040a
 		if (ret) {
a6040a
 			RTE_LOG(ERR, VHOST_CONFIG, "IOTLB pool still empty, failure\n");
a6040a
@@ -186,8 +191,11 @@ vhost_user_iotlb_cache_insert(struct vhost_virtqueue *vq, uint64_t iova,
a6040a
 
a6040a
 	ret = rte_mempool_get(vq->iotlb_pool, (void **)&new_node);
a6040a
 	if (ret) {
a6040a
-		RTE_LOG(DEBUG, VHOST_CONFIG, "IOTLB pool empty, evict one entry\n");
a6040a
-		vhost_user_iotlb_cache_random_evict(vq);
a6040a
+		RTE_LOG(DEBUG, VHOST_CONFIG, "IOTLB pool empty, clear entries\n");
a6040a
+		if (!TAILQ_EMPTY(&vq->iotlb_list))
a6040a
+			vhost_user_iotlb_cache_random_evict(vq);
a6040a
+		else
a6040a
+			vhost_user_iotlb_pending_remove_all(vq);
a6040a
 		ret = rte_mempool_get(vq->iotlb_pool, (void **)&new_node);
a6040a
 		if (ret) {
a6040a
 			RTE_LOG(ERR, VHOST_CONFIG, "IOTLB pool still empty, failure\n");
a6040a
-- 
a6040a
2.14.3
a6040a