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.
This commit is contained in:
parent
c38aa2537b
commit
8a41675372
@ -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_scsiio *ctsio, int alloc_len)
|
||||
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_t *lba, uint64_t *len)
|
||||
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_t *lba, uint64_t *len)
|
||||
|
||||
cdb = (struct scsi_write_verify_16 *)io->scsiio.cdb;
|
||||
|
||||
|
||||
*lba = scsi_8btou64(cdb->addr);
|
||||
*len = scsi_4btoul(cdb->length);
|
||||
break;
|
||||
|
@ -144,6 +144,8 @@ typedef void (*be_lun_config_t)(void *be_lun,
|
||||
*
|
||||
* 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 */
|
||||
|
@ -2003,6 +2003,9 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
|
||||
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;
|
||||
|
@ -595,6 +595,7 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
|
||||
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) {
|
||||
|
@ -1117,8 +1117,11 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
|
||||
/* 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},
|
||||
|
@ -1115,6 +1115,7 @@ ctlfe_adjust_cdb(struct ccb_accept_tio *atio, uint32_t offset)
|
||||
}
|
||||
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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user