Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Jun 2014 08:56:36 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r267905 - head/sys/cam/ctl
Message-ID:  <201406260856.s5Q8uaSo065596@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406260856.s5Q8uaSo065596>