Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5787cacd authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Nicholas Bellinger
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent cf572a96
Loading
Loading
Loading
Loading
+42 −75
Original line number Diff line number Diff line
@@ -244,53 +244,33 @@ static void fd_free_device(void *p)
	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);
}


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 se_device *se_dev = cmd->se_dev;
	struct fd_dev *dev = se_dev->dev_ptr;
	struct file *fd = dev->fd_file;
	struct scatterlist *sg = task->task_sg;
	struct scatterlist *sg;
	struct iovec *iov;
	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);
	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) {
		pr_err("Unable to allocate fd_do_readv iov[]\n");
		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_base = sg_virt(sg);
	}

	old_fs = get_fs();
	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);

	kfree(iov);
@@ -300,10 +280,10 @@ static int fd_do_readv(struct se_task *task)
	 * block_device.
	 */
	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,"
				" expecting %d for S_ISBLK\n", ret,
				(int)task->task_se_cmd->data_length);
				(int)cmd->data_length);
			return (ret < 0 ? ret : -EINVAL);
		}
	} else {
@@ -317,38 +297,38 @@ static int fd_do_readv(struct se_task *task)
	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 = req->fd_task.task_se_cmd->se_dev;
	struct se_device *se_dev = cmd->se_dev;
	struct fd_dev *dev = se_dev->dev_ptr;
	struct file *fd = dev->fd_file;
	struct scatterlist *sg = task->task_sg;
	struct scatterlist *sg;
	struct iovec *iov;
	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);
	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) {
		pr_err("Unable to allocate fd_do_writev iov[]\n");
		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_base = sg_virt(sg);
	}

	old_fs = get_fs();
	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);

	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);
		return (ret < 0 ? ret : -EINVAL);
	}
@@ -369,7 +349,7 @@ static void fd_emulate_sync_cache(struct se_cmd *cmd)
	 * for this SYNCHRONIZE_CACHE op
	 */
	if (immed)
		transport_complete_sync_cache(cmd, 1);
		target_complete_cmd(cmd, SAM_STAT_GOOD);

	/*
	 * 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)
		pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);

	if (!immed)
		transport_complete_sync_cache(cmd, ret == 0);
	if (immed)
		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);
	}
}

/*
 * 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)
static void fd_emulate_write_fua(struct se_cmd *cmd)
{
	struct se_device *dev = cmd->se_dev;
	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;
	loff_t end = start + task->task_se_cmd->data_length;
	loff_t end = start + cmd->data_length;
	int ret;

	pr_debug("FILEIO: FUA WRITE LBA: %llu, bytes: %u\n",
			task->task_se_cmd->t_task_lba,
			task->task_se_cmd->data_length);
		cmd->t_task_lba, cmd->data_length);

	ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1);
	if (ret != 0)
		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;
	int ret = 0;

@@ -425,10 +407,10 @@ static int fd_do_task(struct se_task *task)
	 * Call vectorized fileio functions to map struct scatterlist
	 * physical memory addresses to struct iovec virtual memory.
	 */
	if (task->task_data_direction == DMA_FROM_DEVICE) {
		ret = fd_do_readv(task);
	if (data_direction == DMA_FROM_DEVICE) {
		ret = fd_do_readv(cmd, sgl, sgl_nents);
	} else {
		ret = fd_do_writev(task);
		ret = fd_do_writev(cmd, sgl, sgl_nents);

		if (ret > 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
			 * 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;
		return ret;
	}
	if (ret) {
		task->task_scsi_status = GOOD;
		transport_complete_task(task, 1);
	}
	if (ret)
		target_complete_cmd(cmd, SAM_STAT_GOOD);
	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 {
	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,
	.create_virtdevice	= fd_create_virtdevice,
	.free_device		= fd_free_device,
	.alloc_task		= fd_alloc_task,
	.do_task		= fd_do_task,
	.execute_cmd		= fd_execute_cmd,
	.do_sync_cache		= fd_emulate_sync_cache,
	.free_task		= fd_free_task,
	.check_configfs_dev_params = fd_check_configfs_dev_params,
	.set_configfs_dev_params = fd_set_configfs_dev_params,
	.show_configfs_dev_params = fd_show_configfs_dev_params,
+0 −4
Original line number Diff line number Diff line
@@ -12,10 +12,6 @@
#define RRF_EMULATE_CDB		0x01
#define RRF_GOT_LBA		0x02

struct fd_request {
	struct se_task	fd_task;
};

#define FBDF_HAS_PATH		0x01
#define FBDF_HAS_SIZE		0x02
#define FDBD_USE_BUFFERED_IO	0x04
+65 −77
Original line number Diff line number Diff line
@@ -189,26 +189,6 @@ static void iblock_free_device(void *p)
	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(
	struct se_device *dev,
	struct block_device *bd,
@@ -295,8 +275,16 @@ static void iblock_end_io_flush(struct bio *bio, int err)
	if (err)
		pr_err("IBLOCK: cache flush failed: %d\n", err);

	if (cmd)
		transport_complete_sync_cache(cmd, err == 0);
	if (cmd) {
		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);
}

@@ -315,7 +303,7 @@ static void iblock_emulate_sync_cache(struct se_cmd *cmd)
	 * for this SYNCHRONIZE_CACHE op.
	 */
	if (immed)
		transport_complete_sync_cache(cmd, 1);
		target_complete_cmd(cmd, SAM_STAT_GOOD);

	bio = bio_alloc(GFP_KERNEL, 0);
	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);
}

static void iblock_free_task(struct se_task *task)
{
	kfree(IBLOCK_REQ(task));
}

enum {
	Opt_udev_path, Opt_force, Opt_err
};
@@ -447,19 +430,35 @@ static ssize_t iblock_show_configfs_dev_params(
	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)
{
	struct se_task *task = bio->bi_private;
	struct iblock_dev *ib_dev = task->task_se_cmd->se_dev->dev_ptr;
	struct se_cmd *cmd = bio->bi_private;
	struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;

	bio_free(bio, ib_dev->ibd_bio_set);
}

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_req *ib_req = IBLOCK_REQ(task);
	struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
	struct bio *bio;

	/*
@@ -475,20 +474,11 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
		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_private = task;
	bio->bi_private = cmd;
	bio->bi_destructor = iblock_bio_destructor;
	bio->bi_end_io = &iblock_bio_done;
	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;
}

@@ -503,20 +493,21 @@ static void iblock_submit_bios(struct bio_list *list, int rw)
	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 iblock_req *ibr = IBLOCK_REQ(task);
	struct iblock_req *ibr;
	struct bio *bio;
	struct bio_list list;
	struct scatterlist *sg;
	u32 i, sg_num = task->task_sg_nents;
	u32 sg_num = sgl_nents;
	sector_t block_lba;
	unsigned bio_cnt;
	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
		 * 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
	 * struct se_task SCSI blocksize into Linux/Block 512 units for BIO.
	 * Convert the blocksize advertised to the initiator to the 512 byte
	 * units unconditionally used by the Linux block layer.
	 */
	if (dev->se_sub_dev->se_dev_attrib.block_size == 4096)
		block_lba = (cmd->t_task_lba << 3);
@@ -550,17 +541,22 @@ static int iblock_do_task(struct se_task *task)
		return -ENOSYS;
	}

	bio = iblock_get_bio(task, block_lba, sg_num);
	if (!bio) {
		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
		return -ENOMEM;
	}
	ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
	if (!ibr)
		goto fail;
	cmd->priv = ibr;

	bio = iblock_get_bio(cmd, block_lba, sgl_nents);
	if (!bio)
		goto fail_free_ibr;

	bio_list_init(&list);
	bio_list_add(&list, bio);

	atomic_set(&ibr->pending, 2);
	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
		 *	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 = iblock_get_bio(task, block_lba, sg_num);
			bio = iblock_get_bio(cmd, block_lba, sg_num);
			if (!bio)
				goto fail;
				goto fail_put_bios;

			atomic_inc(&ibr->pending);
			bio_list_add(&list, bio);
			bio_cnt++;
		}
@@ -586,17 +584,16 @@ static int iblock_do_task(struct se_task *task)
	}

	iblock_submit_bios(&list, rw);

	if (atomic_dec_and_test(&ibr->pending)) {
		transport_complete_task(task,
				!atomic_read(&ibr->ib_bio_err_cnt));
	}
	iblock_complete_cmd(cmd);
	return 0;

fail:
fail_put_bios:
	while ((bio = bio_list_pop(&list)))
		bio_put(bio);
fail_free_ibr:
	kfree(ibr);
	cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
fail:
	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)
{
	struct se_task *task = bio->bi_private;
	struct iblock_req *ibr = IBLOCK_REQ(task);
	struct se_cmd *cmd = bio->bi_private;
	struct iblock_req *ibr = cmd->priv;

	/*
	 * 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);

	if (!atomic_dec_and_test(&ibr->pending))
		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));
	iblock_complete_cmd(cmd);
}

static struct se_subsystem_api iblock_template = {
@@ -663,11 +653,9 @@ static struct se_subsystem_api iblock_template = {
	.allocate_virtdevice	= iblock_allocate_virtdevice,
	.create_virtdevice	= iblock_create_virtdevice,
	.free_device		= iblock_free_device,
	.alloc_task		= iblock_alloc_task,
	.do_task		= iblock_do_task,
	.execute_cmd		= iblock_execute_cmd,
	.do_discard		= iblock_do_discard,
	.do_sync_cache		= iblock_emulate_sync_cache,
	.free_task		= iblock_free_task,
	.check_configfs_dev_params = iblock_check_configfs_dev_params,
	.set_configfs_dev_params = iblock_set_configfs_dev_params,
	.show_configfs_dev_params = iblock_show_configfs_dev_params,
+0 −1
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@
#define IBLOCK_LBA_SHIFT	9

struct iblock_req {
	struct se_task ib_task;
	atomic_t pending;
	atomic_t ib_bio_err_cnt;
} ____cacheline_aligned;
+61 −111
Original line number Diff line number Diff line
@@ -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 @@ static int pscsi_transport_complete(struct se_task *task)
	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 @@ static int pscsi_transport_complete(struct se_task *task)
	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 @@ static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
	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 @@ static int pscsi_do_task(struct se_task *task)
		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,
Loading