aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-08-08 09:57:37 -0700
committerRichard Henderson <richard.henderson@linaro.org>2022-08-08 09:57:37 -0700
commit8a1337e60400ef54432e063164faf5043a55555d (patch)
treeb41a8db1f3e8d035e45f76d85a2292eba26cc388 /hw
parent0b86b4e0dabbef15ba8d50e13bfecc582df70653 (diff)
parentf6a5f380627ab2af384bf2f2940d29386dea11ff (diff)
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* Fix and tests for -readconfig * Fixes for changeable block size # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmLxB6wUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroMbgQgAmj38xh/KurUvjAwlki9OF+jIXem/ # r7eHtc6wG/dGN7CyL+EK08c2GfPIphhii3JGfLT3P/xHvHRVgYow2AELNvYSG85M # SBQGfDsHLoKvY6Wni3AolECvtGycXkd30RtrzqdTT8iZyIhTTsikEG2hSgE+Z6Yy # 9XGPHN9puTkkD5HYnDV1+T4+yc28F8UTVob3fv9b7LMH7mSYz7UN5Tw4zB7DjOL1 # JNTuYqW9JN1X1vIYKxYw9Y5Jb3qNjnl8y6if8bPuvrLRw94sd0ax23yEQHwtgcUj # cYGcvZ2/X0SQg4AHTsqGJCuffKNDfHhmmA7w0Xb2DEvBvoveYOaDp3dKZQ== # =L9FI # -----END PGP SIGNATURE----- # gpg: Signature made Mon 08 Aug 2022 05:55:08 AM PDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [undefined] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: tests/qtest: add scenario for -readconfig handling vl: remove dead code in parse_memory_options() vl: fix [memory] section with -readconfig scsi-disk: ensure block size is non-zero and changes limited to bits 8-15 scsi-disk: fix overflow when block size is not a multiple of BDRV_SECTOR_SIZE Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/scsi/scsi-disk.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index f5cdb9ad4b..efee6739f9 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -1591,7 +1591,7 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
int cmd = r->req.cmd.buf[0];
int len = r->req.cmd.xfer;
int hdr_len = (cmd == MODE_SELECT ? 4 : 8);
- int bd_len;
+ int bd_len, bs;
int pass;
if ((r->req.cmd.buf[1] & 0x11) != 0x10) {
@@ -1617,9 +1617,19 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
}
/* Allow changing the block size */
- if (bd_len && p[6] != (s->qdev.blocksize >> 8)) {
- s->qdev.blocksize = p[6] << 8;
- trace_scsi_disk_mode_select_set_blocksize(s->qdev.blocksize);
+ if (bd_len) {
+ bs = p[5] << 16 | p[6] << 8 | p[7];
+
+ /*
+ * Since the existing code only checks/updates bits 8-15 of the block
+ * size, restrict ourselves to the same requirement for now to ensure
+ * that a block size set by a block descriptor and then read back by
+ * a subsequent SCSI command will be the same
+ */
+ if (bs && !(bs & ~0xff00) && bs != s->qdev.blocksize) {
+ s->qdev.blocksize = bs;
+ trace_scsi_disk_mode_select_set_blocksize(s->qdev.blocksize);
+ }
}
len -= bd_len;
@@ -1849,7 +1859,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
uint32_t nb_sectors = scsi_data_cdb_xfer(r->req.cmd.buf);
WriteSameCBData *data;
uint8_t *buf;
- int i;
+ int i, l;
/* Fail if PBDATA=1 or LBDATA=1 or ANCHOR=1. */
if (nb_sectors == 0 || (req->cmd.buf[1] & 0x16)) {
@@ -1891,8 +1901,9 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
data->iov.iov_len);
qemu_iovec_init_external(&data->qiov, &data->iov, 1);
- for (i = 0; i < data->iov.iov_len; i += s->qdev.blocksize) {
- memcpy(&buf[i], inbuf, s->qdev.blocksize);
+ for (i = 0; i < data->iov.iov_len; i += l) {
+ l = MIN(s->qdev.blocksize, data->iov.iov_len - i);
+ memcpy(&buf[i], inbuf, l);
}
scsi_req_ref(&r->req);