From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <qi.z.zhang@intel.com>
Received: from mga14.intel.com (mga14.intel.com [192.55.52.115])
 by dpdk.org (Postfix) with ESMTP id 97A754CE4
 for <dev@dpdk.org>; Tue,  6 Nov 2018 01:30:44 +0100 (CET)
X-Amp-Result: SKIPPED(no attachment in message)
X-Amp-File-Uploaded: False
Received: from orsmga007.jf.intel.com ([10.7.209.58])
 by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;
 05 Nov 2018 16:30:43 -0800
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.54,469,1534834800"; d="scan'208";a="86927974"
Received: from dpdk51.sh.intel.com ([10.67.110.190])
 by orsmga007.jf.intel.com with ESMTP; 05 Nov 2018 16:30:42 -0800
From: Qi Zhang <qi.z.zhang@intel.com>
To: thomas@monjalon.net,
	gaetan.rivet@6wind.com,
	ferruh.yigit@intel.com
Cc: dev@dpdk.org,
	Qi Zhang <qi.z.zhang@intel.com>
Date: Tue,  6 Nov 2018 08:31:50 +0800
Message-Id: <20181106003150.10560-1-qi.z.zhang@intel.com>
X-Mailer: git-send-email 2.13.6
Subject: [dpdk-dev] [PATCH] bus/vdev: fix probe same device twice
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Tue, 06 Nov 2018 00:30:45 -0000

When probe the same device at second time, devargs will be
replaced in devargs_list, old version is destoried but they
are still referenced by vdev->device. So we break the link
between vdev->device to devargs_list by clone, and the copy
one will be freed by vdev bus itself.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 drivers/bus/vdev/vdev.c | 44 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

diff --git a/drivers/bus/vdev/vdev.c b/drivers/bus/vdev/vdev.c
index 9c66bdc78..2e2b6dc57 100644
--- a/drivers/bus/vdev/vdev.c
+++ b/drivers/bus/vdev/vdev.c
@@ -176,6 +176,21 @@ find_vdev(const char *name)
 }
 
 static struct rte_devargs *
+clone_devargs(struct rte_devargs *devargs)
+{
+	struct rte_devargs *da;
+
+	da = calloc(1, sizeof(*devargs));
+	if (da == NULL)
+		return NULL;
+
+	*da = *devargs;
+	da->args = strdup(devargs->args);
+
+	return da;
+}
+
+static struct rte_devargs *
 alloc_devargs(const char *name, const char *args)
 {
 	struct rte_devargs *devargs;
@@ -208,6 +223,7 @@ insert_vdev(const char *name, const char *args,
 {
 	struct rte_vdev_device *dev;
 	struct rte_devargs *devargs;
+	struct rte_devargs *devargs2;
 	int ret;
 
 	if (name == NULL)
@@ -217,6 +233,13 @@ insert_vdev(const char *name, const char *args,
 	if (!devargs)
 		return -ENOMEM;
 
+	devargs2 = clone_devargs(devargs);
+	if (!devargs2) {
+		free(devargs->args);
+		free(devargs);
+		return -ENOMEM;
+	}
+
 	dev = calloc(1, sizeof(*dev));
 	if (!dev) {
 		ret = -ENOMEM;
@@ -224,9 +247,9 @@ insert_vdev(const char *name, const char *args,
 	}
 
 	dev->device.bus = &rte_vdev_bus;
-	dev->device.devargs = devargs;
+	dev->device.devargs = devargs2;
 	dev->device.numa_node = SOCKET_ID_ANY;
-	dev->device.name = devargs->name;
+	dev->device.name = devargs2->name;
 
 	if (find_vdev(name)) {
 		/*
@@ -249,6 +272,8 @@ insert_vdev(const char *name, const char *args,
 fail:
 	free(devargs->args);
 	free(devargs);
+	free(devargs2->args);
+	free(devargs2);
 	free(dev);
 	return ret;
 }
@@ -269,6 +294,8 @@ rte_vdev_init(const char *name, const char *args)
 			/* If fails, remove it from vdev list */
 			TAILQ_REMOVE(&vdev_device_list, dev, next);
 			rte_devargs_remove(dev->device.devargs);
+			free(dev->device.devargs->args);
+			free(dev->device.devargs);
 			free(dev);
 		}
 	}
@@ -315,6 +342,8 @@ rte_vdev_uninit(const char *name)
 
 	TAILQ_REMOVE(&vdev_device_list, dev, next);
 	rte_devargs_remove(dev->device.devargs);
+	free(dev->device.devargs->args);
+	free(dev->device.devargs);
 	free(dev);
 
 unlock:
@@ -404,6 +433,7 @@ vdev_scan(void)
 {
 	struct rte_vdev_device *dev;
 	struct rte_devargs *devargs;
+	struct rte_devargs *devargs2;
 	struct vdev_custom_scan *custom_scan;
 
 	if (rte_mp_action_register(VDEV_MP_KEY, vdev_action) < 0 &&
@@ -457,18 +487,24 @@ vdev_scan(void)
 		if (!dev)
 			return -1;
 
+		devargs2 = clone_devargs(devargs);
+		if (!devargs2) {
+			free(dev);
+			return -1;
+		}
 		rte_spinlock_recursive_lock(&vdev_device_list_lock);
 
 		if (find_vdev(devargs->name)) {
 			rte_spinlock_recursive_unlock(&vdev_device_list_lock);
+			free(devargs2);
 			free(dev);
 			continue;
 		}
 
 		dev->device.bus = &rte_vdev_bus;
-		dev->device.devargs = devargs;
+		dev->device.devargs = devargs2;
 		dev->device.numa_node = SOCKET_ID_ANY;
-		dev->device.name = devargs->name;
+		dev->device.name = devargs2->name;
 
 		TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
 
-- 
2.13.6