Commit ad9a842c authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Daniel Verkamp
Browse files

rpc/vhost_scsi: defer remove_scsi_dev RPC response



Defer writing RPC response until after the device has been hotremoved.

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


Reviewed-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent f61b71d7
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -73,7 +73,8 @@ int spdk_vhost_scsi_dev_remove(struct spdk_vhost_dev *vdev);
struct spdk_scsi_dev *spdk_vhost_scsi_dev_get_dev(struct spdk_vhost_dev *ctrl, uint8_t num);
int spdk_vhost_scsi_dev_add_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_num,
				const char *lun_name);
int spdk_vhost_scsi_dev_remove_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_num);
int spdk_vhost_scsi_dev_remove_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_num,
				   spdk_vhost_event_fn cb_fn, void *cb_arg);

int spdk_vhost_blk_construct(const char *name, const char *cpumask, const char *dev_name,
			     bool readonly);
+22 −12
Original line number Diff line number Diff line
@@ -307,33 +307,43 @@ static const struct spdk_json_object_decoder rpc_vhost_remove_dev[] = {
};

static int
spdk_rpc_remove_vhost_scsi_dev_cb(struct spdk_vhost_dev *vdev, void *arg)
spdk_rpc_remove_vhost_scsi_dev_finish_cb(struct spdk_vhost_dev *vdev, void *arg)
{
	struct rpc_remove_vhost_scsi_ctrlr_dev *rpc = arg;
	struct spdk_jsonrpc_request *request = rpc->request;
	struct spdk_json_write_ctx *w;
	int rc;

	free_rpc_remove_vhost_scsi_ctrlr_dev(rpc);

	w = spdk_jsonrpc_begin_result(request);
	if (w == NULL) {
		return -1;
	}

	spdk_json_write_bool(w, true);
	spdk_jsonrpc_end_result(request, w);
	return 0;
}

static int
spdk_rpc_remove_vhost_scsi_dev_cb(struct spdk_vhost_dev *vdev, void *arg)
{
	struct rpc_remove_vhost_scsi_ctrlr_dev *rpc = arg;
	struct spdk_jsonrpc_request *request = rpc->request;
	char buf[64];
	int rc;

	if (vdev == NULL) {
		rc = -ENODEV;
		goto invalid;
	}

	rc = spdk_vhost_scsi_dev_remove_dev(vdev, rpc->scsi_dev_num);
	rc = spdk_vhost_scsi_dev_remove_dev(vdev, rpc->scsi_dev_num,
					    spdk_rpc_remove_vhost_scsi_dev_finish_cb, rpc);
	if (rc < 0) {
		goto invalid;
	}

	free_rpc_remove_vhost_scsi_ctrlr_dev(rpc);

	w = spdk_jsonrpc_begin_result(request);
	if (w == NULL) {
		return -1;
	}

	spdk_json_write_bool(w, true);
	spdk_jsonrpc_end_result(request, w);
	return 0;

invalid:
+34 −7
Original line number Diff line number Diff line
@@ -66,10 +66,16 @@
#define VIRTIO_SCSI_EVENTQ   1
#define VIRTIO_SCSI_REQUESTQ   2

struct spdk_scsi_dev_vhost_state {
	bool removed;
	spdk_vhost_event_fn remove_cb;
	void *remove_ctx;
};

struct spdk_vhost_scsi_dev {
	struct spdk_vhost_dev vdev;
	struct spdk_scsi_dev *scsi_dev[SPDK_VHOST_SCSI_CTRLR_MAX_DEVS];
	bool removed_dev[SPDK_VHOST_SCSI_CTRLR_MAX_DEVS];
	struct spdk_scsi_dev_vhost_state scsi_dev_state[SPDK_VHOST_SCSI_CTRLR_MAX_DEVS];

	struct spdk_ring *task_pool;
	struct spdk_poller *requestq_poller;
@@ -142,15 +148,21 @@ static void
process_removed_devs(struct spdk_vhost_scsi_dev *svdev)
{
	struct spdk_scsi_dev *dev;
	struct spdk_scsi_dev_vhost_state *state;
	int i;

	for (i = 0; i < SPDK_VHOST_SCSI_CTRLR_MAX_DEVS; ++i) {
		dev = svdev->scsi_dev[i];
		state = &svdev->scsi_dev_state[i];

		if (dev && svdev->removed_dev[i] && !spdk_scsi_dev_has_pending_tasks(dev)) {
		if (dev && state->removed && !spdk_scsi_dev_has_pending_tasks(dev)) {
			spdk_scsi_dev_free_io_channels(dev);
			spdk_scsi_dev_destruct(dev);
			svdev->scsi_dev[i] = NULL;
			if (state->remove_cb) {
				state->remove_cb(&svdev->vdev, state->remove_ctx);
				state->remove_cb = NULL;
			}
			SPDK_NOTICELOG("%s: hot-detached device 'Dev %u'.\n", svdev->vdev.name, i);
		}
	}
@@ -281,7 +293,7 @@ spdk_vhost_scsi_task_init_target(struct spdk_vhost_scsi_task *task, const __u8 *
		/* If dev has been hotdetached, return 0 to allow sending
		 * additional hotremove event via sense codes.
		 */
		return task->svdev->removed_dev[lun[1]] ? 0 : -1;
		return task->svdev->scsi_dev_state[lun[1]].removed ? 0 : -1;
	}

	task->scsi.target_port = spdk_scsi_dev_find_port_by_id(task->scsi_dev, 0);
@@ -741,7 +753,7 @@ spdk_vhost_scsi_dev_add_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_num,
	lun_id_list[0] = 0;
	lun_names_list[0] = (char *)lun_name;

	svdev->removed_dev[scsi_dev_num] = false;
	svdev->scsi_dev_state[scsi_dev_num].removed = false;
	svdev->scsi_dev[scsi_dev_num] = spdk_scsi_dev_construct(dev_name, lun_names_list, lun_id_list, 1,
					SPDK_SPC_PROTOCOL_IDENTIFIER_SAS, spdk_vhost_scsi_lun_hotremove, svdev);

@@ -763,10 +775,13 @@ spdk_vhost_scsi_dev_add_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_num,
}

int
spdk_vhost_scsi_dev_remove_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_num)
spdk_vhost_scsi_dev_remove_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_num,
			       spdk_vhost_event_fn cb_fn, void *cb_arg)
{
	struct spdk_vhost_scsi_dev *svdev;
	struct spdk_scsi_dev *scsi_dev;
	struct spdk_scsi_dev_vhost_state *scsi_dev_state;
	int rc = 0;

	if (scsi_dev_num >= SPDK_VHOST_SCSI_CTRLR_MAX_DEVS) {
		SPDK_ERRLOG("%s: invalid device number %d\n", vdev->name, scsi_dev_num);
@@ -788,8 +803,11 @@ spdk_vhost_scsi_dev_remove_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_nu
		/* controller is not in use, remove dev and exit */
		spdk_scsi_dev_destruct(scsi_dev);
		svdev->scsi_dev[scsi_dev_num] = NULL;
		if (cb_fn) {
			rc = cb_fn(vdev, cb_arg);
		}
		SPDK_NOTICELOG("%s: removed device 'Dev %u'\n", vdev->name, scsi_dev_num);
		return 0;
		return rc;
	}

	if (!spdk_vhost_dev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
@@ -798,7 +816,16 @@ spdk_vhost_scsi_dev_remove_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_nu
		return -ENOTSUP;
	}

	svdev->removed_dev[scsi_dev_num] = true;
	scsi_dev_state = &svdev->scsi_dev_state[scsi_dev_num];
	if (scsi_dev_state->removed) {
		SPDK_WARNLOG("%s: 'Dev %u' has been already marked to hotremove.\n", svdev->vdev.name,
			     scsi_dev_num);
		return -EBUSY;
	}

	scsi_dev_state->remove_cb = cb_fn;
	scsi_dev_state->remove_ctx = cb_arg;
	scsi_dev_state->removed = true;
	eventq_enqueue(svdev, scsi_dev_num, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED);

	SPDK_NOTICELOG("%s: queued 'Dev %u' for hot-detach.\n", vdev->name, scsi_dev_num);
+3 −3
Original line number Diff line number Diff line
@@ -282,11 +282,11 @@ vhost_scsi_dev_remove_dev_test(void)
	svdev->vdev.name = strdup("vhost.0");

	/* Invalid device number */
	rc = spdk_vhost_scsi_dev_remove_dev(&svdev->vdev, SPDK_VHOST_SCSI_CTRLR_MAX_DEVS + 1);
	rc = spdk_vhost_scsi_dev_remove_dev(&svdev->vdev, SPDK_VHOST_SCSI_CTRLR_MAX_DEVS + 1, NULL, NULL);
	CU_ASSERT(rc == -EINVAL);

	/* Try to remove nonexistent device */
	rc = spdk_vhost_scsi_dev_remove_dev(&svdev->vdev, 0);
	rc = spdk_vhost_scsi_dev_remove_dev(&svdev->vdev, 0, NULL, NULL);
	CU_ASSERT(rc == -ENODEV);

	/* Try to remove device when controller is in use */
@@ -294,7 +294,7 @@ vhost_scsi_dev_remove_dev_test(void)
	scsi_dev = alloc_scsi_dev();
	svdev->scsi_dev[0] = scsi_dev;
	MOCK_SET(spdk_vhost_dev_has_feature, bool, false);
	rc = spdk_vhost_scsi_dev_remove_dev(&svdev->vdev, 0);
	rc = spdk_vhost_scsi_dev_remove_dev(&svdev->vdev, 0, NULL, NULL);
	CU_ASSERT(rc == -ENOTSUP);
	free(scsi_dev);
	free(svdev->vdev.name);