scsi: sd_zbc: Avoid that resetting a zone fails sporadically
authorBart Van Assche <bart.vanassche@wdc.com>
Tue, 17 Apr 2018 01:04:41 +0000 (18:04 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 11 Jun 2018 20:49:17 +0000 (22:49 +0200)
commit7cb10a4ce724ba1d72b0d10673176124c379714c
treecec167c17fdd0bb1f3d214b0cd384ece4ba0beb2
parent1110636ed2d91dd63599af646305e280d89000a8
scsi: sd_zbc: Avoid that resetting a zone fails sporadically

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