get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/22137/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 22137,
    "url": "http://patches.dpdk.org/api/patches/22137/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1490253059-28112-19-git-send-email-yuanhan.liu@linux.intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1490253059-28112-19-git-send-email-yuanhan.liu@linux.intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1490253059-28112-19-git-send-email-yuanhan.liu@linux.intel.com",
    "date": "2017-03-23T07:10:55",
    "name": "[dpdk-dev,v2,18/22] vhost: introduce API to start a specific driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "955e6e5cd8c62640d96bf67580af027ad3edd0f1",
    "submitter": {
        "id": 307,
        "url": "http://patches.dpdk.org/api/people/307/?format=api",
        "name": "Yuanhan Liu",
        "email": "yuanhan.liu@linux.intel.com"
    },
    "delegate": {
        "id": 355,
        "url": "http://patches.dpdk.org/api/users/355/?format=api",
        "username": "yliu",
        "first_name": "Yuanhan",
        "last_name": "Liu",
        "email": "yuanhan.liu@linux.intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1490253059-28112-19-git-send-email-yuanhan.liu@linux.intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/22137/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/22137/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id CC576D223;\n\tThu, 23 Mar 2017 08:14:17 +0100 (CET)",
            "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n\tby dpdk.org (Postfix) with ESMTP id C5C195599\n\tfor <dev@dpdk.org>; Thu, 23 Mar 2017 08:13:22 +0100 (CET)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby fmsmga105.fm.intel.com with ESMTP; 23 Mar 2017 00:13:22 -0700",
            "from yliu-dev.sh.intel.com ([10.239.67.162])\n\tby FMSMGA003.fm.intel.com with ESMTP; 23 Mar 2017 00:13:21 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.36,208,1486454400\"; d=\"scan'208\";a=\"837675416\"",
        "From": "Yuanhan Liu <yuanhan.liu@linux.intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "Maxime Coquelin <maxime.coquelin@redhat.com>,\n\tHarris James R <james.r.harris@intel.com>,\n\tLiu Changpeng <changpeng.liu@intel.com>,\n\tYuanhan Liu <yuanhan.liu@linux.intel.com>",
        "Date": "Thu, 23 Mar 2017 15:10:55 +0800",
        "Message-Id": "<1490253059-28112-19-git-send-email-yuanhan.liu@linux.intel.com>",
        "X-Mailer": "git-send-email 1.9.0",
        "In-Reply-To": "<1490253059-28112-1-git-send-email-yuanhan.liu@linux.intel.com>",
        "References": "<1488534682-3494-1-git-send-email-yuanhan.liu@linux.intel.com>\n\t<1490253059-28112-1-git-send-email-yuanhan.liu@linux.intel.com>",
        "Subject": "[dpdk-dev] [PATCH v2 18/22] vhost: introduce API to start a\n\tspecific driver",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "We used to use rte_vhost_driver_session_start() to trigger the vhost-user\nsession. It takes no argument, thus it's a global trigger. And it could\nbe problematic.\n\nThe issue is, currently, rte_vhost_driver_register(path, flags) actually\ntries to put it into the session loop (by fdset_add). However, it needs\na set of APIs to set a vhost-user driver properly:\n  * rte_vhost_driver_register(path, flags);\n  * rte_vhost_driver_set_features(path, features);\n  * rte_vhost_driver_callback_register(path, vhost_device_ops);\n\nIf a new vhost-user driver is registered after the trigger (think OVS-DPDK\nthat could add a port dynamically from cmdline), the current code will\neffectively starts the session for the new driver just after the first\nAPI rte_vhost_driver_register() is invoked, leaving later calls taking\nno effect at all.\n\nTo handle the case properly, this patch introduce a new API,\nrte_vhost_driver_start(path), to trigger a specific vhost-user driver.\nTo do that, the rte_vhost_driver_register(path, flags) is simplified\nto create the socket only and let rte_vhost_driver_start(path) to\nactually put it into the session loop.\n\nMeanwhile, the rte_vhost_driver_session_start is removed: we could hide\nthe session thread internally (create the thread if it has not been\ncreated). This would also simplify the application.\n\nNOTE: the API order in prog guide is slightly adjusted for showing the\ncorrect invoke order.\n\nSigned-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>\n---\n doc/guides/prog_guide/vhost_lib.rst    | 24 +++++------\n doc/guides/rel_notes/release_17_05.rst |  8 ++++\n drivers/net/vhost/rte_eth_vhost.c      | 50 ++-------------------\n examples/tep_termination/main.c        |  8 +++-\n examples/vhost/main.c                  |  9 +++-\n lib/librte_vhost/fd_man.c              |  9 ++--\n lib/librte_vhost/fd_man.h              |  2 +-\n lib/librte_vhost/rte_vhost_version.map |  2 +-\n lib/librte_vhost/rte_virtio_net.h      | 15 ++++++-\n lib/librte_vhost/socket.c              | 79 +++++++++++++++++++---------------\n 10 files changed, 104 insertions(+), 102 deletions(-)",
    "diff": "diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst\nindex a4fb1f1..5979290 100644\n--- a/doc/guides/prog_guide/vhost_lib.rst\n+++ b/doc/guides/prog_guide/vhost_lib.rst\n@@ -116,12 +116,6 @@ The following is an overview of some key Vhost API functions:\n   vhost-user driver could be vhost-user net, yet it could be something else,\n   say, vhost-user SCSI.\n \n-* ``rte_vhost_driver_session_start()``\n-\n-  This function starts the vhost session loop to handle vhost messages. It\n-  starts an infinite loop, therefore it should be called in a dedicated\n-  thread.\n-\n * ``rte_vhost_driver_callback_register(path, vhost_device_ops)``\n \n   This function registers a set of callbacks, to let DPDK applications take\n@@ -149,6 +143,17 @@ The following is an overview of some key Vhost API functions:\n     ``VHOST_F_LOG_ALL`` will be set/cleared at the start/end of live\n     migration, respectively.\n \n+* ``rte_vhost_driver_disable/enable_features(path, features))``\n+\n+  This function disables/enables some features. For example, it can be used to\n+  disable mergeable buffers and TSO features, which both are enabled by\n+  default.\n+\n+* ``rte_vhost_driver_start(path)``\n+\n+  This function triggers the vhost-user negotiation. It should be invoked at\n+  the end of initializing a vhost-user driver.\n+\n * ``rte_vhost_enqueue_burst(vid, queue_id, pkts, count)``\n \n   Transmits (enqueues) ``count`` packets from host to guest.\n@@ -157,13 +162,6 @@ The following is an overview of some key Vhost API functions:\n \n   Receives (dequeues) ``count`` packets from guest, and stored them at ``pkts``.\n \n-* ``rte_vhost_driver_disable/enable_features(path, features))``\n-\n-  This function disables/enables some features. For example, it can be used to\n-  disable mergeable buffers and TSO features, which both are enabled by\n-  default.\n-\n-\n Vhost-user Implementations\n --------------------------\n \ndiff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst\nindex 2efe292..8f06fc4 100644\n--- a/doc/guides/rel_notes/release_17_05.rst\n+++ b/doc/guides/rel_notes/release_17_05.rst\n@@ -57,6 +57,11 @@ New Features\n   * Enable Vhost PMD's MTU get feature.\n   * Get max MTU value from host in Virtio PMD\n \n+* **Made the vhost lib be a generic vhost-user lib.**\n+\n+  Now it could be used to implement any other vhost-user drivers, such\n+  as, vhost-user SCSI.\n+\n \n Resolved Issues\n ---------------\n@@ -157,6 +162,9 @@ API Changes\n    * The vhost struct ``virtio_net_device_ops`` is renamed to\n      ``vhost_device_ops``\n \n+   * The vhost API ``rte_vhost_driver_session_start`` is removed. Instead,\n+     ``rte_vhost_driver_start`` should be used.\n+\n \n ABI Changes\n -----------\ndiff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c\nindex 97a765f..e6c0758 100644\n--- a/drivers/net/vhost/rte_eth_vhost.c\n+++ b/drivers/net/vhost/rte_eth_vhost.c\n@@ -127,9 +127,6 @@ struct internal_list {\n \n static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;\n \n-static rte_atomic16_t nb_started_ports;\n-static pthread_t session_th;\n-\n static struct rte_eth_link pmd_link = {\n \t\t.link_speed = 10000,\n \t\t.link_duplex = ETH_LINK_FULL_DUPLEX,\n@@ -743,42 +740,6 @@ struct vhost_xstats_name_off {\n \treturn vid;\n }\n \n-static void *\n-vhost_driver_session(void *param __rte_unused)\n-{\n-\t/* start event handling */\n-\trte_vhost_driver_session_start();\n-\n-\treturn NULL;\n-}\n-\n-static int\n-vhost_driver_session_start(void)\n-{\n-\tint ret;\n-\n-\tret = pthread_create(&session_th,\n-\t\t\tNULL, vhost_driver_session, NULL);\n-\tif (ret)\n-\t\tRTE_LOG(ERR, PMD, \"Can't create a thread\\n\");\n-\n-\treturn ret;\n-}\n-\n-static void\n-vhost_driver_session_stop(void)\n-{\n-\tint ret;\n-\n-\tret = pthread_cancel(session_th);\n-\tif (ret)\n-\t\tRTE_LOG(ERR, PMD, \"Can't cancel the thread\\n\");\n-\n-\tret = pthread_join(session_th, NULL);\n-\tif (ret)\n-\t\tRTE_LOG(ERR, PMD, \"Can't join the thread\\n\");\n-}\n-\n static int\n eth_dev_start(struct rte_eth_dev *dev)\n {\n@@ -1083,10 +1044,10 @@ struct vhost_xstats_name_off {\n \t\tgoto error;\n \t}\n \n-\t/* We need only one message handling thread */\n-\tif (rte_atomic16_add_return(&nb_started_ports, 1) == 1) {\n-\t\tif (vhost_driver_session_start())\n-\t\t\tgoto error;\n+\tif (rte_vhost_driver_start(iface_name) < 0) {\n+\t\tRTE_LOG(ERR, PMD, \"Failed to start driver for %s\\n\",\n+\t\t\tiface_name);\n+\t\tgoto error;\n \t}\n \n \treturn data->port_id;\n@@ -1213,9 +1174,6 @@ struct vhost_xstats_name_off {\n \n \teth_dev_close(eth_dev);\n \n-\tif (rte_atomic16_sub_return(&nb_started_ports, 1) == 0)\n-\t\tvhost_driver_session_stop();\n-\n \trte_free(vring_states[eth_dev->data->port_id]);\n \tvring_states[eth_dev->data->port_id] = NULL;\n \ndiff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c\nindex 738f2d2..24c62cd 100644\n--- a/examples/tep_termination/main.c\n+++ b/examples/tep_termination/main.c\n@@ -1263,7 +1263,13 @@ static inline void __attribute__((always_inline))\n \t\t\t\"failed to register vhost driver callbacks.\\n\");\n \t}\n \n-\trte_vhost_driver_session_start();\n+\tif (rte_vhost_driver_start(dev_basename) < 0) {\n+\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\"failed to start vhost driver.\\n\");\n+\t}\n+\n+\tRTE_LCORE_FOREACH_SLAVE(lcore_id)\n+\t\trte_eal_wait_lcore(lcore_id);\n \n \treturn 0;\n }\ndiff --git a/examples/vhost/main.c b/examples/vhost/main.c\nindex 4395306..64b3eea 100644\n--- a/examples/vhost/main.c\n+++ b/examples/vhost/main.c\n@@ -1545,9 +1545,16 @@ static inline void __attribute__((always_inline))\n \t\t\trte_exit(EXIT_FAILURE,\n \t\t\t\t\"failed to register vhost driver callbacks.\\n\");\n \t\t}\n+\n+\t\tif (rte_vhost_driver_start(file) < 0) {\n+\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\"failed to start vhost driver.\\n\");\n+\t\t}\n \t}\n \n-\trte_vhost_driver_session_start();\n+\tRTE_LCORE_FOREACH_SLAVE(lcore_id)\n+\t\trte_eal_wait_lcore(lcore_id);\n+\n \treturn 0;\n \n }\ndiff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c\nindex c7a4490..2ceacc9 100644\n--- a/lib/librte_vhost/fd_man.c\n+++ b/lib/librte_vhost/fd_man.c\n@@ -210,8 +210,8 @@\n  * will wait until the flag is reset to zero(which indicates the callback is\n  * finished), then it could free the context after fdset_del.\n  */\n-void\n-fdset_event_dispatch(struct fdset *pfdset)\n+void *\n+fdset_event_dispatch(void *arg)\n {\n \tint i;\n \tstruct pollfd *pfd;\n@@ -221,9 +221,10 @@\n \tint fd, numfds;\n \tint remove1, remove2;\n \tint need_shrink;\n+\tstruct fdset *pfdset = arg;\n \n \tif (pfdset == NULL)\n-\t\treturn;\n+\t\treturn NULL;\n \n \twhile (1) {\n \n@@ -294,4 +295,6 @@\n \t\tif (need_shrink)\n \t\t\tfdset_shrink(pfdset);\n \t}\n+\n+\treturn NULL;\n }\ndiff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h\nindex d319cac..90d34db 100644\n--- a/lib/librte_vhost/fd_man.h\n+++ b/lib/librte_vhost/fd_man.h\n@@ -64,6 +64,6 @@ int fdset_add(struct fdset *pfdset, int fd,\n \n void *fdset_del(struct fdset *pfdset, int fd);\n \n-void fdset_event_dispatch(struct fdset *pfdset);\n+void *fdset_event_dispatch(void *arg);\n \n #endif\ndiff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map\nindex 70c28f7..4395fa5 100644\n--- a/lib/librte_vhost/rte_vhost_version.map\n+++ b/lib/librte_vhost/rte_vhost_version.map\n@@ -4,7 +4,6 @@ DPDK_2.0 {\n \trte_vhost_dequeue_burst;\n \trte_vhost_driver_callback_register;\n \trte_vhost_driver_register;\n-\trte_vhost_driver_session_start;\n \trte_vhost_enable_guest_notification;\n \trte_vhost_enqueue_burst;\n \n@@ -35,6 +34,7 @@ DPDK_17.05 {\n \trte_vhost_driver_enable_features;\n \trte_vhost_driver_get_features;\n \trte_vhost_driver_set_features;\n+\trte_vhost_driver_start;\n \trte_vhost_get_mem_table;\n \trte_vhost_get_mtu;\n \trte_vhost_get_negotiated_features\ndiff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h\nindex 11b204d..627708d 100644\n--- a/lib/librte_vhost/rte_virtio_net.h\n+++ b/lib/librte_vhost/rte_virtio_net.h\n@@ -250,8 +250,19 @@ void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,\n /* Register callbacks. */\n int rte_vhost_driver_callback_register(const char *path,\n \tstruct vhost_device_ops const * const ops);\n-/* Start vhost driver session blocking loop. */\n-int rte_vhost_driver_session_start(void);\n+\n+/**\n+ *\n+ * Start the vhost-user driver.\n+ *\n+ * This function triggers the vhost-user negotiation.\n+ *\n+ * @param path\n+ *  The vhost-user socket file path\n+ * @return\n+ *  0 on success, -1 on failure\n+ */\n+int rte_vhost_driver_start(const char *path);\n \n /**\n  * Get the MTU value of the device if set in QEMU.\ndiff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c\nindex 31b868d..b056a17 100644\n--- a/lib/librte_vhost/socket.c\n+++ b/lib/librte_vhost/socket.c\n@@ -58,8 +58,9 @@\n  */\n struct vhost_user_socket {\n \tchar *path;\n-\tint listenfd;\n \tint connfd;\n+\tstruct sockaddr_un un;\n+\tint socket_fd;\n \tbool is_server;\n \tbool reconnect;\n \tbool dequeue_zero_copy;\n@@ -94,7 +95,7 @@ struct vhost_user {\n \n static void vhost_user_server_new_connection(int fd, void *data, int *remove);\n static void vhost_user_read_cb(int fd, void *dat, int *remove);\n-static int vhost_user_create_client(struct vhost_user_socket *vsocket);\n+static int vhost_user_start_client(struct vhost_user_socket *vsocket);\n \n static struct vhost_user vhost_user = {\n \t.fdset = {\n@@ -266,22 +267,23 @@ struct vhost_user {\n \t\tfree(conn);\n \n \t\tif (vsocket->reconnect)\n-\t\t\tvhost_user_create_client(vsocket);\n+\t\t\tvhost_user_start_client(vsocket);\n \t}\n }\n \n static int\n-create_unix_socket(const char *path, struct sockaddr_un *un, bool is_server)\n+create_unix_socket(struct vhost_user_socket *vsocket)\n {\n \tint fd;\n+\tstruct sockaddr_un *un = &vsocket->un;\n \n \tfd = socket(AF_UNIX, SOCK_STREAM, 0);\n \tif (fd < 0)\n \t\treturn -1;\n \tRTE_LOG(INFO, VHOST_CONFIG, \"vhost-user %s: socket created, fd: %d\\n\",\n-\t\tis_server ? \"server\" : \"client\", fd);\n+\t\tvsocket->is_server ? \"server\" : \"client\", fd);\n \n-\tif (!is_server && fcntl(fd, F_SETFL, O_NONBLOCK)) {\n+\tif (!vsocket->is_server && fcntl(fd, F_SETFL, O_NONBLOCK)) {\n \t\tRTE_LOG(ERR, VHOST_CONFIG,\n \t\t\t\"vhost-user: can't set nonblocking mode for socket, fd: \"\n \t\t\t\"%d (%s)\\n\", fd, strerror(errno));\n@@ -291,25 +293,21 @@ struct vhost_user {\n \n \tmemset(un, 0, sizeof(*un));\n \tun->sun_family = AF_UNIX;\n-\tstrncpy(un->sun_path, path, sizeof(un->sun_path));\n+\tstrncpy(un->sun_path, vsocket->path, sizeof(un->sun_path));\n \tun->sun_path[sizeof(un->sun_path) - 1] = '\\0';\n \n-\treturn fd;\n+\tvsocket->socket_fd = fd;\n+\treturn 0;\n }\n \n static int\n-vhost_user_create_server(struct vhost_user_socket *vsocket)\n+vhost_user_start_server(struct vhost_user_socket *vsocket)\n {\n-\tint fd;\n \tint ret;\n-\tstruct sockaddr_un un;\n+\tint fd = vsocket->socket_fd;\n \tconst char *path = vsocket->path;\n \n-\tfd = create_unix_socket(path, &un, vsocket->is_server);\n-\tif (fd < 0)\n-\t\treturn -1;\n-\n-\tret = bind(fd, (struct sockaddr *)&un, sizeof(un));\n+\tret = bind(fd, (struct sockaddr *)&vsocket->un, sizeof(vsocket->un));\n \tif (ret < 0) {\n \t\tRTE_LOG(ERR, VHOST_CONFIG,\n \t\t\t\"failed to bind to %s: %s; remove it and try again\\n\",\n@@ -322,7 +320,6 @@ struct vhost_user {\n \tif (ret < 0)\n \t\tgoto err;\n \n-\tvsocket->listenfd = fd;\n \tret = fdset_add(&vhost_user.fdset, fd, vhost_user_server_new_connection,\n \t\t  NULL, vsocket);\n \tif (ret < 0) {\n@@ -441,20 +438,15 @@ struct vhost_user_reconnect_list {\n }\n \n static int\n-vhost_user_create_client(struct vhost_user_socket *vsocket)\n+vhost_user_start_client(struct vhost_user_socket *vsocket)\n {\n-\tint fd;\n \tint ret;\n-\tstruct sockaddr_un un;\n+\tint fd = vsocket->socket_fd;\n \tconst char *path = vsocket->path;\n \tstruct vhost_user_reconnect *reconn;\n \n-\tfd = create_unix_socket(path, &un, vsocket->is_server);\n-\tif (fd < 0)\n-\t\treturn -1;\n-\n-\tret = vhost_user_connect_nonblock(fd, (struct sockaddr *)&un,\n-\t\t\t\t\t  sizeof(un));\n+\tret = vhost_user_connect_nonblock(fd, (struct sockaddr *)&vsocket->un,\n+\t\t\t\t\t  sizeof(vsocket->un));\n \tif (ret == 0) {\n \t\tvhost_user_add_connection(fd, vsocket);\n \t\treturn 0;\n@@ -477,7 +469,7 @@ struct vhost_user_reconnect_list {\n \t\tclose(fd);\n \t\treturn -1;\n \t}\n-\treconn->un = un;\n+\treconn->un = vsocket->un;\n \treconn->fd = fd;\n \treconn->vsocket = vsocket;\n \tpthread_mutex_lock(&reconn_list.mutex);\n@@ -627,11 +619,10 @@ struct vhost_user_reconnect_list {\n \t\t\t\tgoto out;\n \t\t\t}\n \t\t}\n-\t\tret = vhost_user_create_client(vsocket);\n \t} else {\n \t\tvsocket->is_server = true;\n-\t\tret = vhost_user_create_server(vsocket);\n \t}\n+\tret = create_unix_socket(vsocket);\n \tif (ret < 0) {\n \t\tfree(vsocket->path);\n \t\tfree(vsocket);\n@@ -687,8 +678,8 @@ struct vhost_user_reconnect_list {\n \n \t\tif (!strcmp(vsocket->path, path)) {\n \t\t\tif (vsocket->is_server) {\n-\t\t\t\tfdset_del(&vhost_user.fdset, vsocket->listenfd);\n-\t\t\t\tclose(vsocket->listenfd);\n+\t\t\t\tfdset_del(&vhost_user.fdset, vsocket->socket_fd);\n+\t\t\t\tclose(vsocket->socket_fd);\n \t\t\t\tunlink(path);\n \t\t\t} else if (vsocket->reconnect) {\n \t\t\t\tvhost_user_remove_reconnect(vsocket);\n@@ -751,8 +742,28 @@ struct vhost_device_ops const *\n }\n \n int\n-rte_vhost_driver_session_start(void)\n+rte_vhost_driver_start(const char *path)\n {\n-\tfdset_event_dispatch(&vhost_user.fdset);\n-\treturn 0;\n+\tstruct vhost_user_socket *vsocket;\n+\tstatic pthread_t fdset_tid;\n+\n+\tpthread_mutex_lock(&vhost_user.mutex);\n+\tvsocket = find_vhost_user_socket(path);\n+\tpthread_mutex_unlock(&vhost_user.mutex);\n+\n+\tif (!vsocket)\n+\t\treturn -1;\n+\n+\tif (fdset_tid == 0) {\n+\t\tint ret = pthread_create(&fdset_tid, NULL, fdset_event_dispatch,\n+\t\t\t\t     &vhost_user.fdset);\n+\t\tif (ret < 0)\n+\t\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\t\"failed to create fdset handling thread\");\n+\t}\n+\n+\tif (vsocket->is_server)\n+\t\treturn vhost_user_start_server(vsocket);\n+\telse\n+\t\treturn vhost_user_start_client(vsocket);\n }\n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "18/22"
    ]
}