target: remove struct se_task

We can use struct se_cmd for everything it did.  Make sure to pass the S/G
list and data direction to the execution function to ease adding back BIDI
support later on.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Christoph Hellwig
2012-04-24 00:25:06 -04:00
committed by Nicholas Bellinger
parent cf572a9627
commit 5787cacd0b
11 changed files with 211 additions and 423 deletions
+61 -111
View File
@@ -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,