Commit 5d1a2066 authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Jim Harris
Browse files

vhost: added API to call external spdk_events on vdev reactor



The next step towards fixing synchronization issues between RPC and
vhost controller reactor.

The general idea is to hide spdk_vhost_dev_find declaration, so that
vdev-related functions can't be (incorrectly) called from outside of
the vhost controller reactor. The vdev pointer should only be acquired
via spdk_vhost_call_external_event.

Change-Id: I689226c2271f81624b2651bae3b960b7efb1c01b
Signed-off-by: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/371098


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent e28f3397
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -80,4 +80,21 @@ int spdk_vhost_blk_destroy(struct spdk_vhost_dev *dev);
struct spdk_bdev *spdk_vhost_blk_get_dev(struct spdk_vhost_dev *ctrlr);
bool spdk_vhost_blk_get_readonly(struct spdk_vhost_dev *vdev);

/**
 * Call function on reactor of given vhost controller.
 * If controller is not in use, the event will be called
 * right away on the caller's thread.
 *
 * This function is thread safe.
 *
 * \param ctrlr_name name of the vhost controller to run
 * this event on
 * \param fn function to be called. The first parameter
 * of callback function is either actual spdk_vhost_dev
 * pointer or NULL in case vdev with given name doesn't
 * exist. The second param is user provided argument *arg*.
 * \param arg parameter to be passed to *fn*.
 */
void spdk_vhost_call_external_event(const char *ctrlr_name, spdk_vhost_event_fn fn, void *arg);

#endif /* SPDK_VHOST_H */
+66 −0
Original line number Diff line number Diff line
@@ -548,6 +548,26 @@ spdk_vhost_event_cb(void *arg1, void *arg2)
	sem_post(&ctx->sem);
}

static void
spdk_vhost_event_async_fn(void *arg1, void *arg2)
{
	struct spdk_vhost_dev_event_ctx *ctx = arg1;
	struct spdk_vhost_dev *vdev;

	pthread_mutex_lock(&g_spdk_vhost_mutex);
	vdev = spdk_vhost_dev_find(ctx->ctrlr_name);
	if (vdev != ctx->vdev) {
		/* vdev has been changed after enqueuing this event */
		vdev = NULL;
	}

	ctx->cb_fn(vdev, arg2);
	pthread_mutex_unlock(&g_spdk_vhost_mutex);

	free(ctx->ctrlr_name);
	free(ctx);
}

int
spdk_vhost_event_send(struct spdk_vhost_dev *vdev, spdk_vhost_event_fn cb_fn, void *arg,
		      unsigned timeout_sec, const char *errmsg)
@@ -585,6 +605,29 @@ spdk_vhost_event_send(struct spdk_vhost_dev *vdev, spdk_vhost_event_fn cb_fn, vo
	return ev_ctx.response;
}

static int
spdk_vhost_event_async_send(struct spdk_vhost_dev *vdev, spdk_vhost_event_fn cb_fn, void *arg)
{
	struct spdk_vhost_dev_event_ctx *ev_ctx;
	struct spdk_event *ev;

	ev_ctx = calloc(1, sizeof(*ev_ctx));
	if (ev_ctx == NULL) {
		SPDK_ERRLOG("Failed to alloc vhost event.\n");
		return -ENOMEM;
	}

	ev_ctx->vdev = vdev;
	ev_ctx->ctrlr_name = strdup(vdev->name);
	ev_ctx->cb_fn = cb_fn;

	ev = spdk_event_allocate(vdev->lcore, spdk_vhost_event_async_fn, ev_ctx, arg);
	assert(ev);
	spdk_event_call(ev);

	return 0;
}

static void
destroy_device(int vid)
{
@@ -822,4 +865,27 @@ destroy_connection(int vid)
	pthread_mutex_unlock(&g_spdk_vhost_mutex);
}

void
spdk_vhost_call_external_event(const char *ctrlr_name, spdk_vhost_event_fn fn, void *arg)
{
	struct spdk_vhost_dev *vdev;

	pthread_mutex_lock(&g_spdk_vhost_mutex);
	vdev = spdk_vhost_dev_find(ctrlr_name);

	if (vdev == NULL) {
		pthread_mutex_unlock(&g_spdk_vhost_mutex);
		fn(NULL, arg);
		return;
	}

	if (vdev->lcore == -1) {
		fn(vdev, arg);
	} else {
		spdk_vhost_event_async_send(vdev, fn, arg);
	}

	pthread_mutex_unlock(&g_spdk_vhost_mutex);
}

SPDK_LOG_REGISTER_TRACE_FLAG("vhost_ring", SPDK_TRACE_VHOST_RING)
+1 −7
Original line number Diff line number Diff line
@@ -451,13 +451,7 @@ bdev_remove_cb(void *remove_ctx)
{
	struct spdk_vhost_blk_dev *bvdev = remove_ctx;

	if (bvdev->vdev.lcore != -1 && (uint32_t)bvdev->vdev.lcore != spdk_env_get_current_core()) {
		/* Call on proper core. */
		spdk_vhost_event_send(&bvdev->vdev, _bdev_remove_cb, bvdev, 1, "vhost blk hot remove");
		return;
	}

	_bdev_remove_cb(&bvdev->vdev, bvdev);
	spdk_vhost_call_external_event(bvdev->vdev.name, _bdev_remove_cb, bvdev);
}