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: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/371119
Reviewed-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Dariusz Stojaczyk 2017-07-25 15:42:27 +02:00 committed by Daniel Verkamp
parent f61b71d71a
commit ad9a842c71
4 changed files with 62 additions and 24 deletions

View File

@ -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);

View File

@ -307,23 +307,11 @@ 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;
char buf[64];
if (vdev == NULL) {
rc = -ENODEV;
goto invalid;
}
rc = spdk_vhost_scsi_dev_remove_dev(vdev, rpc->scsi_dev_num);
if (rc < 0) {
goto invalid;
}
free_rpc_remove_vhost_scsi_ctrlr_dev(rpc);
@ -335,6 +323,28 @@ spdk_rpc_remove_vhost_scsi_dev_cb(struct spdk_vhost_dev *vdev, void *arg)
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,
spdk_rpc_remove_vhost_scsi_dev_finish_cb, rpc);
if (rc < 0) {
goto invalid;
}
return 0;
invalid:
free_rpc_remove_vhost_scsi_ctrlr_dev(rpc);

View File

@ -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);

View File

@ -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);