Commit f26eb3c277 for qemu.org
commit f26eb3c2770ea6a85ffb306a6ca5602f0d2f79ec
Author: Denis V. Lunev <den@openvz.org>
Date: Wed Aug 12 14:14:58 2026 +0200
scsi-disk: refresh the cached capacity from the resize callback
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 <den@openvz.org>
Message-ID: <20260812121500.1034178-3-den@openvz.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 6341089ddf..de2b6d85da 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2398,13 +2398,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;
@@ -2412,6 +2409,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;
@@ -2437,6 +2443,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.
*/