aboutsummaryrefslogtreecommitdiff
path: root/sys/cam/ctl/ctl_frontend_iscsi.c
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2017-01-16 16:19:55 +0000
committerAlexander Motin <mav@FreeBSD.org>2017-01-16 16:19:55 +0000
commiteb6ac6f9db762bf753e5b6837279f992eb8a5800 (patch)
tree503e9ffd3dd4c74fd5e968f0a0143cb0320e55b2 /sys/cam/ctl/ctl_frontend_iscsi.c
parent662e30fca3530b5dba603d97aeedcc3fbc81ee97 (diff)
downloadsrc-eb6ac6f9db762bf753e5b6837279f992eb8a5800.tar.gz
src-eb6ac6f9db762bf753e5b6837279f992eb8a5800.zip
Make CTL frontends report kern_data_resid for under-/overruns.
It seems like kern_data_resid was never really implemented. This change finally does it. Now frontends update this field while transferring data, while CTL/backends getting it can more flexibly handle the result. At this point behavior should not change significantly, still reporting errors on write overrun, but that may be changed later, if we decide so. CAM target frontend still does not properly handle overruns due to CAM API limitations. We may need to add some fields to struct ccb_accept_tio to pass information about initiator requested transfer size(s). MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=312291
Diffstat (limited to 'sys/cam/ctl/ctl_frontend_iscsi.c')
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index 443a4790a126..1171eb0876d6 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -769,6 +769,7 @@ cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *c
cdw->cdw_sg_len -= copy_len;
off += copy_len;
io->scsiio.ext_data_filled += copy_len;
+ io->scsiio.kern_data_resid -= copy_len;
if (cdw->cdw_sg_len == 0) {
/*
@@ -2514,6 +2515,7 @@ cfiscsi_datamove_in(union ctl_io *io)
}
sg_addr += len;
sg_len -= len;
+ io->scsiio.kern_data_resid -= len;
KASSERT(buffer_offset + response->ip_data_len <= expected_len,
("buffer_offset %zd + ip_data_len %zd > expected_len %zd",
@@ -2599,7 +2601,7 @@ cfiscsi_datamove_out(union ctl_io *io)
struct iscsi_bhs_r2t *bhsr2t;
struct cfiscsi_data_wait *cdw;
struct ctl_sg_entry ctl_sg_entry, *ctl_sglist;
- uint32_t expected_len, r2t_off, r2t_len;
+ uint32_t expected_len, datamove_len, r2t_off, r2t_len;
uint32_t target_transfer_tag;
bool done;
@@ -2618,16 +2620,15 @@ cfiscsi_datamove_out(union ctl_io *io)
PDU_TOTAL_TRANSFER_LEN(request) = io->scsiio.kern_total_len;
/*
- * Report write underflow as error since CTL and backends don't
- * really support it, and SCSI does not tell how to do it right.
+ * Complete write underflow. Not a single byte to read. Return.
*/
expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length);
- if (io->scsiio.kern_rel_offset + io->scsiio.kern_data_len >
- expected_len) {
- io->scsiio.io_hdr.port_status = 43;
+ if (io->scsiio.kern_rel_offset > expected_len) {
io->scsiio.be_move_done(io);
return;
}
+ datamove_len = MIN(io->scsiio.kern_data_len,
+ expected_len - io->scsiio.kern_rel_offset);
target_transfer_tag =
atomic_fetchadd_32(&cs->cs_target_transfer_tag, 1);
@@ -2650,7 +2651,7 @@ cfiscsi_datamove_out(union ctl_io *io)
cdw->cdw_ctl_io = io;
cdw->cdw_target_transfer_tag = target_transfer_tag;
cdw->cdw_initiator_task_tag = bhssc->bhssc_initiator_task_tag;
- cdw->cdw_r2t_end = io->scsiio.kern_data_len;
+ cdw->cdw_r2t_end = datamove_len;
cdw->cdw_datasn = 0;
/* Set initial data pointer for the CDW respecting ext_data_filled. */
@@ -2659,7 +2660,7 @@ cfiscsi_datamove_out(union ctl_io *io)
} else {
ctl_sglist = &ctl_sg_entry;
ctl_sglist->addr = io->scsiio.kern_data_ptr;
- ctl_sglist->len = io->scsiio.kern_data_len;
+ ctl_sglist->len = datamove_len;
}
cdw->cdw_sg_index = 0;
cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr;
@@ -2690,7 +2691,7 @@ cfiscsi_datamove_out(union ctl_io *io)
}
r2t_off = io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled;
- r2t_len = MIN(io->scsiio.kern_data_len - io->scsiio.ext_data_filled,
+ r2t_len = MIN(datamove_len - io->scsiio.ext_data_filled,
cs->cs_max_burst_length);
cdw->cdw_r2t_end = io->scsiio.ext_data_filled + r2t_len;