[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