diff options
author | mav <mav@FreeBSD.org> | 2017-01-26 21:21:26 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2017-01-26 21:21:26 +0000 |
commit | 33c6bc1575b9a02ad0f5d30f52eedd409ab6a552 (patch) | |
tree | 5f10cf2634096edbaeb9126385ed6ec6b4181329 | |
parent | 794bd5396d443928b9a4456413c1a4ec6fbc6301 (diff) | |
download | FreeBSD-src-33c6bc1575b9a02ad0f5d30f52eedd409ab6a552.zip FreeBSD-src-33c6bc1575b9a02ad0f5d30f52eedd409ab6a552.tar.gz |
MFC r312232: Add under-/overrun support to IOCTL and CAM SIM frontends.
-rw-r--r-- | sys/cam/ctl/ctl_frontend_cam_sim.c | 21 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_frontend_ioctl.c | 24 |
2 files changed, 32 insertions, 13 deletions
diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c index dc54cde..68a156d 100644 --- a/sys/cam/ctl/ctl_frontend_cam_sim.c +++ b/sys/cam/ctl/ctl_frontend_cam_sim.c @@ -304,10 +304,6 @@ cfcs_datamove(union ctl_io *io) int ctl_watermark, cam_watermark; int i, j; - - cam_sg_offset = 0; - cam_sg_start = 0; - ccb = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; /* @@ -330,6 +326,8 @@ cfcs_datamove(union ctl_io *io) cam_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr; cam_sg_count = ccb->csio.sglist_cnt; + cam_sg_start = cam_sg_count; + cam_sg_offset = 0; for (i = 0, len_seen = 0; i < cam_sg_count; i++) { if ((len_seen + cam_sglist[i].ds_len) >= @@ -422,9 +420,20 @@ cfcs_datamove(union ctl_io *io) io->scsiio.ext_data_filled += len_copied; + /* + * Report write underflow as error, since CTL and backends don't + * really support it. + */ + if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_OUT && + j < ctl_sg_count) { + io->io_hdr.port_status = 43; + } else + if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = NULL; io->io_hdr.flags |= CTL_FLAG_STATUS_SENT; + ccb->csio.resid = ccb->csio.dxfer_len - + io->scsiio.ext_data_filled; ccb->ccb_h.status &= ~CAM_STATUS_MASK; ccb->ccb_h.status |= CAM_REQ_CMP; xpt_done(ccb); @@ -453,6 +462,10 @@ cfcs_done(union ctl_io *io) /* * Translate CTL status to CAM status. */ + if (ccb->ccb_h.func_code == XPT_SCSI_IO) { + ccb->csio.resid = ccb->csio.dxfer_len - + io->scsiio.ext_data_filled; + } ccb->ccb_h.status &= ~CAM_STATUS_MASK; switch (io->io_hdr.status & CTL_STATUS_MASK) { case CTL_SUCCESS: diff --git a/sys/cam/ctl/ctl_frontend_ioctl.c b/sys/cam/ctl/ctl_frontend_ioctl.c index 97f29f1..6f90fe3 100644 --- a/sys/cam/ctl/ctl_frontend_ioctl.c +++ b/sys/cam/ctl/ctl_frontend_ioctl.c @@ -143,16 +143,13 @@ ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio) int ext_sglist_malloced; int i, j; - ext_sglist_malloced = 0; - ext_sg_start = 0; - ext_offset = 0; - CTL_DEBUG_PRINT(("ctl_ioctl_do_datamove\n")); /* * If this flag is set, fake the data transfer. */ if (ctsio->io_hdr.flags & CTL_FLAG_NO_DATAMOVE) { + ext_sglist_malloced = 0; ctsio->ext_data_filled = ctsio->ext_data_len; goto bailout; } @@ -165,7 +162,6 @@ ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio) int len_seen; ext_sglen = ctsio->ext_sg_entries * sizeof(*ext_sglist); - ext_sglist = (struct ctl_sg_entry *)malloc(ext_sglen, M_CTL, M_WAITOK); ext_sglist_malloced = 1; @@ -174,6 +170,8 @@ ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio) goto bailout; } ext_sg_entries = ctsio->ext_sg_entries; + ext_sg_start = ext_sg_entries; + ext_offset = 0; len_seen = 0; for (i = 0; i < ext_sg_entries; i++) { if ((len_seen + ext_sglist[i].len) >= @@ -186,6 +184,7 @@ ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio) } } else { ext_sglist = &ext_entry; + ext_sglist_malloced = 0; ext_sglist->addr = ctsio->ext_data_ptr; ext_sglist->len = ctsio->ext_data_len; ext_sg_entries = 1; @@ -203,7 +202,6 @@ ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio) kern_sg_entries = 1; } - kern_watermark = 0; ext_watermark = ext_offset; len_copied = 0; @@ -274,10 +272,16 @@ ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio) "kern_data_len = %d\n", ctsio->ext_data_len, ctsio->kern_data_len)); + /* + * Report write underflow as error, since CTL and backends don't + * really support it. + */ + if ((ctsio->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_OUT && + j < kern_sg_entries) { + ctsio->io_hdr.port_status = 43; + } - /* XXX KDM set residual?? */ bailout: - if (ext_sglist_malloced != 0) free(ext_sglist, M_CTL); @@ -397,7 +401,7 @@ ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) { union ctl_io *io; - void *pool_tmp; + void *pool_tmp, *sc_tmp; int retval = 0; /* @@ -414,8 +418,10 @@ ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag, * spammed by the user's ctl_io. */ pool_tmp = io->io_hdr.pool; + sc_tmp = CTL_SOFTC(io); memcpy(io, (void *)addr, sizeof(*io)); io->io_hdr.pool = pool_tmp; + CTL_SOFTC(io) = sc_tmp; /* * No status yet, so make sure the status is set properly. |