vhost/scsi: handle io_channel allocation failure

We assumed io_channel allocation always succeeds, but
that's not true. Doing I/O to any vhost session that
failed to allocate an io_channel would most likely
cause a crash.

We'll now detect io_channel allocation failure and
print a proper error message. The SCSI target for
which the channel allocation failed simply won't be
visible to the vhost master. All I/O to that target
will be rejected.

We should probably report the error to the upper
layer and either prevent the device from starting
or fail the SCSI target hotplug request. But for now
let's just prevent the crash.

Change-Id: I735dfb930d8905f70636a236b4fa94288d0aaf3a
Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/444874
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Darek Stojaczyk 2019-02-15 11:29:09 +01:00 committed by Jim Harris
parent 6b0d7b82c9
commit 5d07cfad54

View File

@ -900,13 +900,14 @@ spdk_vhost_scsi_session_add_tgt(struct spdk_vhost_dev *vdev,
{
unsigned scsi_tgt_num = (unsigned)(uintptr_t)ctx;
struct spdk_vhost_scsi_session *svsession;
int rc;
if (vsession == NULL) {
/* Nothing more to do */
return 0;
}
svsession = (struct spdk_vhost_scsi_session *)vsession;;
svsession = (struct spdk_vhost_scsi_session *)vsession;
/* copy the entire device state */
svsession->scsi_dev_state[scsi_tgt_num] = svsession->svdev->scsi_dev_state[scsi_tgt_num];
@ -915,7 +916,25 @@ spdk_vhost_scsi_session_add_tgt(struct spdk_vhost_dev *vdev,
return 0;
}
spdk_scsi_dev_allocate_io_channels(svsession->scsi_dev_state[scsi_tgt_num].dev);
rc = spdk_scsi_dev_allocate_io_channels(svsession->scsi_dev_state[scsi_tgt_num].dev);
if (rc != 0) {
SPDK_ERRLOG("Couldn't allocate io channnel for SCSI target %u in device %s\n",
scsi_tgt_num, vdev->name);
/* unset the SCSI target so that all I/O to it will be rejected */
svsession->scsi_dev_state[scsi_tgt_num].dev = NULL;
/* unset the removed flag so that we won't reply with SCSI hotremove
* sense codes - the device hasn't ever been added.
*/
svsession->scsi_dev_state[scsi_tgt_num].removed = false;
/* Return with no error. We'll continue allocating io_channels for
* other sessions on this device in hopes they succeed. The sessions
* that failed to allocate io_channels simply won't be able to
* detect the SCSI target, nor do any I/O to it.
*/
return 0;
}
if (spdk_vhost_dev_has_feature(vsession, VIRTIO_SCSI_F_HOTPLUG)) {
eventq_enqueue(svsession, scsi_tgt_num,
@ -1249,7 +1268,17 @@ spdk_vhost_scsi_start_cb(struct spdk_vhost_dev *vdev,
continue;
}
svsession->scsi_dev_state[i] = *state;
spdk_scsi_dev_allocate_io_channels(state->dev);
rc = spdk_scsi_dev_allocate_io_channels(state->dev);
if (rc != 0) {
SPDK_ERRLOG("%s: failed to alloc io_channel for SCSI target %"PRIu32"\n", vdev->name, i);
/* unset the SCSI target so that all I/O to it will be rejected */
svsession->scsi_dev_state[i].dev = NULL;
/* unset the removed flag so that we won't reply with SCSI hotremove
* sense codes - the device hasn't ever been added.
*/
svsession->scsi_dev_state[i].removed = false;
continue;
}
}
SPDK_INFOLOG(SPDK_LOG_VHOST, "Started poller for vhost controller %s on lcore %d\n",
vdev->name, vsession->lcore);