[dpdk-stable] [PATCH] net/vdev_netvsc: Prevent alarm lost on failed device probe

Long Li longli at linuxonhyperv.com
Thu Oct 15 21:33:05 CEST 2020


From: Long Li <longli at microsoft.com>

If a device probe fails, the alarm is canceled and will no longer work for
previously probed devices.

Fix this by introducing a flag to track if alarm has been set. Because it's
possible that an alarm is triggered while probing is in progress that may
modify vdev_netvsc_ctx_list, introduce a lock to protect it.

Cc: stable at dpdk.org
Signed-off-by: Long Li <longli at microsoft.com>
---
 drivers/net/vdev_netvsc/vdev_netvsc.c | 41 +++++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/drivers/net/vdev_netvsc/vdev_netvsc.c b/drivers/net/vdev_netvsc/vdev_netvsc.c
index be8f19c..bd7e308 100644
--- a/drivers/net/vdev_netvsc/vdev_netvsc.c
+++ b/drivers/net/vdev_netvsc/vdev_netvsc.c
@@ -76,6 +76,11 @@ struct vdev_netvsc_ctx {
 /** Context list is common to all driver instances. */
 static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 	LIST_HEAD_INITIALIZER(vdev_netvsc_ctx_list);
+/* Lock to protect concurrent accesses to vdev_netvsc_ctx_list */
+static rte_rwlock_t vdev_netvsc_ctx_list_lock;
+
+/* Flag to track if alarm has been set */
+static int vdev_netvsc_alarm_set;
 
 /** Number of entries in context list. */
 static unsigned int vdev_netvsc_ctx_count;
@@ -454,19 +459,26 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 	struct vdev_netvsc_ctx *ctx;
 	int ret;
 
+	rte_rwlock_write_lock(&vdev_netvsc_ctx_list_lock);
 	LIST_FOREACH(ctx, &vdev_netvsc_ctx_list, entry) {
 		ret = vdev_netvsc_foreach_iface(vdev_netvsc_device_probe, 0,
 		      ctx);
 		if (ret < 0)
 			break;
 	}
-	if (!vdev_netvsc_ctx_count)
+	rte_rwlock_write_unlock(&vdev_netvsc_ctx_list_lock);
+
+	if (!vdev_netvsc_ctx_count) {
+		vdev_netvsc_alarm_set = 0;
 		return;
+	}
+
 	ret = rte_eal_alarm_set(VDEV_NETVSC_PROBE_MS * 1000,
 				vdev_netvsc_alarm, NULL);
 	if (ret < 0) {
 		DRV_LOG(ERR, "unable to reschedule alarm callback: %s",
 			rte_strerror(-ret));
+		vdev_netvsc_alarm_set = 0;
 	}
 }
 
@@ -698,34 +710,41 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 			" device.");
 		goto error;
 	}
-	rte_eal_alarm_cancel(vdev_netvsc_alarm, NULL);
+
+	rte_rwlock_write_lock(&vdev_netvsc_ctx_list_lock);
 	/* Gather interfaces. */
 	ret = vdev_netvsc_foreach_iface(vdev_netvsc_netvsc_probe, 1, name,
 					kvargs, specified, &matched);
 	if (ret < 0)
-		goto error;
+		goto error_unlock;
 	if (specified && matched < specified) {
 		if (!force) {
 			DRV_LOG(ERR, "Cannot find the specified netvsc device");
-			goto error;
+			goto error_unlock;
 		}
 		/* Try to force probing on non-netvsc specified device. */
 		if (vdev_netvsc_foreach_iface(vdev_netvsc_netvsc_probe, 0, name,
 					      kvargs, specified, &matched) < 0)
-			goto error;
+			goto error_unlock;
 		if (matched < specified) {
 			DRV_LOG(ERR, "Cannot find the specified device");
-			goto error;
+			goto error_unlock;
 		}
 		DRV_LOG(WARNING, "non-netvsc device was probed as netvsc");
 	}
-	ret = rte_eal_alarm_set(VDEV_NETVSC_PROBE_MS * 1000,
+	if (!vdev_netvsc_alarm_set) {
+		ret = rte_eal_alarm_set(VDEV_NETVSC_PROBE_MS * 1000,
 				vdev_netvsc_alarm, NULL);
-	if (ret < 0) {
-		DRV_LOG(ERR, "unable to schedule alarm callback: %s",
-			rte_strerror(-ret));
-		goto error;
+		if (ret < 0)
+			DRV_LOG(ERR, "unable to schedule alarm callback: %s",
+				rte_strerror(-ret));
+		else
+			vdev_netvsc_alarm_set = 1;
 	}
+
+error_unlock:
+	rte_rwlock_write_unlock(&vdev_netvsc_ctx_list_lock);
+
 error:
 	if (kvargs)
 		rte_kvargs_free(kvargs);
-- 
1.8.3.1



More information about the stable mailing list