|
@@ -663,22 +663,12 @@ static void pscsi_free_device(void *p)
|
|
|
kfree(pdv);
|
|
|
}
|
|
|
|
|
|
-static inline struct pscsi_plugin_task *PSCSI_TASK(struct se_task *task)
|
|
|
+static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
|
|
|
{
|
|
|
- return container_of(task, struct pscsi_plugin_task, pscsi_task);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/* pscsi_transport_complete():
|
|
|
- *
|
|
|
- *
|
|
|
- */
|
|
|
-static int pscsi_transport_complete(struct se_task *task)
|
|
|
-{
|
|
|
- struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
|
|
|
+ struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
|
|
|
struct scsi_device *sd = pdv->pdv_sd;
|
|
|
int result;
|
|
|
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
|
|
|
+ struct pscsi_plugin_task *pt = cmd->priv;
|
|
|
unsigned char *cdb = &pt->pscsi_cdb[0];
|
|
|
|
|
|
result = pt->pscsi_result;
|
|
@@ -688,12 +678,11 @@ static int pscsi_transport_complete(struct se_task *task)
|
|
|
*/
|
|
|
if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) &&
|
|
|
(status_byte(result) << 1) == SAM_STAT_GOOD) {
|
|
|
- if (!task->task_se_cmd->se_deve)
|
|
|
+ if (!cmd->se_deve)
|
|
|
goto after_mode_sense;
|
|
|
|
|
|
- if (task->task_se_cmd->se_deve->lun_flags &
|
|
|
- TRANSPORT_LUNFLAGS_READ_ONLY) {
|
|
|
- unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd);
|
|
|
+ if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) {
|
|
|
+ unsigned char *buf = transport_kmap_data_sg(cmd);
|
|
|
|
|
|
if (cdb[0] == MODE_SENSE_10) {
|
|
|
if (!(buf[3] & 0x80))
|
|
@@ -703,7 +692,7 @@ static int pscsi_transport_complete(struct se_task *task)
|
|
|
buf[2] |= 0x80;
|
|
|
}
|
|
|
|
|
|
- transport_kunmap_data_sg(task->task_se_cmd);
|
|
|
+ transport_kunmap_data_sg(cmd);
|
|
|
}
|
|
|
}
|
|
|
after_mode_sense:
|
|
@@ -722,7 +711,6 @@ after_mode_sense:
|
|
|
if (((cdb[0] == MODE_SELECT) || (cdb[0] == MODE_SELECT_10)) &&
|
|
|
(status_byte(result) << 1) == SAM_STAT_GOOD) {
|
|
|
unsigned char *buf;
|
|
|
- struct scatterlist *sg = task->task_sg;
|
|
|
u16 bdl;
|
|
|
u32 blocksize;
|
|
|
|
|
@@ -757,35 +745,6 @@ after_mode_select:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static struct se_task *
|
|
|
-pscsi_alloc_task(unsigned char *cdb)
|
|
|
-{
|
|
|
- struct pscsi_plugin_task *pt;
|
|
|
-
|
|
|
- /*
|
|
|
- * Dynamically alloc cdb space, since it may be larger than
|
|
|
- * TCM_MAX_COMMAND_SIZE
|
|
|
- */
|
|
|
- pt = kzalloc(sizeof(*pt) + scsi_command_size(cdb), GFP_KERNEL);
|
|
|
- if (!pt) {
|
|
|
- pr_err("Unable to allocate struct pscsi_plugin_task\n");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- return &pt->pscsi_task;
|
|
|
-}
|
|
|
-
|
|
|
-static void pscsi_free_task(struct se_task *task)
|
|
|
-{
|
|
|
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
|
|
|
-
|
|
|
- /*
|
|
|
- * We do not release the bio(s) here associated with this task, as
|
|
|
- * this is handled by bio_put() and pscsi_bi_endio().
|
|
|
- */
|
|
|
- kfree(pt);
|
|
|
-}
|
|
|
-
|
|
|
enum {
|
|
|
Opt_scsi_host_id, Opt_scsi_channel_id, Opt_scsi_target_id,
|
|
|
Opt_scsi_lun_id, Opt_err
|
|
@@ -958,26 +917,25 @@ static inline struct bio *pscsi_get_bio(int sg_num)
|
|
|
return bio;
|
|
|
}
|
|
|
|
|
|
-static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
|
|
|
+static int pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl,
|
|
|
+ u32 sgl_nents, enum dma_data_direction data_direction,
|
|
|
struct bio **hbio)
|
|
|
{
|
|
|
- struct se_cmd *cmd = task->task_se_cmd;
|
|
|
- struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
|
|
|
- u32 task_sg_num = task->task_sg_nents;
|
|
|
+ struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
|
|
|
struct bio *bio = NULL, *tbio = NULL;
|
|
|
struct page *page;
|
|
|
struct scatterlist *sg;
|
|
|
u32 data_len = cmd->data_length, i, len, bytes, off;
|
|
|
- int nr_pages = (cmd->data_length + task_sg[0].offset +
|
|
|
+ int nr_pages = (cmd->data_length + sgl[0].offset +
|
|
|
PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
|
int nr_vecs = 0, rc;
|
|
|
- int rw = (task->task_data_direction == DMA_TO_DEVICE);
|
|
|
+ int rw = (data_direction == DMA_TO_DEVICE);
|
|
|
|
|
|
*hbio = NULL;
|
|
|
|
|
|
pr_debug("PSCSI: nr_pages: %d\n", nr_pages);
|
|
|
|
|
|
- for_each_sg(task_sg, sg, task_sg_num, i) {
|
|
|
+ for_each_sg(sgl, sg, sgl_nents, i) {
|
|
|
page = sg_page(sg);
|
|
|
off = sg->offset;
|
|
|
len = sg->length;
|
|
@@ -1009,7 +967,7 @@ static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
|
|
|
* Set *hbio pointer to handle the case:
|
|
|
* nr_pages > BIO_MAX_PAGES, where additional
|
|
|
* bios need to be added to complete a given
|
|
|
- * struct se_task
|
|
|
+ * command.
|
|
|
*/
|
|
|
if (!*hbio)
|
|
|
*hbio = tbio = bio;
|
|
@@ -1049,7 +1007,7 @@ static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return task->task_sg_nents;
|
|
|
+ return sgl_nents;
|
|
|
fail:
|
|
|
while (*hbio) {
|
|
|
bio = *hbio;
|
|
@@ -1061,53 +1019,61 @@ fail:
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
-static int pscsi_do_task(struct se_task *task)
|
|
|
+static int pscsi_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
|
|
|
+ u32 sgl_nents, enum dma_data_direction data_direction)
|
|
|
{
|
|
|
- struct se_cmd *cmd = task->task_se_cmd;
|
|
|
- struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
|
|
|
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
|
|
|
+ struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
|
|
|
+ struct pscsi_plugin_task *pt;
|
|
|
struct request *req;
|
|
|
struct bio *hbio;
|
|
|
int ret;
|
|
|
|
|
|
+ /*
|
|
|
+ * Dynamically alloc cdb space, since it may be larger than
|
|
|
+ * TCM_MAX_COMMAND_SIZE
|
|
|
+ */
|
|
|
+ pt = kzalloc(sizeof(*pt) + scsi_command_size(cmd->t_task_cdb), GFP_KERNEL);
|
|
|
+ if (!pt) {
|
|
|
+ cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ cmd->priv = pt;
|
|
|
+
|
|
|
memcpy(pt->pscsi_cdb, cmd->t_task_cdb,
|
|
|
scsi_command_size(cmd->t_task_cdb));
|
|
|
|
|
|
- if (task->task_se_cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
|
|
|
+ if (cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
|
|
|
req = blk_get_request(pdv->pdv_sd->request_queue,
|
|
|
- (task->task_data_direction == DMA_TO_DEVICE),
|
|
|
+ (data_direction == DMA_TO_DEVICE),
|
|
|
GFP_KERNEL);
|
|
|
if (!req || IS_ERR(req)) {
|
|
|
pr_err("PSCSI: blk_get_request() failed: %ld\n",
|
|
|
req ? IS_ERR(req) : -ENOMEM);
|
|
|
cmd->scsi_sense_reason =
|
|
|
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -ENODEV;
|
|
|
+ goto fail;
|
|
|
}
|
|
|
} else {
|
|
|
BUG_ON(!cmd->data_length);
|
|
|
|
|
|
- /*
|
|
|
- * Setup the main struct request for the task->task_sg[] payload
|
|
|
- */
|
|
|
- ret = pscsi_map_sg(task, task->task_sg, &hbio);
|
|
|
+ ret = pscsi_map_sg(cmd, sgl, sgl_nents, data_direction, &hbio);
|
|
|
if (ret < 0) {
|
|
|
cmd->scsi_sense_reason =
|
|
|
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return ret;
|
|
|
+ goto fail;
|
|
|
}
|
|
|
|
|
|
req = blk_make_request(pdv->pdv_sd->request_queue, hbio,
|
|
|
GFP_KERNEL);
|
|
|
if (IS_ERR(req)) {
|
|
|
pr_err("pSCSI: blk_make_request() failed\n");
|
|
|
- goto fail;
|
|
|
+ goto fail_free_bio;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
req->cmd_type = REQ_TYPE_BLOCK_PC;
|
|
|
req->end_io = pscsi_req_done;
|
|
|
- req->end_io_data = task;
|
|
|
+ req->end_io_data = cmd;
|
|
|
req->cmd_len = scsi_command_size(pt->pscsi_cdb);
|
|
|
req->cmd = &pt->pscsi_cdb[0];
|
|
|
req->sense = &pt->pscsi_sense[0];
|
|
@@ -1119,12 +1085,12 @@ static int pscsi_do_task(struct se_task *task)
|
|
|
req->retries = PS_RETRY;
|
|
|
|
|
|
blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, req,
|
|
|
- (task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG),
|
|
|
+ (cmd->sam_task_attr == MSG_HEAD_TAG),
|
|
|
pscsi_req_done);
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
-fail:
|
|
|
+fail_free_bio:
|
|
|
while (hbio) {
|
|
|
struct bio *bio = hbio;
|
|
|
hbio = hbio->bi_next;
|
|
@@ -1132,16 +1098,14 @@ fail:
|
|
|
bio_endio(bio, 0); /* XXX: should be error */
|
|
|
}
|
|
|
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+fail:
|
|
|
+ kfree(pt);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
-/* pscsi_get_sense_buffer():
|
|
|
- *
|
|
|
- *
|
|
|
- */
|
|
|
-static unsigned char *pscsi_get_sense_buffer(struct se_task *task)
|
|
|
+static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd)
|
|
|
{
|
|
|
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
|
|
|
+ struct pscsi_plugin_task *pt = cmd->priv;
|
|
|
|
|
|
return pt->pscsi_sense;
|
|
|
}
|
|
@@ -1181,48 +1145,36 @@ static sector_t pscsi_get_blocks(struct se_device *dev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/* pscsi_handle_SAM_STATUS_failures():
|
|
|
- *
|
|
|
- *
|
|
|
- */
|
|
|
-static inline void pscsi_process_SAM_status(
|
|
|
- struct se_task *task,
|
|
|
- struct pscsi_plugin_task *pt)
|
|
|
+static void pscsi_req_done(struct request *req, int uptodate)
|
|
|
{
|
|
|
- task->task_scsi_status = status_byte(pt->pscsi_result);
|
|
|
- if (task->task_scsi_status) {
|
|
|
- task->task_scsi_status <<= 1;
|
|
|
- pr_debug("PSCSI Status Byte exception at task: %p CDB:"
|
|
|
- " 0x%02x Result: 0x%08x\n", task, pt->pscsi_cdb[0],
|
|
|
+ struct se_cmd *cmd = req->end_io_data;
|
|
|
+ struct pscsi_plugin_task *pt = cmd->priv;
|
|
|
+
|
|
|
+ pt->pscsi_result = req->errors;
|
|
|
+ pt->pscsi_resid = req->resid_len;
|
|
|
+
|
|
|
+ cmd->scsi_status = status_byte(pt->pscsi_result) << 1;
|
|
|
+ if (cmd->scsi_status) {
|
|
|
+ pr_debug("PSCSI Status Byte exception at cmd: %p CDB:"
|
|
|
+ " 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0],
|
|
|
pt->pscsi_result);
|
|
|
}
|
|
|
|
|
|
switch (host_byte(pt->pscsi_result)) {
|
|
|
case DID_OK:
|
|
|
- transport_complete_task(task, (!task->task_scsi_status));
|
|
|
+ target_complete_cmd(cmd, cmd->scsi_status);
|
|
|
break;
|
|
|
default:
|
|
|
- pr_debug("PSCSI Host Byte exception at task: %p CDB:"
|
|
|
- " 0x%02x Result: 0x%08x\n", task, pt->pscsi_cdb[0],
|
|
|
+ pr_debug("PSCSI Host Byte exception at cmd: %p CDB:"
|
|
|
+ " 0x%02x Result: 0x%08x\n", cmd, pt->pscsi_cdb[0],
|
|
|
pt->pscsi_result);
|
|
|
- task->task_scsi_status = SAM_STAT_CHECK_CONDITION;
|
|
|
- task->task_se_cmd->scsi_sense_reason =
|
|
|
- TCM_UNSUPPORTED_SCSI_OPCODE;
|
|
|
- transport_complete_task(task, 0);
|
|
|
+ cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
|
|
|
+ target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
|
|
|
break;
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-static void pscsi_req_done(struct request *req, int uptodate)
|
|
|
-{
|
|
|
- struct se_task *task = req->end_io_data;
|
|
|
- struct pscsi_plugin_task *pt = PSCSI_TASK(task);
|
|
|
-
|
|
|
- pt->pscsi_result = req->errors;
|
|
|
- pt->pscsi_resid = req->resid_len;
|
|
|
-
|
|
|
- pscsi_process_SAM_status(task, pt);
|
|
|
__blk_put_request(req->q, req);
|
|
|
+ kfree(pt);
|
|
|
}
|
|
|
|
|
|
static struct se_subsystem_api pscsi_template = {
|
|
@@ -1236,9 +1188,7 @@ static struct se_subsystem_api pscsi_template = {
|
|
|
.create_virtdevice = pscsi_create_virtdevice,
|
|
|
.free_device = pscsi_free_device,
|
|
|
.transport_complete = pscsi_transport_complete,
|
|
|
- .alloc_task = pscsi_alloc_task,
|
|
|
- .do_task = pscsi_do_task,
|
|
|
- .free_task = pscsi_free_task,
|
|
|
+ .execute_cmd = pscsi_execute_cmd,
|
|
|
.check_configfs_dev_params = pscsi_check_configfs_dev_params,
|
|
|
.set_configfs_dev_params = pscsi_set_configfs_dev_params,
|
|
|
.show_configfs_dev_params = pscsi_show_configfs_dev_params,
|