Add configuration options to override physical and UNMAP blocks geometry.

While in most cases CTL should correctly fetch those values from backing
storages, there are some initiators (like MS SQL), that may not like large
physical block sizes, even if they are true.  For such cases allow override
fetched values with supported ones (like 4K).

MFC after:	1 week
This commit is contained in:
mav 2014-12-17 17:30:54 +00:00
parent fe9781bb78
commit 7582ed74ee
5 changed files with 79 additions and 11 deletions

View File

@ -3900,7 +3900,7 @@ ctl_copy_io(union ctl_io *src, union ctl_io *dest)
dest->io_hdr.flags |= CTL_FLAG_INT_COPY;
}
static int
int
ctl_expand_number(const char *buf, uint64_t *num)
{
char *endptr;
@ -10146,10 +10146,10 @@ 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),
if (lun->be_lun->ublockexp != 0) {
scsi_ulto4b((1 << lun->be_lun->ublockexp),
bl_ptr->opt_unmap_grain);
scsi_ulto4b(0x80000000 | lun->be_lun->pblockoff,
scsi_ulto4b(0x80000000 | lun->be_lun->ublockoff,
bl_ptr->unmap_grain_align);
}
}

View File

@ -206,6 +206,7 @@ struct ctl_be_arg;
void ctl_init_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args);
void ctl_free_opts(ctl_options_t *opts);
char * ctl_get_opt(ctl_options_t *opts, const char *name);
int ctl_expand_number(const char *buf, uint64_t *num);
#endif /* _KERNEL */

View File

@ -194,6 +194,8 @@ struct ctl_be_lun {
uint32_t blocksize; /* passed to CTL */
uint16_t pblockexp; /* passed to CTL */
uint16_t pblockoff; /* passed to CTL */
uint16_t ublockexp; /* passed to CTL */
uint16_t ublockoff; /* passed to CTL */
uint32_t atomicblock; /* passed to CTL */
uint32_t req_lun_id; /* passed to CTL */
uint32_t lun_id; /* returned from CTL */

View File

@ -173,6 +173,8 @@ struct ctl_be_block_lun {
int blocksize_shift;
uint16_t pblockexp;
uint16_t pblockoff;
uint16_t ublockexp;
uint16_t ublockoff;
struct ctl_be_block_softc *softc;
struct devstat *disk_stats;
ctl_be_block_lun_flags flags;
@ -1739,8 +1741,9 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
{
struct ctl_be_block_filedata *file_data;
struct ctl_lun_create_params *params;
char *value;
struct vattr vattr;
off_t pss;
off_t ps, pss, po, pos, us, uss, uo, uos;
int error;
error = 0;
@ -1800,11 +1803,36 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
be_lun->blocksize = params->blocksize_bytes;
else
be_lun->blocksize = 512;
pss = vattr.va_blocksize / be_lun->blocksize;
if ((pss > 0) && (pss * be_lun->blocksize == vattr.va_blocksize) &&
((pss & (pss - 1)) == 0)) {
us = ps = vattr.va_blocksize;
uo = po = 0;
value = ctl_get_opt(&be_lun->ctl_be_lun.options, "pblocksize");
if (value != NULL)
ctl_expand_number(value, &ps);
value = ctl_get_opt(&be_lun->ctl_be_lun.options, "pblockoffset");
if (value != NULL)
ctl_expand_number(value, &po);
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 = 0;
be_lun->pblockoff = (pss - pos) % pss;
}
value = ctl_get_opt(&be_lun->ctl_be_lun.options, "ublocksize");
if (value != NULL)
ctl_expand_number(value, &us);
value = ctl_get_opt(&be_lun->ctl_be_lun.options, "ublockoffset");
if (value != NULL)
ctl_expand_number(value, &uo);
uss = us / be_lun->blocksize;
uos = uo / be_lun->blocksize;
if ((uss > 0) && (uss * be_lun->blocksize == us) && (uss >= uos) &&
((uss & (uss - 1)) == 0) && (uos * be_lun->blocksize == uo)) {
be_lun->ublockexp = fls(uss) - 1;
be_lun->ublockoff = (uss - uos) % uss;
}
/*
@ -1827,8 +1855,9 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
struct vattr vattr;
struct cdev *dev;
struct cdevsw *devsw;
char *value;
int error;
off_t ps, pss, po, pos;
off_t ps, pss, po, pos, us, uss, uo, uos;
params = &be_lun->params;
@ -1942,6 +1971,15 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
if (error)
po = 0;
}
us = ps;
uo = po;
value = ctl_get_opt(&be_lun->ctl_be_lun.options, "pblocksize");
if (value != NULL)
ctl_expand_number(value, &ps);
value = ctl_get_opt(&be_lun->ctl_be_lun.options, "pblockoffset");
if (value != NULL)
ctl_expand_number(value, &po);
pss = ps / be_lun->blocksize;
pos = po / be_lun->blocksize;
if ((pss > 0) && (pss * be_lun->blocksize == ps) && (pss >= pos) &&
@ -1950,6 +1988,20 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
be_lun->pblockoff = (pss - pos) % pss;
}
value = ctl_get_opt(&be_lun->ctl_be_lun.options, "ublocksize");
if (value != NULL)
ctl_expand_number(value, &us);
value = ctl_get_opt(&be_lun->ctl_be_lun.options, "ublockoffset");
if (value != NULL)
ctl_expand_number(value, &uo);
uss = us / be_lun->blocksize;
uos = uo / be_lun->blocksize;
if ((uss > 0) && (uss * be_lun->blocksize == us) && (uss >= uos) &&
((uss & (uss - 1)) == 0) && (uos * be_lun->blocksize == uo)) {
be_lun->ublockexp = fls(uss) - 1;
be_lun->ublockoff = (uss - uos) % uss;
}
return (0);
}
@ -2162,6 +2214,8 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
be_lun->blocksize = 0;
be_lun->pblockexp = 0;
be_lun->pblockoff = 0;
be_lun->ublockexp = 0;
be_lun->ublockoff = 0;
be_lun->size_blocks = 0;
be_lun->size_bytes = 0;
be_lun->ctl_be_lun.maxlba = 0;
@ -2212,6 +2266,8 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
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;
be_lun->ctl_be_lun.ublockexp = be_lun->ublockexp;
be_lun->ctl_be_lun.ublockoff = be_lun->ublockoff;
if (be_lun->dispatch == ctl_be_block_dispatch_zvol &&
be_lun->blocksize != 0)
be_lun->ctl_be_lun.atomicblock = CTLBLK_MAX_IO_SIZE /
@ -2591,6 +2647,8 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
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;
be_lun->ctl_be_lun.ublockexp = be_lun->ublockexp;
be_lun->ctl_be_lun.ublockoff = be_lun->ublockoff;
if (be_lun->dispatch == ctl_be_block_dispatch_zvol &&
be_lun->blocksize != 0)
be_lun->ctl_be_lun.atomicblock = CTLBLK_MAX_IO_SIZE /

View File

@ -34,7 +34,7 @@
.\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $
.\" $FreeBSD$
.\"
.Dd December 6, 2014
.Dd December 17, 2014
.Dt CTLADM 8
.Os
.Sh NAME
@ -1002,6 +1002,13 @@ Set to "off" to allow them be issued in parallel.
Parallel issue of consecutive operations may confuse logic of the
backing file system, hurting performance; but it may improve performance
of backing stores without prefetch/write-back.
.It Va psectorsize
.It Va psectoroffset
Specify physical block size and offset of the device.
.It Va usectorsize
.It Va usectoroffset
Specify UNMAP block size and offset of the device.
.It Va rpm
.It Va rpm
Specifies medium rotation rate of the device: 0 -- not reported,
1 -- non-rotating (SSD), >1024 -- value in revolutions per minute.