dect
/
linux-2.6
Archived
13
0
Fork 0

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

View File

@ -244,53 +244,33 @@ static void fd_free_device(void *p)
kfree(fd_dev); kfree(fd_dev);
} }
static inline struct fd_request *FILE_REQ(struct se_task *task) static int fd_do_readv(struct se_cmd *cmd, struct scatterlist *sgl,
u32 sgl_nents)
{ {
return container_of(task, struct fd_request, fd_task); struct se_device *se_dev = cmd->se_dev;
}
static struct se_task *
fd_alloc_task(unsigned char *cdb)
{
struct fd_request *fd_req;
fd_req = kzalloc(sizeof(struct fd_request), GFP_KERNEL);
if (!fd_req) {
pr_err("Unable to allocate struct fd_request\n");
return NULL;
}
return &fd_req->fd_task;
}
static int fd_do_readv(struct se_task *task)
{
struct fd_request *req = FILE_REQ(task);
struct se_device *se_dev = req->fd_task.task_se_cmd->se_dev;
struct fd_dev *dev = se_dev->dev_ptr; struct fd_dev *dev = se_dev->dev_ptr;
struct file *fd = dev->fd_file; struct file *fd = dev->fd_file;
struct scatterlist *sg = task->task_sg; struct scatterlist *sg;
struct iovec *iov; struct iovec *iov;
mm_segment_t old_fs; mm_segment_t old_fs;
loff_t pos = (task->task_se_cmd->t_task_lba * loff_t pos = (cmd->t_task_lba *
se_dev->se_sub_dev->se_dev_attrib.block_size); se_dev->se_sub_dev->se_dev_attrib.block_size);
int ret = 0, i; int ret = 0, i;
iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL); iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL);
if (!iov) { if (!iov) {
pr_err("Unable to allocate fd_do_readv iov[]\n"); pr_err("Unable to allocate fd_do_readv iov[]\n");
return -ENOMEM; return -ENOMEM;
} }
for_each_sg(task->task_sg, sg, task->task_sg_nents, i) { for_each_sg(sgl, sg, sgl_nents, i) {
iov[i].iov_len = sg->length; iov[i].iov_len = sg->length;
iov[i].iov_base = sg_virt(sg); iov[i].iov_base = sg_virt(sg);
} }
old_fs = get_fs(); old_fs = get_fs();
set_fs(get_ds()); set_fs(get_ds());
ret = vfs_readv(fd, &iov[0], task->task_sg_nents, &pos); ret = vfs_readv(fd, &iov[0], sgl_nents, &pos);
set_fs(old_fs); set_fs(old_fs);
kfree(iov); kfree(iov);
@ -300,10 +280,10 @@ static int fd_do_readv(struct se_task *task)
* block_device. * block_device.
*/ */
if (S_ISBLK(fd->f_dentry->d_inode->i_mode)) { if (S_ISBLK(fd->f_dentry->d_inode->i_mode)) {
if (ret < 0 || ret != task->task_se_cmd->data_length) { if (ret < 0 || ret != cmd->data_length) {
pr_err("vfs_readv() returned %d," pr_err("vfs_readv() returned %d,"
" expecting %d for S_ISBLK\n", ret, " expecting %d for S_ISBLK\n", ret,
(int)task->task_se_cmd->data_length); (int)cmd->data_length);
return (ret < 0 ? ret : -EINVAL); return (ret < 0 ? ret : -EINVAL);
} }
} else { } else {
@ -317,38 +297,38 @@ static int fd_do_readv(struct se_task *task)
return 1; return 1;
} }
static int fd_do_writev(struct se_task *task) static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl,
u32 sgl_nents)
{ {
struct fd_request *req = FILE_REQ(task); struct se_device *se_dev = cmd->se_dev;
struct se_device *se_dev = req->fd_task.task_se_cmd->se_dev;
struct fd_dev *dev = se_dev->dev_ptr; struct fd_dev *dev = se_dev->dev_ptr;
struct file *fd = dev->fd_file; struct file *fd = dev->fd_file;
struct scatterlist *sg = task->task_sg; struct scatterlist *sg;
struct iovec *iov; struct iovec *iov;
mm_segment_t old_fs; mm_segment_t old_fs;
loff_t pos = (task->task_se_cmd->t_task_lba * loff_t pos = (cmd->t_task_lba *
se_dev->se_sub_dev->se_dev_attrib.block_size); se_dev->se_sub_dev->se_dev_attrib.block_size);
int ret, i = 0; int ret, i = 0;
iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL); iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL);
if (!iov) { if (!iov) {
pr_err("Unable to allocate fd_do_writev iov[]\n"); pr_err("Unable to allocate fd_do_writev iov[]\n");
return -ENOMEM; return -ENOMEM;
} }
for_each_sg(task->task_sg, sg, task->task_sg_nents, i) { for_each_sg(sgl, sg, sgl_nents, i) {
iov[i].iov_len = sg->length; iov[i].iov_len = sg->length;
iov[i].iov_base = sg_virt(sg); iov[i].iov_base = sg_virt(sg);
} }
old_fs = get_fs(); old_fs = get_fs();
set_fs(get_ds()); set_fs(get_ds());
ret = vfs_writev(fd, &iov[0], task->task_sg_nents, &pos); ret = vfs_writev(fd, &iov[0], sgl_nents, &pos);
set_fs(old_fs); set_fs(old_fs);
kfree(iov); kfree(iov);
if (ret < 0 || ret != task->task_se_cmd->data_length) { if (ret < 0 || ret != cmd->data_length) {
pr_err("vfs_writev() returned %d\n", ret); pr_err("vfs_writev() returned %d\n", ret);
return (ret < 0 ? ret : -EINVAL); return (ret < 0 ? ret : -EINVAL);
} }
@ -369,7 +349,7 @@ static void fd_emulate_sync_cache(struct se_cmd *cmd)
* for this SYNCHRONIZE_CACHE op * for this SYNCHRONIZE_CACHE op
*/ */
if (immed) if (immed)
transport_complete_sync_cache(cmd, 1); target_complete_cmd(cmd, SAM_STAT_GOOD);
/* /*
* Determine if we will be flushing the entire device. * Determine if we will be flushing the entire device.
@ -389,35 +369,37 @@ static void fd_emulate_sync_cache(struct se_cmd *cmd)
if (ret != 0) if (ret != 0)
pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret); pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);
if (!immed) if (immed)
transport_complete_sync_cache(cmd, ret == 0); return;
if (ret) {
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
} else {
target_complete_cmd(cmd, SAM_STAT_GOOD);
}
} }
/* static void fd_emulate_write_fua(struct se_cmd *cmd)
* WRITE Force Unit Access (FUA) emulation on a per struct se_task
* LBA range basis..
*/
static void fd_emulate_write_fua(struct se_cmd *cmd, struct se_task *task)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct fd_dev *fd_dev = dev->dev_ptr; struct fd_dev *fd_dev = dev->dev_ptr;
loff_t start = task->task_se_cmd->t_task_lba * loff_t start = cmd->t_task_lba *
dev->se_sub_dev->se_dev_attrib.block_size; dev->se_sub_dev->se_dev_attrib.block_size;
loff_t end = start + task->task_se_cmd->data_length; loff_t end = start + cmd->data_length;
int ret; int ret;
pr_debug("FILEIO: FUA WRITE LBA: %llu, bytes: %u\n", pr_debug("FILEIO: FUA WRITE LBA: %llu, bytes: %u\n",
task->task_se_cmd->t_task_lba, cmd->t_task_lba, cmd->data_length);
task->task_se_cmd->data_length);
ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1); ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1);
if (ret != 0) if (ret != 0)
pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret); pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);
} }
static int fd_do_task(struct se_task *task) static int fd_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 se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
int ret = 0; int ret = 0;
@ -425,10 +407,10 @@ static int fd_do_task(struct se_task *task)
* Call vectorized fileio functions to map struct scatterlist * Call vectorized fileio functions to map struct scatterlist
* physical memory addresses to struct iovec virtual memory. * physical memory addresses to struct iovec virtual memory.
*/ */
if (task->task_data_direction == DMA_FROM_DEVICE) { if (data_direction == DMA_FROM_DEVICE) {
ret = fd_do_readv(task); ret = fd_do_readv(cmd, sgl, sgl_nents);
} else { } else {
ret = fd_do_writev(task); ret = fd_do_writev(cmd, sgl, sgl_nents);
if (ret > 0 && if (ret > 0 &&
dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0 && dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0 &&
@ -439,7 +421,7 @@ static int fd_do_task(struct se_task *task)
* and return some sense data to let the initiator * and return some sense data to let the initiator
* know the FUA WRITE cache sync failed..? * know the FUA WRITE cache sync failed..?
*/ */
fd_emulate_write_fua(cmd, task); fd_emulate_write_fua(cmd);
} }
} }
@ -448,24 +430,11 @@ static int fd_do_task(struct se_task *task)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return ret; return ret;
} }
if (ret) { if (ret)
task->task_scsi_status = GOOD; target_complete_cmd(cmd, SAM_STAT_GOOD);
transport_complete_task(task, 1);
}
return 0; return 0;
} }
/* fd_free_task(): (Part of se_subsystem_api_t template)
*
*
*/
static void fd_free_task(struct se_task *task)
{
struct fd_request *req = FILE_REQ(task);
kfree(req);
}
enum { enum {
Opt_fd_dev_name, Opt_fd_dev_size, Opt_fd_buffered_io, Opt_err Opt_fd_dev_name, Opt_fd_dev_size, Opt_fd_buffered_io, Opt_err
}; };
@ -618,10 +587,8 @@ static struct se_subsystem_api fileio_template = {
.allocate_virtdevice = fd_allocate_virtdevice, .allocate_virtdevice = fd_allocate_virtdevice,
.create_virtdevice = fd_create_virtdevice, .create_virtdevice = fd_create_virtdevice,
.free_device = fd_free_device, .free_device = fd_free_device,
.alloc_task = fd_alloc_task, .execute_cmd = fd_execute_cmd,
.do_task = fd_do_task,
.do_sync_cache = fd_emulate_sync_cache, .do_sync_cache = fd_emulate_sync_cache,
.free_task = fd_free_task,
.check_configfs_dev_params = fd_check_configfs_dev_params, .check_configfs_dev_params = fd_check_configfs_dev_params,
.set_configfs_dev_params = fd_set_configfs_dev_params, .set_configfs_dev_params = fd_set_configfs_dev_params,
.show_configfs_dev_params = fd_show_configfs_dev_params, .show_configfs_dev_params = fd_show_configfs_dev_params,

View File

@ -12,10 +12,6 @@
#define RRF_EMULATE_CDB 0x01 #define RRF_EMULATE_CDB 0x01
#define RRF_GOT_LBA 0x02 #define RRF_GOT_LBA 0x02
struct fd_request {
struct se_task fd_task;
};
#define FBDF_HAS_PATH 0x01 #define FBDF_HAS_PATH 0x01
#define FBDF_HAS_SIZE 0x02 #define FBDF_HAS_SIZE 0x02
#define FDBD_USE_BUFFERED_IO 0x04 #define FDBD_USE_BUFFERED_IO 0x04

View File

@ -189,26 +189,6 @@ static void iblock_free_device(void *p)
kfree(ib_dev); kfree(ib_dev);
} }
static inline struct iblock_req *IBLOCK_REQ(struct se_task *task)
{
return container_of(task, struct iblock_req, ib_task);
}
static struct se_task *
iblock_alloc_task(unsigned char *cdb)
{
struct iblock_req *ib_req;
ib_req = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
if (!ib_req) {
pr_err("Unable to allocate memory for struct iblock_req\n");
return NULL;
}
atomic_set(&ib_req->pending, 1);
return &ib_req->ib_task;
}
static unsigned long long iblock_emulate_read_cap_with_block_size( static unsigned long long iblock_emulate_read_cap_with_block_size(
struct se_device *dev, struct se_device *dev,
struct block_device *bd, struct block_device *bd,
@ -295,8 +275,16 @@ static void iblock_end_io_flush(struct bio *bio, int err)
if (err) if (err)
pr_err("IBLOCK: cache flush failed: %d\n", err); pr_err("IBLOCK: cache flush failed: %d\n", err);
if (cmd) if (cmd) {
transport_complete_sync_cache(cmd, err == 0); if (err) {
cmd->scsi_sense_reason =
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
target_complete_cmd(cmd, SAM_STAT_CHECK_CONDITION);
} else {
target_complete_cmd(cmd, SAM_STAT_GOOD);
}
}
bio_put(bio); bio_put(bio);
} }
@ -315,7 +303,7 @@ static void iblock_emulate_sync_cache(struct se_cmd *cmd)
* for this SYNCHRONIZE_CACHE op. * for this SYNCHRONIZE_CACHE op.
*/ */
if (immed) if (immed)
transport_complete_sync_cache(cmd, 1); target_complete_cmd(cmd, SAM_STAT_GOOD);
bio = bio_alloc(GFP_KERNEL, 0); bio = bio_alloc(GFP_KERNEL, 0);
bio->bi_end_io = iblock_end_io_flush; bio->bi_end_io = iblock_end_io_flush;
@ -334,11 +322,6 @@ static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range)
return blkdev_issue_discard(bd, lba, range, GFP_KERNEL, barrier); return blkdev_issue_discard(bd, lba, range, GFP_KERNEL, barrier);
} }
static void iblock_free_task(struct se_task *task)
{
kfree(IBLOCK_REQ(task));
}
enum { enum {
Opt_udev_path, Opt_force, Opt_err Opt_udev_path, Opt_force, Opt_err
}; };
@ -447,19 +430,35 @@ static ssize_t iblock_show_configfs_dev_params(
return bl; return bl;
} }
static void iblock_complete_cmd(struct se_cmd *cmd)
{
struct iblock_req *ibr = cmd->priv;
u8 status;
if (!atomic_dec_and_test(&ibr->pending))
return;
if (atomic_read(&ibr->ib_bio_err_cnt))
status = SAM_STAT_CHECK_CONDITION;
else
status = SAM_STAT_GOOD;
target_complete_cmd(cmd, status);
kfree(ibr);
}
static void iblock_bio_destructor(struct bio *bio) static void iblock_bio_destructor(struct bio *bio)
{ {
struct se_task *task = bio->bi_private; struct se_cmd *cmd = bio->bi_private;
struct iblock_dev *ib_dev = task->task_se_cmd->se_dev->dev_ptr; struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
bio_free(bio, ib_dev->ibd_bio_set); bio_free(bio, ib_dev->ibd_bio_set);
} }
static struct bio * static struct bio *
iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num) iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num)
{ {
struct iblock_dev *ib_dev = task->task_se_cmd->se_dev->dev_ptr; struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
struct iblock_req *ib_req = IBLOCK_REQ(task);
struct bio *bio; struct bio *bio;
/* /*
@ -475,20 +474,11 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
return NULL; return NULL;
} }
pr_debug("Allocated bio: %p task_sg_nents: %u using ibd_bio_set:"
" %p\n", bio, task->task_sg_nents, ib_dev->ibd_bio_set);
pr_debug("Allocated bio: %p task_size: %u\n", bio,
task->task_se_cmd->data_length);
bio->bi_bdev = ib_dev->ibd_bd; bio->bi_bdev = ib_dev->ibd_bd;
bio->bi_private = task; bio->bi_private = cmd;
bio->bi_destructor = iblock_bio_destructor; bio->bi_destructor = iblock_bio_destructor;
bio->bi_end_io = &iblock_bio_done; bio->bi_end_io = &iblock_bio_done;
bio->bi_sector = lba; bio->bi_sector = lba;
atomic_inc(&ib_req->pending);
pr_debug("Set bio->bi_sector: %llu\n", (unsigned long long)bio->bi_sector);
pr_debug("Set ib_req->pending: %d\n", atomic_read(&ib_req->pending));
return bio; return bio;
} }
@ -503,20 +493,21 @@ static void iblock_submit_bios(struct bio_list *list, int rw)
blk_finish_plug(&plug); blk_finish_plug(&plug);
} }
static int iblock_do_task(struct se_task *task) static int iblock_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 se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct iblock_req *ibr = IBLOCK_REQ(task); struct iblock_req *ibr;
struct bio *bio; struct bio *bio;
struct bio_list list; struct bio_list list;
struct scatterlist *sg; struct scatterlist *sg;
u32 i, sg_num = task->task_sg_nents; u32 sg_num = sgl_nents;
sector_t block_lba; sector_t block_lba;
unsigned bio_cnt; unsigned bio_cnt;
int rw; int rw;
int i;
if (task->task_data_direction == DMA_TO_DEVICE) { if (data_direction == DMA_TO_DEVICE) {
/* /*
* Force data to disk if we pretend to not have a volatile * Force data to disk if we pretend to not have a volatile
* write cache, or the initiator set the Force Unit Access bit. * write cache, or the initiator set the Force Unit Access bit.
@ -532,8 +523,8 @@ static int iblock_do_task(struct se_task *task)
} }
/* /*
* Do starting conversion up from non 512-byte blocksize with * Convert the blocksize advertised to the initiator to the 512 byte
* struct se_task SCSI blocksize into Linux/Block 512 units for BIO. * units unconditionally used by the Linux block layer.
*/ */
if (dev->se_sub_dev->se_dev_attrib.block_size == 4096) if (dev->se_sub_dev->se_dev_attrib.block_size == 4096)
block_lba = (cmd->t_task_lba << 3); block_lba = (cmd->t_task_lba << 3);
@ -550,17 +541,22 @@ static int iblock_do_task(struct se_task *task)
return -ENOSYS; return -ENOSYS;
} }
bio = iblock_get_bio(task, block_lba, sg_num); ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
if (!bio) { if (!ibr)
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; goto fail;
return -ENOMEM; cmd->priv = ibr;
}
bio = iblock_get_bio(cmd, block_lba, sgl_nents);
if (!bio)
goto fail_free_ibr;
bio_list_init(&list); bio_list_init(&list);
bio_list_add(&list, bio); bio_list_add(&list, bio);
atomic_set(&ibr->pending, 2);
bio_cnt = 1; bio_cnt = 1;
for_each_sg(task->task_sg, sg, task->task_sg_nents, i) { for_each_sg(sgl, sg, sgl_nents, i) {
/* /*
* XXX: if the length the device accepts is shorter than the * XXX: if the length the device accepts is shorter than the
* length of the S/G list entry this will cause and * length of the S/G list entry this will cause and
@ -573,9 +569,11 @@ static int iblock_do_task(struct se_task *task)
bio_cnt = 0; bio_cnt = 0;
} }
bio = iblock_get_bio(task, block_lba, sg_num); bio = iblock_get_bio(cmd, block_lba, sg_num);
if (!bio) if (!bio)
goto fail; goto fail_put_bios;
atomic_inc(&ibr->pending);
bio_list_add(&list, bio); bio_list_add(&list, bio);
bio_cnt++; bio_cnt++;
} }
@ -586,17 +584,16 @@ static int iblock_do_task(struct se_task *task)
} }
iblock_submit_bios(&list, rw); iblock_submit_bios(&list, rw);
iblock_complete_cmd(cmd);
if (atomic_dec_and_test(&ibr->pending)) {
transport_complete_task(task,
!atomic_read(&ibr->ib_bio_err_cnt));
}
return 0; return 0;
fail: fail_put_bios:
while ((bio = bio_list_pop(&list))) while ((bio = bio_list_pop(&list)))
bio_put(bio); bio_put(bio);
fail_free_ibr:
kfree(ibr);
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
fail:
return -ENOMEM; return -ENOMEM;
} }
@ -621,8 +618,8 @@ static sector_t iblock_get_blocks(struct se_device *dev)
static void iblock_bio_done(struct bio *bio, int err) static void iblock_bio_done(struct bio *bio, int err)
{ {
struct se_task *task = bio->bi_private; struct se_cmd *cmd = bio->bi_private;
struct iblock_req *ibr = IBLOCK_REQ(task); struct iblock_req *ibr = cmd->priv;
/* /*
* Set -EIO if !BIO_UPTODATE and the passed is still err=0 * Set -EIO if !BIO_UPTODATE and the passed is still err=0
@ -642,14 +639,7 @@ static void iblock_bio_done(struct bio *bio, int err)
bio_put(bio); bio_put(bio);
if (!atomic_dec_and_test(&ibr->pending)) iblock_complete_cmd(cmd);
return;
pr_debug("done[%p] bio: %p task_lba: %llu bio_lba: %llu err=%d\n",
task, bio, task->task_se_cmd->t_task_lba,
(unsigned long long)bio->bi_sector, err);
transport_complete_task(task, !atomic_read(&ibr->ib_bio_err_cnt));
} }
static struct se_subsystem_api iblock_template = { static struct se_subsystem_api iblock_template = {
@ -663,11 +653,9 @@ static struct se_subsystem_api iblock_template = {
.allocate_virtdevice = iblock_allocate_virtdevice, .allocate_virtdevice = iblock_allocate_virtdevice,
.create_virtdevice = iblock_create_virtdevice, .create_virtdevice = iblock_create_virtdevice,
.free_device = iblock_free_device, .free_device = iblock_free_device,
.alloc_task = iblock_alloc_task, .execute_cmd = iblock_execute_cmd,
.do_task = iblock_do_task,
.do_discard = iblock_do_discard, .do_discard = iblock_do_discard,
.do_sync_cache = iblock_emulate_sync_cache, .do_sync_cache = iblock_emulate_sync_cache,
.free_task = iblock_free_task,
.check_configfs_dev_params = iblock_check_configfs_dev_params, .check_configfs_dev_params = iblock_check_configfs_dev_params,
.set_configfs_dev_params = iblock_set_configfs_dev_params, .set_configfs_dev_params = iblock_set_configfs_dev_params,
.show_configfs_dev_params = iblock_show_configfs_dev_params, .show_configfs_dev_params = iblock_show_configfs_dev_params,

View File

@ -7,7 +7,6 @@
#define IBLOCK_LBA_SHIFT 9 #define IBLOCK_LBA_SHIFT 9
struct iblock_req { struct iblock_req {
struct se_task ib_task;
atomic_t pending; atomic_t pending;
atomic_t ib_bio_err_cnt; atomic_t ib_bio_err_cnt;
} ____cacheline_aligned; } ____cacheline_aligned;

View File

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

View File

@ -22,7 +22,6 @@
#include <linux/kobject.h> #include <linux/kobject.h>
struct pscsi_plugin_task { struct pscsi_plugin_task {
struct se_task pscsi_task;
unsigned char pscsi_sense[SCSI_SENSE_BUFFERSIZE]; unsigned char pscsi_sense[SCSI_SENSE_BUFFERSIZE];
int pscsi_direction; int pscsi_direction;
int pscsi_result; int pscsi_result;

View File

@ -266,12 +266,6 @@ static void rd_free_device(void *p)
kfree(rd_dev); kfree(rd_dev);
} }
static struct se_task *
rd_alloc_task(unsigned char *cdb)
{
return kzalloc(sizeof(struct se_task), GFP_KERNEL);
}
static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page) static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
{ {
u32 i; u32 i;
@ -290,9 +284,10 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
return NULL; return NULL;
} }
static int rd_do_task(struct se_task *task) static int rd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
u32 sgl_nents, enum dma_data_direction data_direction)
{ {
struct se_device *se_dev = task->task_se_cmd->se_dev; struct se_device *se_dev = cmd->se_dev;
struct rd_dev *dev = se_dev->dev_ptr; struct rd_dev *dev = se_dev->dev_ptr;
struct rd_dev_sg_table *table; struct rd_dev_sg_table *table;
struct scatterlist *rd_sg; struct scatterlist *rd_sg;
@ -303,11 +298,10 @@ static int rd_do_task(struct se_task *task)
u32 src_len; u32 src_len;
u64 tmp; u64 tmp;
tmp = task->task_se_cmd->t_task_lba * tmp = cmd->t_task_lba * se_dev->se_sub_dev->se_dev_attrib.block_size;
se_dev->se_sub_dev->se_dev_attrib.block_size;
rd_offset = do_div(tmp, PAGE_SIZE); rd_offset = do_div(tmp, PAGE_SIZE);
rd_page = tmp; rd_page = tmp;
rd_size = task->task_se_cmd->data_length; rd_size = cmd->data_length;
table = rd_get_sg_table(dev, rd_page); table = rd_get_sg_table(dev, rd_page);
if (!table) if (!table)
@ -317,14 +311,12 @@ static int rd_do_task(struct se_task *task)
pr_debug("RD[%u]: %s LBA: %llu, Size: %u Page: %u, Offset: %u\n", pr_debug("RD[%u]: %s LBA: %llu, Size: %u Page: %u, Offset: %u\n",
dev->rd_dev_id, dev->rd_dev_id,
task->task_data_direction == DMA_FROM_DEVICE ? data_direction == DMA_FROM_DEVICE ? "Read" : "Write",
"Read" : "Write", cmd->t_task_lba, rd_size, rd_page, rd_offset);
task->task_se_cmd->t_task_lba,
rd_size, rd_page, rd_offset);
src_len = PAGE_SIZE - rd_offset; src_len = PAGE_SIZE - rd_offset;
sg_miter_start(&m, task->task_sg, task->task_sg_nents, sg_miter_start(&m, sgl, sgl_nents,
task->task_data_direction == DMA_FROM_DEVICE ? data_direction == DMA_FROM_DEVICE ?
SG_MITER_TO_SG : SG_MITER_FROM_SG); SG_MITER_TO_SG : SG_MITER_FROM_SG);
while (rd_size) { while (rd_size) {
u32 len; u32 len;
@ -336,7 +328,7 @@ static int rd_do_task(struct se_task *task)
rd_addr = sg_virt(rd_sg) + rd_offset; rd_addr = sg_virt(rd_sg) + rd_offset;
if (task->task_data_direction == DMA_FROM_DEVICE) if (data_direction == DMA_FROM_DEVICE)
memcpy(m.addr, rd_addr, len); memcpy(m.addr, rd_addr, len);
else else
memcpy(rd_addr, m.addr, len); memcpy(rd_addr, m.addr, len);
@ -371,16 +363,10 @@ static int rd_do_task(struct se_task *task)
} }
sg_miter_stop(&m); sg_miter_stop(&m);
task->task_scsi_status = GOOD; target_complete_cmd(cmd, SAM_STAT_GOOD);
transport_complete_task(task, 1);
return 0; return 0;
} }
static void rd_free_task(struct se_task *task)
{
kfree(task);
}
enum { enum {
Opt_rd_pages, Opt_err Opt_rd_pages, Opt_err
}; };
@ -482,9 +468,7 @@ static struct se_subsystem_api rd_mcp_template = {
.allocate_virtdevice = rd_allocate_virtdevice, .allocate_virtdevice = rd_allocate_virtdevice,
.create_virtdevice = rd_create_virtdevice, .create_virtdevice = rd_create_virtdevice,
.free_device = rd_free_device, .free_device = rd_free_device,
.alloc_task = rd_alloc_task, .execute_cmd = rd_execute_cmd,
.do_task = rd_do_task,
.free_task = rd_free_task,
.check_configfs_dev_params = rd_check_configfs_dev_params, .check_configfs_dev_params = rd_check_configfs_dev_params,
.set_configfs_dev_params = rd_set_configfs_dev_params, .set_configfs_dev_params = rd_set_configfs_dev_params,
.show_configfs_dev_params = rd_show_configfs_dev_params, .show_configfs_dev_params = rd_show_configfs_dev_params,

View File

@ -374,13 +374,11 @@ static void core_tmr_drain_cmd_list(
struct se_queue_obj *qobj = &dev->dev_queue_obj; struct se_queue_obj *qobj = &dev->dev_queue_obj;
struct se_cmd *cmd, *tcmd; struct se_cmd *cmd, *tcmd;
unsigned long flags; unsigned long flags;
/* /*
* Release all commands remaining in the struct se_device cmd queue. * Release all commands remaining in the per-device command queue.
* *
* This follows the same logic as above for the struct se_device * This follows the same logic as above for the state list.
* struct se_task state list, where commands are returned with
* TASK_ABORTED status, if there is an outstanding $FABRIC_MOD
* reference, otherwise the struct se_cmd is released.
*/ */
spin_lock_irqsave(&qobj->cmd_queue_lock, flags); spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
list_for_each_entry_safe(cmd, tcmd, &qobj->qobj_list, se_queue_node) { list_for_each_entry_safe(cmd, tcmd, &qobj->qobj_list, se_queue_node) {

View File

@ -72,7 +72,6 @@ static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *);
static void transport_complete_task_attr(struct se_cmd *cmd); static void transport_complete_task_attr(struct se_cmd *cmd);
static void transport_handle_queue_full(struct se_cmd *cmd, static void transport_handle_queue_full(struct se_cmd *cmd,
struct se_device *dev); struct se_device *dev);
static void transport_free_dev_tasks(struct se_cmd *cmd);
static int transport_generic_get_mem(struct se_cmd *cmd); static int transport_generic_get_mem(struct se_cmd *cmd);
static void transport_put_cmd(struct se_cmd *cmd); static void transport_put_cmd(struct se_cmd *cmd);
static void transport_remove_cmd_from_queue(struct se_cmd *cmd); static void transport_remove_cmd_from_queue(struct se_cmd *cmd);
@ -662,28 +661,6 @@ static void transport_remove_cmd_from_queue(struct se_cmd *cmd)
spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags); spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
} }
/*
* Completion function used by TCM subsystem plugins (such as FILEIO)
* for queueing up response from struct se_subsystem_api->do_task()
*/
void transport_complete_sync_cache(struct se_cmd *cmd, int good)
{
struct se_task *task = cmd->t_task;
if (good) {
cmd->scsi_status = SAM_STAT_GOOD;
task->task_scsi_status = GOOD;
} else {
task->task_scsi_status = SAM_STAT_CHECK_CONDITION;
task->task_se_cmd->scsi_sense_reason =
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
transport_complete_task(task, good);
}
EXPORT_SYMBOL(transport_complete_sync_cache);
static void target_complete_failure_work(struct work_struct *work) static void target_complete_failure_work(struct work_struct *work)
{ {
struct se_cmd *cmd = container_of(work, struct se_cmd, work); struct se_cmd *cmd = container_of(work, struct se_cmd, work);
@ -691,35 +668,28 @@ static void target_complete_failure_work(struct work_struct *work)
transport_generic_request_failure(cmd); transport_generic_request_failure(cmd);
} }
/* transport_complete_task(): void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
*
* Called from interrupt and non interrupt context depending
* on the transport plugin.
*/
void transport_complete_task(struct se_task *task, int success)
{ {
struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
int success = scsi_status == GOOD;
unsigned long flags; unsigned long flags;
cmd->scsi_status = scsi_status;
spin_lock_irqsave(&cmd->t_state_lock, flags); spin_lock_irqsave(&cmd->t_state_lock, flags);
cmd->transport_state &= ~CMD_T_BUSY; cmd->transport_state &= ~CMD_T_BUSY;
/*
* See if any sense data exists, if so set the TASK_SENSE flag.
* Also check for any other post completion work that needs to be
* done by the plugins.
*/
if (dev && dev->transport->transport_complete) { if (dev && dev->transport->transport_complete) {
if (dev->transport->transport_complete(task) != 0) { if (dev->transport->transport_complete(cmd,
cmd->t_data_sg) != 0) {
cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE; cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE;
success = 1; success = 1;
} }
} }
/* /*
* See if we are waiting for outstanding struct se_task * See if we are waiting to complete for an exception condition.
* to complete for an exception condition
*/ */
if (cmd->transport_state & CMD_T_REQUEST_STOP) { if (cmd->transport_state & CMD_T_REQUEST_STOP) {
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@ -730,15 +700,11 @@ void transport_complete_task(struct se_task *task, int success)
if (!success) if (!success)
cmd->transport_state |= CMD_T_FAILED; cmd->transport_state |= CMD_T_FAILED;
/*
* Decrement the outstanding t_task_cdbs_left count. The last
* struct se_task from struct se_cmd will complete itself into the
* device queue depending upon int success.
*/
if (!atomic_dec_and_test(&cmd->t_task_cdbs_left)) { if (!atomic_dec_and_test(&cmd->t_task_cdbs_left)) {
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
return; return;
} }
/* /*
* Check for case where an explict ABORT_TASK has been received * Check for case where an explict ABORT_TASK has been received
* and transport_wait_for_tasks() will be waiting for completion.. * and transport_wait_for_tasks() will be waiting for completion..
@ -761,15 +727,6 @@ void transport_complete_task(struct se_task *task, int success)
queue_work(target_completion_wq, &cmd->work); queue_work(target_completion_wq, &cmd->work);
} }
EXPORT_SYMBOL(transport_complete_task);
void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
{
struct se_task *task = cmd->t_task;
task->task_scsi_status = scsi_status;
transport_complete_task(task, scsi_status == GOOD);
}
EXPORT_SYMBOL(target_complete_cmd); EXPORT_SYMBOL(target_complete_cmd);
static void target_add_to_state_list(struct se_cmd *cmd) static void target_add_to_state_list(struct se_cmd *cmd)
@ -2076,8 +2033,10 @@ check_depth:
if (cmd->execute_cmd) if (cmd->execute_cmd)
error = cmd->execute_cmd(cmd); error = cmd->execute_cmd(cmd);
else else {
error = dev->transport->do_task(cmd->t_task); error = dev->transport->execute_cmd(cmd, cmd->t_data_sg,
cmd->t_data_nents, cmd->data_direction);
}
if (error != 0) { if (error != 0) {
spin_lock_irqsave(&cmd->t_state_lock, flags); spin_lock_irqsave(&cmd->t_state_lock, flags);
@ -2312,7 +2271,6 @@ static int transport_get_sense_data(struct se_cmd *cmd)
{ {
unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL; unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_task *task = NULL;
unsigned long flags; unsigned long flags;
u32 offset = 0; u32 offset = 0;
@ -2327,9 +2285,6 @@ static int transport_get_sense_data(struct se_cmd *cmd)
return 0; return 0;
} }
if (!cmd->t_task)
goto out;
if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)) if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
goto out; goto out;
@ -2338,19 +2293,19 @@ static int transport_get_sense_data(struct se_cmd *cmd)
goto out; goto out;
} }
sense_buffer = dev->transport->get_sense_buffer(task); sense_buffer = dev->transport->get_sense_buffer(cmd);
if (!sense_buffer) { if (!sense_buffer) {
pr_err("ITT[0x%08x]_TASK[%p]: Unable to locate" pr_err("ITT 0x%08x cmd %p: Unable to locate"
" sense buffer for task with sense\n", " sense buffer for task with sense\n",
cmd->se_tfo->get_task_tag(cmd), task); cmd->se_tfo->get_task_tag(cmd), cmd);
goto out; goto out;
} }
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER); offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER); memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER);
cmd->scsi_status = task->task_scsi_status;
/* Automatically padded */ /* Automatically padded */
cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset; cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
@ -3199,10 +3154,6 @@ static void target_complete_ok_work(struct work_struct *work)
if (transport_get_sense_data(cmd) < 0) if (transport_get_sense_data(cmd) < 0)
reason = TCM_NON_EXISTENT_LUN; reason = TCM_NON_EXISTENT_LUN;
/*
* Only set when an struct se_task->task_scsi_status returned
* a non GOOD status.
*/
if (cmd->scsi_status) { if (cmd->scsi_status) {
ret = transport_send_check_condition_and_sense( ret = transport_send_check_condition_and_sense(
cmd, reason, 1); cmd, reason, 1);
@ -3277,15 +3228,6 @@ queue_full:
transport_handle_queue_full(cmd, cmd->se_dev); transport_handle_queue_full(cmd, cmd->se_dev);
} }
static void transport_free_dev_tasks(struct se_cmd *cmd)
{
struct se_task *task;
task = cmd->t_task;
if (task && !(cmd->transport_state & CMD_T_BUSY))
cmd->se_dev->transport->free_task(task);
}
static inline void transport_free_sgl(struct scatterlist *sgl, int nents) static inline void transport_free_sgl(struct scatterlist *sgl, int nents)
{ {
struct scatterlist *sg; struct scatterlist *sg;
@ -3346,7 +3288,6 @@ static void transport_release_cmd(struct se_cmd *cmd)
static void transport_put_cmd(struct se_cmd *cmd) static void transport_put_cmd(struct se_cmd *cmd)
{ {
unsigned long flags; unsigned long flags;
int free_tasks = 0;
spin_lock_irqsave(&cmd->t_state_lock, flags); spin_lock_irqsave(&cmd->t_state_lock, flags);
if (atomic_read(&cmd->t_fe_count)) { if (atomic_read(&cmd->t_fe_count)) {
@ -3362,13 +3303,9 @@ static void transport_put_cmd(struct se_cmd *cmd)
if (cmd->transport_state & CMD_T_DEV_ACTIVE) { if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
cmd->transport_state &= ~CMD_T_DEV_ACTIVE; cmd->transport_state &= ~CMD_T_DEV_ACTIVE;
target_remove_from_state_list(cmd); target_remove_from_state_list(cmd);
free_tasks = 1;
} }
spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_unlock_irqrestore(&cmd->t_state_lock, flags);
if (free_tasks != 0)
transport_free_dev_tasks(cmd);
transport_free_pages(cmd); transport_free_pages(cmd);
transport_release_cmd(cmd); transport_release_cmd(cmd);
return; return;
@ -3526,7 +3463,6 @@ out:
int transport_generic_new_cmd(struct se_cmd *cmd) int transport_generic_new_cmd(struct se_cmd *cmd)
{ {
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_task *task;
int ret = 0; int ret = 0;
/* /*
@ -3572,19 +3508,6 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
attr->max_sectors); attr->max_sectors);
} }
task = dev->transport->alloc_task(cmd->t_task_cdb);
if (!task) {
pr_err("Unable to allocate struct se_task\n");
goto out_fail;
}
task->task_se_cmd = cmd;
task->task_data_direction = cmd->data_direction;
task->task_sg = cmd->t_data_sg;
task->task_sg_nents = cmd->t_data_nents;
cmd->t_task = task;
atomic_inc(&cmd->t_fe_count); atomic_inc(&cmd->t_fe_count);
atomic_inc(&cmd->t_se_count); atomic_inc(&cmd->t_se_count);
@ -3592,19 +3515,17 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
atomic_set(&cmd->t_task_cdbs_ex_left, 1); atomic_set(&cmd->t_task_cdbs_ex_left, 1);
/* /*
* For WRITEs, let the fabric know its buffer is ready.. * For WRITEs, let the fabric know its buffer is ready.
* This WRITE struct se_cmd (and all of its associated struct se_task's) *
* will be added to the struct se_device execution queue after its WRITE * The command will be added to the execution queue after its write
* data has arrived. (ie: It gets handled by the transport processing * data has arrived.
* thread a second time)
*/ */
if (cmd->data_direction == DMA_TO_DEVICE) { if (cmd->data_direction == DMA_TO_DEVICE) {
target_add_to_state_list(cmd); target_add_to_state_list(cmd);
return transport_generic_write_pending(cmd); return transport_generic_write_pending(cmd);
} }
/* /*
* Everything else but a WRITE, add the struct se_cmd's struct se_task's * Everything else but a WRITE, add the command to the execution queue.
* to the execution queue.
*/ */
transport_execute_tasks(cmd); transport_execute_tasks(cmd);
return 0; return 0;
@ -3691,8 +3612,6 @@ void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
if (cmd->se_lun) if (cmd->se_lun)
transport_lun_remove_cmd(cmd); transport_lun_remove_cmd(cmd);
transport_free_dev_tasks(cmd);
transport_put_cmd(cmd); transport_put_cmd(cmd);
} }
} }
@ -3832,7 +3751,6 @@ EXPORT_SYMBOL(target_wait_for_sess_cmds);
*/ */
static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun) static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun)
{ {
struct se_task *task = cmd->t_task;
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
@ -3944,7 +3862,6 @@ static void __transport_clear_lun_from_sessions(struct se_lun *lun)
target_remove_from_state_list(cmd); target_remove_from_state_list(cmd);
spin_unlock_irqrestore(&cmd->t_state_lock, cmd_flags); spin_unlock_irqrestore(&cmd->t_state_lock, cmd_flags);
transport_free_dev_tasks(cmd);
/* /*
* The Storage engine stopped this struct se_cmd before it was * The Storage engine stopped this struct se_cmd before it was
* send to the fabric frontend for delivery back to the * send to the fabric frontend for delivery back to the

View File

@ -23,12 +23,11 @@ struct se_subsystem_api {
struct se_device *(*create_virtdevice)(struct se_hba *, struct se_device *(*create_virtdevice)(struct se_hba *,
struct se_subsystem_dev *, void *); struct se_subsystem_dev *, void *);
void (*free_device)(void *); void (*free_device)(void *);
int (*transport_complete)(struct se_task *task); int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *);
struct se_task *(*alloc_task)(unsigned char *cdb); int (*execute_cmd)(struct se_cmd *, struct scatterlist *, u32,
int (*do_task)(struct se_task *); enum dma_data_direction);
int (*do_discard)(struct se_device *, sector_t, u32); int (*do_discard)(struct se_device *, sector_t, u32);
void (*do_sync_cache)(struct se_cmd *); void (*do_sync_cache)(struct se_cmd *);
void (*free_task)(struct se_task *);
ssize_t (*check_configfs_dev_params)(struct se_hba *, ssize_t (*check_configfs_dev_params)(struct se_hba *,
struct se_subsystem_dev *); struct se_subsystem_dev *);
ssize_t (*set_configfs_dev_params)(struct se_hba *, ssize_t (*set_configfs_dev_params)(struct se_hba *,
@ -38,7 +37,7 @@ struct se_subsystem_api {
u32 (*get_device_rev)(struct se_device *); u32 (*get_device_rev)(struct se_device *);
u32 (*get_device_type)(struct se_device *); u32 (*get_device_type)(struct se_device *);
sector_t (*get_blocks)(struct se_device *); sector_t (*get_blocks)(struct se_device *);
unsigned char *(*get_sense_buffer)(struct se_task *); unsigned char *(*get_sense_buffer)(struct se_cmd *);
}; };
int transport_subsystem_register(struct se_subsystem_api *); int transport_subsystem_register(struct se_subsystem_api *);
@ -48,8 +47,6 @@ struct se_device *transport_add_device_to_core_hba(struct se_hba *,
struct se_subsystem_api *, struct se_subsystem_dev *, u32, struct se_subsystem_api *, struct se_subsystem_dev *, u32,
void *, struct se_dev_limits *, const char *, const char *); void *, struct se_dev_limits *, const char *, const char *);
void transport_complete_sync_cache(struct se_cmd *, int);
void transport_complete_task(struct se_task *, int);
void target_complete_cmd(struct se_cmd *, u8); void target_complete_cmd(struct se_cmd *, u8);
void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *); void transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);

View File

@ -477,14 +477,6 @@ struct se_queue_obj {
wait_queue_head_t thread_wq; wait_queue_head_t thread_wq;
}; };
struct se_task {
struct se_cmd *task_se_cmd;
struct scatterlist *task_sg;
u32 task_sg_nents;
u8 task_scsi_status;
enum dma_data_direction task_data_direction;
};
struct se_tmr_req { struct se_tmr_req {
/* Task Management function to be performed */ /* Task Management function to be performed */
u8 function; u8 function;
@ -592,7 +584,8 @@ struct se_cmd {
/* old task stop completion, consider merging with some of the above */ /* old task stop completion, consider merging with some of the above */
struct completion task_stop_comp; struct completion task_stop_comp;
struct se_task *t_task; /* backend private data */
void *priv;
}; };
struct se_ua { struct se_ua {