diff options
author | mav <mav@FreeBSD.org> | 2014-08-17 18:24:59 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2014-08-17 18:24:59 +0000 |
commit | b70f4cf9fc392c39962fcebd40ebe7ca804b1e70 (patch) | |
tree | c75b71464d549b98a081c1d691651fd570eaab5a /sys/cam/ctl | |
parent | 8fabb08e857fecab7fe854eee84d1738745f8c5b (diff) | |
download | FreeBSD-src-b70f4cf9fc392c39962fcebd40ebe7ca804b1e70.zip FreeBSD-src-b70f4cf9fc392c39962fcebd40ebe7ca804b1e70.tar.gz |
MFC r269622:
Fix several issues and inconsistencies in UNMAP capabilities reporting.
This makes Windows 2012 to start using UNMAP on our disks.
Diffstat (limited to 'sys/cam/ctl')
-rw-r--r-- | sys/cam/ctl/ctl.c | 78 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_backend_block.c | 8 | ||||
-rw-r--r-- | sys/cam/ctl/ctl_cmd_table.c | 6 |
3 files changed, 78 insertions, 14 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index fa05d44..e7d1e3e 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -322,10 +322,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); @@ -385,6 +385,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); @@ -7254,7 +7255,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; @@ -9811,8 +9812,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; @@ -10168,6 +10171,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); @@ -10181,6 +10190,54 @@ 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) +{ + 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) { struct scsi_vpd_logical_block_prov *lbp_ptr; @@ -10217,8 +10274,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; @@ -10261,6 +10322,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; diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index 436425d..55796c6 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -1042,8 +1042,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, @@ -1079,7 +1079,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; @@ -1149,7 +1149,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, diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c index 3066483..6ad90dd 100644 --- a/sys/cam/ctl/ctl_cmd_table.c +++ b/sys/cam/ctl/ctl_cmd_table.c @@ -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 */ |