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
This commit is contained in:
mav 2019-07-27 17:27:26 +00:00
parent c8881f19b6
commit 336ad2a4b3
2 changed files with 47 additions and 12 deletions

View File

@ -1438,7 +1438,7 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
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, int alloc_len)
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);

View File

@ -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];