Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu in…
…to staging

Pull request

v2:
- Fix authorship information lost by the mailing list for Andrey Drobyshev

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCAAdFiEEhpWov9P5fNqsNXdanKSrs4Grc8gFAmTuKQoACgkQnKSrs4Gr
# c8g5GAf+JtBfWqhkytG+x7BVp8GmLCtvK+LYiLdjld1lfpLlMzdnbiXA9iJidDHl
# AAMYVCoN9T81RDuEqkvSuJEuBDMGkKpJGK8NOHEfUPln1QtikLtEq1VUBRGpnsEy
# 8el9hA84iP5kaQtbP+qVlxo6Y9Jm8hhemHukuIOIMLHmTJKt0utXojftvHFwwM5c
# UBMJfVMo1FTdD0ywuY7e+uPPJV4/D8kXTOXkXxbQrx43ztJBT6K6N0kDDuOAlPxJ
# l+U6zxvlKlB22vXt/Q4bkP9c1K8oukKOr8FjU1PxvLSZADXbbm2xq7yDPSRw9YpN
# igSA2n9O8aZcp0xpviT0D6alTibl4w==
# =SMYB
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 29 Aug 2023 13:21:14 EDT
# gpg:                using RSA key 8695A8BFD3F97CDAAC35775A9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" [ultimate]
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>" [ultimate]
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8

* tag 'block-pull-request' of https://gitlab.com/stefanha/qemu:
  tests/qemu-iotests/197: add testcase for CoR with subclusters
  block/io: align requests to subcluster_size
  block: add subcluster_size field to BlockDriverInfo
  block-migration: Ensure we don't crash during migration cleanup
  tests/qtest: Introduce tests for UFS
  hw/ufs: Support for UFS logical unit
  hw/ufs: Support for Query Transfer Requests
  hw/ufs: Initial commit for emulated Universal-Flash-Storage

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
  • Loading branch information
Stefan Hajnoczi committed Aug 29, 2023
2 parents 3df11e5 + 3f5f228 commit 05ba96b
Show file tree
Hide file tree
Showing 27 changed files with 4,932 additions and 35 deletions.
7 changes: 7 additions & 0 deletions MAINTAINERS
Expand Up @@ -2256,6 +2256,13 @@ F: tests/qtest/nvme-test.c
F: docs/system/devices/nvme.rst
T: git git://git.infradead.org/qemu-nvme.git nvme-next

ufs
M: Jeuk Kim <jeuk20.kim@samsung.com>
S: Supported
F: hw/ufs/*
F: include/block/ufs.h
F: tests/qtest/ufs-test.c

megasas
M: Hannes Reinecke <hare@suse.com>
L: qemu-block@nongnu.org
Expand Down
7 changes: 7 additions & 0 deletions block.c
Expand Up @@ -6480,6 +6480,13 @@ int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
}
memset(bdi, 0, sizeof(*bdi));
ret = drv->bdrv_co_get_info(bs, bdi);
if (bdi->subcluster_size == 0) {
/*
* If the driver left this unset, subclusters are not supported.
* Then it is safe to treat each cluster as having only one subcluster.
*/
bdi->subcluster_size = bdi->cluster_size;
}
if (ret < 0) {
return ret;
}
Expand Down
50 changes: 25 additions & 25 deletions block/io.c
Expand Up @@ -728,21 +728,21 @@ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs)
}

/**
* Round a region to cluster boundaries
* Round a region to subcluster (if supported) or cluster boundaries
*/
void coroutine_fn GRAPH_RDLOCK
bdrv_round_to_clusters(BlockDriverState *bs, int64_t offset, int64_t bytes,
int64_t *cluster_offset, int64_t *cluster_bytes)
bdrv_round_to_subclusters(BlockDriverState *bs, int64_t offset, int64_t bytes,
int64_t *align_offset, int64_t *align_bytes)
{
BlockDriverInfo bdi;
IO_CODE();
if (bdrv_co_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
*cluster_offset = offset;
*cluster_bytes = bytes;
if (bdrv_co_get_info(bs, &bdi) < 0 || bdi.subcluster_size == 0) {
*align_offset = offset;
*align_bytes = bytes;
} else {
int64_t c = bdi.cluster_size;
*cluster_offset = QEMU_ALIGN_DOWN(offset, c);
*cluster_bytes = QEMU_ALIGN_UP(offset - *cluster_offset + bytes, c);
int64_t c = bdi.subcluster_size;
*align_offset = QEMU_ALIGN_DOWN(offset, c);
*align_bytes = QEMU_ALIGN_UP(offset - *align_offset + bytes, c);
}
}

Expand Down Expand Up @@ -1168,8 +1168,8 @@ bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
void *bounce_buffer = NULL;

BlockDriver *drv = bs->drv;
int64_t cluster_offset;
int64_t cluster_bytes;
int64_t align_offset;
int64_t align_bytes;
int64_t skip_bytes;
int ret;
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
Expand Down Expand Up @@ -1203,28 +1203,28 @@ bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
* BDRV_REQUEST_MAX_BYTES (even when the original read did not), which
* is one reason we loop rather than doing it all at once.
*/
bdrv_round_to_clusters(bs, offset, bytes, &cluster_offset, &cluster_bytes);
skip_bytes = offset - cluster_offset;
bdrv_round_to_subclusters(bs, offset, bytes, &align_offset, &align_bytes);
skip_bytes = offset - align_offset;

trace_bdrv_co_do_copy_on_readv(bs, offset, bytes,
cluster_offset, cluster_bytes);
align_offset, align_bytes);

while (cluster_bytes) {
while (align_bytes) {
int64_t pnum;

if (skip_write) {
ret = 1; /* "already allocated", so nothing will be copied */
pnum = MIN(cluster_bytes, max_transfer);
pnum = MIN(align_bytes, max_transfer);
} else {
ret = bdrv_is_allocated(bs, cluster_offset,
MIN(cluster_bytes, max_transfer), &pnum);
ret = bdrv_is_allocated(bs, align_offset,
MIN(align_bytes, max_transfer), &pnum);
if (ret < 0) {
/*
* Safe to treat errors in querying allocation as if
* unallocated; we'll probably fail again soon on the
* read, but at least that will set a decent errno.
*/
pnum = MIN(cluster_bytes, max_transfer);
pnum = MIN(align_bytes, max_transfer);
}

/* Stop at EOF if the image ends in the middle of the cluster */
Expand All @@ -1242,7 +1242,7 @@ bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
/* Must copy-on-read; use the bounce buffer */
pnum = MIN(pnum, MAX_BOUNCE_BUFFER);
if (!bounce_buffer) {
int64_t max_we_need = MAX(pnum, cluster_bytes - pnum);
int64_t max_we_need = MAX(pnum, align_bytes - pnum);
int64_t max_allowed = MIN(max_transfer, MAX_BOUNCE_BUFFER);
int64_t bounce_buffer_len = MIN(max_we_need, max_allowed);

Expand All @@ -1254,7 +1254,7 @@ bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
}
qemu_iovec_init_buf(&local_qiov, bounce_buffer, pnum);

ret = bdrv_driver_preadv(bs, cluster_offset, pnum,
ret = bdrv_driver_preadv(bs, align_offset, pnum,
&local_qiov, 0, 0);
if (ret < 0) {
goto err;
Expand All @@ -1266,13 +1266,13 @@ bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
/* FIXME: Should we (perhaps conditionally) be setting
* BDRV_REQ_MAY_UNMAP, if it will allow for a sparser copy
* that still correctly reads as zero? */
ret = bdrv_co_do_pwrite_zeroes(bs, cluster_offset, pnum,
ret = bdrv_co_do_pwrite_zeroes(bs, align_offset, pnum,
BDRV_REQ_WRITE_UNCHANGED);
} else {
/* This does not change the data on the disk, it is not
* necessary to flush even in cache=writethrough mode.
*/
ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
ret = bdrv_driver_pwritev(bs, align_offset, pnum,
&local_qiov, 0,
BDRV_REQ_WRITE_UNCHANGED);
}
Expand Down Expand Up @@ -1301,8 +1301,8 @@ bdrv_co_do_copy_on_readv(BdrvChild *child, int64_t offset, int64_t bytes,
}
}

cluster_offset += pnum;
cluster_bytes -= pnum;
align_offset += pnum;
align_bytes -= pnum;
progress += pnum - skip_bytes;
skip_bytes = 0;
}
Expand Down
8 changes: 4 additions & 4 deletions block/mirror.c
Expand Up @@ -283,8 +283,8 @@ static int coroutine_fn mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
need_cow |= !test_bit((*offset + *bytes - 1) / s->granularity,
s->cow_bitmap);
if (need_cow) {
bdrv_round_to_clusters(blk_bs(s->target), *offset, *bytes,
&align_offset, &align_bytes);
bdrv_round_to_subclusters(blk_bs(s->target), *offset, *bytes,
&align_offset, &align_bytes);
}

if (align_bytes > max_bytes) {
Expand Down Expand Up @@ -576,8 +576,8 @@ static void coroutine_fn mirror_iteration(MirrorBlockJob *s)
int64_t target_offset;
int64_t target_bytes;
WITH_GRAPH_RDLOCK_GUARD() {
bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes,
&target_offset, &target_bytes);
bdrv_round_to_subclusters(blk_bs(s->target), offset, io_bytes,
&target_offset, &target_bytes);
}
if (target_offset == offset &&
target_bytes == io_bytes) {
Expand Down
1 change: 1 addition & 0 deletions block/qcow2.c
Expand Up @@ -5197,6 +5197,7 @@ qcow2_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVQcow2State *s = bs->opaque;
bdi->cluster_size = s->cluster_size;
bdi->subcluster_size = s->subcluster_size;
bdi->vm_state_offset = qcow2_vm_state_offset(s);
bdi->is_dirty = s->incompatible_features & QCOW2_INCOMPAT_DIRTY;
return 0;
Expand Down
2 changes: 2 additions & 0 deletions docs/specs/pci-ids.rst
Expand Up @@ -92,6 +92,8 @@ PCI devices (other than virtio):
PCI PVPanic device (``-device pvpanic-pci``)
1b36:0012
PCI ACPI ERST device (``-device acpi-erst``)
1b36:0013
PCI UFS device (``-device ufs``)

All these devices are documented in :doc:`index`.

Expand Down
1 change: 1 addition & 0 deletions hw/Kconfig
Expand Up @@ -38,6 +38,7 @@ source smbios/Kconfig
source ssi/Kconfig
source timer/Kconfig
source tpm/Kconfig
source ufs/Kconfig
source usb/Kconfig
source virtio/Kconfig
source vfio/Kconfig
Expand Down
1 change: 1 addition & 0 deletions hw/meson.build
Expand Up @@ -37,6 +37,7 @@ subdir('smbios')
subdir('ssi')
subdir('timer')
subdir('tpm')
subdir('ufs')
subdir('usb')
subdir('vfio')
subdir('virtio')
Expand Down
4 changes: 4 additions & 0 deletions hw/ufs/Kconfig
@@ -0,0 +1,4 @@
config UFS_PCI
bool
default y if PCI_DEVICES
depends on PCI

0 comments on commit 05ba96b

Please sign in to comment.