[dpdk-dev] [PATCH 3/3] eal: handle bus rescan failures during hotplug
Darek Stojaczyk
dariusz.stojaczyk at intel.com
Mon Nov 5 08:04:47 CET 2018
Fixes for devargs dangling pointers and various segfaults
caused by failed hotplug requests.
If rescan failed, we have one the following scenarios
to cover:
a) the device was never scanned at all; the devargs that
were just allocated are not referenced anywhere and
can be removed straight away. Previous devargs (if any)
need to be re-inserted as they are still in use.
b) the device was scanned before, but the rescan failed
before it reached our device, meaning that its devargs
were not overridden and we can remove our newly allocated
ones. Previous devargs need to be re-inserted.
c) we managed to rescan our device and only failed on
something after that, which means we have to free the
memory of previous devargs and stick with the new ones,
despite the fact that the hotplug still needs to be
failed.
Fixes: 7e8b26650146 ("eal: fix hotplug add / remove")
Cc: gaetan.rivet at 6wind.com
Cc: qi.z.zhang at intel.com
Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk at intel.com>
---
lib/librte_eal/common/eal_common_dev.c | 30 ++++++++++++++++++--------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/lib/librte_eal/common/eal_common_dev.c b/lib/librte_eal/common/eal_common_dev.c
index 4cb424df1..b090295b9 100644
--- a/lib/librte_eal/common/eal_common_dev.c
+++ b/lib/librte_eal/common/eal_common_dev.c
@@ -7,6 +7,7 @@
#include <string.h>
#include <inttypes.h>
#include <sys/queue.h>
+#include <assert.h>
#include <rte_compat.h>
#include <rte_bus.h>
@@ -141,32 +142,33 @@ local_dev_probe(const char *devargs, struct rte_device **new_dev)
ret = rte_devargs_parse(da, devargs);
if (ret)
- goto err_devarg;
+ goto err_remove_devargs;
if (da->bus->plug == NULL) {
RTE_LOG(ERR, EAL, "Function plug not supported by bus (%s)\n",
da->bus->name);
ret = -ENOTSUP;
- goto err_devarg;
+ goto err_remove_devargs;
}
rte_devargs_insert(da, &prev_da);
+ ret = da->bus->scan();
+ if (ret)
+ goto err_rollback_devargs;
+
if (prev_da != NULL) {
free(prev_da->args);
free(prev_da);
+ prev_da = NULL;
}
- ret = da->bus->scan();
- if (ret)
- goto err_devarg;
-
dev = da->bus->find_device(NULL, cmp_dev_name, da->name);
if (dev == NULL) {
RTE_LOG(ERR, EAL, "Cannot find device (%s)\n",
da->name);
ret = -ENODEV;
- goto err_devarg;
+ goto err_remove_devargs;
}
ret = dev->bus->plug(dev);
@@ -175,13 +177,23 @@ local_dev_probe(const char *devargs, struct rte_device **new_dev)
return ret; /* no rollback */
RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n",
dev->name);
- goto err_devarg;
+ goto err_remove_devargs;
}
*new_dev = dev;
return 0;
-err_devarg:
+err_rollback_devargs:
+ dev = da->bus->find_device(NULL, cmp_dev_name, da->name);
+ if (prev_da != NULL && (dev == NULL || dev->devargs != da)) {
+ /* either the device wasn't scanned, or we didn't
+ * manage yet to update its devargs.
+ */
+ rte_devargs_insert(prev_da, &da);
+ assert(da != NULL);
+ }
+
+err_remove_devargs:
if (rte_devargs_remove(da) != 0) {
free(da->args);
free(da);
--
2.17.1
More information about the dev
mailing list