git: b06771aa667d - main - CTL: Allow I/Os up to 8MB, depending on maxphys value.

From: Alexander Motin <mav_at_FreeBSD.org>
Date: Thu, 30 Dec 2021 04:49:28 UTC
The branch main has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=b06771aa667dadeffa0b0ec840af13b74d55e186

commit b06771aa667dadeffa0b0ec840af13b74d55e186
Author:     Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2021-12-30 03:58:52 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2021-12-30 04:49:24 +0000

    CTL: Allow I/Os up to 8MB, depending on maxphys value.
    
    For years CTL block backend limited I/O size to 1MB, splitting larger
    requests into sequentially processed chunks.  It is sufficient for
    most of use cases, since typical initiators rarely use bigger I/Os.
    
    One of known exceptions is VMWare VAAI offload, by default sending up
    to 8 4MB EXTENDED COPY requests same time.  CTL internally converted
    those into 32 1MB READ/WRITE requests, that could overwhelm the block
    backend, having finite number of processing threads and making more
    important interactive I/Os to wait in its queue.  Previously it was
    partially covered by CTL core serializing sequential reads to help
    ZFS speculative prefetcher, but that serialization was significantly
    relaxed after recent ZFS improvements.
    
    With the new settings block backend receives 8 4MB requests, that
    should be easier for both CTL itself and the underlying storage.
    
    MFC after:      2 weeks
    Sponsored by:   iXsystems, Inc.
---
 sys/cam/ctl/ctl_backend_block.c | 28 +++++++++++++---------------
 sys/cam/ctl/ctl_tpc.c           |  6 +++---
 2 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index ae558e496514..289da02398cc 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2003 Silicon Graphics International Corp.
  * Copyright (c) 2009-2011 Spectra Logic Corporation
  * Copyright (c) 2012,2021 The FreeBSD Foundation
- * Copyright (c) 2014-2015 Alexander Motin <mav@FreeBSD.org>
+ * Copyright (c) 2014-2021 Alexander Motin <mav@FreeBSD.org>
  * All rights reserved.
  *
  * Portions of this software were developed by Edward Tomasz Napierala
@@ -101,16 +101,15 @@ __FBSDID("$FreeBSD$");
 #include <cam/ctl/ctl_error.h>
 
 /*
- * The idea here is that we'll allocate enough S/G space to hold a 1MB
- * I/O.  If we get an I/O larger than that, we'll split it.
+ * The idea here is to allocate enough S/G space to handle at least 1MB I/Os.
+ * On systems with small maxphys it can be 8 128KB segments.  On large systems
+ * it can be up to 8 1MB segments.  I/Os larger than that we'll split.
  */
-#define	CTLBLK_HALF_IO_SIZE	(512 * 1024)
-#define	CTLBLK_MAX_IO_SIZE	(CTLBLK_HALF_IO_SIZE * 2)
+#define	CTLBLK_MAX_SEGS		8
+#define	CTLBLK_HALF_SEGS	(CTLBLK_MAX_SEGS / 2)
 #define	CTLBLK_MIN_SEG		(128 * 1024)
-#define	CTLBLK_MAX_SEG		MIN(CTLBLK_HALF_IO_SIZE, maxphys)
-#define	CTLBLK_HALF_SEGS	MAX(CTLBLK_HALF_IO_SIZE / CTLBLK_MIN_SEG, 1)
-#define	CTLBLK_MAX_SEGS		(CTLBLK_HALF_SEGS * 2)
-#define	CTLBLK_NUM_SEGS		(CTLBLK_MAX_IO_SIZE / CTLBLK_MAX_SEG)
+#define	CTLBLK_MAX_SEG		MIN(1024 * 1024, MAX(CTLBLK_MIN_SEG, maxphys))
+#define	CTLBLK_MAX_IO_SIZE	(CTLBLK_MAX_SEG * CTLBLK_MAX_SEGS)
 
 #ifdef CTLBLK_DEBUG
 #define DPRINTF(fmt, args...) \
@@ -1230,10 +1229,10 @@ ctl_be_block_dispatch_dev(struct ctl_be_block_lun *be_lun,
 	 */
 	if (csw) {
 		max_iosize = dev->si_iosize_max;
-		if (max_iosize < PAGE_SIZE)
+		if (max_iosize <= 0)
 			max_iosize = DFLTPHYS;
 	} else
-		max_iosize = DFLTPHYS;
+		max_iosize = maxphys;
 
 	cur_offset = beio->io_offset;
 	for (i = 0; i < beio->num_segs; i++) {
@@ -1401,7 +1400,7 @@ ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
 	else
 		pbo = 0;
 	len_left = (uint64_t)lbalen->len * cbe_lun->blocksize;
-	for (i = 0, lba = 0; i < CTLBLK_NUM_SEGS && len_left > 0; i++) {
+	for (i = 0, lba = 0; i < CTLBLK_MAX_SEGS && len_left > 0; i++) {
 		/*
 		 * Setup the S/G entry for this chunk.
 		 */
@@ -1669,11 +1668,10 @@ ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun,
 	DPRINTF("%s at LBA %jx len %u @%ju\n",
 	       (beio->bio_cmd == BIO_READ) ? "READ" : "WRITE",
 	       (uintmax_t)lbalen->lba, lbalen->len, bptrlen->len);
+	lbas = CTLBLK_MAX_IO_SIZE;
 	if (lbalen->flags & CTL_LLF_COMPARE) {
 		beio->two_sglists = 1;
-		lbas = CTLBLK_HALF_IO_SIZE;
-	} else {
-		lbas = CTLBLK_MAX_IO_SIZE;
+		lbas /= 2;
 	}
 	lbas = MIN(lbalen->len - bptrlen->len, lbas / cbe_lun->blocksize);
 	beio->io_offset = (lbalen->lba + bptrlen->len) * cbe_lun->blocksize;
diff --git a/sys/cam/ctl/ctl_tpc.c b/sys/cam/ctl/ctl_tpc.c
index de9e97b87a3e..60cd5611643d 100644
--- a/sys/cam/ctl/ctl_tpc.c
+++ b/sys/cam/ctl/ctl_tpc.c
@@ -1,7 +1,7 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
- * Copyright (c) 2014 Alexander Motin <mav@FreeBSD.org>
+ * Copyright (c) 2014-2021 Alexander Motin <mav@FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -67,8 +67,8 @@ __FBSDID("$FreeBSD$");
 #define	TPC_MAX_LIST	8192
 #define	TPC_MAX_INLINE	0
 #define	TPC_MAX_LISTS	255
-#define	TPC_MAX_IO_SIZE	(1024 * 1024)
-#define	TPC_MAX_IOCHUNK_SIZE	(TPC_MAX_IO_SIZE * 16)
+#define	TPC_MAX_IO_SIZE	(8 * MIN(1024 * 1024, MAX(128 * 1024, maxphys)))
+#define	TPC_MAX_IOCHUNK_SIZE	(TPC_MAX_IO_SIZE * 4)
 #define	TPC_MIN_TOKEN_TIMEOUT	1
 #define	TPC_DFL_TOKEN_TIMEOUT	60
 #define	TPC_MAX_TOKEN_TIMEOUT	600