From b7af62a945706e32b987f1dd0cc86bb41a8210c3 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Tue, 5 Sep 2017 20:55:35 +0900 Subject: scsi: sd: Align maximum write same blocks to physical block size Reporting a maximum number of blocks that is not aligned on the device physical size would cause a large write same request to be split into physically unaligned chunks by __blkdev_issue_write_zeroes() and __blkdev_issue_write_same(), even if the caller of these functions took care to align its request to physical sectors. Make sure the maximum reported is aligned to the device physical block size. This is only an optional optimization for regular disks, but this is mandatory to avoid failure of large write same requests directed at sequential write required zones of host-managed ZBC disks. [mkp: tweaked commit message] Signed-off-by: Damien Le Moal Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/sd.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/scsi/sd.c') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 11c1738c2100..3ef221493d6c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -898,6 +898,26 @@ static void sd_config_write_same(struct scsi_disk *sdkp) else sdkp->zeroing_mode = SD_ZERO_WRITE; + if (sdkp->max_ws_blocks && + sdkp->physical_block_size > logical_block_size) { + /* + * Reporting a maximum number of blocks that is not aligned + * on the device physical size would cause a large write same + * request to be split into physically unaligned chunks by + * __blkdev_issue_write_zeroes() and __blkdev_issue_write_same() + * even if the caller of these functions took care to align the + * large request. So make sure the maximum reported is aligned + * to the device physical block size. This is only an optional + * optimization for regular disks, but this is mandatory to + * avoid failure of large write same requests directed at + * sequential write required zones of host-managed ZBC disks. + */ + sdkp->max_ws_blocks = + round_down(sdkp->max_ws_blocks, + bytes_to_logical(sdkp->device, + sdkp->physical_block_size)); + } + out: blk_queue_max_write_same_sectors(q, sdkp->max_ws_blocks * (logical_block_size >> 9)); -- cgit From 658e9a6dc1126f21fa417cd213e1cdbff8be0ba2 Mon Sep 17 00:00:00 2001 From: weiping zhang Date: Thu, 12 Oct 2017 14:56:44 +0800 Subject: scsi: sd: change allow_restart to bool in sysfs interface /sys/class/scsi_disk/0:2:0:0/allow_restart can be changed to 0 unexpectedly by writing an invalid string such as the following: echo asdf > /sys/class/scsi_disk/0:2:0:0/allow_restart Signed-off-by: weiping zhang Signed-off-by: Martin K. Petersen --- drivers/scsi/sd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/sd.c') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3ef221493d6c..ce9cc7afd095 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -253,6 +253,7 @@ static ssize_t allow_restart_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + bool v; struct scsi_disk *sdkp = to_scsi_disk(dev); struct scsi_device *sdp = sdkp->device; @@ -262,7 +263,10 @@ allow_restart_store(struct device *dev, struct device_attribute *attr, if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC) return -EINVAL; - sdp->allow_restart = simple_strtoul(buf, NULL, 10); + if (kstrtobool(buf, &v)) + return -EINVAL; + + sdp->allow_restart = v; return count; } -- cgit From 623401ee33e42cee64d333877892be8db02951eb Mon Sep 17 00:00:00 2001 From: weiping zhang Date: Thu, 12 Oct 2017 14:57:06 +0800 Subject: scsi: sd: change manage_start_stop to bool in sysfs interface /sys/class/scsi_disk/0:2:0:0/manage_start_stop can be changed to 0 unexpectly by writing an invalid string. Signed-off-by: weiping zhang Signed-off-by: Martin K. Petersen --- drivers/scsi/sd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/scsi/sd.c') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index ce9cc7afd095..37daf9a42afe 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -231,11 +231,15 @@ manage_start_stop_store(struct device *dev, struct device_attribute *attr, { struct scsi_disk *sdkp = to_scsi_disk(dev); struct scsi_device *sdp = sdkp->device; + bool v; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - sdp->manage_start_stop = simple_strtoul(buf, NULL, 10); + if (kstrtobool(buf, &v)) + return -EINVAL; + + sdp->manage_start_stop = v; return count; } -- cgit