lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20210113155009.9592-1-mj0123.lee@samsung.com>
Date:   Thu, 14 Jan 2021 00:50:08 +0900
From:   Manjong Lee <mj0123.lee@...sung.com>
To:     jejb@...ux.ibm.com, martin.petersen@...cle.com,
        linux-scsi@...r.kernel.org, linux-kernel@...r.kernel.org
Cc:     seunghwan.hyun@...sung.com, sookwan7.kim@...sung.com,
        nanich.lee@...sung.com, woosung2.lee@...sung.com,
        yt0928.kim@...sung.com, junho89.kim@...sung.com,
        jisoo2146.oh@...sung.com, Manjong Lee <mj0123.lee@...sung.com>
Subject: [PATCH 1/1] scsi: sd: use max_xfer_blocks for set rw_max if
 max_xfer_blocks is available

SCSI device has max_xfer_size and opt_xfer_size,
but current kernel uses only opt_xfer_size.

It causes the limitation on setting IO chunk size,
although it can support larger one.

So, I propose this patch to use max_xfer_size in case it has valid value.
It can support to use the larger chunk IO on SCSI device.

For example,
This patch is effective in case of some SCSI device like UFS
with opt_xfer_size 512KB, queue depth 32 and max_xfer_size over 512KB.

I expect both the performance improvement
and the efficiency use of smaller command queue depth.

Signed-off-by: Manjong Lee <mj0123.lee@...sung.com>
---
 drivers/scsi/sd.c | 56 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 52 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 679c2c025047..de59f01c1304 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -3108,6 +3108,53 @@ static void sd_read_security(struct scsi_disk *sdkp, unsigned char *buffer)
 		sdkp->security = 1;
 }
 
+static bool sd_validate_max_xfer_size(struct scsi_disk *sdkp,
+				      unsigned int dev_max)
+{
+	struct scsi_device *sdp = sdkp->device;
+	unsigned int max_xfer_bytes =
+		logical_to_bytes(sdp, sdkp->max_xfer_blocks);
+
+	if (sdkp->max_xfer_blocks == 0)
+		return false;
+
+	if (sdkp->max_xfer_blocks > SD_MAX_XFER_BLOCKS) {
+		sd_first_printk(KERN_WARNING, sdkp,
+				"Maximal transfer size %u logical blocks " \
+				"> sd driver limit (%u logical blocks)\n",
+				sdkp->max_xfer_blocks, SD_DEF_XFER_BLOCKS);
+		return false;
+	}
+
+	if (sdkp->max_xfer_blocks > dev_max) {
+		sd_first_printk(KERN_WARNING, sdkp,
+				"Maximal transfer size %u logical blocks "
+				"> dev_max (%u logical blocks)\n",
+				sdkp->max_xfer_blocks, dev_max);
+		return false;
+	}
+
+	if (max_xfer_bytes < PAGE_SIZE) {
+		sd_first_printk(KERN_WARNING, sdkp,
+				"Maximal transfer size %u bytes < " \
+				"PAGE_SIZE (%u bytes)\n",
+				max_xfer_bytes, (unsigned int)PAGE_SIZE);
+		return false;
+	}
+
+	if (max_xfer_bytes & (sdkp->physical_block_size - 1)) {
+		sd_first_printk(KERN_WARNING, sdkp,
+				"Maximal transfer size %u bytes not a " \
+				"multiple of physical block size (%u bytes)\n",
+				max_xfer_bytes, sdkp->physical_block_size);
+		return false;
+	}
+
+	sd_first_printk(KERN_INFO, sdkp, "Maximal transfer size %u bytes\n",
+			max_xfer_bytes);
+	return true;
+}
+
 /*
  * Determine the device's preferred I/O size for reads and writes
  * unless the reported value is unreasonably small, large, not a
@@ -3233,12 +3280,13 @@ static int sd_revalidate_disk(struct gendisk *disk)
 
 	/* Initial block count limit based on CDB TRANSFER LENGTH field size. */
 	dev_max = sdp->use_16_for_rw ? SD_MAX_XFER_BLOCKS : SD_DEF_XFER_BLOCKS;
-
-	/* Some devices report a maximum block count for READ/WRITE requests. */
-	dev_max = min_not_zero(dev_max, sdkp->max_xfer_blocks);
 	q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max);
 
-	if (sd_validate_opt_xfer_size(sdkp, dev_max)) {
+	if (sd_validate_max_xfer_size(sdkp, dev_max)) {
+		q->limits.io_opt = 0;
+		rw_max = logical_to_sectors(sdp, sdkp->max_xfer_blocks);
+		q->limits.max_dev_sectors = rw_max;
+	} else if (sd_validate_opt_xfer_size(sdkp, dev_max)) {
 		q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks);
 		rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
 	} else {
-- 
2.29.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ