Author: mav
Date: Mon Oct 20 07:33:41 2014
New Revision: 273311
URL: https://svnweb.freebsd.org/changeset/base/273311

Log:
  MFC r272734:
  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:
  stable/10/sys/cam/ctl/ctl.c
  stable/10/sys/cam/ctl/ctl_backend.h
  stable/10/sys/cam/ctl/ctl_backend_block.c
  stable/10/sys/cam/ctl/ctl_backend_ramdisk.c
  stable/10/sys/cam/ctl/ctl_cmd_table.c
  stable/10/sys/cam/ctl/scsi_ctl.c
  stable/10/sys/cam/scsi/scsi_all.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cam/ctl/ctl.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl.c Mon Oct 20 07:32:33 2014        (r273310)
+++ stable/10/sys/cam/ctl/ctl.c Mon Oct 20 07:33:41 2014        (r273311)
@@ -9128,6 +9128,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;
 
@@ -10301,6 +10326,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);
 
@@ -10696,13 +10725,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:
@@ -10820,7 +10849,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;
@@ -10834,7 +10864,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: stable/10/sys/cam/ctl/ctl_backend.h
==============================================================================
--- stable/10/sys/cam/ctl/ctl_backend.h Mon Oct 20 07:32:33 2014        
(r273310)
+++ stable/10/sys/cam/ctl/ctl_backend.h Mon Oct 20 07:33:41 2014        
(r273311)
@@ -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: stable/10/sys/cam/ctl/ctl_backend_block.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_backend_block.c   Mon Oct 20 07:32:33 2014        
(r273310)
+++ stable/10/sys/cam/ctl/ctl_backend_block.c   Mon Oct 20 07:33:41 2014        
(r273311)
@@ -2006,6 +2006,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: stable/10/sys/cam/ctl/ctl_backend_ramdisk.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_backend_ramdisk.c Mon Oct 20 07:32:33 2014        
(r273310)
+++ stable/10/sys/cam/ctl/ctl_backend_ramdisk.c Mon Oct 20 07:33:41 2014        
(r273311)
@@ -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: stable/10/sys/cam/ctl/ctl_cmd_table.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_cmd_table.c       Mon Oct 20 07:32:33 2014        
(r273310)
+++ stable/10/sys/cam/ctl/ctl_cmd_table.c       Mon Oct 20 07:33:41 2014        
(r273311)
@@ -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: stable/10/sys/cam/ctl/scsi_ctl.c
==============================================================================
--- stable/10/sys/cam/ctl/scsi_ctl.c    Mon Oct 20 07:32:33 2014        
(r273310)
+++ stable/10/sys/cam/ctl/scsi_ctl.c    Mon Oct 20 07:33:41 2014        
(r273311)
@@ -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: stable/10/sys/cam/scsi/scsi_all.h
==============================================================================
--- stable/10/sys/cam/scsi/scsi_all.h   Mon Oct 20 07:32:33 2014        
(r273310)
+++ stable/10/sys/cam/scsi/scsi_all.h   Mon Oct 20 07:33:41 2014        
(r273311)
@@ -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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to