target: rewrite fd_execute_write_same
With the new bio_vec backed iov_iter helpers we can simply set up on bio_vec per LBA, all pointing to the same initiator-supplied buffer. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
6b9a44d093
commit
d4c5dcacfa
|
@ -433,59 +433,17 @@ fd_execute_sync_cache(struct se_cmd *cmd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *
|
|
||||||
fd_setup_write_same_buf(struct se_cmd *cmd, struct scatterlist *sg,
|
|
||||||
unsigned int len)
|
|
||||||
{
|
|
||||||
struct se_device *se_dev = cmd->se_dev;
|
|
||||||
unsigned int block_size = se_dev->dev_attrib.block_size;
|
|
||||||
unsigned int i = 0, end;
|
|
||||||
unsigned char *buf, *p, *kmap_buf;
|
|
||||||
|
|
||||||
buf = kzalloc(min_t(unsigned int, len, PAGE_SIZE), GFP_KERNEL);
|
|
||||||
if (!buf) {
|
|
||||||
pr_err("Unable to allocate fd_execute_write_same buf\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
kmap_buf = kmap(sg_page(sg)) + sg->offset;
|
|
||||||
if (!kmap_buf) {
|
|
||||||
pr_err("kmap() failed in fd_setup_write_same\n");
|
|
||||||
kfree(buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Fill local *buf to contain multiple WRITE_SAME blocks up to
|
|
||||||
* min(len, PAGE_SIZE)
|
|
||||||
*/
|
|
||||||
p = buf;
|
|
||||||
end = min_t(unsigned int, len, PAGE_SIZE);
|
|
||||||
|
|
||||||
while (i < end) {
|
|
||||||
memcpy(p, kmap_buf, block_size);
|
|
||||||
|
|
||||||
i += block_size;
|
|
||||||
p += block_size;
|
|
||||||
}
|
|
||||||
kunmap(sg_page(sg));
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sense_reason_t
|
static sense_reason_t
|
||||||
fd_execute_write_same(struct se_cmd *cmd)
|
fd_execute_write_same(struct se_cmd *cmd)
|
||||||
{
|
{
|
||||||
struct se_device *se_dev = cmd->se_dev;
|
struct se_device *se_dev = cmd->se_dev;
|
||||||
struct fd_dev *fd_dev = FD_DEV(se_dev);
|
struct fd_dev *fd_dev = FD_DEV(se_dev);
|
||||||
struct file *f = fd_dev->fd_file;
|
|
||||||
struct scatterlist *sg;
|
|
||||||
struct iovec *iov;
|
|
||||||
mm_segment_t old_fs;
|
|
||||||
sector_t nolb = sbc_get_write_same_sectors(cmd);
|
|
||||||
loff_t pos = cmd->t_task_lba * se_dev->dev_attrib.block_size;
|
loff_t pos = cmd->t_task_lba * se_dev->dev_attrib.block_size;
|
||||||
unsigned int len, len_tmp, iov_num;
|
sector_t nolb = sbc_get_write_same_sectors(cmd);
|
||||||
int i, rc;
|
struct iov_iter iter;
|
||||||
unsigned char *buf;
|
struct bio_vec *bvec;
|
||||||
|
unsigned int len = 0, i;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
if (!nolb) {
|
if (!nolb) {
|
||||||
target_complete_cmd(cmd, SAM_STAT_GOOD);
|
target_complete_cmd(cmd, SAM_STAT_GOOD);
|
||||||
|
@ -496,49 +454,35 @@ fd_execute_write_same(struct se_cmd *cmd)
|
||||||
" backends not supported\n");
|
" backends not supported\n");
|
||||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||||
}
|
}
|
||||||
sg = &cmd->t_data_sg[0];
|
|
||||||
|
|
||||||
if (cmd->t_data_nents > 1 ||
|
if (cmd->t_data_nents > 1 ||
|
||||||
sg->length != cmd->se_dev->dev_attrib.block_size) {
|
cmd->t_data_sg[0].length != cmd->se_dev->dev_attrib.block_size) {
|
||||||
pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u"
|
pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u"
|
||||||
" block_size: %u\n", cmd->t_data_nents, sg->length,
|
" block_size: %u\n",
|
||||||
|
cmd->t_data_nents,
|
||||||
|
cmd->t_data_sg[0].length,
|
||||||
cmd->se_dev->dev_attrib.block_size);
|
cmd->se_dev->dev_attrib.block_size);
|
||||||
return TCM_INVALID_CDB_FIELD;
|
return TCM_INVALID_CDB_FIELD;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = len_tmp = nolb * se_dev->dev_attrib.block_size;
|
bvec = kcalloc(nolb, sizeof(struct bio_vec), GFP_KERNEL);
|
||||||
iov_num = DIV_ROUND_UP(len, PAGE_SIZE);
|
if (!bvec)
|
||||||
|
|
||||||
buf = fd_setup_write_same_buf(cmd, sg, len);
|
|
||||||
if (!buf)
|
|
||||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||||
|
|
||||||
iov = vzalloc(sizeof(struct iovec) * iov_num);
|
for (i = 0; i < nolb; i++) {
|
||||||
if (!iov) {
|
bvec[i].bv_page = sg_page(&cmd->t_data_sg[0]);
|
||||||
pr_err("Unable to allocate fd_execute_write_same iovecs\n");
|
bvec[i].bv_len = cmd->t_data_sg[0].length;
|
||||||
kfree(buf);
|
bvec[i].bv_offset = cmd->t_data_sg[0].offset;
|
||||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
||||||
}
|
len += se_dev->dev_attrib.block_size;
|
||||||
/*
|
|
||||||
* Map the single fabric received scatterlist block now populated
|
|
||||||
* in *buf into each iovec for I/O submission.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < iov_num; i++) {
|
|
||||||
iov[i].iov_base = buf;
|
|
||||||
iov[i].iov_len = min_t(unsigned int, len_tmp, PAGE_SIZE);
|
|
||||||
len_tmp -= iov[i].iov_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
old_fs = get_fs();
|
iov_iter_bvec(&iter, ITER_BVEC, bvec, nolb, len);
|
||||||
set_fs(get_ds());
|
ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos);
|
||||||
rc = vfs_writev(f, &iov[0], iov_num, &pos);
|
|
||||||
set_fs(old_fs);
|
|
||||||
|
|
||||||
vfree(iov);
|
kfree(bvec);
|
||||||
kfree(buf);
|
if (ret < 0 || ret != len) {
|
||||||
|
pr_err("vfs_iter_write() returned %zd for write same\n", ret);
|
||||||
if (rc < 0 || rc != len) {
|
|
||||||
pr_err("vfs_writev() returned %d for write same\n", rc);
|
|
||||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue