aboutsummaryrefslogtreecommitdiff
path: root/drivers/vhost/scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vhost/scsi.c')
-rw-r--r--drivers/vhost/scsi.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 962c7e3c3baa..fb97bc0b80e7 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -820,6 +820,23 @@ static int vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd,
return 0;
}
+static int vhost_scsi_to_tcm_attr(int attr)
+{
+ switch (attr) {
+ case VIRTIO_SCSI_S_SIMPLE:
+ return MSG_SIMPLE_TAG;
+ case VIRTIO_SCSI_S_ORDERED:
+ return MSG_ORDERED_TAG;
+ case VIRTIO_SCSI_S_HEAD:
+ return MSG_HEAD_TAG;
+ case VIRTIO_SCSI_S_ACA:
+ return MSG_ACA_TAG;
+ default:
+ break;
+ }
+ return MSG_SIMPLE_TAG;
+}
+
static void tcm_vhost_submission_work(struct work_struct *work)
{
struct tcm_vhost_cmd *tv_cmd =
@@ -846,9 +863,9 @@ static void tcm_vhost_submission_work(struct work_struct *work)
rc = target_submit_cmd_map_sgls(se_cmd, tv_nexus->tvn_se_sess,
tv_cmd->tvc_cdb, &tv_cmd->tvc_sense_buf[0],
tv_cmd->tvc_lun, tv_cmd->tvc_exp_data_len,
- tv_cmd->tvc_task_attr, tv_cmd->tvc_data_direction,
- 0, sg_ptr, tv_cmd->tvc_sgl_count,
- sg_bidi_ptr, sg_no_bidi);
+ vhost_scsi_to_tcm_attr(tv_cmd->tvc_task_attr),
+ tv_cmd->tvc_data_direction, 0, sg_ptr,
+ tv_cmd->tvc_sgl_count, sg_bidi_ptr, sg_no_bidi);
if (rc < 0) {
transport_send_check_condition_and_sense(se_cmd,
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
@@ -1150,6 +1167,7 @@ static int vhost_scsi_set_endpoint(
struct vhost_scsi *vs,
struct vhost_scsi_target *t)
{
+ struct se_portal_group *se_tpg;
struct tcm_vhost_tport *tv_tport;
struct tcm_vhost_tpg *tv_tpg;
struct tcm_vhost_tpg **vs_tpg;
@@ -1197,6 +1215,21 @@ static int vhost_scsi_set_endpoint(
ret = -EEXIST;
goto out;
}
+ /*
+ * In order to ensure individual vhost-scsi configfs
+ * groups cannot be removed while in use by vhost ioctl,
+ * go ahead and take an explicit se_tpg->tpg_group.cg_item
+ * dependency now.
+ */
+ se_tpg = &tv_tpg->se_tpg;
+ ret = configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys,
+ &se_tpg->tpg_group.cg_item);
+ if (ret) {
+ pr_warn("configfs_depend_item() failed: %d\n", ret);
+ kfree(vs_tpg);
+ mutex_unlock(&tv_tpg->tv_tpg_mutex);
+ goto out;
+ }
tv_tpg->tv_tpg_vhost_count++;
tv_tpg->vhost_scsi = vs;
vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
@@ -1240,6 +1273,7 @@ static int vhost_scsi_clear_endpoint(
struct vhost_scsi *vs,
struct vhost_scsi_target *t)
{
+ struct se_portal_group *se_tpg;
struct tcm_vhost_tport *tv_tport;
struct tcm_vhost_tpg *tv_tpg;
struct vhost_virtqueue *vq;
@@ -1288,6 +1322,13 @@ static int vhost_scsi_clear_endpoint(
vs->vs_tpg[target] = NULL;
match = true;
mutex_unlock(&tv_tpg->tv_tpg_mutex);
+ /*
+ * Release se_tpg->tpg_group.cg_item configfs dependency now
+ * to allow vhost-scsi WWPN se_tpg->tpg_group shutdown to occur.
+ */
+ se_tpg = &tv_tpg->se_tpg;
+ configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys,
+ &se_tpg->tpg_group.cg_item);
}
if (match) {
for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {