aboutsummaryrefslogtreecommitdiff
path: root/sys/cam
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2015-02-12 10:28:45 +0000
committerAlexander Motin <mav@FreeBSD.org>2015-02-12 10:28:45 +0000
commit93b8c96cfd6f47092154cd088731e51078c5a1cd (patch)
tree10d208d48e67bd753356e18bd89289f5dbaaa3b7 /sys/cam
parent24f1069ab4efbd288ee4bc898da21404a5613300 (diff)
downloadsrc-93b8c96cfd6f47092154cd088731e51078c5a1cd.tar.gz
src-93b8c96cfd6f47092154cd088731e51078c5a1cd.zip
Make WRITE SAME commands respect physical block size.
This change by 2-3 times improves performance of misaligned WRITE SAME commands by avoiding unneeded read-modify-write cycles inside ZFS. MFC after: 1 week
Notes
Notes: svn path=/head/; revision=278619
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/ctl/ctl_backend_block.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index a5e45024541d..6b5f703a5bff 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -1187,7 +1187,7 @@ ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
struct ctl_be_block_io *beio;
struct ctl_be_block_softc *softc;
struct ctl_lba_len_flags *lbalen;
- uint64_t len_left, lba;
+ uint64_t len_left, lba, pb, pbo, adj;
int i, seglen;
uint8_t *buf, *end;
@@ -1241,6 +1241,8 @@ ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
DPRINTF("WRITE SAME at LBA %jx len %u\n",
(uintmax_t)lbalen->lba, lbalen->len);
+ pb = (uint64_t)be_lun->blocksize << be_lun->pblockexp;
+ pbo = pb - (uint64_t)be_lun->blocksize * be_lun->pblockoff;
len_left = (uint64_t)lbalen->len * be_lun->blocksize;
for (i = 0, lba = 0; i < CTLBLK_MAX_SEGS && len_left > 0; i++) {
@@ -1248,7 +1250,15 @@ ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
* Setup the S/G entry for this chunk.
*/
seglen = MIN(CTLBLK_MAX_SEG, len_left);
- seglen -= seglen % be_lun->blocksize;
+ if (pb > be_lun->blocksize) {
+ adj = ((lbalen->lba + lba) * be_lun->blocksize +
+ seglen - pbo) % pb;
+ if (seglen > adj)
+ seglen -= adj;
+ else
+ seglen -= seglen % be_lun->blocksize;
+ } else
+ seglen -= seglen % be_lun->blocksize;
beio->sg_segs[i].len = seglen;
beio->sg_segs[i].addr = uma_zalloc(be_lun->lun_zone, M_WAITOK);