|
@@ -48,12 +48,14 @@
|
|
|
#include <linux/virtio_scsi.h>
|
|
|
#include <linux/llist.h>
|
|
|
#include <linux/bitmap.h>
|
|
|
+#include <linux/percpu_ida.h>
|
|
|
|
|
|
#include "vhost.h"
|
|
|
|
|
|
#define TCM_VHOST_VERSION "v0.1"
|
|
|
#define TCM_VHOST_NAMELEN 256
|
|
|
#define TCM_VHOST_MAX_CDB_SIZE 32
|
|
|
+#define TCM_VHOST_DEFAULT_TAGS 256
|
|
|
|
|
|
struct vhost_scsi_inflight {
|
|
|
/* Wait for the flush operation to finish */
|
|
@@ -450,6 +452,7 @@ static void tcm_vhost_release_cmd(struct se_cmd *se_cmd)
|
|
|
{
|
|
|
struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd,
|
|
|
struct tcm_vhost_cmd, tvc_se_cmd);
|
|
|
+ struct se_session *se_sess = se_cmd->se_sess;
|
|
|
|
|
|
if (tv_cmd->tvc_sgl_count) {
|
|
|
u32 i;
|
|
@@ -460,7 +463,7 @@ static void tcm_vhost_release_cmd(struct se_cmd *se_cmd)
|
|
|
}
|
|
|
|
|
|
tcm_vhost_put_inflight(tv_cmd->inflight);
|
|
|
- kfree(tv_cmd);
|
|
|
+ percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
|
|
|
}
|
|
|
|
|
|
static int tcm_vhost_shutdown_session(struct se_session *se_sess)
|
|
@@ -704,7 +707,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
|
|
|
}
|
|
|
|
|
|
static struct tcm_vhost_cmd *
|
|
|
-vhost_scsi_allocate_cmd(struct vhost_virtqueue *vq,
|
|
|
+vhost_scsi_get_tag(struct vhost_virtqueue *vq,
|
|
|
struct tcm_vhost_tpg *tpg,
|
|
|
struct virtio_scsi_cmd_req *v_req,
|
|
|
u32 exp_data_len,
|
|
@@ -712,18 +715,21 @@ vhost_scsi_allocate_cmd(struct vhost_virtqueue *vq,
|
|
|
{
|
|
|
struct tcm_vhost_cmd *cmd;
|
|
|
struct tcm_vhost_nexus *tv_nexus;
|
|
|
+ struct se_session *se_sess;
|
|
|
+ int tag;
|
|
|
|
|
|
tv_nexus = tpg->tpg_nexus;
|
|
|
if (!tv_nexus) {
|
|
|
pr_err("Unable to locate active struct tcm_vhost_nexus\n");
|
|
|
return ERR_PTR(-EIO);
|
|
|
}
|
|
|
+ se_sess = tv_nexus->tvn_se_sess;
|
|
|
|
|
|
- cmd = kzalloc(sizeof(struct tcm_vhost_cmd), GFP_ATOMIC);
|
|
|
- if (!cmd) {
|
|
|
- pr_err("Unable to allocate struct tcm_vhost_cmd\n");
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
- }
|
|
|
+ tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_KERNEL);
|
|
|
+ cmd = &((struct tcm_vhost_cmd *)se_sess->sess_cmd_map)[tag];
|
|
|
+ memset(cmd, 0, sizeof(struct tcm_vhost_cmd));
|
|
|
+
|
|
|
+ cmd->tvc_se_cmd.map_tag = tag;
|
|
|
cmd->tvc_tag = v_req->tag;
|
|
|
cmd->tvc_task_attr = v_req->task_attr;
|
|
|
cmd->tvc_exp_data_len = exp_data_len;
|
|
@@ -989,10 +995,10 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
|
|
|
for (i = 0; i < data_num; i++)
|
|
|
exp_data_len += vq->iov[data_first + i].iov_len;
|
|
|
|
|
|
- cmd = vhost_scsi_allocate_cmd(vq, tpg, &v_req,
|
|
|
- exp_data_len, data_direction);
|
|
|
+ cmd = vhost_scsi_get_tag(vq, tpg, &v_req,
|
|
|
+ exp_data_len, data_direction);
|
|
|
if (IS_ERR(cmd)) {
|
|
|
- vq_err(vq, "vhost_scsi_allocate_cmd failed %ld\n",
|
|
|
+ vq_err(vq, "vhost_scsi_get_tag failed %ld\n",
|
|
|
PTR_ERR(cmd));
|
|
|
goto err_cmd;
|
|
|
}
|
|
@@ -1675,9 +1681,12 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tpg,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
/*
|
|
|
- * Initialize the struct se_session pointer
|
|
|
+ * Initialize the struct se_session pointer and setup tagpool
|
|
|
+ * for struct tcm_vhost_cmd descriptors
|
|
|
*/
|
|
|
- tv_nexus->tvn_se_sess = transport_init_session();
|
|
|
+ tv_nexus->tvn_se_sess = transport_init_session_tags(
|
|
|
+ TCM_VHOST_DEFAULT_TAGS,
|
|
|
+ sizeof(struct tcm_vhost_cmd));
|
|
|
if (IS_ERR(tv_nexus->tvn_se_sess)) {
|
|
|
mutex_unlock(&tpg->tv_tpg_mutex);
|
|
|
kfree(tv_nexus);
|