From owner-svn-src-all@FreeBSD.ORG Thu Jun 26 08:56:38 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 2DBD2CCD; Thu, 26 Jun 2014 08:56:38 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1A4C72F42; Thu, 26 Jun 2014 08:56:38 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s5Q8ubDS065600; Thu, 26 Jun 2014 08:56:37 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s5Q8uaSo065596; Thu, 26 Jun 2014 08:56:36 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201406260856.s5Q8uaSo065596@svn.freebsd.org> From: Alexander Motin Date: Thu, 26 Jun 2014 08:56:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r267905 - head/sys/cam/ctl X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 26 Jun 2014 08:56:38 -0000 Author: mav Date: Thu Jun 26 08:56:36 2014 New Revision: 267905 URL: http://svnweb.freebsd.org/changeset/base/267905 Log: Add READ BUFFER and improve WRITE BUFFER SCSI commands support. This gives some use to 512KB per-LUN buffers, allocated for Copan-specific processor code and not used. It allows, for example, to test transport performance and/or correctness without accessing the media, as supported by Linux version of sg3_utils. MFC after: 2 weeks Modified: head/sys/cam/ctl/ctl.c head/sys/cam/ctl/ctl_cmd_table.c head/sys/cam/ctl/ctl_frontend_iscsi.c head/sys/cam/ctl/ctl_private.h Modified: head/sys/cam/ctl/ctl.c ============================================================================== --- head/sys/cam/ctl/ctl.c Thu Jun 26 08:55:06 2014 (r267904) +++ head/sys/cam/ctl/ctl.c Thu Jun 26 08:56:36 2014 (r267905) @@ -4854,7 +4854,8 @@ ctl_config_move_done(union ctl_io *io) /*sks_valid*/ 1, /*retry_count*/ io->io_hdr.port_status); - free(io->scsiio.kern_data_ptr, M_CTL); + if (io->io_hdr.flags & CTL_FLAG_ALLOCATED) + free(io->scsiio.kern_data_ptr, M_CTL); ctl_done(io); goto bailout; } @@ -4867,7 +4868,8 @@ ctl_config_move_done(union ctl_io *io) * S/G list. If we start using S/G lists for config data, * we'll need to know how to clean them up here as well. */ - free(io->scsiio.kern_data_ptr, M_CTL); + 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); } else { @@ -5612,26 +5614,40 @@ bailout: } int -ctl_write_buffer(struct ctl_scsiio *ctsio) +ctl_read_buffer(struct ctl_scsiio *ctsio) { - struct scsi_write_buffer *cdb; - struct copan_page_header *header; + struct scsi_read_buffer *cdb; struct ctl_lun *lun; - struct ctl_softc *ctl_softc; int buffer_offset, len; - int retval; + static uint8_t descr[4]; + static uint8_t echo_descr[4] = { 0 }; - header = NULL; + CTL_DEBUG_PRINT(("ctl_read_buffer\n")); - retval = CTL_RETVAL_COMPLETE; + lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; + cdb = (struct scsi_read_buffer *)ctsio->cdb; - CTL_DEBUG_PRINT(("ctl_write_buffer\n")); + if (lun->flags & CTL_LUN_PR_RESERVED) { + uint32_t residx; - lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; - ctl_softc = control_softc; - cdb = (struct scsi_write_buffer *)ctsio->cdb; + /* + * XXX KDM need a lock here. + */ + residx = ctl_get_resindex(&ctsio->io_hdr.nexus); + if ((lun->res_type == SPR_TYPE_EX_AC + && residx != lun->pr_res_idx) + || ((lun->res_type == SPR_TYPE_EX_AC_RO + || lun->res_type == SPR_TYPE_EX_AC_AR) + && !lun->per_res[residx].registered)) { + ctl_set_reservation_conflict(ctsio); + ctl_done((union ctl_io *)ctsio); + return (CTL_RETVAL_COMPLETE); + } + } - if ((cdb->byte2 & RWB_MODE) != RWB_MODE_DATA) { + if ((cdb->byte2 & RWB_MODE) != RWB_MODE_DATA && + (cdb->byte2 & RWB_MODE) != RWB_MODE_ECHO_DESCR && + (cdb->byte2 & RWB_MODE) != RWB_MODE_DESCR) { ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 1, @@ -5655,7 +5671,7 @@ ctl_write_buffer(struct ctl_scsiio *ctsi len = scsi_3btoul(cdb->length); buffer_offset = scsi_3btoul(cdb->offset); - if (len > sizeof(lun->write_buffer)) { + if (buffer_offset + len > sizeof(lun->write_buffer)) { ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 1, @@ -5666,11 +5682,68 @@ ctl_write_buffer(struct ctl_scsiio *ctsi return (CTL_RETVAL_COMPLETE); } - if (buffer_offset != 0) { + if ((cdb->byte2 & RWB_MODE) == RWB_MODE_DESCR) { + descr[0] = 0; + scsi_ulto3b(sizeof(lun->write_buffer), &descr[1]); + ctsio->kern_data_ptr = descr; + len = min(len, sizeof(descr)); + } else if ((cdb->byte2 & RWB_MODE) == RWB_MODE_ECHO_DESCR) { + ctsio->kern_data_ptr = echo_descr; + len = min(len, sizeof(echo_descr)); + } else + ctsio->kern_data_ptr = lun->write_buffer + buffer_offset; + ctsio->kern_data_len = len; + ctsio->kern_total_len = len; + ctsio->kern_data_resid = 0; + ctsio->kern_rel_offset = 0; + ctsio->kern_sg_entries = 0; + ctsio->be_move_done = ctl_config_move_done; + ctl_datamove((union ctl_io *)ctsio); + + return (CTL_RETVAL_COMPLETE); +} + +int +ctl_write_buffer(struct ctl_scsiio *ctsio) +{ + struct scsi_write_buffer *cdb; + struct ctl_lun *lun; + int buffer_offset, len; + + CTL_DEBUG_PRINT(("ctl_write_buffer\n")); + + lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; + cdb = (struct scsi_write_buffer *)ctsio->cdb; + + if ((cdb->byte2 & RWB_MODE) != RWB_MODE_DATA) { + ctl_set_invalid_field(ctsio, + /*sks_valid*/ 1, + /*command*/ 1, + /*field*/ 1, + /*bit_valid*/ 1, + /*bit*/ 4); + ctl_done((union ctl_io *)ctsio); + return (CTL_RETVAL_COMPLETE); + } + if (cdb->buffer_id != 0) { + ctl_set_invalid_field(ctsio, + /*sks_valid*/ 1, + /*command*/ 1, + /*field*/ 2, + /*bit_valid*/ 0, + /*bit*/ 0); + ctl_done((union ctl_io *)ctsio); + return (CTL_RETVAL_COMPLETE); + } + + len = scsi_3btoul(cdb->length); + buffer_offset = scsi_3btoul(cdb->offset); + + if (buffer_offset + len > sizeof(lun->write_buffer)) { ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 1, - /*field*/ 3, + /*field*/ 6, /*bit_valid*/ 0, /*bit*/ 0); ctl_done((union ctl_io *)ctsio); @@ -5682,7 +5755,7 @@ ctl_write_buffer(struct ctl_scsiio *ctsi * malloc it and tell the caller the data buffer is here. */ if ((ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) { - ctsio->kern_data_ptr = lun->write_buffer; + ctsio->kern_data_ptr = lun->write_buffer + buffer_offset; ctsio->kern_data_len = len; ctsio->kern_total_len = len; ctsio->kern_data_resid = 0; @@ -6893,6 +6966,7 @@ ctl_mode_sense(struct ctl_scsiio *ctsio) ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -6952,6 +7026,7 @@ ctl_read_capacity(struct ctl_scsiio *cts ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -7014,6 +7089,7 @@ ctl_read_capacity_16(struct ctl_scsiio * ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -7184,6 +7260,7 @@ ctl_maintenance_in(struct ctl_scsiio *ct } } + 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", @@ -7409,6 +7486,7 @@ retry: } mtx_unlock(&lun->lun_lock); + 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", @@ -9120,6 +9198,7 @@ ctl_report_luns(struct ctl_scsiio *ctsio */ ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -9246,7 +9325,7 @@ ctl_request_sense(struct ctl_scsiio *cts * parameter data. */ ctsio->sense_len = 0; - + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -9275,6 +9354,7 @@ no_sense: * autosense in this case. We're reporting sense as parameter data. */ ctsio->sense_len = 0; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -9362,6 +9442,7 @@ ctl_inquiry_evpd_supported(struct ctl_sc ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -9417,6 +9498,7 @@ ctl_inquiry_evpd_serial(struct ctl_scsii } ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -9602,6 +9684,7 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -9658,6 +9741,7 @@ ctl_inquiry_evpd_block_limits(struct ctl scsi_u64to8b(UINT64_MAX, bl_ptr->max_write_same_length); ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -9707,6 +9791,7 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio * lbp_ptr->flags = SVPD_LBP_UNMAP | SVPD_LBP_WS16 | SVPD_LBP_WS10; ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); @@ -9989,6 +10074,7 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio ctsio->scsi_status = SCSI_STATUS_OK; if (ctsio->kern_data_len > 0) { + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); } else { Modified: head/sys/cam/ctl/ctl_cmd_table.c ============================================================================== --- head/sys/cam/ctl/ctl_cmd_table.c Thu Jun 26 08:55:06 2014 (r267904) +++ head/sys/cam/ctl/ctl_cmd_table.c Thu Jun 26 08:56:36 2014 (r267905) @@ -314,12 +314,15 @@ struct ctl_cmd_entry ctl_cmd_table[] = {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, /* 3B WRITE BUFFER */ -{ctl_write_buffer, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_PROC | - CTL_FLAG_DATA_OUT, +{ctl_write_buffer, CTL_SERIDX_MD_SEL, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_FLAG_DATA_OUT, CTL_LUN_PAT_NONE}, /* 3C READ BUFFER */ -{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, +{ctl_read_buffer, CTL_SERIDX_MD_SNS, CTL_CMD_FLAG_OK_ON_BOTH | + CTL_FLAG_DATA_IN | + CTL_CMD_FLAG_ALLOW_ON_PR_RESV, + CTL_LUN_PAT_NONE}, /* 3D UPDATE BLOCK */ {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE}, Modified: head/sys/cam/ctl/ctl_frontend_iscsi.c ============================================================================== --- head/sys/cam/ctl/ctl_frontend_iscsi.c Thu Jun 26 08:55:06 2014 (r267904) +++ head/sys/cam/ctl/ctl_frontend_iscsi.c Thu Jun 26 08:56:36 2014 (r267905) @@ -2239,6 +2239,7 @@ cfiscsi_devid(struct ctl_scsiio *ctsio, ctsio->scsi_status = SCSI_STATUS_OK; + ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; ctsio->be_move_done = ctl_config_move_done; ctl_datamove((union ctl_io *)ctsio); Modified: head/sys/cam/ctl/ctl_private.h ============================================================================== --- head/sys/cam/ctl/ctl_private.h Thu Jun 26 08:55:06 2014 (r267904) +++ head/sys/cam/ctl/ctl_private.h Thu Jun 26 08:56:36 2014 (r267905) @@ -476,6 +476,7 @@ int ctl_scsi_reserve(struct ctl_scsiio * int ctl_start_stop(struct ctl_scsiio *ctsio); int ctl_sync_cache(struct ctl_scsiio *ctsio); int ctl_format(struct ctl_scsiio *ctsio); +int ctl_read_buffer(struct ctl_scsiio *ctsio); int ctl_write_buffer(struct ctl_scsiio *ctsio); int ctl_write_same(struct ctl_scsiio *ctsio); int ctl_unmap(struct ctl_scsiio *ctsio);