From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Bart Van Assche <bart.vanassche@wdc.com>,
Jens Axboe <axboe@kernel.dk>,
Damien Le Moal <damien.lemoal@wdc.com>,
Christoph Hellwig <hch@lst.de>, Hannes Reinecke <hare@suse.com>,
"Martin K. Petersen" <martin.petersen@oracle.com>
Subject: [PATCH 4.14 02/41] scsi: sd_zbc: Avoid that resetting a zone fails sporadically
Date: Sat, 9 Jun 2018 17:29:34 +0200 [thread overview]
Message-ID: <20180609152926.534377413@linuxfoundation.org> (raw)
In-Reply-To: <20180609152926.389750182@linuxfoundation.org>
4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bart Van Assche <bart.vanassche@wdc.com>
commit ccce20fc7968d546fb1e8e147bf5cdc8afc4278a upstream.
Since SCSI scanning occurs asynchronously, since sd_revalidate_disk() is
called from sd_probe_async() and since sd_revalidate_disk() calls
sd_zbc_read_zones() it can happen that sd_zbc_read_zones() is called
concurrently with blkdev_report_zones() and/or blkdev_reset_zones(). That can
cause these functions to fail with -EIO because sd_zbc_read_zones() e.g. sets
q->nr_zones to zero before restoring it to the actual value, even if no drive
characteristics have changed. Avoid that this can happen by making the
following changes:
- Protect the code that updates zone information with blk_queue_enter()
and blk_queue_exit().
- Modify sd_zbc_setup_seq_zones_bitmap() and sd_zbc_setup() such that
these functions do not modify struct scsi_disk before all zone
information has been obtained.
Note: since commit 055f6e18e08f ("block: Make q_usage_counter also track
legacy requests"; kernel v4.15) the request queue freezing mechanism also
affects legacy request queues.
Fixes: 89d947561077 ("sd: Implement support for ZBC devices")
Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Damien Le Moal <damien.lemoal@wdc.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.com>
Cc: stable@vger.kernel.org # v4.16
Reviewed-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/sd_zbc.c | 98 ++++++++++++++++++++++++++++++++------------------
1 file changed, 63 insertions(+), 35 deletions(-)
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -423,7 +423,16 @@ static int sd_zbc_check_capacity(struct
#define SD_ZBC_BUF_SIZE 131072
-static int sd_zbc_check_zone_size(struct scsi_disk *sdkp)
+/**
+ * sd_zbc_check_zone_size - Check the device zone sizes
+ * @sdkp: Target disk
+ *
+ * Check that all zones of the device are equal. The last zone can however
+ * be smaller. The zone size must also be a power of two number of LBAs.
+ *
+ * Returns the zone size in bytes upon success or an error code upon failure.
+ */
+static s64 sd_zbc_check_zone_size(struct scsi_disk *sdkp)
{
u64 zone_blocks = 0;
sector_t block = 0;
@@ -434,8 +443,6 @@ static int sd_zbc_check_zone_size(struct
int ret;
u8 same;
- sdkp->zone_blocks = 0;
-
/* Get a buffer */
buf = kmalloc(SD_ZBC_BUF_SIZE, GFP_KERNEL);
if (!buf)
@@ -470,16 +477,17 @@ static int sd_zbc_check_zone_size(struct
/* Parse zone descriptors */
while (rec < buf + buf_len) {
- zone_blocks = get_unaligned_be64(&rec[8]);
- if (sdkp->zone_blocks == 0) {
- sdkp->zone_blocks = zone_blocks;
- } else if (zone_blocks != sdkp->zone_blocks &&
- (block + zone_blocks < sdkp->capacity
- || zone_blocks > sdkp->zone_blocks)) {
+ u64 this_zone_blocks = get_unaligned_be64(&rec[8]);
+
+ if (zone_blocks == 0) {
+ zone_blocks = this_zone_blocks;
+ } else if (this_zone_blocks != zone_blocks &&
+ (block + this_zone_blocks < sdkp->capacity
+ || this_zone_blocks > zone_blocks)) {
zone_blocks = 0;
goto out;
}
- block += zone_blocks;
+ block += this_zone_blocks;
rec += 64;
}
@@ -492,8 +500,6 @@ static int sd_zbc_check_zone_size(struct
} while (block < sdkp->capacity);
- zone_blocks = sdkp->zone_blocks;
-
out:
if (!zone_blocks) {
if (sdkp->first_scan)
@@ -513,8 +519,7 @@ out:
"Zone size too large\n");
ret = -ENODEV;
} else {
- sdkp->zone_blocks = zone_blocks;
- sdkp->zone_shift = ilog2(zone_blocks);
+ ret = zone_blocks;
}
out_free:
@@ -523,23 +528,44 @@ out_free:
return ret;
}
-static int sd_zbc_setup(struct scsi_disk *sdkp)
+static int sd_zbc_setup(struct scsi_disk *sdkp, u32 zone_blocks)
{
+ struct request_queue *q = sdkp->disk->queue;
+ u32 zone_shift = ilog2(zone_blocks);
+ u32 nr_zones;
/* chunk_sectors indicates the zone size */
- blk_queue_chunk_sectors(sdkp->disk->queue,
- logical_to_sectors(sdkp->device, sdkp->zone_blocks));
- sdkp->zone_shift = ilog2(sdkp->zone_blocks);
- sdkp->nr_zones = sdkp->capacity >> sdkp->zone_shift;
- if (sdkp->capacity & (sdkp->zone_blocks - 1))
- sdkp->nr_zones++;
-
- if (!sdkp->zones_wlock) {
- sdkp->zones_wlock = kcalloc(BITS_TO_LONGS(sdkp->nr_zones),
- sizeof(unsigned long),
- GFP_KERNEL);
- if (!sdkp->zones_wlock)
- return -ENOMEM;
+ blk_queue_chunk_sectors(q,
+ logical_to_sectors(sdkp->device, zone_blocks));
+ nr_zones = round_up(sdkp->capacity, zone_blocks) >> zone_shift;
+
+ /*
+ * Initialize the disk zone write lock bitmap if the number
+ * of zones changed.
+ */
+ if (nr_zones != sdkp->nr_zones) {
+ unsigned long *zones_wlock = NULL;
+
+ if (nr_zones) {
+ zones_wlock = kcalloc(BITS_TO_LONGS(nr_zones),
+ sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!zones_wlock)
+ return -ENOMEM;
+ }
+
+ blk_mq_freeze_queue(q);
+ sdkp->zone_blocks = zone_blocks;
+ sdkp->zone_shift = zone_shift;
+ sdkp->nr_zones = nr_zones;
+ swap(sdkp->zones_wlock, zones_wlock);
+ blk_mq_unfreeze_queue(q);
+
+ kfree(zones_wlock);
+
+ /* READ16/WRITE16 is mandatory for ZBC disks */
+ sdkp->device->use_16_for_rw = 1;
+ sdkp->device->use_10_for_rw = 0;
}
return 0;
@@ -548,6 +574,7 @@ static int sd_zbc_setup(struct scsi_disk
int sd_zbc_read_zones(struct scsi_disk *sdkp,
unsigned char *buf)
{
+ int64_t zone_blocks;
int ret;
if (!sd_is_zoned(sdkp))
@@ -585,19 +612,19 @@ int sd_zbc_read_zones(struct scsi_disk *
* Check zone size: only devices with a constant zone size (except
* an eventual last runt zone) that is a power of 2 are supported.
*/
- ret = sd_zbc_check_zone_size(sdkp);
- if (ret)
+ zone_blocks = sd_zbc_check_zone_size(sdkp);
+ ret = -EFBIG;
+ if (zone_blocks != (u32)zone_blocks)
+ goto err;
+ ret = zone_blocks;
+ if (ret < 0)
goto err;
/* The drive satisfies the kernel restrictions: set it up */
- ret = sd_zbc_setup(sdkp);
+ ret = sd_zbc_setup(sdkp, zone_blocks);
if (ret)
goto err;
- /* READ16/WRITE16 is mandatory for ZBC disks */
- sdkp->device->use_16_for_rw = 1;
- sdkp->device->use_10_for_rw = 0;
-
return 0;
err:
@@ -610,6 +637,7 @@ void sd_zbc_remove(struct scsi_disk *sdk
{
kfree(sdkp->zones_wlock);
sdkp->zones_wlock = NULL;
+ sdkp->nr_zones = 0;
}
void sd_zbc_print_zones(struct scsi_disk *sdkp)
next prev parent reply other threads:[~2018-06-09 15:34 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-09 15:29 [PATCH 4.14 00/41] 4.14.49-stable review Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 01/41] scsi: sd_zbc: Fix potential memory leak Greg Kroah-Hartman
2018-06-09 15:29 ` Greg Kroah-Hartman [this message]
2018-06-09 15:29 ` [PATCH 4.14 03/41] mmap: introduce sane default mmap limits Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 04/41] mmap: relax file size limit for regular files Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 05/41] btrfs: define SUPER_FLAG_METADUMP_V2 Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 07/41] be2net: Fix error detection logic for BE3 Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 08/41] bnx2x: use the right constant Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 09/41] dccp: dont free ccid2_hc_tx_sock struct in dccp_disconnect() Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 10/41] enic: set DMA mask to 47 bit Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 11/41] ip6mr: only set ip6mr_table from setsockopt when ip6mr_new_table succeeds Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 12/41] ip6_tunnel: remove magic mtu value 0xFFF8 Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 13/41] ipmr: properly check rhltable_init() return value Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 14/41] ipv4: remove warning in ip_recv_error Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 15/41] ipv6: omit traffic class when calculating flow hash Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 16/41] isdn: eicon: fix a missing-check bug Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 17/41] kcm: Fix use-after-free caused by clonned sockets Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 18/41] netdev-FAQ: clarify DaveMs position for stable backports Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 19/41] net: ipv4: add missing RTA_TABLE to rtm_ipv4_policy Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 20/41] net: metrics: add proper netlink validation Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 21/41] net/packet: refine check for priv area size Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 22/41] net: phy: broadcom: Fix bcm_write_exp() Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 24/41] packet: fix reserve calculation Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 25/41] qed: Fix mask for physical address in ILT entry Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 26/41] sctp: not allow transport timeout value less than HZ/5 for hb_timer Greg Kroah-Hartman
2018-06-09 15:29 ` [PATCH 4.14 27/41] team: use netdev_features_t instead of u32 Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 28/41] vhost: synchronize IOTLB message with dev cleanup Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 29/41] vrf: check the original netdevice for generating redirect Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 30/41] ipv6: sr: fix memory OOB access in seg6_do_srh_encap/inline Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 31/41] net: phy: broadcom: Fix auxiliary control register reads Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 32/41] net-sysfs: Fix memory leak in XPS configuration Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 33/41] virtio-net: correctly transmit XDP buff after linearizing Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 34/41] net/mlx4: Fix irq-unsafe spinlock usage Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 35/41] tun: Fix NULL pointer dereference in XDP redirect Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 36/41] virtio-net: correctly check num_buf during err path Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 37/41] net/mlx5e: When RXFCS is set, add FCS data into checksum calculation Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 38/41] virtio-net: fix leaking page for gso packet during mergeable XDP Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 39/41] rtnetlink: validate attributes in do_setlink() Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 40/41] cls_flower: Fix incorrect idr release when failing to modify rule Greg Kroah-Hartman
2018-06-09 15:30 ` [PATCH 4.14 41/41] PCI: hv: Do not wait forever on a device that has disappeared Greg Kroah-Hartman
2018-06-10 9:06 ` [PATCH 4.14 00/41] 4.14.49-stable review Naresh Kamboju
2018-06-10 15:13 ` Guenter Roeck
2018-06-11 19:36 ` Shuah Khan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180609152926.534377413@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=axboe@kernel.dk \
--cc=bart.vanassche@wdc.com \
--cc=damien.lemoal@wdc.com \
--cc=hare@suse.com \
--cc=hch@lst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.