Fix several issues and inconsistencies in UNMAP capabilities reporting.
This makes Windows 2012 to start using UNMAP on our disks. MFC after: 2 weeks Sponsored by: iXsystems, Inc.
This commit is contained in:
parent
90539cb791
commit
8e18ceaa15
@ -320,10 +320,10 @@ SYSCTL_INT(_kern_cam_ctl, OID_AUTO, verbose, CTLFLAG_RWTUN,
|
||||
|
||||
/*
|
||||
* Supported pages (0x00), Serial number (0x80), Device ID (0x83),
|
||||
* SCSI Ports (0x88), Third-party Copy (0x8F), Block limits (0xB0) and
|
||||
* Logical Block Provisioning (0xB2)
|
||||
* SCSI Ports (0x88), Third-party Copy (0x8F), Block limits (0xB0),
|
||||
* Block Device Characteristics (0xB1) and Logical Block Provisioning (0xB2)
|
||||
*/
|
||||
#define SCSI_EVPD_NUM_SUPPORTED_PAGES 7
|
||||
#define SCSI_EVPD_NUM_SUPPORTED_PAGES 8
|
||||
|
||||
static void ctl_isc_event_handler(ctl_ha_channel chanel, ctl_ha_event event,
|
||||
int param);
|
||||
@ -383,6 +383,7 @@ static int ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio,
|
||||
int alloc_len);
|
||||
static int ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio,
|
||||
int alloc_len);
|
||||
static int ctl_inquiry_evpd_bdc(struct ctl_scsiio *ctsio, int alloc_len);
|
||||
static int ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len);
|
||||
static int ctl_inquiry_evpd(struct ctl_scsiio *ctsio);
|
||||
static int ctl_inquiry_std(struct ctl_scsiio *ctsio);
|
||||
@ -7252,7 +7253,7 @@ ctl_read_capacity_16(struct ctl_scsiio *ctsio)
|
||||
data->prot_lbppbe = lun->be_lun->pblockexp & SRC16_LBPPBE;
|
||||
scsi_ulto2b(lun->be_lun->pblockoff & SRC16_LALBA_A, data->lalba_lbp);
|
||||
if (lun->be_lun->flags & CTL_LUN_FLAG_UNMAP)
|
||||
data->lalba_lbp[0] |= SRC16_LBPME;
|
||||
data->lalba_lbp[0] |= SRC16_LBPME | SRC16_LBPRZ;
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
@ -9809,8 +9810,10 @@ ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
pages->page_list[4] = SVPD_SCSI_TPC;
|
||||
/* Block limits */
|
||||
pages->page_list[5] = SVPD_BLOCK_LIMITS;
|
||||
/* Block Device Characteristics */
|
||||
pages->page_list[6] = SVPD_BDC;
|
||||
/* Logical Block Provisioning */
|
||||
pages->page_list[6] = SVPD_LBP;
|
||||
pages->page_list[7] = SVPD_LBP;
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
|
||||
@ -10166,6 +10169,12 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
if (lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) {
|
||||
scsi_ulto4b(0xffffffff, bl_ptr->max_unmap_lba_cnt);
|
||||
scsi_ulto4b(0xffffffff, bl_ptr->max_unmap_blk_cnt);
|
||||
if (lun->be_lun->pblockexp != 0) {
|
||||
scsi_ulto4b((1 << lun->be_lun->pblockexp),
|
||||
bl_ptr->opt_unmap_grain);
|
||||
scsi_ulto4b(0x80000000 | lun->be_lun->pblockoff,
|
||||
bl_ptr->unmap_grain_align);
|
||||
}
|
||||
}
|
||||
}
|
||||
scsi_u64to8b(UINT64_MAX, bl_ptr->max_write_same_length);
|
||||
@ -10178,6 +10187,54 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_inquiry_evpd_bdc(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
{
|
||||
struct scsi_vpd_block_device_characteristics *bdc_ptr;
|
||||
struct ctl_lun *lun;
|
||||
|
||||
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
|
||||
|
||||
ctsio->kern_data_ptr = malloc(sizeof(*bdc_ptr), M_CTL, M_WAITOK | M_ZERO);
|
||||
bdc_ptr = (struct scsi_vpd_block_device_characteristics *)ctsio->kern_data_ptr;
|
||||
ctsio->kern_sg_entries = 0;
|
||||
|
||||
if (sizeof(*bdc_ptr) < alloc_len) {
|
||||
ctsio->residual = alloc_len - sizeof(*bdc_ptr);
|
||||
ctsio->kern_data_len = sizeof(*bdc_ptr);
|
||||
ctsio->kern_total_len = sizeof(*bdc_ptr);
|
||||
} else {
|
||||
ctsio->residual = 0;
|
||||
ctsio->kern_data_len = alloc_len;
|
||||
ctsio->kern_total_len = alloc_len;
|
||||
}
|
||||
ctsio->kern_data_resid = 0;
|
||||
ctsio->kern_rel_offset = 0;
|
||||
ctsio->kern_sg_entries = 0;
|
||||
|
||||
/*
|
||||
* The control device is always connected. The disk device, on the
|
||||
* other hand, may not be online all the time. Need to change this
|
||||
* to figure out whether the disk device is actually online or not.
|
||||
*/
|
||||
if (lun != NULL)
|
||||
bdc_ptr->device = (SID_QUAL_LU_CONNECTED << 5) |
|
||||
lun->be_lun->lun_type;
|
||||
else
|
||||
bdc_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
|
||||
bdc_ptr->page_code = SVPD_BDC;
|
||||
scsi_ulto2b(sizeof(*bdc_ptr) - 4, bdc_ptr->page_length);
|
||||
scsi_ulto2b(SVPD_NON_ROTATING, bdc_ptr->medium_rotation_rate);
|
||||
bdc_ptr->flags = SVPD_FUAB | SVPD_VBULS;
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
static int
|
||||
ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
{
|
||||
@ -10215,8 +10272,12 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
lbp_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
|
||||
|
||||
lbp_ptr->page_code = SVPD_LBP;
|
||||
if (lun != NULL && lun->be_lun->flags & CTL_LUN_FLAG_UNMAP)
|
||||
lbp_ptr->flags = SVPD_LBP_UNMAP | SVPD_LBP_WS16 | SVPD_LBP_WS10;
|
||||
scsi_ulto2b(sizeof(*lbp_ptr) - 4, lbp_ptr->page_length);
|
||||
if (lun != NULL && lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) {
|
||||
lbp_ptr->flags = SVPD_LBP_UNMAP | SVPD_LBP_WS16 |
|
||||
SVPD_LBP_WS10 | SVPD_LBP_RZ | SVPD_LBP_ANC_SUP;
|
||||
lbp_ptr->prov_type = SVPD_LBP_RESOURCE;
|
||||
}
|
||||
|
||||
ctsio->scsi_status = SCSI_STATUS_OK;
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
@ -10259,6 +10320,9 @@ ctl_inquiry_evpd(struct ctl_scsiio *ctsio)
|
||||
case SVPD_BLOCK_LIMITS:
|
||||
retval = ctl_inquiry_evpd_block_limits(ctsio, alloc_len);
|
||||
break;
|
||||
case SVPD_BDC:
|
||||
retval = ctl_inquiry_evpd_bdc(ctsio, alloc_len);
|
||||
break;
|
||||
case SVPD_LBP:
|
||||
retval = ctl_inquiry_evpd_lbp(ctsio, alloc_len);
|
||||
break;
|
||||
|
@ -1039,8 +1039,8 @@ ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
|
||||
softc = be_lun->softc;
|
||||
lbalen = ARGS(beio->io);
|
||||
|
||||
if (lbalen->flags & ~(SWS_LBDATA | SWS_UNMAP) ||
|
||||
(lbalen->flags & SWS_UNMAP && be_lun->unmap == NULL)) {
|
||||
if (lbalen->flags & ~(SWS_LBDATA | SWS_UNMAP | SWS_ANCHOR) ||
|
||||
(lbalen->flags & (SWS_UNMAP | SWS_ANCHOR) && be_lun->unmap == NULL)) {
|
||||
ctl_free_beio(beio);
|
||||
ctl_set_invalid_field(&io->scsiio,
|
||||
/*sks_valid*/ 1,
|
||||
@ -1076,7 +1076,7 @@ ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
|
||||
break;
|
||||
}
|
||||
|
||||
if (lbalen->flags & SWS_UNMAP) {
|
||||
if (lbalen->flags & (SWS_UNMAP | SWS_ANCHOR)) {
|
||||
beio->io_offset = lbalen->lba * be_lun->blocksize;
|
||||
beio->io_len = (uint64_t)lbalen->len * be_lun->blocksize;
|
||||
beio->bio_cmd = BIO_DELETE;
|
||||
@ -1146,7 +1146,7 @@ ctl_be_block_cw_dispatch_unmap(struct ctl_be_block_lun *be_lun,
|
||||
softc = be_lun->softc;
|
||||
ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
|
||||
|
||||
if (ptrlen->flags != 0 || be_lun->unmap == NULL) {
|
||||
if ((ptrlen->flags & ~SU_ANCHOR) != 0 || be_lun->unmap == NULL) {
|
||||
ctl_free_beio(beio);
|
||||
ctl_set_invalid_field(&io->scsiio,
|
||||
/*sks_valid*/ 0,
|
||||
|
@ -785,12 +785,12 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
|
||||
{ctl_write_same, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN |
|
||||
CTL_FLAG_DATA_OUT,
|
||||
CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
|
||||
10, {0x0a, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
|
||||
10, {0x1a, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
|
||||
|
||||
/* 42 READ SUB-CHANNEL / UNMAP */
|
||||
{ctl_unmap, CTL_SERIDX_UNMAP, CTL_CMD_FLAG_OK_ON_SLUN | CTL_FLAG_DATA_OUT,
|
||||
CTL_LUN_PAT_WRITE,
|
||||
10, {0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x07}},
|
||||
10, {1, 0, 0, 0, 0, 0, 0xff, 0xff, 0x07}},
|
||||
|
||||
/* 43 READ TOC/PMA/ATIP */
|
||||
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
|
||||
@ -1085,7 +1085,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
|
||||
{ctl_write_same, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN |
|
||||
CTL_FLAG_DATA_OUT,
|
||||
CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
|
||||
16, {0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
16, {0x1a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
|
||||
|
||||
/* 94 */
|
||||
|
@ -2314,6 +2314,27 @@ struct scsi_vpd_block_characteristics
|
||||
u_int8_t reserved2[56];
|
||||
};
|
||||
|
||||
/*
|
||||
* Block Device Characteristics VPD Page
|
||||
*/
|
||||
struct scsi_vpd_block_device_characteristics
|
||||
{
|
||||
uint8_t device;
|
||||
uint8_t page_code;
|
||||
#define SVPD_BDC 0xB1
|
||||
uint8_t page_length[2];
|
||||
uint8_t medium_rotation_rate[2];
|
||||
#define SVPD_NOT_REPORTED 0x0000
|
||||
#define SVPD_NON_ROTATING 0x0001
|
||||
uint8_t product_type;
|
||||
uint8_t wab_wac_ff;
|
||||
uint8_t flags;
|
||||
#define SVPD_VBULS 0x01
|
||||
#define SVPD_FUAB 0x02
|
||||
#define SVPD_HAW_ZBC 0x10
|
||||
uint8_t reserved[55];
|
||||
};
|
||||
|
||||
/*
|
||||
* Logical Block Provisioning VPD Page based on
|
||||
* T10/1799-D Revision 31
|
||||
|
Loading…
Reference in New Issue
Block a user