Author: mav
Date: Sat Jul 27 17:27:26 2019
New Revision: 350378
URL: https://svnweb.freebsd.org/changeset/base/350378

Log:
  Allow WRITE SAME handle more then 2^^32 blocks.
  
  If not limited by write_same_max_lba option, split operation into several
  2^^31 blocks chunks in a loop.  For large disks it may take a while, so
  setting write_same_max_lba may be useful to avoid timeouts.
  
  While there, fix build with CAM_CTL_DEBUG.
  
  MFC after:    2 weeks

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/scsi/scsi_all.h

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c      Sat Jul 27 17:24:19 2019        (r350377)
+++ head/sys/cam/ctl/ctl.c      Sat Jul 27 17:27:26 2019        (r350378)
@@ -1438,7 +1438,7 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_e
                        return;
                }
 
-               CTL_DEBUG_PRINT(("CTL: msg_type %d\n", msg->msg_type));
+               CTL_DEBUG_PRINT(("CTL: msg_type %d\n", msg->hdr.msg_type));
                switch (msg->hdr.msg_type) {
                case CTL_MSG_SERIALIZE:
                        io = ctl_alloc_io(softc->othersc_pool);
@@ -5685,12 +5685,36 @@ ctl_write_buffer(struct ctl_scsiio *ctsio)
        return (CTL_RETVAL_COMPLETE);
 }
 
+static int
+ctl_write_same_cont(union ctl_io *io)
+{
+       struct ctl_lun *lun = CTL_LUN(io);
+       struct ctl_scsiio *ctsio;
+       struct ctl_lba_len_flags *lbalen;
+       int retval;
+
+       ctsio = &io->scsiio;
+       ctsio->io_hdr.status = CTL_STATUS_NONE;
+       lbalen = (struct ctl_lba_len_flags *)
+           &ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
+       lbalen->lba += lbalen->len;
+       if ((lun->be_lun->maxlba + 1) - lbalen->lba <= UINT32_MAX) {
+               ctsio->io_hdr.flags &= ~CTL_FLAG_IO_CONT;
+               lbalen->len = (lun->be_lun->maxlba + 1) - lbalen->lba;
+       }
+
+       CTL_DEBUG_PRINT(("ctl_write_same_cont: calling config_write()\n"));
+       retval = lun->backend->config_write((union ctl_io *)ctsio);
+       return (retval);
+}
+
 int
 ctl_write_same(struct ctl_scsiio *ctsio)
 {
        struct ctl_lun *lun = CTL_LUN(ctsio);
        struct ctl_lba_len_flags *lbalen;
-       uint64_t lba;
+       const char *val;
+       uint64_t lba, ival;
        uint32_t num_blocks;
        int len, retval;
        uint8_t byte2;
@@ -5754,17 +5778,25 @@ ctl_write_same(struct ctl_scsiio *ctsio)
 
        /* Zero number of blocks means "to the last logical block" */
        if (num_blocks == 0) {
-               if ((lun->be_lun->maxlba + 1) - lba > UINT32_MAX) {
+               ival = UINT64_MAX;
+               val = dnvlist_get_string(lun->be_lun->options,
+                   "write_same_max_lba", NULL);
+               if (val != NULL)
+                       ctl_expand_number(val, &ival);
+               if ((lun->be_lun->maxlba + 1) - lba > ival) {
                        ctl_set_invalid_field(ctsio,
-                                             /*sks_valid*/ 0,
-                                             /*command*/ 1,
-                                             /*field*/ 0,
-                                             /*bit_valid*/ 0,
-                                             /*bit*/ 0);
+                           /*sks_valid*/ 1, /*command*/ 1,
+                           /*field*/ ctsio->cdb[0] == WRITE_SAME_10 ? 7 : 10,
+                           /*bit_valid*/ 0, /*bit*/ 0);
                        ctl_done((union ctl_io *)ctsio);
                        return (CTL_RETVAL_COMPLETE);
                }
-               num_blocks = (lun->be_lun->maxlba + 1) - lba;
+               if ((lun->be_lun->maxlba + 1) - lba > UINT32_MAX) {
+                       ctsio->io_hdr.flags |= CTL_FLAG_IO_CONT;
+                       ctsio->io_cont = ctl_write_same_cont;
+                       num_blocks = 1 << 31;
+               } else
+                       num_blocks = (lun->be_lun->maxlba + 1) - lba;
        }
 
        len = lun->be_lun->blocksize;
@@ -9876,6 +9908,8 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio
                if (val != NULL)
                        ctl_expand_number(val, &ival);
                scsi_u64to8b(ival, bl_ptr->max_write_same_length);
+               if (lun->be_lun->maxlba + 1 > ival)
+                       bl_ptr->flags |= SVPD_BL_WSNZ;
        }
 
        ctl_set_success(ctsio);
@@ -11322,7 +11356,7 @@ ctl_failover_lun(union ctl_io *rio)
        uint32_t targ_lun;
 
        targ_lun = rio->io_hdr.nexus.targ_mapped_lun;
-       CTL_DEBUG_PRINT(("FAILOVER for lun %ju\n", targ_lun));
+       CTL_DEBUG_PRINT(("FAILOVER for lun %u\n", targ_lun));
 
        /* Find and lock the LUN. */
        mtx_lock(&softc->ctl_lock);

Modified: head/sys/cam/scsi/scsi_all.h
==============================================================================
--- head/sys/cam/scsi/scsi_all.h        Sat Jul 27 17:24:19 2019        
(r350377)
+++ head/sys/cam/scsi/scsi_all.h        Sat Jul 27 17:27:26 2019        
(r350378)
@@ -2886,7 +2886,7 @@ struct scsi_vpd_logical_block_prov
 };
 
 /*
- * Block Limits VDP Page based on SBC-4 Revision 2
+ * Block Limits VDP Page based on SBC-4 Revision 17
  */
 struct scsi_vpd_block_limits
 {
@@ -2896,7 +2896,8 @@ struct scsi_vpd_block_limits
        u_int8_t page_length[2];
 #define SVPD_BL_PL_BASIC       0x10
 #define SVPD_BL_PL_TP          0x3C
-       u_int8_t reserved1;
+       u_int8_t flags;
+#define        SVPD_BL_WSNZ            0x01
        u_int8_t max_cmp_write_len;
        u_int8_t opt_txfer_len_grain[2];
        u_int8_t max_txfer_len[4];
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to