scsi_disk_resize_cb() reports CAPACITY DATA HAS CHANGED but leaves SCSIDevice.max_lba alone, and max_lba is what check_lba_range() compares every request against. Until the guest reacts to the unit attention and issues READ CAPACITY, requests beyond the old size keep being refused with LOGICAL BLOCK ADDRESS OUT OF RANGE, and a guest which never re-reads the capacity never recovers at all. A guest migrated onto a device whose size changed underneath it is exactly such a guest.
ide_resize_cb() refreshes its cached size along with the IDENTIFY data it reports to the guest. Do the same here, so that the notification is what tells the guest about the new capacity rather than what unblocks the device. Factor the computation out of scsi_disk_reset(), which already had it. Signed-off-by: Denis V. Lunev <[email protected]> --- hw/scsi/scsi-disk.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 1b0cce128c..3d404a8651 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2386,13 +2386,10 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf) } } -static void scsi_disk_reset(DeviceState *dev) +static void scsi_disk_refresh_max_lba(SCSIDiskState *s) { - SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev); uint64_t nb_sectors; - scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET)); - blk_get_geometry(s->qdev.conf.blk, &nb_sectors); nb_sectors /= s->qdev.blocksize / BDRV_SECTOR_SIZE; @@ -2400,6 +2397,15 @@ static void scsi_disk_reset(DeviceState *dev) nb_sectors--; } s->qdev.max_lba = nb_sectors; +} + +static void scsi_disk_reset(DeviceState *dev) +{ + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev.qdev, dev); + + scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET)); + + scsi_disk_refresh_max_lba(s); /* reset tray statuses */ s->tray_locked = 0; s->tray_open = 0; @@ -2425,6 +2431,8 @@ static void scsi_disk_resize_cb(void *opaque) { SCSIDiskState *s = opaque; + scsi_disk_refresh_max_lba(s); + /* SPC lists this sense code as available only for * direct-access devices. */ -- 2.53.0
