aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2014-11-25 17:53:35 +0000
committerAlexander Motin <mav@FreeBSD.org>2014-11-25 17:53:35 +0000
commitf7241cceb02f56add7f4a504021069acb81f4bf6 (patch)
treea3a596368ccfcff50a172e691d7ebad9c8822de3
parent82e843b93b2ce12c8cf5c1fd5fb88c1d37a54134 (diff)
downloadsrc-f7241cceb02f56add7f4a504021069acb81f4bf6.tar.gz
src-f7241cceb02f56add7f4a504021069acb81f4bf6.zip
Coalesce last data move and command status for read commands.
Make CTL core and block backend set success status before initiating last data move for read commands. Make CAM target and iSCSI frontends detect such condition and send command status together with data. New I/O flag allows to skip duplicate status sending on later fe_done() call. For Fibre Channel this change saves one of three interrupts per read command, increasing performance from 126K to 160K IOPS. For iSCSI this change saves one of three PDUs per read command, increasing performance from 1M to 1.2M IOPS. MFC after: 1 month Sponsored by: iXsystems, Inc.
Notes
Notes: svn path=/head/; revision=275058
-rw-r--r--sys/cam/ctl/ctl.c132
-rw-r--r--sys/cam/ctl/ctl_backend_block.c21
-rw-r--r--sys/cam/ctl/ctl_backend_ramdisk.c13
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c38
-rw-r--r--sys/cam/ctl/ctl_io.h3
-rw-r--r--sys/cam/ctl/ctl_tpc.c16
-rw-r--r--sys/cam/ctl/scsi_ctl.c34
7 files changed, 128 insertions, 129 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 9d214171fa0f..075405f55e11 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -4996,23 +4996,13 @@ ctl_config_move_done(union ctl_io *io)
{
int retval;
- retval = CTL_RETVAL_COMPLETE;
-
-
CTL_DEBUG_PRINT(("ctl_config_move_done\n"));
- /*
- * XXX KDM this shouldn't happen, but what if it does?
- */
- if (io->io_hdr.io_type != CTL_IO_SCSI)
- panic("I/O type isn't CTL_IO_SCSI!");
+ KASSERT(io->io_hdr.io_type == CTL_IO_SCSI,
+ ("Config I/O type isn't CTL_IO_SCSI (%d)!", io->io_hdr.io_type));
- if ((io->io_hdr.port_status == 0)
- && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0)
- && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE))
- io->io_hdr.status = CTL_SUCCESS;
- else if ((io->io_hdr.port_status != 0)
- && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0)
- && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)){
+ if ((io->io_hdr.port_status != 0) &&
+ ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE ||
+ (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) {
/*
* For hardware error sense keys, the sense key
* specific value is defined to be a retry count,
@@ -5025,15 +5015,12 @@ ctl_config_move_done(union ctl_io *io)
/*sks_valid*/ 1,
/*retry_count*/
io->io_hdr.port_status);
- if (io->io_hdr.flags & CTL_FLAG_ALLOCATED)
- free(io->scsiio.kern_data_ptr, M_CTL);
- ctl_done(io);
- goto bailout;
}
- if (((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN)
- || ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)
- || ((io->io_hdr.flags & CTL_FLAG_ABORT) != 0)) {
+ if (((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) ||
+ ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
+ (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) ||
+ ((io->io_hdr.flags & CTL_FLAG_ABORT) != 0)) {
/*
* XXX KDM just assuming a single pointer here, and not a
* S/G list. If we start using S/G lists for config data,
@@ -5041,8 +5028,8 @@ ctl_config_move_done(union ctl_io *io)
*/
if (io->io_hdr.flags & CTL_FLAG_ALLOCATED)
free(io->scsiio.kern_data_ptr, M_CTL);
- /* Hopefully the user has already set the status... */
ctl_done(io);
+ retval = CTL_RETVAL_COMPLETE;
} else {
/*
* XXX KDM now we need to continue data movement. Some
@@ -5065,7 +5052,6 @@ ctl_config_move_done(union ctl_io *io)
*/
retval = ctl_scsiio(&io->scsiio);
}
-bailout:
return (retval);
}
@@ -5211,13 +5197,12 @@ ctl_scsi_release(struct ctl_scsiio *ctsio)
mtx_unlock(&lun->lun_lock);
- ctl_set_success(ctsio);
-
if (ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) {
free(ctsio->kern_data_ptr, M_CTL);
ctsio->io_hdr.flags &= ~CTL_FLAG_ALLOCATED;
}
+ ctl_set_success(ctsio);
ctl_done((union ctl_io *)ctsio);
return (CTL_RETVAL_COMPLETE);
}
@@ -5681,9 +5666,9 @@ ctl_read_buffer(struct ctl_scsiio *ctsio)
ctsio->kern_data_resid = 0;
ctsio->kern_rel_offset = 0;
ctsio->kern_sg_entries = 0;
+ ctl_set_success(ctsio);
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -5746,8 +5731,8 @@ ctl_write_buffer(struct ctl_scsiio *ctsio)
return (CTL_RETVAL_COMPLETE);
}
+ ctl_set_success(ctsio);
ctl_done((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -6870,12 +6855,10 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
}
}
- ctsio->scsi_status = SCSI_STATUS_OK;
-
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -7025,11 +7008,10 @@ ctl_log_sense(struct ctl_scsiio *ctsio)
memcpy(header + 1, page_index->page_data, page_index->page_len);
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -7084,12 +7066,10 @@ ctl_read_capacity(struct ctl_scsiio *ctsio)
*/
scsi_ulto4b(lun->be_lun->blocksize, data->length);
- ctsio->scsi_status = SCSI_STATUS_OK;
-
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -7147,12 +7127,10 @@ ctl_read_capacity_16(struct ctl_scsiio *ctsio)
if (lun->be_lun->flags & CTL_LUN_FLAG_UNMAP)
data->lalba_lbp[0] |= SRC16_LBPME | SRC16_LBPRZ;
- ctsio->scsi_status = SCSI_STATUS_OK;
-
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -7212,7 +7190,7 @@ ctl_read_defect(struct ctl_scsiio *ctsio)
scsi_ulto4b(0, data12->length);
}
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
@@ -7355,15 +7333,9 @@ ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio)
}
mtx_unlock(&softc->ctl_lock);
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
- CTL_DEBUG_PRINT(("buf = %x %x %x %x %x %x %x %x\n",
- ctsio->kern_data_ptr[0], ctsio->kern_data_ptr[1],
- ctsio->kern_data_ptr[2], ctsio->kern_data_ptr[3],
- ctsio->kern_data_ptr[4], ctsio->kern_data_ptr[5],
- ctsio->kern_data_ptr[6], ctsio->kern_data_ptr[7]));
-
ctl_datamove((union ctl_io *)ctsio);
return(retval);
}
@@ -7527,9 +7499,9 @@ fill_one:
break;
}
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
ctl_datamove((union ctl_io *)ctsio);
return(retval);
}
@@ -7571,9 +7543,9 @@ ctl_report_supported_tmf(struct ctl_scsiio *ctsio)
data->byte1 |= RST_ATS | RST_ATSS | RST_CTSS | RST_LURS | RST_TRS;
data->byte2 |= RST_ITNRS;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
ctl_datamove((union ctl_io *)ctsio);
return (retval);
}
@@ -7621,9 +7593,9 @@ ctl_report_timestamp(struct ctl_scsiio *ctsio)
scsi_ulto4b(timestamp >> 16, data->timestamp);
scsi_ulto2b(timestamp & 0xffff, &data->timestamp[4]);
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
ctl_datamove((union ctl_io *)ctsio);
return (retval);
}
@@ -7888,17 +7860,10 @@ retry:
}
mtx_unlock(&lun->lun_lock);
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
- CTL_DEBUG_PRINT(("buf = %x %x %x %x %x %x %x %x\n",
- ctsio->kern_data_ptr[0], ctsio->kern_data_ptr[1],
- ctsio->kern_data_ptr[2], ctsio->kern_data_ptr[3],
- ctsio->kern_data_ptr[4], ctsio->kern_data_ptr[5],
- ctsio->kern_data_ptr[6], ctsio->kern_data_ptr[7]));
-
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -9427,12 +9392,10 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
* We can only return SCSI_STATUS_CHECK_COND when we can't satisfy
* this request.
*/
- ctsio->scsi_status = SCSI_STATUS_OK;
-
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (retval);
}
@@ -9546,19 +9509,14 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
/*
* We report the SCSI status as OK, since the status of the
* request sense command itself is OK.
- */
- ctsio->scsi_status = SCSI_STATUS_OK;
-
- /*
* We report 0 for the sense length, because we aren't doing
* autosense in this case. We're reporting sense as
* parameter data.
*/
- ctsio->sense_len = 0;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -9577,17 +9535,14 @@ no_sense:
/*ascq*/ 0x00,
SSD_ELEM_NONE);
- ctsio->scsi_status = SCSI_STATUS_OK;
-
/*
* We report 0 for the sense length, because we aren't doing
* autosense in this case. We're reporting sense as parameter data.
*/
- ctsio->sense_len = 0;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -9672,12 +9627,10 @@ ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len)
/* Logical Block Provisioning */
pages->page_list[9] = SVPD_LBP;
- ctsio->scsi_status = SCSI_STATUS_OK;
-
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -9728,12 +9681,11 @@ ctl_inquiry_evpd_serial(struct ctl_scsiio *ctsio, int alloc_len)
(char *)lun->be_lun->serial_num, CTL_SN_LEN);
} else
memset(sn_ptr->serial_num, 0x20, CTL_SN_LEN);
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -9779,11 +9731,10 @@ ctl_inquiry_evpd_eid(struct ctl_scsiio *ctsio, int alloc_len)
eid_ptr->flags2 = SVPD_EID_HEADSUP | SVPD_EID_ORDSUP | SVPD_EID_SIMPSUP;
eid_ptr->flags3 = SVPD_EID_V_SUP;
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -9831,11 +9782,10 @@ ctl_inquiry_evpd_mpp(struct ctl_scsiio *ctsio, int alloc_len)
mpp_ptr->descr[0].subpage_code = 0xff;
mpp_ptr->descr[0].policy = SVPD_MPP_SHARED;
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -9953,11 +9903,10 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
memcpy(desc, port->target_devid->data, port->target_devid->len);
}
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -10068,11 +10017,10 @@ ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len)
}
mtx_unlock(&softc->ctl_lock);
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -10137,11 +10085,10 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
}
scsi_u64to8b(UINT64_MAX, bl_ptr->max_write_same_length);
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -10198,11 +10145,10 @@ ctl_inquiry_evpd_bdc(struct ctl_scsiio *ctsio, int alloc_len)
bdc_ptr->wab_wac_ff = (i & 0x0f);
bdc_ptr->flags = SVPD_FUAB | SVPD_VBULS;
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -10251,11 +10197,10 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len)
lbp_ptr->prov_type = SVPD_LBP_THIN;
}
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
-
return (CTL_RETVAL_COMPLETE);
}
@@ -10555,7 +10500,7 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
}
}
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
@@ -13526,8 +13471,9 @@ ctl_process_done(union ctl_io *io)
* Check to see if we have any errors to inject here. We only
* inject errors for commands that don't already have errors set.
*/
- if ((STAILQ_FIRST(&lun->error_list) != NULL)
- && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS))
+ if ((STAILQ_FIRST(&lun->error_list) != NULL) &&
+ ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) &&
+ ((io->io_hdr.flags & CTL_FLAG_STATUS_SENT) == 0))
ctl_inject_error(lun, io);
/*
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index ecaecbdff315..a90245a26e4b 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -381,8 +381,9 @@ ctl_be_block_move_done(union ctl_io *io)
* We set status at this point for read commands, and write
* commands with errors.
*/
- if ((io->io_hdr.port_status == 0) &&
- ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0) &&
+ if (io->io_hdr.flags & CTL_FLAG_ABORT) {
+ ;
+ } else if ((io->io_hdr.port_status == 0) &&
((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) {
lbalen = ARGS(beio->io);
if (lbalen->flags & CTL_LLF_READ) {
@@ -405,10 +406,9 @@ ctl_be_block_move_done(union ctl_io *io)
else
ctl_set_success(&io->scsiio);
}
- }
- else if ((io->io_hdr.port_status != 0)
- && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0)
- && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) {
+ } else if ((io->io_hdr.port_status != 0) &&
+ ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE ||
+ (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) {
/*
* For hardware error sense keys, the sense key
* specific value is defined to be a retry count,
@@ -532,6 +532,9 @@ ctl_be_block_biodone(struct bio *bio)
ctl_set_success(&io->scsiio);
ctl_complete_beio(beio);
} else {
+ if ((ARGS(io)->flags & CTL_LLF_READ) &&
+ beio->beio_cont == NULL)
+ ctl_set_success(&io->scsiio);
#ifdef CTL_TIME_IO
getbintime(&io->io_hdr.dma_start_bt);
#endif
@@ -739,6 +742,9 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
ctl_set_success(&io->scsiio);
ctl_complete_beio(beio);
} else {
+ if ((ARGS(io)->flags & CTL_LLF_READ) &&
+ beio->beio_cont == NULL)
+ ctl_set_success(&io->scsiio);
#ifdef CTL_TIME_IO
getbintime(&io->io_hdr.dma_start_bt);
#endif
@@ -828,6 +834,9 @@ ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun,
ctl_set_success(&io->scsiio);
ctl_complete_beio(beio);
} else {
+ if ((ARGS(io)->flags & CTL_LLF_READ) &&
+ beio->beio_cont == NULL)
+ ctl_set_success(&io->scsiio);
#ifdef CTL_TIME_IO
getbintime(&io->io_hdr.dma_start_bt);
#endif
diff --git a/sys/cam/ctl/ctl_backend_ramdisk.c b/sys/cam/ctl/ctl_backend_ramdisk.c
index 353245980c68..9b3b14ae5945 100644
--- a/sys/cam/ctl/ctl_backend_ramdisk.c
+++ b/sys/cam/ctl/ctl_backend_ramdisk.c
@@ -238,9 +238,10 @@ ctl_backend_ramdisk_move_done(union ctl_io *io)
if (io->scsiio.kern_sg_entries > 0)
free(io->scsiio.kern_data_ptr, M_RAMDISK);
io->scsiio.kern_rel_offset += io->scsiio.kern_data_len;
- if ((io->io_hdr.port_status == 0)
- && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0)
- && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) {
+ if (io->io_hdr.flags & CTL_FLAG_ABORT) {
+ ;
+ } else if ((io->io_hdr.port_status == 0) &&
+ ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)) {
if (io->io_hdr.ctl_private[CTL_PRIV_BACKEND].integer > 0) {
mtx_lock(&be_lun->queue_lock);
STAILQ_INSERT_TAIL(&be_lun->cont_queue,
@@ -251,9 +252,9 @@ ctl_backend_ramdisk_move_done(union ctl_io *io)
return (0);
}
ctl_set_success(&io->scsiio);
- } else if ((io->io_hdr.port_status != 0)
- && ((io->io_hdr.flags & CTL_FLAG_ABORT) == 0)
- && ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)){
+ } else if ((io->io_hdr.port_status != 0) &&
+ ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE ||
+ (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) {
/*
* For hardware error sense keys, the sense key
* specific value is defined to be a retry count,
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index a0fdc4104c41..8ec582586b77 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -367,14 +367,16 @@ cfiscsi_pdu_prepare(struct icl_pdu *response)
* See the comment below - StatSN is not meaningful and must
* not be advanced.
*/
- if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_SCSI_DATA_IN)
+ if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_SCSI_DATA_IN &&
+ (bhssr->bhssr_flags & BHSDI_FLAGS_S) == 0)
advance_statsn = false;
/*
* 10.7.3: "The fields StatSN, Status, and Residual Count
* only have meaningful content if the S bit is set to 1."
*/
- if (bhssr->bhssr_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN)
+ if (bhssr->bhssr_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN ||
+ (bhssr->bhssr_flags & BHSDI_FLAGS_S))
bhssr->bhssr_statsn = htonl(cs->cs_statsn);
bhssr->bhssr_expcmdsn = htonl(cs->cs_cmdsn);
bhssr->bhssr_maxcmdsn = htonl(cs->cs_cmdsn + maxcmdsn_delta);
@@ -2548,8 +2550,10 @@ cfiscsi_datamove_in(union ctl_io *io)
*/
buffer_offset += response->ip_data_len;
if (buffer_offset == io->scsiio.kern_total_len ||
- buffer_offset == expected_len)
- bhsdi->bhsdi_flags |= BHSDI_FLAGS_F;
+ buffer_offset == expected_len) {
+ buffer_offset -= response->ip_data_len;
+ break;
+ }
cfiscsi_pdu_queue(response);
response = NULL;
bhsdi = NULL;
@@ -2558,8 +2562,27 @@ cfiscsi_datamove_in(union ctl_io *io)
if (response != NULL) {
buffer_offset += response->ip_data_len;
if (buffer_offset == io->scsiio.kern_total_len ||
- buffer_offset == expected_len)
+ buffer_offset == expected_len) {
bhsdi->bhsdi_flags |= BHSDI_FLAGS_F;
+ if (io->io_hdr.status == CTL_SUCCESS) {
+ bhsdi->bhsdi_flags |= BHSDI_FLAGS_S;
+ if (PDU_TOTAL_TRANSFER_LEN(request) <
+ ntohl(bhssc->bhssc_expected_data_transfer_length)) {
+ bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_UNDERFLOW;
+ bhsdi->bhsdi_residual_count =
+ htonl(ntohl(bhssc->bhssc_expected_data_transfer_length) -
+ PDU_TOTAL_TRANSFER_LEN(request));
+ } else if (PDU_TOTAL_TRANSFER_LEN(request) >
+ ntohl(bhssc->bhssc_expected_data_transfer_length)) {
+ bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_OVERFLOW;
+ bhsdi->bhsdi_residual_count =
+ htonl(PDU_TOTAL_TRANSFER_LEN(request) -
+ ntohl(bhssc->bhssc_expected_data_transfer_length));
+ }
+ bhsdi->bhsdi_status = io->scsiio.scsi_status;
+ io->io_hdr.flags |= CTL_FLAG_STATUS_SENT;
+ }
+ }
KASSERT(response->ip_data_len > 0, ("sending empty Data-In"));
cfiscsi_pdu_queue(response);
}
@@ -2765,8 +2788,9 @@ cfiscsi_scsi_command_done(union ctl_io *io)
* Do not return status for aborted commands.
* There are exceptions, but none supported by CTL yet.
*/
- if ((io->io_hdr.flags & CTL_FLAG_ABORT) &&
- (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) {
+ if (((io->io_hdr.flags & CTL_FLAG_ABORT) &&
+ (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) ||
+ (io->io_hdr.flags & CTL_FLAG_STATUS_SENT)) {
ctl_free_io(io);
icl_pdu_free(request);
return;
diff --git a/sys/cam/ctl/ctl_io.h b/sys/cam/ctl/ctl_io.h
index 643f34fc3fbb..2c2459152d85 100644
--- a/sys/cam/ctl/ctl_io.h
+++ b/sys/cam/ctl/ctl_io.h
@@ -124,9 +124,10 @@ typedef enum {
CTL_FLAG_FAILOVER = 0x04000000, /* Killed by a failover */
CTL_FLAG_IO_ACTIVE = 0x08000000, /* I/O active on this SC */
CTL_FLAG_RDMA_MASK = CTL_FLAG_NO_DATASYNC | CTL_FLAG_BUS_ADDR |
- CTL_FLAG_AUTO_MIRROR | CTL_FLAG_REDIR_DONE
+ CTL_FLAG_AUTO_MIRROR | CTL_FLAG_REDIR_DONE,
/* Flags we care about for
remote DMA */
+ CTL_FLAG_STATUS_SENT = 0x10000000 /* Status sent by datamove */
} ctl_io_flags;
diff --git a/sys/cam/ctl/ctl_tpc.c b/sys/cam/ctl/ctl_tpc.c
index f7648a072ac7..c715f877a0af 100644
--- a/sys/cam/ctl/ctl_tpc.c
+++ b/sys/cam/ctl/ctl_tpc.c
@@ -425,7 +425,7 @@ ctl_inquiry_evpd_tpc(struct ctl_scsiio *ctsio, int alloc_len)
gco_ptr->data_segment_granularity = 0;
gco_ptr->inline_data_granularity = 0;
- ctsio->scsi_status = SCSI_STATUS_OK;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
@@ -487,9 +487,9 @@ ctl_receive_copy_operating_parameters(struct ctl_scsiio *ctsio)
data->list_of_implemented_descriptor_type_codes[2] = EC_SEG_REGISTER_KEY;
data->list_of_implemented_descriptor_type_codes[3] = EC_CSCD_ID;
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
ctl_datamove((union ctl_io *)ctsio);
return (retval);
}
@@ -584,9 +584,9 @@ ctl_receive_copy_status_lid1(struct ctl_scsiio *ctsio)
scsi_ulto4b(list_copy.curbytes >> 20, data->transfer_count);
}
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
ctl_datamove((union ctl_io *)ctsio);
return (retval);
}
@@ -656,9 +656,9 @@ ctl_receive_copy_failure_details(struct ctl_scsiio *ctsio)
scsi_ulto2b(list_copy.sense_len, data->sense_data_length);
memcpy(data->sense_data, &list_copy.sense_data, list_copy.sense_len);
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
ctl_datamove((union ctl_io *)ctsio);
return (retval);
}
@@ -742,9 +742,9 @@ ctl_receive_copy_status_lid4(struct ctl_scsiio *ctsio)
data->sense_data_length = list_copy.sense_len;
memcpy(data->sense_data, &list_copy.sense_data, list_copy.sense_len);
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
ctl_datamove((union ctl_io *)ctsio);
return (retval);
}
@@ -1482,8 +1482,6 @@ tpc_done(union ctl_io *io)
* more sophisticated initiator type behavior, the CAM error
* recovery code in ../common might be helpful.
*/
-// if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)
-// ctl_io_error_print(io, NULL);
tio = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
if (((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)
&& (io->io_hdr.retries > 0)) {
@@ -2168,9 +2166,9 @@ ctl_receive_rod_token_information(struct ctl_scsiio *ctsio)
printf("RRTI(list=%u) valid=%d\n",
scsi_4btoul(cdb->list_identifier), list_copy.res_token_valid);
*/
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
ctl_datamove((union ctl_io *)ctsio);
return (retval);
}
@@ -2234,9 +2232,9 @@ ctl_report_all_rod_tokens(struct ctl_scsiio *ctsio)
/*
printf("RART tokens=%d\n", i);
*/
+ ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
-
ctl_datamove((union ctl_io *)ctsio);
return (retval);
}
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index a54771409569..62aa74485ce0 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -792,14 +792,15 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
flags = atio->ccb_h.flags &
(CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK);
+ cmd_info = (struct ctlfe_lun_cmd_info *)io->io_hdr.port_priv;
+ cmd_info->cur_transfer_index = 0;
+ cmd_info->cur_transfer_off = 0;
+ cmd_info->flags = 0;
if (io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) {
/*
* Datamove call, we need to setup the S/G list.
*/
- cmd_info = (struct ctlfe_lun_cmd_info *)
- io->io_hdr.port_priv;
- bzero(cmd_info, sizeof(*cmd_info));
scsi_status = 0;
csio->cdb_len = atio->cdb_len;
ctlfedata(softc, io, &flags, &data_ptr, &dxfer_len,
@@ -880,17 +881,23 @@ ctlfestart(struct cam_periph *periph, union ccb *start_ccb)
xpt_schedule(periph, /*priority*/ 1);
return;
}
-
+ data_ptr = NULL;
+ dxfer_len = 0;
+ csio->sglist_cnt = 0;
+ scsi_status = 0;
+ }
+ if ((io->io_hdr.flags & CTL_FLAG_STATUS_QUEUED) &&
+ (cmd_info->flags & CTLFE_CMD_PIECEWISE) == 0 &&
+ ((io->io_hdr.flags & CTL_FLAG_DMA_QUEUED) == 0 ||
+ io->io_hdr.status == CTL_SUCCESS)) {
+ io->io_hdr.flags |= CTL_FLAG_STATUS_SENT;
flags |= CAM_SEND_STATUS;
scsi_status = io->scsiio.scsi_status;
csio->sense_len = io->scsiio.sense_len;
- data_ptr = NULL;
- dxfer_len = 0;
#ifdef CTLFEDEBUG
printf("%s: tag %04x status %x\n", __func__,
atio->tag_id, io->io_hdr.status);
#endif
- csio->sglist_cnt = 0;
if (csio->sense_len != 0) {
csio->sense_data = io->scsiio.sense_data;
flags |= CAM_SEND_SENSE;
@@ -2042,6 +2049,19 @@ ctlfe_done(union ctl_io *io)
ccb->ccb_h.status = CAM_REQ_INPROG;
ccb->ccb_h.func_code = XPT_NOTIFY_ACKNOWLEDGE;
xpt_action(ccb);
+ } else if (io->io_hdr.flags & CTL_FLAG_STATUS_SENT) {
+ if (softc->flags & CTLFE_LUN_WILDCARD) {
+ ccb->ccb_h.target_id = CAM_TARGET_WILDCARD;
+ ccb->ccb_h.target_lun = CAM_LUN_WILDCARD;
+ }
+ if (periph->flags & CAM_PERIPH_INVALID) {
+ ctlfe_free_ccb(periph, ccb);
+ } else {
+ softc->atios_sent++;
+ cam_periph_unlock(periph);
+ xpt_action(ccb);
+ return;
+ }
} else {
io->io_hdr.flags |= CTL_FLAG_STATUS_QUEUED;
TAILQ_INSERT_TAIL(&softc->work_queue, &ccb->ccb_h,