This is a dangerous operation in that the block size is not protected by a lock, but it can be written concurrently if you have a multi-queue virtio-scsi HBA. Put it behind a quirk that is only enabled by the Q800 machine, since the MODE SELECT feature was added for A/UX.
Cc: [email protected] Reviewed-by: Stefan Hajnoczi <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]> --- include/hw/scsi/scsi.h | 1 + hw/m68k/q800.c | 2 ++ hw/scsi/scsi-disk.c | 12 ++++++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index c60c6e8810e..3eab339b0d2 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -262,5 +262,6 @@ bool scsi_generic_pr_state_preempt(SCSIDevice *s, Error **errp); #define SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD 1 #define SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE 2 #define SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED 3 +#define SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE 4 #endif diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index ab64250c47c..1ad3f93b294 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -710,12 +710,14 @@ static void q800_init(Object *obj) static GlobalProperty hw_compat_q800[] = { { "scsi-hd", "quirk_mode_page_vendor_specific_apple", "on" }, + { "scsi-hd", "quirk_mode_page_set_block_size", "on" }, { "scsi-hd", "vendor", " SEAGATE" }, { "scsi-hd", "product", " ST225N" }, { "scsi-hd", "ver", "1.0 " }, { "scsi-cd", "quirk_mode_page_apple_vendor", "on" }, { "scsi-cd", "quirk_mode_sense_rom_use_dbd", "on" }, { "scsi-cd", "quirk_mode_page_vendor_specific_apple", "on" }, + { "scsi-cd", "quirk_mode_page_set_block_size", "on" }, { "scsi-cd", "quirk_mode_page_truncated", "on" }, { "scsi-cd", "vendor", "MATSHITA" }, { "scsi-cd", "product", "CD-ROM CR-8005" }, diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 5bb7a974d69..a42f7d8e77d 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1673,8 +1673,12 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf) goto invalid_param; } - /* Allow changing the block size */ - if (bd_len) { + /* + * Allow changing the block size only if the quirk is enabled for it. + * Writing s->qdev.blocksize is not thread safe! + */ + if (bd_len && (s->quirks & + (1 << SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE))) { bs = p[5] << 16 | p[6] << 8 | p[7]; /* @@ -3247,6 +3251,8 @@ static const Property scsi_hd_properties[] = { DEFINE_PROP_BIT("quirk_mode_page_vendor_specific_apple", SCSIDiskState, quirks, SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE, 0), + DEFINE_PROP_BIT("quirk_mode_page_set_block_size", SCSIDiskState, + quirks, SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE, 0), DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf), }; @@ -3352,6 +3358,8 @@ static const Property scsi_cd_properties[] = { 0), DEFINE_PROP_BIT("quirk_mode_page_truncated", SCSIDiskState, quirks, SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED, 0), + DEFINE_PROP_BIT("quirk_mode_page_set_block_size", SCSIDiskState, + quirks, SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE, 0), }; static void scsi_cd_class_initfn(ObjectClass *klass, const void *data) -- 2.55.0
