vhost/scsi: fix starting a session while SCSI targets are hotplugged

Vhost sessions currently inherit the SCSI target
status from their vhost devices when started. So
if a session is started while an asynchronous SCSI
target hotplug is in progress, the newly started
session will inherit the VHOST_SCSI_DEV_ADDING
state, which was not meant to be used in sessions
and will likely cause vhost to misbehave. The
ADDING status is used by the entire vhost device
to indicate that some sessions are still hotplugging
the SCSI target and that target can't be hotremoved
just yet. The sessions set their targets' state to
PRESENT when hotplugging them, so newly started
sessions should do the same.

This patch also prevents the same SCSI target to be
hotplugged twice to a single session. It wouldn't
cause any problems, but some resources could've been
leaked.

Change-Id: Icdbff78c167fc1f2f65137087334bd5512e81546
Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/450052
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Darek Stojaczyk 2019-04-03 19:13:41 +02:00 committed by Jim Harris
parent 2fcc09ec34
commit e1c0c4c785

View File

@ -946,15 +946,14 @@ spdk_vhost_scsi_session_add_tgt(struct spdk_vhost_dev *vdev,
return 0;
}
if (vsession->lcore == -1) {
svsession = (struct spdk_vhost_scsi_session *)vsession;
session_sdev = &svsession->scsi_dev_state[scsi_tgt_num];
if (vsession->lcore == -1 || session_sdev->dev != NULL) {
/* Nothing to do. */
return 0;
}
svsession = (struct spdk_vhost_scsi_session *)vsession;
vhost_sdev = &svsession->svdev->scsi_dev_state[scsi_tgt_num];
session_sdev = &svsession->scsi_dev_state[scsi_tgt_num];
session_sdev->dev = vhost_sdev->dev;
session_sdev->status = VHOST_SCSI_DEV_PRESENT;
@ -1333,7 +1332,7 @@ spdk_vhost_scsi_start_cb(struct spdk_vhost_dev *vdev,
assert(svsession->scsi_dev_state[i].status == VHOST_SCSI_DEV_EMPTY);
svsession->scsi_dev_state[i].dev = state->dev;
svsession->scsi_dev_state[i].status = state->status;
svsession->scsi_dev_state[i].status = VHOST_SCSI_DEV_PRESENT;
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);