Storage Performance Development Kit (SPDK)
 help / color / mirror / Atom feed
* [SPDK] [RFC PATCH 2/4] support virtio-scsi to reconnect to vhost process when vhost restart
@ 2018-05-11  3:25 Ming Lin
  0 siblings, 0 replies; only message in thread
From: Ming Lin @ 2018-05-11  3:25 UTC (permalink / raw)
  To: spdk

[-- Attachment #1: Type: text/plain, Size: 19071 bytes --]

From: Sheng Qiu <sheng.qiu(a)alibaba-inc.com>

1. virtio scsi initiator detect io timeout and vhost connection's liveness.
2. reconnect to vhost and resend pending io if current vhost connection is dead

Signed-off-by: Sheng Qiu <sheng.qiu(a)alibaba-inc.com>
---
 include/spdk/io_channel.h          |  20 +++-
 include/spdk_internal/bdev.h       |  10 ++
 include/spdk_internal/virtio.h     |  13 +++
 lib/bdev/bdev.c                    |   2 +-
 lib/bdev/virtio/bdev_virtio_scsi.c | 201 +++++++++++++++++++++++++++++++++----
 lib/util/io_channel.c              |  33 +++---
 lib/vhost/vhost.c                  |   1 +
 lib/virtio/virtio.c                |   2 +-
 lib/virtio/virtio_user.c           | 106 +++++++++++++++++++
 9 files changed, 353 insertions(+), 35 deletions(-)

diff --git a/include/spdk/io_channel.h b/include/spdk/io_channel.h
index 83a26ed..9e37f53 100644
--- a/include/spdk/io_channel.h
+++ b/include/spdk/io_channel.h
@@ -47,10 +47,10 @@ extern "C" {
 #endif
 
 struct spdk_thread;
-struct spdk_io_channel;
 struct spdk_io_channel_iter;
 struct spdk_poller;
 
+
 typedef void (*spdk_thread_fn)(void *ctx);
 typedef void (*spdk_thread_pass_msg)(spdk_thread_fn fn, void *ctx,
 				     void *thread_ctx);
@@ -70,6 +70,21 @@ typedef void (*spdk_io_device_unregister_cb)(void *io_device);
 typedef void (*spdk_channel_msg)(struct spdk_io_channel_iter *i);
 typedef void (*spdk_channel_for_each_cpl)(struct spdk_io_channel_iter *i, int status);
 
+struct spdk_io_channel {
+	struct spdk_thread              *thread;
+	struct io_device                *dev;
+	uint32_t                        ref;
+	TAILQ_ENTRY(spdk_io_channel)    tailq;
+	spdk_io_channel_destroy_cb      destroy_cb;
+
+	/*
+	 * Modules will allocate extra memory off the end of this structure
+	 * to store references to hardware-specific references (i.e. NVMe queue
+	 * pairs, or references to child device spdk_io_channels (i.e.
+	 * virtual bdevs).
+	 */
+};
+
 /**
  * \brief Initializes the calling thread for I/O channel allocation.
  *
@@ -185,6 +200,9 @@ void spdk_io_device_unregister(void *io_device, spdk_io_device_unregister_cb unr
  */
 struct spdk_io_channel *spdk_get_io_channel(void *io_device);
 
+void spdk_get_all_io_channel(void *io_device, struct spdk_io_channel **ch_array, int size,
+			     int *cnt);
+
 /**
  * \brief Releases a reference to an I/O channel. This happens asynchronously.
  *
diff --git a/include/spdk_internal/bdev.h b/include/spdk_internal/bdev.h
index 2b49819..d12907c 100644
--- a/include/spdk_internal/bdev.h
+++ b/include/spdk_internal/bdev.h
@@ -374,6 +374,15 @@ struct spdk_bdev_io {
 	/** It may be used by modules to put the bdev_io into its own list. */
 	TAILQ_ENTRY(spdk_bdev_io) module_link;
 
+	/** outstanding request queue link */
+	TAILQ_ENTRY(spdk_bdev_io) outstanding_req_link;
+
+	/** submit tick */
+	uint64_t submit_tick;
+
+	/** The I/O channel that this was submitted on. */
+	struct spdk_io_channel *io_ch;
+
 	/**
 	 * Per I/O context for use by the bdev module.
 	 */
@@ -415,6 +424,7 @@ void spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb
 void spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io,
 			   enum spdk_bdev_io_status status);
 
+void spdk_bdev_io_submit(struct spdk_bdev_io *bdev_io);
 /**
  * Complete a bdev_io with an NVMe status code.
  *
diff --git a/include/spdk_internal/virtio.h b/include/spdk_internal/virtio.h
index 69416d5..e6143e8 100644
--- a/include/spdk_internal/virtio.h
+++ b/include/spdk_internal/virtio.h
@@ -46,6 +46,7 @@
 #include "spdk/json.h"
 #include "spdk/io_channel.h"
 #include "spdk/pci_ids.h"
+#include "spdk_internal/bdev.h"
 
 /**
  * The maximum virtqueue size is 2^15. Use that value as the end of
@@ -295,6 +296,10 @@ int virtio_dev_start(struct virtio_dev *vdev, uint16_t max_queues,
  */
 void virtio_dev_stop(struct virtio_dev *vdev);
 
+/* free the allocated queue */
+void
+virtio_free_queues(struct virtio_dev *dev);
+
 /**
  * Destruct a virtio device.  Note that it must be in the stopped state.
  * The virtio_dev should be manually freed afterwards.
@@ -453,6 +458,14 @@ int virtio_pci_dev_enumerate(virtio_pci_create_cb enum_cb, uint16_t pci_device_i
 int virtio_user_dev_init(struct virtio_dev *vdev, const char *name, const char *path,
 			 uint32_t queue_size);
 
+/* check vhost aliveness */
+int
+virtio_user_check_vhost_alive(struct virtio_dev *vdev);
+
+/* reconnect vhost */
+void
+virtio_user_dev_reconnect(struct virtio_dev *vdev);
+
 /**
  * Initialize virtio_dev for a given PCI device.
  * The virtio_dev has to be freed with \c virtio_dev_destruct.
diff --git a/lib/bdev/bdev.c b/lib/bdev/bdev.c
index c3aa063..3d34e44 100644
--- a/lib/bdev/bdev.c
+++ b/lib/bdev/bdev.c
@@ -767,7 +767,7 @@ spdk_bdev_put_io(struct spdk_bdev_io *bdev_io)
 	}
 }
 
-static void
+void
 spdk_bdev_io_submit(struct spdk_bdev_io *bdev_io)
 {
 	struct spdk_bdev *bdev = bdev_io->bdev;
diff --git a/lib/bdev/virtio/bdev_virtio_scsi.c b/lib/bdev/virtio/bdev_virtio_scsi.c
index 94f4835..0602597 100644
--- a/lib/bdev/virtio/bdev_virtio_scsi.c
+++ b/lib/bdev/virtio/bdev_virtio_scsi.c
@@ -66,6 +66,10 @@
 #define VIRTIO_SCSI_EVENTQ	1
 #define VIRTIO_SCSI_REQUESTQ	2
 
+/* io timeout value in second */
+#define VIRTIO_SCSI_IO_TIMEMOUT	(1)
+
+
 static int bdev_virtio_initialize(void);
 static void bdev_virtio_finish(void);
 
@@ -90,6 +94,9 @@ struct virtio_scsi_dev {
 
 	/** Device marked for removal. */
 	bool removed;
+
+	/** protect reconnect process */
+	pthread_mutex_t reconn_mutex;
 };
 
 struct virtio_scsi_io_ctx {
@@ -165,6 +172,15 @@ struct bdev_virtio_io_channel {
 
 	/** Virtio response poller. */
 	struct spdk_poller	*poller;
+
+	/** Outstanding Req in this channel */
+	TAILQ_HEAD(virtio_outstanding_req_head, spdk_bdev_io) outstanding_req;
+
+	/** protect channel's status update */
+	pthread_mutex_t 	lock;
+
+	/** whether channel is reconnecting */
+	bool			reconnecting;
 };
 
 /** Module finish in progress */
@@ -268,6 +284,7 @@ virtio_scsi_dev_init(struct virtio_scsi_dev *svdev, uint16_t max_queues)
 	TAILQ_INIT(&svdev->luns);
 	svdev->scan_ctx = NULL;
 	svdev->removed = false;
+	pthread_mutex_init(&svdev->reconn_mutex, NULL);
 
 	spdk_io_device_register(svdev, bdev_virtio_scsi_ch_create_cb,
 				bdev_virtio_scsi_ch_destroy_cb,
@@ -445,29 +462,52 @@ bdev_virtio_send_io(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
 	struct bdev_virtio_io_channel *virtio_channel = spdk_io_channel_get_ctx(ch);
 	struct virtqueue *vq = virtio_channel->vq;
 	struct virtio_scsi_io_ctx *io_ctx = (struct virtio_scsi_io_ctx *)bdev_io->driver_ctx;
-	int rc;
+	int rc = 0;
 
-	rc = virtqueue_req_start(vq, bdev_io, bdev_io->u.bdev.iovcnt + 2);
-	if (rc == -ENOMEM) {
-		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
-		return;
-	} else if (rc != 0) {
-		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
-		return;
+	/* this lock is per channel, only in reconnecting phase it has contention */
+	pthread_mutex_lock(&virtio_channel->lock);
+
+	/* only submit io to vq if it's not in reconnecting */
+	if (!virtio_channel->reconnecting) {
+
+		rc = virtqueue_req_start(vq, bdev_io, bdev_io->u.bdev.iovcnt + 2);
+		if (rc == -ENOMEM) {
+			SPDK_ERRLOG("no memory to submit io\n");
+			spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM);
+			pthread_mutex_unlock(&virtio_channel->lock);
+			return;
+		} else if (rc != 0) {
+			SPDK_ERRLOG("io submit failed\n");
+			spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
+			pthread_mutex_unlock(&virtio_channel->lock);
+			return;
+		}
+
+		virtqueue_req_add_iovs(vq, &io_ctx->iov_req, 1, SPDK_VIRTIO_DESC_RO);
+		if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
+			virtqueue_req_add_iovs(vq, &io_ctx->iov_resp, 1, SPDK_VIRTIO_DESC_WR);
+			virtqueue_req_add_iovs(vq, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
+					       SPDK_VIRTIO_DESC_WR);
+		} else {
+			virtqueue_req_add_iovs(vq, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
+					       SPDK_VIRTIO_DESC_RO);
+			virtqueue_req_add_iovs(vq, &io_ctx->iov_resp, 1, SPDK_VIRTIO_DESC_WR);
+		}
+
+		virtqueue_req_flush(vq);
 	}
 
-	virtqueue_req_add_iovs(vq, &io_ctx->iov_req, 1, SPDK_VIRTIO_DESC_RO);
-	if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
-		virtqueue_req_add_iovs(vq, &io_ctx->iov_resp, 1, SPDK_VIRTIO_DESC_WR);
-		virtqueue_req_add_iovs(vq, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
-				       SPDK_VIRTIO_DESC_WR);
-	} else {
-		virtqueue_req_add_iovs(vq, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
-				       SPDK_VIRTIO_DESC_RO);
-		virtqueue_req_add_iovs(vq, &io_ctx->iov_resp, 1, SPDK_VIRTIO_DESC_WR);
+	/* add io to pending queue if it's successfully submit or it's in reconnecting phase */
+	if (rc == 0) {
+		bdev_io->submit_tick = spdk_get_ticks();
+		bdev_io->io_ch = ch;
+		struct spdk_bdev_io *last = TAILQ_LAST(&virtio_channel->outstanding_req,
+						       virtio_outstanding_req_head);
+		assert(last != bdev_io);
+		TAILQ_INSERT_TAIL(&virtio_channel->outstanding_req, bdev_io, outstanding_req_link);
 	}
 
-	virtqueue_req_flush(vq);
+	pthread_mutex_unlock(&virtio_channel->lock);
 }
 
 static void
@@ -592,6 +632,7 @@ static int _bdev_virtio_submit_request(struct spdk_io_channel *ch, struct spdk_b
 	default:
 		return -1;
 	}
+
 	return 0;
 }
 
@@ -700,6 +741,113 @@ bdev_virtio_io_cpl(struct spdk_bdev_io *bdev_io)
 	spdk_bdev_io_complete_scsi_status(bdev_io, io_ctx->resp.status, sk, asc, ascq);
 }
 
+static int
+bdev_virtio_check_timeout(struct bdev_virtio_io_channel *ch)
+{
+	uint64_t t02;
+	struct spdk_bdev_io *bdev_io;
+	uint64_t timeout_tick = VIRTIO_SCSI_IO_TIMEMOUT * spdk_get_ticks_hz();
+
+	t02 = spdk_get_ticks();
+
+	bdev_io = TAILQ_FIRST(&ch->outstanding_req);
+	if (bdev_io == NULL) {
+		return 0;
+	}
+
+	/* check the oldest request */
+	if (bdev_io->submit_tick + timeout_tick > t02) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+static void
+bdev_virtio_update_all_channel_status(struct virtio_scsi_dev *svdev, bool is_reconnecting)
+{
+	struct spdk_io_channel *ch[1024] = {NULL};
+	int cnt = 0, i;
+	struct bdev_virtio_io_channel *virtio_channel;
+
+	spdk_get_all_io_channel(svdev, ch, 1024, &cnt);
+	for (i = 0; i < cnt; i++) {
+		virtio_channel = spdk_io_channel_get_ctx(ch[i]);
+		pthread_mutex_lock(&virtio_channel->lock);
+		virtio_channel->reconnecting = is_reconnecting;
+		pthread_mutex_unlock(&virtio_channel->lock);
+	}
+}
+
+static void
+bdev_virtio_update_all_io_channel_vq(struct virtio_scsi_dev *svdev)
+{
+	struct spdk_io_channel *ch[1024] = {NULL};
+	int cnt = 0, i;
+	struct bdev_virtio_io_channel *virtio_channel;
+	int32_t queue_idx;
+
+	spdk_get_all_io_channel(svdev, ch, 1024, &cnt);
+	for (i = 0; i < cnt; i++) {
+		virtio_channel = spdk_io_channel_get_ctx(ch[i]);
+		queue_idx = virtio_dev_find_and_acquire_queue(&svdev->vdev, VIRTIO_SCSI_REQUESTQ);
+		if (queue_idx < 0) {
+			SPDK_ERRLOG("Couldn't get an unused queue for the io_channel.\n");
+			assert(0);
+		}
+
+		virtio_channel->vq = svdev->vdev.vqs[queue_idx];
+		virtio_channel->svdev = svdev;
+	}
+}
+
+/*
+ * reconnect to vhost
+ * return only if reconnect is successful
+ * */
+static bool
+bdev_virtio_reconnect(struct virtio_scsi_dev *svdev)
+{
+	bool reconnected = false;
+	/* only one thread can initiate reconnect */
+	pthread_mutex_lock(&svdev->reconn_mutex);
+	if (virtio_user_check_vhost_alive(&svdev->vdev) != 0) {
+		/* lock all virtio channels */
+		bdev_virtio_update_all_channel_status(svdev, true);
+		virtio_user_dev_reconnect(&svdev->vdev);
+		/* update all virtio channels pointing to new vqs*/
+		bdev_virtio_update_all_io_channel_vq(svdev);
+		/* unlock all virtio channels */
+		bdev_virtio_update_all_channel_status(svdev, false);
+		reconnected = true;
+	}
+	pthread_mutex_unlock(&svdev->reconn_mutex);
+
+	return reconnected;
+}
+
+/*
+ * resend pending requests
+ * */
+static void
+bdev_virtio_resend_pending_req(struct virtio_scsi_dev *svdev, struct bdev_virtio_io_channel *ch)
+{
+	struct spdk_bdev_io *bdev_io, *tmp;
+	TAILQ_HEAD(virtio_outstanding_req_head, spdk_bdev_io) requests;
+
+	TAILQ_INIT(&requests);
+	TAILQ_SWAP(&ch->outstanding_req, &requests, spdk_bdev_io, outstanding_req_link);
+
+	TAILQ_FOREACH_SAFE(bdev_io, &requests, outstanding_req_link, tmp) {
+		TAILQ_REMOVE(&requests, (struct spdk_bdev_io *)bdev_io, outstanding_req_link);
+
+		/* Make sure it's in PENDING status */
+		if (bdev_io->status != SPDK_BDEV_IO_STATUS_PENDING)
+			abort();
+		spdk_bdev_io_submit(bdev_io);
+	}
+}
+
 static void
 bdev_virtio_poll(void *arg)
 {
@@ -730,6 +878,9 @@ bdev_virtio_poll(void *arg)
 			continue;
 		}
 
+		/* remove from outstanding queue */
+		TAILQ_REMOVE(&ch->outstanding_req, (struct spdk_bdev_io *)io[i], outstanding_req_link);
+
 		bdev_virtio_io_cpl(io[i]);
 	}
 
@@ -750,6 +901,17 @@ bdev_virtio_poll(void *arg)
 				_virtio_scsi_dev_scan_finish(scan_ctx, rc);
 			}
 		}
+
+		return;
+	}
+
+	if (cnt == 0 && bdev_virtio_check_timeout(ch)) {
+		/* block and reconnect */
+		bool reconnected = bdev_virtio_reconnect(svdev);
+
+		/* resend all outstanding io */
+		if (reconnected)
+			bdev_virtio_resend_pending_req(svdev, ch);
 	}
 }
 
@@ -913,6 +1075,9 @@ bdev_virtio_scsi_ch_create_cb(void *io_device, void *ctx_buf)
 
 	ch->svdev = svdev;
 	ch->vq = vq;
+	ch->reconnecting = false;
+	pthread_mutex_init(&ch->lock, NULL);
+	TAILQ_INIT(&ch->outstanding_req);
 
 	ch->poller = spdk_poller_register(bdev_virtio_poll, ch, 0);
 
diff --git a/lib/util/io_channel.c b/lib/util/io_channel.c
index e1ac2c2..0e803c5 100644
--- a/lib/util/io_channel.c
+++ b/lib/util/io_channel.c
@@ -60,20 +60,6 @@ struct io_device {
 
 static TAILQ_HEAD(, io_device) g_io_devices = TAILQ_HEAD_INITIALIZER(g_io_devices);
 
-struct spdk_io_channel {
-	struct spdk_thread		*thread;
-	struct io_device		*dev;
-	uint32_t			ref;
-	TAILQ_ENTRY(spdk_io_channel)	tailq;
-	spdk_io_channel_destroy_cb	destroy_cb;
-
-	/*
-	 * Modules will allocate extra memory off the end of this structure
-	 *  to store references to hardware-specific references (i.e. NVMe queue
-	 *  pairs, or references to child device spdk_io_channels (i.e.
-	 *  virtual bdevs).
-	 */
-};
 
 struct spdk_thread {
 	pthread_t thread_id;
@@ -396,6 +382,25 @@ spdk_io_device_unregister(void *io_device, spdk_io_device_unregister_cb unregist
 	_spdk_io_device_attempt_free(dev);
 }
 
+void
+spdk_get_all_io_channel(void *io_device, struct spdk_io_channel **ch_array, int size,  int *cnt)
+{
+	struct spdk_thread *thread;
+	struct spdk_io_channel *ch;
+	int i = 0;
+
+	TAILQ_FOREACH(thread, &g_threads, tailq) {
+		TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
+			if (ch->dev->io_device == io_device) {
+				ch_array[i++] = ch;
+				assert(i < size);
+			}
+		}
+	}
+
+	*cnt = i;
+}
+
 struct spdk_io_channel *
 spdk_get_io_channel(void *io_device)
 {
diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c
index bd3473e..79a2a21 100644
--- a/lib/vhost/vhost.c
+++ b/lib/vhost/vhost.c
@@ -1138,6 +1138,7 @@ destroy_connection(int vid)
 
 	/* since pollers are not running it safe not to use spdk_event here */
 	vdev->vid = -1;
+	vdev->status = 0;
 	pthread_mutex_unlock(&g_spdk_vhost_mutex);
 }
 
diff --git a/lib/virtio/virtio.c b/lib/virtio/virtio.c
index 3e22d9e..f4c0e5d 100644
--- a/lib/virtio/virtio.c
+++ b/lib/virtio/virtio.c
@@ -233,7 +233,7 @@ fail_q_alloc:
 	return ret;
 }
 
-static void
+void
 virtio_free_queues(struct virtio_dev *dev)
 {
 	uint16_t nr_vq = dev->max_queues;
diff --git a/lib/virtio/virtio_user.c b/lib/virtio/virtio_user.c
index d7010cc..86237a5 100644
--- a/lib/virtio/virtio_user.c
+++ b/lib/virtio/virtio_user.c
@@ -46,6 +46,10 @@
 
 #include "spdk_internal/virtio.h"
 
+/* reconnect interval in second */
+#define RECONNECT_INTERVAL (3)
+
+
 static int
 virtio_user_create_queue(struct virtio_dev *vdev, uint32_t queue_sel)
 {
@@ -400,6 +404,108 @@ static const struct virtio_dev_ops virtio_user_ops = {
 	.dump_json_config = virtio_user_dump_json_config,
 };
 
+
+
+int
+virtio_user_check_vhost_alive(struct virtio_dev *vdev)
+{
+	struct virtio_user_dev *dev = vdev->ctx;
+	uint64_t host_max_queues;
+	int ret;
+
+	/* ignore SIGPIPE, so won't exit on broken pipe */
+	signal(SIGPIPE, SIG_IGN);
+
+	/* Hack: use VHOST_USER_GET_QUEUE_NUM to check vhost alive */
+	ret = dev->ops->send_request(dev, VHOST_USER_GET_QUEUE_NUM, &host_max_queues);
+	return ret;
+}
+
+static int
+vhost_user_check_vhost_socket(struct virtio_user_dev *dev)
+{
+	int fd;
+	struct sockaddr_un un;
+	ssize_t rc;
+
+	fd = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (fd < 0)
+		return -1;
+
+	memset(&un, 0, sizeof(un));
+	un.sun_family = AF_UNIX;
+
+	rc = snprintf(un.sun_path, sizeof(un.sun_path), "%s", dev->path);
+	if (rc < 0 || (size_t)rc >= sizeof(un.sun_path)) {
+		close(fd);
+		return -1;
+	}
+
+	if (connect(fd, (struct sockaddr *)&un, sizeof(un)) < 0) {
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+	return 0;
+}
+
+static int
+_virtio_user_del_queue(struct virtio_dev *vdev, uint32_t queue_sel)
+{
+	struct virtio_user_dev *dev = vdev->ctx;
+	close(dev->callfds[queue_sel]);
+	close(dev->kickfds[queue_sel]);
+	dev->callfds[queue_sel] = -1;
+	dev->kickfds[queue_sel] = -1;
+	return 0;
+}
+
+static int
+virtio_user_dev_reconnect_impl(struct virtio_dev *vdev, const char *name, const char *path,
+			       uint32_t queue_size)
+{
+	virtio_user_queue_setup(vdev, _virtio_user_del_queue);
+	virtio_free_queues(vdev);
+	virtio_dev_destruct(vdev);
+
+	virtio_user_dev_init(vdev, name, path, queue_size);
+	virtio_dev_start(vdev, vdev->max_queues - vdev->fixed_queues_num, vdev->fixed_queues_num);
+	return 0;
+}
+
+void
+virtio_user_dev_reconnect(struct virtio_dev *vdev)
+{
+	bool alive = false;
+
+	while (1) {
+		struct virtio_user_dev *dev = vdev->ctx;
+
+		/* check vhost liveness before reconnect */
+		if (!alive)
+			alive = virtio_user_check_vhost_alive(vdev) == 0;
+
+		if (!alive) {
+			if (vhost_user_check_vhost_socket(dev) == 0) {
+				SPDK_NOTICELOG("Reconnecting: start reconnect %s\n", dev->path);
+				char path[PATH_MAX];
+				memcpy(path, dev->path, PATH_MAX);
+				virtio_user_dev_reconnect_impl(vdev, vdev->name, path, dev->queue_size);
+
+				sleep(RECONNECT_INTERVAL);
+			} else {
+				/* vhost socket not ready, wait some time*/
+				sleep(RECONNECT_INTERVAL);
+			}
+		} else {
+			break;
+		}
+	}
+
+	SPDK_NOTICELOG("Reconnecting: done\n");
+}
+
 int
 virtio_user_dev_init(struct virtio_dev *vdev, const char *name, const char *path,
 		     uint32_t queue_size)
-- 
1.9.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2018-05-11  3:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-11  3:25 [SPDK] [RFC PATCH 2/4] support virtio-scsi to reconnect to vhost process when vhost restart Ming Lin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox