svn commit: r272734 - in head/sys/cam: ctl scsi

Alexander Motin mav at FreeBSD.org
Wed Oct 8 07:48:39 UTC 2014


Author: mav
Date: Wed Oct  8 07:48:36 2014
New Revision: 272734
URL: https://svnweb.freebsd.org/changeset/base/272734

Log:
  Add support for WRITE ATOMIC (16) command and report SBC-4 compliance.
  
  Atomic writes are only supported for ZVOLs in "dev" mode.  In other cases
  atomicity can not be guarantied and so the command is blocked.

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/ctl/ctl_backend.h
  head/sys/cam/ctl/ctl_backend_block.c
  head/sys/cam/ctl/ctl_backend_ramdisk.c
  head/sys/cam/ctl/ctl_cmd_table.c
  head/sys/cam/ctl/scsi_ctl.c
  head/sys/cam/scsi/scsi_all.h

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Wed Oct  8 07:00:50 2014	(r272733)
+++ head/sys/cam/ctl/ctl.c	Wed Oct  8 07:48:36 2014	(r272734)
@@ -9126,6 +9126,31 @@ ctl_read_write(struct ctl_scsiio *ctsio)
 		num_blocks = scsi_4btoul(cdb->length);
 		break;
 	}
+	case WRITE_ATOMIC_16: {
+		struct scsi_rw_16 *cdb;
+
+		if (lun->be_lun->atomicblock == 0) {
+			ctl_set_invalid_opcode(ctsio);
+			ctl_done((union ctl_io *)ctsio);
+			return (CTL_RETVAL_COMPLETE);
+		}
+
+		cdb = (struct scsi_rw_16 *)ctsio->cdb;
+		if (cdb->byte2 & SRW12_FUA)
+			flags |= CTL_LLF_FUA;
+		if (cdb->byte2 & SRW12_DPO)
+			flags |= CTL_LLF_DPO;
+		lba = scsi_8btou64(cdb->addr);
+		num_blocks = scsi_4btoul(cdb->length);
+		if (num_blocks > lun->be_lun->atomicblock) {
+			ctl_set_invalid_field(ctsio, /*sks_valid*/ 1,
+			    /*command*/ 1, /*field*/ 12, /*bit_valid*/ 0,
+			    /*bit*/ 0);
+			ctl_done((union ctl_io *)ctsio);
+			return (CTL_RETVAL_COMPLETE);
+		}
+		break;
+	}
 	case WRITE_VERIFY_16: {
 		struct scsi_write_verify_16 *cdb;
 
@@ -10299,6 +10324,10 @@ ctl_inquiry_evpd_block_limits(struct ctl
 				    bl_ptr->unmap_grain_align);
 			}
 		}
+		scsi_ulto4b(lun->be_lun->atomicblock,
+		    bl_ptr->max_atomic_transfer_length);
+		scsi_ulto4b(0, bl_ptr->atomic_alignment);
+		scsi_ulto4b(0, bl_ptr->atomic_transfer_length_granularity);
 	}
 	scsi_u64to8b(UINT64_MAX, bl_ptr->max_write_same_length);
 
@@ -10694,13 +10723,13 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio
 	}
 
 	if (lun == NULL) {
-		/* SBC-3 (no version claimed) */
-		scsi_ulto2b(0x04C0, inq_ptr->version4);
+		/* SBC-4 (no version claimed) */
+		scsi_ulto2b(0x0600, inq_ptr->version4);
 	} else {
 		switch (lun->be_lun->lun_type) {
 		case T_DIRECT:
-			/* SBC-3 (no version claimed) */
-			scsi_ulto2b(0x04C0, inq_ptr->version4);
+			/* SBC-4 (no version claimed) */
+			scsi_ulto2b(0x0600, inq_ptr->version4);
 			break;
 		case T_PROCESSOR:
 		default:
@@ -10818,7 +10847,8 @@ ctl_get_lba_len(union ctl_io *io, uint64
 		break;
 	}
 	case READ_16:
-	case WRITE_16: {
+	case WRITE_16:
+	case WRITE_ATOMIC_16: {
 		struct scsi_rw_16 *cdb;
 
 		cdb = (struct scsi_rw_16 *)io->scsiio.cdb;
@@ -10832,7 +10862,6 @@ ctl_get_lba_len(union ctl_io *io, uint64
 
 		cdb = (struct scsi_write_verify_16 *)io->scsiio.cdb;
 
-		
 		*lba = scsi_8btou64(cdb->addr);
 		*len = scsi_4btoul(cdb->length);
 		break;

Modified: head/sys/cam/ctl/ctl_backend.h
==============================================================================
--- head/sys/cam/ctl/ctl_backend.h	Wed Oct  8 07:00:50 2014	(r272733)
+++ head/sys/cam/ctl/ctl_backend.h	Wed Oct  8 07:48:36 2014	(r272734)
@@ -144,6 +144,8 @@ typedef void (*be_lun_config_t)(void *be
  *
  * pblockoff is the lowest LBA on the LUN aligned ot physical sector.
  *
+ * atomicblock is the number of blocks that can be written atomically.
+ *
  * req_lun_id is the requested LUN ID.  CTL only pays attention to this
  * field if the CTL_LUN_FLAG_ID_REQ flag is set.  If the requested LUN ID is
  * not available, the LUN addition will fail.  If a particular LUN ID isn't
@@ -188,6 +190,7 @@ struct ctl_be_lun {
 	uint32_t		blocksize;	/* passed to CTL */
 	uint16_t		pblockexp;	/* passed to CTL */
 	uint16_t		pblockoff;	/* passed to CTL */
+	uint32_t		atomicblock;	/* passed to CTL */
 	uint32_t		req_lun_id;	/* passed to CTL */
 	uint32_t		lun_id;		/* returned from CTL */
 	uint8_t			serial_num[CTL_SN_LEN];	 /* passed to CTL */

Modified: head/sys/cam/ctl/ctl_backend_block.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend_block.c	Wed Oct  8 07:00:50 2014	(r272733)
+++ head/sys/cam/ctl/ctl_backend_block.c	Wed Oct  8 07:48:36 2014	(r272734)
@@ -2003,6 +2003,9 @@ ctl_be_block_create(struct ctl_be_block_
 	be_lun->ctl_be_lun.flags = CTL_LUN_FLAG_PRIMARY;
 	if (unmap)
 		be_lun->ctl_be_lun.flags |= CTL_LUN_FLAG_UNMAP;
+	if (be_lun->dispatch == ctl_be_block_dispatch_zvol)
+		be_lun->ctl_be_lun.atomicblock = CTLBLK_MAX_IO_SIZE /
+		    be_lun->blocksize;
 	be_lun->ctl_be_lun.be_lun = be_lun;
 	be_lun->ctl_be_lun.blocksize = be_lun->blocksize;
 	be_lun->ctl_be_lun.pblockexp = be_lun->pblockexp;

Modified: head/sys/cam/ctl/ctl_backend_ramdisk.c
==============================================================================
--- head/sys/cam/ctl/ctl_backend_ramdisk.c	Wed Oct  8 07:00:50 2014	(r272733)
+++ head/sys/cam/ctl/ctl_backend_ramdisk.c	Wed Oct  8 07:48:36 2014	(r272734)
@@ -595,6 +595,7 @@ ctl_backend_ramdisk_create(struct ctl_be
 	be_lun->ctl_be_lun.flags = CTL_LUN_FLAG_PRIMARY;
 	if (unmap)
 		be_lun->ctl_be_lun.flags |= CTL_LUN_FLAG_UNMAP;
+	be_lun->ctl_be_lun.atomicblock = UINT32_MAX;
 	be_lun->ctl_be_lun.be_lun = be_lun;
 
 	if (params->flags & CTL_LUN_FLAG_ID_REQ) {

Modified: head/sys/cam/ctl/ctl_cmd_table.c
==============================================================================
--- head/sys/cam/ctl/ctl_cmd_table.c	Wed Oct  8 07:00:50 2014	(r272733)
+++ head/sys/cam/ctl/ctl_cmd_table.c	Wed Oct  8 07:48:36 2014	(r272734)
@@ -1117,8 +1117,11 @@ const struct ctl_cmd_entry ctl_cmd_table
 /* 9B */
 {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
 
-/* 9C */
-{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
+/* 9C WRITE ATOMIC (16) */
+{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT,
+ CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
+ 16, {0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0, 0, 0xff, 0xff, 0, 0x07}},
 
 /* 9D */
 {NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},

Modified: head/sys/cam/ctl/scsi_ctl.c
==============================================================================
--- head/sys/cam/ctl/scsi_ctl.c	Wed Oct  8 07:00:50 2014	(r272733)
+++ head/sys/cam/ctl/scsi_ctl.c	Wed Oct  8 07:48:36 2014	(r272734)
@@ -1115,6 +1115,7 @@ ctlfe_adjust_cdb(struct ccb_accept_tio *
 	}
 	case READ_16:
 	case WRITE_16:
+	case WRITE_ATOMIC_16:
 	{
 		struct scsi_rw_16 *cdb = (struct scsi_rw_16 *)cmdbyt;
 		lba = scsi_8btou64(cdb->addr);

Modified: head/sys/cam/scsi/scsi_all.h
==============================================================================
--- head/sys/cam/scsi/scsi_all.h	Wed Oct  8 07:00:50 2014	(r272733)
+++ head/sys/cam/scsi/scsi_all.h	Wed Oct  8 07:48:36 2014	(r272734)
@@ -1720,6 +1720,7 @@ struct ata_pass_16 {
 #define	VERIFY_16		0x8F
 #define	SYNCHRONIZE_CACHE_16	0x91
 #define	WRITE_SAME_16		0x93
+#define	WRITE_ATOMIC_16		0x9C
 #define	SERVICE_ACTION_IN	0x9E
 #define	REPORT_LUNS		0xA0
 #define	ATA_PASS_12		0xA1
@@ -2437,8 +2438,7 @@ struct scsi_vpd_logical_block_prov
 };
 
 /*
- * Block Limits VDP Page based on
- * T10/1799-D Revision 31
+ * Block Limits VDP Page based on SBC-4 Revision 2
  */
 struct scsi_vpd_block_limits
 {
@@ -2459,7 +2459,10 @@ struct scsi_vpd_block_limits
 	u_int8_t opt_unmap_grain[4];
 	u_int8_t unmap_grain_align[4];
 	u_int8_t max_write_same_length[8];
-	u_int8_t reserved2[20];
+	u_int8_t max_atomic_transfer_length[4];
+	u_int8_t atomic_alignment[4];
+	u_int8_t atomic_transfer_length_granularity[4];
+	u_int8_t reserved2[8];
 };
 
 struct scsi_read_capacity


More information about the svn-src-all mailing list