summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-04-21 16:26:24 +0000
committermav <mav@FreeBSD.org>2014-04-21 16:26:24 +0000
commitf908bd3cc2d3ff64e9a095d3dabc3b64b47d8cdd (patch)
treef0ebe607afa7e82ebdfa7ef87019e7225bad58e8 /sys/cam
parent7125a2147cc52c985593e47671e0d1de30e3ba40 (diff)
downloadFreeBSD-src-f908bd3cc2d3ff64e9a095d3dabc3b64b47d8cdd.zip
FreeBSD-src-f908bd3cc2d3ff64e9a095d3dabc3b64b47d8cdd.tar.gz
MFC r264191:
Report stripe size and offset of the backing device in READ CAPACITY (16) as physical sector size and offset.
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/ctl/ctl.c2
-rw-r--r--sys/cam/ctl/ctl_backend.h6
-rw-r--r--sys/cam/ctl/ctl_backend_block.c25
3 files changed, 33 insertions, 0 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 0edb4b1..05f2333 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -6883,6 +6883,8 @@ ctl_read_capacity_16(struct ctl_scsiio *ctsio)
scsi_u64to8b(lun->be_lun->maxlba, data->addr);
/* XXX KDM this may not be 512 bytes... */
scsi_ulto4b(lun->be_lun->blocksize, data->length);
+ data->prot_lbppbe = lun->be_lun->pblockexp & SRC16_LBPPBE;
+ scsi_ulto2b(lun->be_lun->pblockoff & SRC16_LALBA_A, data->lalba_lbp);
ctsio->scsi_status = SCSI_STATUS_OK;
diff --git a/sys/cam/ctl/ctl_backend.h b/sys/cam/ctl/ctl_backend.h
index 56fb8a5..c64492d 100644
--- a/sys/cam/ctl/ctl_backend.h
+++ b/sys/cam/ctl/ctl_backend.h
@@ -137,6 +137,10 @@ typedef void (*be_lun_config_t)(void *be_lun,
* this should be 512. In theory CTL should be able to handle other block
* sizes. Host application software may not deal with it very well, though.
*
+ * pblockexp is the log2() of number of LBAs on the LUN per physical sector.
+ *
+ * pblockoff is the lowest LBA on the LUN aligned ot physical sector.
+ *
* 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
@@ -185,6 +189,8 @@ struct ctl_be_lun {
void *be_lun; /* passed to CTL */
uint64_t maxlba; /* passed to CTL */
uint32_t blocksize; /* passed to CTL */
+ uint16_t pblockexp; /* passed to CTL */
+ uint16_t pblockoff; /* 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 */
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index af6d6a3..2e0a071 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -158,6 +158,8 @@ struct ctl_be_block_lun {
uint64_t size_bytes;
uint32_t blocksize;
int blocksize_shift;
+ uint16_t pblockexp;
+ uint16_t pblockoff;
struct ctl_be_block_softc *softc;
struct devstat *disk_stats;
ctl_be_block_lun_flags flags;
@@ -1370,6 +1372,7 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
struct cdev *dev;
struct cdevsw *devsw;
int error;
+ off_t ps, pss, po, pos;
params = &req->reqdata.create;
@@ -1467,6 +1470,24 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
be_lun->size_bytes = params->lun_size_bytes;
}
+ error = devsw->d_ioctl(dev, DIOCGSTRIPESIZE,
+ (caddr_t)&ps, FREAD, curthread);
+ if (error)
+ ps = po = 0;
+ else {
+ error = devsw->d_ioctl(dev, DIOCGSTRIPEOFFSET,
+ (caddr_t)&po, FREAD, curthread);
+ if (error)
+ po = 0;
+ }
+ pss = ps / be_lun->blocksize;
+ pos = po / be_lun->blocksize;
+ if ((pss > 0) && (pss * be_lun->blocksize == ps) && (pss >= pos) &&
+ ((pss & (pss - 1)) == 0) && (pos * be_lun->blocksize == po)) {
+ be_lun->pblockexp = fls(pss) - 1;
+ be_lun->pblockoff = (pss - pos) % pss;
+ }
+
return (0);
}
@@ -1691,6 +1712,8 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
* For processor devices, we don't have any size.
*/
be_lun->blocksize = 0;
+ be_lun->pblockexp = 0;
+ be_lun->pblockoff = 0;
be_lun->size_blocks = 0;
be_lun->size_bytes = 0;
be_lun->ctl_be_lun.maxlba = 0;
@@ -1751,6 +1774,8 @@ 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;
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;
+ be_lun->ctl_be_lun.pblockoff = be_lun->pblockoff;
/* Tell the user the blocksize we ended up using */
params->blocksize_bytes = be_lun->blocksize;
if (params->flags & CTL_LUN_FLAG_ID_REQ) {
OpenPOWER on IntegriCloud