|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [qemu-xen staging] Merge remote-tracking branch 'remotes/vivier/tags/m68k-next-pull-request' into staging
=== This changeset includes merge from high-traffic branch ===
Commits on that branch are not reported individually.
commit 48f22ad04ead83e61b4b35871ec6f6109779b791
Merge: 8796c64ecdfd34be394ea277aaaaa53df0c76996
d159dd058c7dc48a9291fde92eaae52a9f26a4d1
Author: Peter Maydell <peter.maydell@xxxxxxxxxx>
AuthorDate: Wed Jul 8 21:38:47 2020 +0100
Commit: Peter Maydell <peter.maydell@xxxxxxxxxx>
CommitDate: Wed Jul 8 21:38:47 2020 +0100
Merge remote-tracking branch 'remotes/vivier/tags/m68k-next-pull-request'
into staging
m68k pull-request 20200706
disable floatx80_invalid_encoding() for m68k
fix m68k_cpu_get_phys_page_debug()
# gpg: Signature made Mon 06 Jul 2020 21:05:33 BST
# gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg: issuer "laurent@xxxxxxxxx"
# gpg: Good signature from "Laurent Vivier <lvivier@xxxxxxxxxx>" [full]
# gpg: aka "Laurent Vivier <laurent@xxxxxxxxx>" [full]
# gpg: aka "Laurent Vivier (Red Hat) <lvivier@xxxxxxxxxx>"
[full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F
BE3C
* remotes/vivier/tags/m68k-next-pull-request:
softfloat,m68k: disable floatx80_invalid_encoding() for m68k
target/m68k: consolidate physical translation offset into
get_physical_address()
target/m68k: fix physical address translation in
m68k_cpu_get_phys_page_debug()
Signed-off-by: Peter Maydell <peter.maydell@xxxxxxxxxx>
MAINTAINERS | 23 +-
accel/kvm/kvm-all.c | 4 +-
balloon.c | 17 -
block.c | 19 +-
block/Makefile.objs | 2 +-
block/amend.c | 113 +
block/block-copy.c | 4 +-
block/crypto.c | 207 +-
block/crypto.h | 37 +
block/file-posix.c | 3 -
block/io.c | 8 +-
block/iscsi.c | 1 -
block/qcow2.c | 350 +-
block/qed.c | 65 +-
block/qed.h | 1 -
block/vdi.c | 3 +-
block/vhdx.c | 3 -
block/vpc.c | 3 +-
block/vvfat.c | 67 +-
bsd-user/main.c | 6 +-
configure | 40 +-
crypto/block-luks.c | 416 ++-
crypto/block.c | 29 +
crypto/blockpriv.h | 8 +
docs/interop/index.rst | 1 +
docs/interop/vhost-user.rst | 24 +
docs/interop/vhost-vdpa.rst | 17 +
docs/system/deprecated.rst | 20 +
docs/system/target-i386-desc.rst.inc | 13 +-
docs/tools/qemu-img.rst | 5 +-
docs/tools/virtiofsd.rst | 5 +
exec.c | 52 +
hw/arm/fsl-imx6ul.c | 10 +
hw/arm/mcimx6ul-evk.c | 2 +
hw/arm/pxa2xx_pic.c | 9 +-
hw/arm/spitz.c | 505 +--
hw/arm/virt-acpi-build.c | 5 +-
hw/arm/virt.c | 35 +
hw/arm/z2.c | 11 +-
hw/audio/ac97.c | 9 +-
hw/audio/adlib.c | 8 +-
hw/audio/cs4231a.c | 8 +-
hw/audio/es1370.c | 9 +-
hw/audio/gus.c | 8 +-
hw/audio/intel-hda.c | 3 +
hw/audio/pcspk.c | 26 +-
hw/audio/sb16.c | 9 +-
hw/audio/soundhw.c | 24 +-
hw/core/numa.c | 17 +-
hw/core/qdev-properties.c | 89 +
hw/display/ads7846.c | 9 +-
hw/display/bcm2835_fb.c | 4 +
hw/display/ssd0323.c | 10 +-
hw/gpio/zaurus.c | 12 +-
hw/i386/Kconfig | 1 +
hw/i386/microvm.c | 1 +
hw/i386/pc.c | 80 +-
hw/i386/pc_piix.c | 4 +-
hw/i386/pc_q35.c | 4 +-
hw/isa/i82378.c | 2 +-
hw/m68k/mcf5206.c | 39 +-
hw/mips/jazz.c | 2 +-
hw/misc/max111x.c | 86 +-
hw/net/imx_fec.c | 24 +-
hw/net/trace-events | 4 +-
hw/net/vhost_net-stub.c | 11 +
hw/net/vhost_net.c | 44 +-
hw/net/virtio-net.c | 19 +
hw/riscv/sifive_clint.c | 2 +-
hw/riscv/sifive_plic.c | 20 +-
hw/s390x/s390-pci-bus.c | 16 +-
hw/s390x/s390-virtio-ccw.c | 22 +-
hw/s390x/virtio-ccw.c | 18 +-
hw/sd/ssi-sd.c | 4 +-
hw/ssi/ssi.c | 7 +-
hw/vfio/ap.c | 8 +-
hw/vfio/ccw.c | 11 +-
hw/vfio/common.c | 53 +-
hw/vfio/pci.c | 6 +-
hw/virtio/Kconfig | 11 +
hw/virtio/Makefile.objs | 3 +
hw/virtio/trace-events | 11 +
hw/virtio/vhost-backend.c | 6 +
hw/virtio/vhost-vdpa.c | 475 +++
hw/virtio/vhost.c | 52 +-
hw/virtio/virtio-balloon.c | 36 +-
hw/virtio/virtio-iommu-pci.c | 11 +
hw/virtio/virtio-iommu.c | 114 +-
hw/virtio/virtio-mem-pci.c | 157 +
hw/virtio/virtio-mem-pci.h | 34 +
hw/virtio/virtio-mem.c | 873 +++++
hw/virtio/virtio-pci.c | 13 +
hw/virtio/virtio.c | 6 +
include/block/block.h | 7 +-
include/block/block_int.h | 36 +-
include/crypto/block.h | 22 +
include/exec/memory.h | 47 +
include/exec/ram_addr.h | 5 +-
include/exec/user/thunk.h | 1 +
include/hw/arm/fsl-imx6ul.h | 2 +
include/hw/arm/pxa.h | 1 -
include/hw/arm/sharpsl.h | 3 -
include/hw/arm/virt.h | 8 +
include/hw/audio/pcspk.h | 12 +-
include/hw/audio/soundhw.h | 2 +
include/hw/boards.h | 1 +
include/hw/i386/pc.h | 6 +-
include/hw/misc/max111x.h | 56 +
include/hw/net/imx_fec.h | 1 +
include/hw/pci/pci.h | 1 +
include/hw/qdev-properties.h | 3 +
include/hw/ssi/ssi.h | 31 +-
include/hw/vfio/vfio-common.h | 4 +-
include/hw/virtio/vhost-backend.h | 19 +-
include/hw/virtio/vhost-vdpa.h | 26 +
include/hw/virtio/vhost.h | 7 +
include/hw/virtio/virtio-bus.h | 4 +
include/hw/virtio/virtio-iommu.h | 2 +
include/hw/virtio/virtio-mem.h | 86 +
include/migration/colo.h | 2 +-
include/migration/misc.h | 2 +
include/net/net.h | 1 +
include/net/vhost-vdpa.h | 22 +
include/net/vhost_net.h | 5 +
include/qemu/typedefs.h | 1 +
include/sysemu/balloon.h | 2 -
linux-user/ioctls.h | 17 +-
linux-user/qemu.h | 40 +-
linux-user/sparc/cpu_loop.c | 6 +-
linux-user/strace.c | 435 ++-
linux-user/strace.list | 40 +-
linux-user/syscall.c | 136 +-
linux-user/syscall_defs.h | 15 +
linux-user/syscall_types.h | 33 +
migration/migration.c | 15 +-
migration/postcopy-ram.c | 25 +-
migration/ram.c | 8 +-
migration/rdma.c | 18 +-
migration/savevm.c | 11 +-
monitor/hmp-cmds.c | 16 +
monitor/monitor.c | 1 +
net/Makefile.objs | 2 +-
net/clients.h | 2 +
net/net.c | 10 +
net/vhost-vdpa.c | 228 ++
pc-bios/bios-256k.bin | Bin 262144 -> 262144 bytes
pc-bios/bios.bin | Bin 131072 -> 131072 bytes
pc-bios/s390-ccw.img | Bin 42608 -> 42608 bytes
pc-bios/s390-ccw/Makefile | 3 +
pc-bios/s390-ccw/bootmap.c | 4 +-
pc-bios/s390-ccw/cio.c | 40 +-
pc-bios/s390-ccw/cio.h | 17 +-
pc-bios/s390-ccw/helper.h | 19 +-
pc-bios/s390-ccw/jump2ipl.c | 10 +-
pc-bios/s390-ccw/main.c | 15 +-
pc-bios/s390-ccw/menu.c | 1 +
pc-bios/s390-ccw/netboot.mak | 13 +-
pc-bios/s390-ccw/netmain.c | 23 +-
pc-bios/s390-ccw/s390-arch.h | 4 +-
pc-bios/s390-ccw/s390-ccw.h | 27 +-
pc-bios/s390-ccw/s390-time.h | 23 +
pc-bios/s390-ccw/start.S | 5 +-
pc-bios/s390-ccw/virtio-net.c | 2 +
pc-bios/s390-ccw/virtio-scsi.c | 2 +
pc-bios/s390-ccw/virtio.c | 18 +-
pc-bios/s390-netboot.img | Bin 67232 -> 67232 bytes
pc-bios/vgabios-ati.bin | Bin 39424 -> 39424 bytes
pc-bios/vgabios-bochs-display.bin | Bin 28672 -> 28672 bytes
pc-bios/vgabios-cirrus.bin | Bin 38912 -> 38912 bytes
pc-bios/vgabios-qxl.bin | Bin 39424 -> 39424 bytes
pc-bios/vgabios-ramfb.bin | Bin 28672 -> 28672 bytes
pc-bios/vgabios-stdvga.bin | Bin 39424 -> 39424 bytes
pc-bios/vgabios-virtio.bin | Bin 39424 -> 39424 bytes
pc-bios/vgabios-vmware.bin | Bin 39424 -> 39424 bytes
pc-bios/vgabios.bin | Bin 38912 -> 38912 bytes
qapi/block-core.json | 68 +
qapi/crypto.json | 73 +-
qapi/job.json | 4 +-
qapi/misc.json | 64 +-
qapi/net.json | 28 +-
qdev-monitor.c | 2 +
qemu-img-cmds.hx | 4 +-
qemu-img.c | 57 +-
qemu-options.hx | 12 +
qemu-storage-daemon.c | 5 +
roms/config.seabios-128k | 3 +
roms/seabios | 2 +-
softmmu/vl.c | 24 +-
stubs/Makefile.objs | 2 +
stubs/isa-bus.c | 7 +
stubs/pci-bus.c | 7 +
target/arm/cpu.h | 2 +
target/arm/kvm.c | 80 +
target/arm/kvm32.c | 34 +
target/arm/kvm64.c | 49 +
target/arm/kvm_arm.h | 10 +
target/arm/translate-a64.c | 6 +
target/arm/translate-a64.h | 1 +
target/arm/translate-sve.c | 8 +-
target/i386/sev.c | 7 +
target/riscv/Makefile.objs | 2 +-
target/riscv/cpu.c | 50 +
target/riscv/cpu.h | 82 +-
target/riscv/cpu_bits.h | 15 +
target/riscv/csr.c | 75 +-
target/riscv/fpu_helper.c | 33 +-
target/riscv/helper.h | 1069 ++++++
target/riscv/insn32-64.decode | 11 +
target/riscv/insn32.decode | 372 ++
target/riscv/insn_trans/trans_rvv.inc.c | 2888 ++++++++++++++++
target/riscv/internals.h | 41 +
target/riscv/translate.c | 27 +-
target/riscv/vector_helper.c | 4899 +++++++++++++++++++++++++++
target/s390x/insn-data.def | 2 +-
target/sparc/translate.c | 2 +
tcg/ppc/tcg-target.inc.c | 15 +-
tcg/tcg-op.c | 10 +-
tests/acceptance/machine_sparc64_sun4u.py | 36 +
tests/data/acpi/disassemle-aml.sh | 52 +
tests/data/acpi/rebuild-expected-aml.sh | 1 +
tests/data/acpi/virt/DSDT | Bin 5307 -> 5205 bytes
tests/data/acpi/virt/DSDT.memhp | Bin 6668 -> 6566 bytes
tests/data/acpi/virt/DSDT.numamem | Bin 5307 -> 5205 bytes
tests/qemu-iotests/049.out | 102 +-
tests/qemu-iotests/051.pc.out | 4 +-
tests/qemu-iotests/061.out | 12 +-
tests/qemu-iotests/082.out | 185 +-
tests/qemu-iotests/085.out | 38 +-
tests/qemu-iotests/087 | 1 +
tests/qemu-iotests/087.out | 6 +-
tests/qemu-iotests/112.out | 2 +-
tests/qemu-iotests/125 | 24 +
tests/qemu-iotests/125.out | 9 +
tests/qemu-iotests/134.out | 2 +-
tests/qemu-iotests/141 | 2 +-
tests/qemu-iotests/144.out | 4 +-
tests/qemu-iotests/146 | 60 +-
tests/qemu-iotests/146.out | 405 ++-
tests/qemu-iotests/153 | 9 +-
tests/qemu-iotests/158.out | 4 +-
tests/qemu-iotests/178 | 1 +
tests/qemu-iotests/182.out | 2 +-
tests/qemu-iotests/185.out | 8 +-
tests/qemu-iotests/188 | 1 +
tests/qemu-iotests/188.out | 2 +-
tests/qemu-iotests/189 | 1 +
tests/qemu-iotests/189.out | 4 +-
tests/qemu-iotests/198 | 1 +
tests/qemu-iotests/198.out | 4 +-
tests/qemu-iotests/206 | 1 +
tests/qemu-iotests/255.out | 8 +-
tests/qemu-iotests/263 | 1 +
tests/qemu-iotests/263.out | 4 +-
tests/qemu-iotests/274.out | 46 +-
tests/qemu-iotests/280.out | 2 +-
tests/qemu-iotests/284 | 1 +
tests/qemu-iotests/284.out | 6 +-
tests/qemu-iotests/291 | 4 -
tests/qemu-iotests/291.out | 33 -
tests/qemu-iotests/293 | 208 ++
tests/qemu-iotests/293.out | 99 +
tests/qemu-iotests/294 | 90 +
tests/qemu-iotests/294.out | 30 +
tests/qemu-iotests/295 | 280 ++
tests/qemu-iotests/295.out | 40 +
tests/qemu-iotests/296 | 234 ++
tests/qemu-iotests/296.out | 33 +
tests/qemu-iotests/common.filter | 106 +-
tests/qemu-iotests/common.rc | 30 +
tests/qemu-iotests/group | 4 +
tests/qemu-iotests/iotests.py | 108 +-
tests/qtest/bios-tables-test-allowed-diff.h | 18 -
tests/qtest/device-introspect-test.c | 5 -
tests/qtest/fuzz/fork_fuzz.c | 40 +-
tests/qtest/fuzz/fuzz.c | 3 +
tests/qtest/libqtest.c | 4 +
tests/qtest/migration-test.c | 2 +-
tests/qtest/qom-test.c | 5 -
tests/qtest/test-hmp.c | 5 -
thunk.c | 154 +
tools/virtiofsd/helper.c | 2 +
tools/virtiofsd/passthrough_ll.c | 71 +-
util/qemu-openpty.c | 5 +-
283 files changed, 17535 insertions(+), 1671 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index dec252f38b..42388f1de2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -787,6 +787,7 @@ F: hw/gpio/max7310.c
F: hw/gpio/zaurus.c
F: hw/misc/mst_fpga.c
F: hw/misc/max111x.c
+F: include/hw/misc/max111x.h
F: include/hw/arm/pxa.h
F: include/hw/arm/sharpsl.h
F: include/hw/display/tc6393xb.h
@@ -1318,6 +1319,7 @@ F: include/hw/pci-host/sabre.h
F: hw/pci-bridge/simba.c
F: include/hw/pci-bridge/simba.h
F: pc-bios/openbios-sparc64
+F: tests/acceptance/machine_sparc64_sun4u.py
Sun4v
M: Artyom Tarasenko <atar4qemu@xxxxxxxxx>
@@ -1790,6 +1792,15 @@ F: hw/virtio/virtio-crypto.c
F: hw/virtio/virtio-crypto-pci.c
F: include/hw/virtio/virtio-crypto.h
+virtio-mem
+M: David Hildenbrand <david@xxxxxxxxxx>
+S: Supported
+W: https://virtio-mem.gitlab.io/
+F: hw/virtio/virtio-mem.c
+F: hw/virtio/virtio-mem-pci.h
+F: hw/virtio/virtio-mem-pci.c
+F: include/hw/virtio/virtio-mem.h
+
nvme
M: Keith Busch <kbusch@xxxxxxxxxx>
L: qemu-block@xxxxxxxxxx
@@ -2615,6 +2626,15 @@ F: tests/uefi-test-tools/
F: .gitlab-ci.d/edk2.yml
F: .gitlab-ci.d/edk2/
+VT-d Emulation
+M: Michael S. Tsirkin <mst@xxxxxxxxxx>
+M: Peter Xu <peterx@xxxxxxxxxx>
+R: Jason Wang <jasowang@xxxxxxxxxx>
+S: Supported
+F: hw/i386/intel_iommu.c
+F: hw/i386/intel_iommu_internal.h
+F: include/hw/i386/intel_iommu.h
+
Usermode Emulation
------------------
Overall usermode emulation
@@ -2629,8 +2649,7 @@ F: bsd-user/
F: default-configs/*-bsd-user.mak
Linux user
-M: Riku Voipio <riku.voipio@xxxxxx>
-R: Laurent Vivier <laurent@xxxxxxxxx>
+M: Laurent Vivier <laurent@xxxxxxxxx>
S: Maintained
F: linux-user/
F: default-configs/*-linux-user.mak
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index d54a8701d8..ab36fbfa0c 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -40,7 +40,6 @@
#include "trace.h"
#include "hw/irq.h"
#include "sysemu/sev.h"
-#include "sysemu/balloon.h"
#include "qapi/visitor.h"
#include "qapi/qapi-types-common.h"
#include "qapi/qapi-visit-common.h"
@@ -2229,7 +2228,8 @@ static int kvm_init(MachineState *ms)
s->sync_mmu = !!kvm_vm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
if (!s->sync_mmu) {
- qemu_balloon_inhibit(true);
+ ret = ram_block_discard_disable(true);
+ assert(!ret);
}
return 0;
diff --git a/balloon.c b/balloon.c
index f104b42961..354408c6ea 100644
--- a/balloon.c
+++ b/balloon.c
@@ -36,23 +36,6 @@
static QEMUBalloonEvent *balloon_event_fn;
static QEMUBalloonStatus *balloon_stat_fn;
static void *balloon_opaque;
-static int balloon_inhibit_count;
-
-bool qemu_balloon_is_inhibited(void)
-{
- return atomic_read(&balloon_inhibit_count) > 0;
-}
-
-void qemu_balloon_inhibit(bool state)
-{
- if (state) {
- atomic_inc(&balloon_inhibit_count);
- } else {
- atomic_dec(&balloon_inhibit_count);
- }
-
- assert(atomic_read(&balloon_inhibit_count) >= 0);
-}
static bool have_balloon(Error **errp)
{
diff --git a/block.c b/block.c
index 6dbcb7e083..62e40db2f1 100644
--- a/block.c
+++ b/block.c
@@ -5408,21 +5408,6 @@ int bdrv_has_zero_init(BlockDriverState *bs)
return 0;
}
-bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs)
-{
- BlockDriverInfo bdi;
-
- if (bs->backing) {
- return false;
- }
-
- if (bdrv_get_info(bs, &bdi) == 0) {
- return bdi.unallocated_blocks_are_zero;
- }
-
- return false;
-}
-
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs)
{
if (!(bs->open_flags & BDRV_O_UNMAP)) {
@@ -6482,6 +6467,7 @@ void bdrv_remove_aio_context_notifier(BlockDriverState
*bs,
int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts,
BlockDriverAmendStatusCB *status_cb, void *cb_opaque,
+ bool force,
Error **errp)
{
if (!bs->drv) {
@@ -6493,7 +6479,8 @@ int bdrv_amend_options(BlockDriverState *bs, QemuOpts
*opts,
bs->drv->format_name);
return -ENOTSUP;
}
- return bs->drv->bdrv_amend_options(bs, opts, status_cb, cb_opaque, errp);
+ return bs->drv->bdrv_amend_options(bs, opts, status_cb,
+ cb_opaque, force, errp);
}
/*
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 96028eedce..577e578bc2 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -19,7 +19,7 @@ block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o
block-obj-$(CONFIG_POSIX) += file-posix.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
block-obj-$(CONFIG_LINUX_IO_URING) += io_uring.o
-block-obj-y += null.o mirror.o commit.o io.o create.o
+block-obj-y += null.o mirror.o commit.o io.o create.o amend.o
block-obj-y += throttle-groups.o
block-obj-$(CONFIG_LINUX) += nvme.o
diff --git a/block/amend.c b/block/amend.c
new file mode 100644
index 0000000000..f4612dcf08
--- /dev/null
+++ b/block/amend.c
@@ -0,0 +1,113 @@
+/*
+ * Block layer code related to image options amend
+ *
+ * Copyright (c) 2018 Kevin Wolf <kwolf@xxxxxxxxxx>
+ * Copyright (c) 2020 Red Hat. Inc
+ *
+ * Heavily based on create.c
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "block/block_int.h"
+#include "qemu/job.h"
+#include "qemu/main-loop.h"
+#include "qapi/qapi-commands-block-core.h"
+#include "qapi/qapi-visit-block-core.h"
+#include "qapi/clone-visitor.h"
+#include "qapi/error.h"
+
+typedef struct BlockdevAmendJob {
+ Job common;
+ BlockdevAmendOptions *opts;
+ BlockDriverState *bs;
+ bool force;
+} BlockdevAmendJob;
+
+static int coroutine_fn blockdev_amend_run(Job *job, Error **errp)
+{
+ BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common);
+ int ret;
+
+ job_progress_set_remaining(&s->common, 1);
+ ret = s->bs->drv->bdrv_co_amend(s->bs, s->opts, s->force, errp);
+ job_progress_update(&s->common, 1);
+ qapi_free_BlockdevAmendOptions(s->opts);
+ return ret;
+}
+
+static const JobDriver blockdev_amend_job_driver = {
+ .instance_size = sizeof(BlockdevAmendJob),
+ .job_type = JOB_TYPE_AMEND,
+ .run = blockdev_amend_run,
+};
+
+void qmp_x_blockdev_amend(const char *job_id,
+ const char *node_name,
+ BlockdevAmendOptions *options,
+ bool has_force,
+ bool force,
+ Error **errp)
+{
+ BlockdevAmendJob *s;
+ const char *fmt = BlockdevDriver_str(options->driver);
+ BlockDriver *drv = bdrv_find_format(fmt);
+ BlockDriverState *bs = bdrv_find_node(node_name);
+
+
+ if (!drv) {
+ error_setg(errp, "Block driver '%s' not found or not supported", fmt);
+ return;
+ }
+
+ /*
+ * If the driver is in the schema, we know that it exists. But it may not
+ * be whitelisted.
+ */
+ if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) {
+ error_setg(errp, "Driver is not whitelisted");
+ return;
+ }
+
+ if (bs->drv != drv) {
+ error_setg(errp,
+ "x-blockdev-amend doesn't support changing the block
driver");
+ return;
+ }
+
+ /* Error out if the driver doesn't support .bdrv_co_amend */
+ if (!drv->bdrv_co_amend) {
+ error_setg(errp, "Driver does not support x-blockdev-amend");
+ return;
+ }
+
+ /* Create the block job */
+ s = job_create(job_id, &blockdev_amend_job_driver, NULL,
+ bdrv_get_aio_context(bs), JOB_DEFAULT | JOB_MANUAL_DISMISS,
+ NULL, NULL, errp);
+ if (!s) {
+ return;
+ }
+
+ s->bs = bs,
+ s->opts = QAPI_CLONE(BlockdevAmendOptions, options),
+ s->force = has_force ? force : false;
+ job_start(&s->common);
+}
diff --git a/block/block-copy.c b/block/block-copy.c
index bb8d0569f2..f7428a7c08 100644
--- a/block/block-copy.c
+++ b/block/block-copy.c
@@ -622,8 +622,10 @@ out:
* block_copy_task_run. If it fails, it means some task already failed
* for real reason, let's return first failure.
* Still, assert that we don't rewrite failure by success.
+ *
+ * Note: ret may be positive here because of block-status result.
*/
- assert(ret == 0 || aio_task_pool_status(aio) < 0);
+ assert(ret >= 0 || aio_task_pool_status(aio) < 0);
ret = aio_task_pool_status(aio);
aio_task_pool_free(aio);
diff --git a/block/crypto.c b/block/crypto.c
index 973b57b3eb..2636e959ae 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -37,6 +37,7 @@ typedef struct BlockCrypto BlockCrypto;
struct BlockCrypto {
QCryptoBlock *block;
+ bool updating_keys;
};
@@ -71,6 +72,24 @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
return ret;
}
+static ssize_t block_crypto_write_func(QCryptoBlock *block,
+ size_t offset,
+ const uint8_t *buf,
+ size_t buflen,
+ void *opaque,
+ Error **errp)
+{
+ BlockDriverState *bs = opaque;
+ ssize_t ret;
+
+ ret = bdrv_pwrite(bs->file, offset, buf, buflen);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "Could not write encryption header");
+ return ret;
+ }
+ return ret;
+}
+
struct BlockCryptoCreateData {
BlockBackend *blk;
@@ -79,12 +98,12 @@ struct BlockCryptoCreateData {
};
-static ssize_t block_crypto_write_func(QCryptoBlock *block,
- size_t offset,
- const uint8_t *buf,
- size_t buflen,
- void *opaque,
- Error **errp)
+static ssize_t block_crypto_create_write_func(QCryptoBlock *block,
+ size_t offset,
+ const uint8_t *buf,
+ size_t buflen,
+ void *opaque,
+ Error **errp)
{
struct BlockCryptoCreateData *data = opaque;
ssize_t ret;
@@ -97,11 +116,10 @@ static ssize_t block_crypto_write_func(QCryptoBlock *block,
return ret;
}
-
-static ssize_t block_crypto_init_func(QCryptoBlock *block,
- size_t headerlen,
- void *opaque,
- Error **errp)
+static ssize_t block_crypto_create_init_func(QCryptoBlock *block,
+ size_t headerlen,
+ void *opaque,
+ Error **errp)
{
struct BlockCryptoCreateData *data = opaque;
Error *local_error = NULL;
@@ -167,6 +185,19 @@ static QemuOptsList block_crypto_create_opts_luks = {
};
+static QemuOptsList block_crypto_amend_opts_luks = {
+ .name = "crypto",
+ .head = QTAILQ_HEAD_INITIALIZER(block_crypto_create_opts_luks.head),
+ .desc = {
+ BLOCK_CRYPTO_OPT_DEF_LUKS_STATE(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET(""),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
+ { /* end of list */ }
+ },
+};
+
QCryptoBlockOpenOptions *
block_crypto_open_opts_init(QDict *opts, Error **errp)
{
@@ -202,6 +233,23 @@ block_crypto_create_opts_init(QDict *opts, Error **errp)
return ret;
}
+QCryptoBlockAmendOptions *
+block_crypto_amend_opts_init(QDict *opts, Error **errp)
+{
+ Visitor *v;
+ QCryptoBlockAmendOptions *ret;
+
+ v = qobject_input_visitor_new_flat_confused(opts, errp);
+ if (!v) {
+ return NULL;
+ }
+
+ visit_type_QCryptoBlockAmendOptions(v, NULL, &ret, errp);
+
+ visit_free(v);
+ return ret;
+}
+
static int block_crypto_open_generic(QCryptoBlockFormat format,
QemuOptsList *opts_spec,
@@ -296,8 +344,8 @@ static int block_crypto_co_create_generic(BlockDriverState
*bs,
};
crypto = qcrypto_block_create(opts, NULL,
- block_crypto_init_func,
- block_crypto_write_func,
+ block_crypto_create_init_func,
+ block_crypto_create_write_func,
&data,
errp);
@@ -710,7 +758,6 @@ static int block_crypto_get_info_luks(BlockDriverState *bs,
return ret;
}
- bdi->unallocated_blocks_are_zero = false;
bdi->cluster_size = subbdi.cluster_size;
return 0;
@@ -742,6 +789,131 @@ block_crypto_get_specific_info_luks(BlockDriverState *bs,
Error **errp)
return spec_info;
}
+static int
+block_crypto_amend_options_generic_luks(BlockDriverState *bs,
+ QCryptoBlockAmendOptions
*amend_options,
+ bool force,
+ Error **errp)
+{
+ BlockCrypto *crypto = bs->opaque;
+ int ret;
+
+ assert(crypto);
+ assert(crypto->block);
+
+ /* apply for exclusive read/write permissions to the underlying file*/
+ crypto->updating_keys = true;
+ ret = bdrv_child_refresh_perms(bs, bs->file, errp);
+ if (ret) {
+ goto cleanup;
+ }
+
+ ret = qcrypto_block_amend_options(crypto->block,
+ block_crypto_read_func,
+ block_crypto_write_func,
+ bs,
+ amend_options,
+ force,
+ errp);
+cleanup:
+ /* release exclusive read/write permissions to the underlying file*/
+ crypto->updating_keys = false;
+ bdrv_child_refresh_perms(bs, bs->file, errp);
+ return ret;
+}
+
+static int
+block_crypto_amend_options_luks(BlockDriverState *bs,
+ QemuOpts *opts,
+ BlockDriverAmendStatusCB *status_cb,
+ void *cb_opaque,
+ bool force,
+ Error **errp)
+{
+ BlockCrypto *crypto = bs->opaque;
+ QDict *cryptoopts = NULL;
+ QCryptoBlockAmendOptions *amend_options = NULL;
+ int ret = -EINVAL;
+
+ assert(crypto);
+ assert(crypto->block);
+
+ cryptoopts = qemu_opts_to_qdict(opts, NULL);
+ qdict_put_str(cryptoopts, "format", "luks");
+ amend_options = block_crypto_amend_opts_init(cryptoopts, errp);
+ qobject_unref(cryptoopts);
+ if (!amend_options) {
+ goto cleanup;
+ }
+ ret = block_crypto_amend_options_generic_luks(bs, amend_options,
+ force, errp);
+cleanup:
+ qapi_free_QCryptoBlockAmendOptions(amend_options);
+ return ret;
+}
+
+static int
+coroutine_fn block_crypto_co_amend_luks(BlockDriverState *bs,
+ BlockdevAmendOptions *opts,
+ bool force,
+ Error **errp)
+{
+ QCryptoBlockAmendOptions amend_opts;
+
+ amend_opts = (QCryptoBlockAmendOptions) {
+ .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
+ .u.luks = *qapi_BlockdevAmendOptionsLUKS_base(&opts->u.luks),
+ };
+ return block_crypto_amend_options_generic_luks(bs, &amend_opts,
+ force, errp);
+}
+
+static void
+block_crypto_child_perms(BlockDriverState *bs, BdrvChild *c,
+ const BdrvChildRole role,
+ BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
+{
+
+ BlockCrypto *crypto = bs->opaque;
+
+ bdrv_default_perms(bs, c, role, reopen_queue, perm, shared, nperm,
nshared);
+
+ /*
+ * For backward compatibility, manually share the write
+ * and resize permission
+ */
+ *nshared |= (BLK_PERM_WRITE | BLK_PERM_RESIZE);
+ /*
+ * Since we are not fully a format driver, don't always request
+ * the read/resize permission but only when explicitly
+ * requested
+ */
+ *nperm &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
+ *nperm |= perm & (BLK_PERM_WRITE | BLK_PERM_RESIZE);
+
+ /*
+ * This driver doesn't modify LUKS metadata except
+ * when updating the encryption slots.
+ * Thus unlike a proper format driver we don't ask for
+ * shared write/read permission. However we need it
+ * when we are updating the keys, to ensure that only we
+ * have access to the device.
+ *
+ * Encryption update will set the crypto->updating_keys
+ * during that period and refresh permissions
+ *
+ */
+ if (crypto->updating_keys) {
+ /* need exclusive write access for header update */
+ *nperm |= BLK_PERM_WRITE;
+ /* unshare read and write permission */
+ *nshared &= ~(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE);
+ }
+}
+
+
static const char *const block_crypto_strong_runtime_opts[] = {
BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
@@ -754,13 +926,12 @@ static BlockDriver bdrv_crypto_luks = {
.bdrv_probe = block_crypto_probe_luks,
.bdrv_open = block_crypto_open_luks,
.bdrv_close = block_crypto_close,
- /* This driver doesn't modify LUKS metadata except when creating image.
- * Allow share-rw=on as a special case. */
- .bdrv_child_perm = bdrv_default_perms,
+ .bdrv_child_perm = block_crypto_child_perms,
.bdrv_co_create = block_crypto_co_create_luks,
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
.bdrv_co_truncate = block_crypto_co_truncate,
.create_opts = &block_crypto_create_opts_luks,
+ .amend_opts = &block_crypto_amend_opts_luks,
.bdrv_reopen_prepare = block_crypto_reopen_prepare,
.bdrv_refresh_limits = block_crypto_refresh_limits,
@@ -770,6 +941,8 @@ static BlockDriver bdrv_crypto_luks = {
.bdrv_measure = block_crypto_measure,
.bdrv_get_info = block_crypto_get_info_luks,
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
+ .bdrv_amend_options = block_crypto_amend_options_luks,
+ .bdrv_co_amend = block_crypto_co_amend_luks,
.is_format = true,
diff --git a/block/crypto.h b/block/crypto.h
index b935695e79..c72c3dec61 100644
--- a/block/crypto.h
+++ b/block/crypto.h
@@ -41,6 +41,11 @@
#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg"
#define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
#define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
+#define BLOCK_CRYPTO_OPT_LUKS_KEYSLOT "keyslot"
+#define BLOCK_CRYPTO_OPT_LUKS_STATE "state"
+#define BLOCK_CRYPTO_OPT_LUKS_OLD_SECRET "old-secret"
+#define BLOCK_CRYPTO_OPT_LUKS_NEW_SECRET "new-secret"
+
#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix) \
BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \
@@ -88,9 +93,41 @@
.help = "Time to spend in PBKDF in milliseconds", \
}
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_STATE(prefix) \
+ { \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_STATE, \
+ .type = QEMU_OPT_STRING, \
+ .help = "Select new state of affected keyslots (active/inactive)",\
+ }
+
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT(prefix) \
+ { \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_KEYSLOT, \
+ .type = QEMU_OPT_NUMBER, \
+ .help = "Select a single keyslot to modify explicitly",\
+ }
+
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET(prefix) \
+ { \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_OLD_SECRET, \
+ .type = QEMU_OPT_STRING, \
+ .help = "Select all keyslots that match this password", \
+ }
+
+#define BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET(prefix) \
+ { \
+ .name = prefix BLOCK_CRYPTO_OPT_LUKS_NEW_SECRET, \
+ .type = QEMU_OPT_STRING, \
+ .help = "New secret to set in the matching keyslots. " \
+ "Empty string to erase", \
+ }
+
QCryptoBlockCreateOptions *
block_crypto_create_opts_init(QDict *opts, Error **errp);
+QCryptoBlockAmendOptions *
+block_crypto_amend_opts_init(QDict *opts, Error **errp);
+
QCryptoBlockOpenOptions *
block_crypto_open_opts_init(QDict *opts, Error **errp);
diff --git a/block/file-posix.c b/block/file-posix.c
index 3ab8f5a0fa..d86ea57769 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2878,9 +2878,6 @@ static int coroutine_fn raw_co_pwrite_zeroes(
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
- BDRVRawState *s = bs->opaque;
-
- bdi->unallocated_blocks_are_zero = s->discard_zeroes;
return 0;
}
diff --git a/block/io.c b/block/io.c
index df8f2a98d4..b6564e34c5 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2406,16 +2406,16 @@ static int coroutine_fn
bdrv_co_block_status(BlockDriverState *bs,
if (ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ZERO)) {
ret |= BDRV_BLOCK_ALLOCATED;
- } else if (want_zero) {
- if (bdrv_unallocated_blocks_are_zero(bs)) {
- ret |= BDRV_BLOCK_ZERO;
- } else if (bs->backing) {
+ } else if (want_zero && bs->drv->supports_backing) {
+ if (bs->backing) {
BlockDriverState *bs2 = bs->backing->bs;
int64_t size2 = bdrv_getlength(bs2);
if (size2 >= 0 && offset >= size2) {
ret |= BDRV_BLOCK_ZERO;
}
+ } else {
+ ret |= BDRV_BLOCK_ZERO;
}
}
diff --git a/block/iscsi.c b/block/iscsi.c
index a8b76979d8..767e3e75fd 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -2163,7 +2163,6 @@ static int coroutine_fn
iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
static int iscsi_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
IscsiLun *iscsilun = bs->opaque;
- bdi->unallocated_blocks_are_zero = iscsilun->lbprz;
bdi->cluster_size = iscsilun->cluster_size;
return 0;
}
diff --git a/block/qcow2.c b/block/qcow2.c
index 0cd2e6757e..38198b4e75 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -176,6 +176,19 @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock
*block, size_t offset,
return ret;
}
+static QDict*
+qcow2_extract_crypto_opts(QemuOpts *opts, const char *fmt, Error **errp)
+{
+ QDict *cryptoopts_qdict;
+ QDict *opts_qdict;
+
+ /* Extract "encrypt." options into a qdict */
+ opts_qdict = qemu_opts_to_qdict(opts, NULL);
+ qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
+ qobject_unref(opts_qdict);
+ qdict_put_str(cryptoopts_qdict, "format", fmt);
+ return cryptoopts_qdict;
+}
/*
* read qcow2 extension and fill bs
@@ -3042,17 +3055,6 @@ static int qcow2_change_backing_file(BlockDriverState
*bs,
return qcow2_update_header(bs);
}
-static int qcow2_crypt_method_from_format(const char *encryptfmt)
-{
- if (g_str_equal(encryptfmt, "luks")) {
- return QCOW_CRYPT_LUKS;
- } else if (g_str_equal(encryptfmt, "aes")) {
- return QCOW_CRYPT_AES;
- } else {
- return -EINVAL;
- }
-}
-
static int qcow2_set_up_encryption(BlockDriverState *bs,
QCryptoBlockCreateOptions *cryptoopts,
Error **errp)
@@ -4239,8 +4241,8 @@ static int coroutine_fn
qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
old_file_size = ROUND_UP(old_file_size, s->cluster_size);
}
- nb_new_data_clusters = DIV_ROUND_UP(offset - old_length,
- s->cluster_size);
+ nb_new_data_clusters = (ROUND_UP(offset, s->cluster_size) -
+ start_of_cluster(s, old_length)) >> s->cluster_bits;
/* This is an overestimation; we will not actually allocate space for
* these in the file but just make sure the new refcount structures are
@@ -4317,10 +4319,21 @@ static int coroutine_fn
qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
int64_t nb_clusters = MIN(
nb_new_data_clusters,
s->l2_slice_size - offset_to_l2_slice_index(s, guest_offset));
- QCowL2Meta allocation = {
+ unsigned cow_start_length = offset_into_cluster(s, guest_offset);
+ QCowL2Meta allocation;
+ guest_offset = start_of_cluster(s, guest_offset);
+ allocation = (QCowL2Meta) {
.offset = guest_offset,
.alloc_offset = host_offset,
.nb_clusters = nb_clusters,
+ .cow_start = {
+ .offset = 0,
+ .nb_bytes = cow_start_length,
+ },
+ .cow_end = {
+ .offset = nb_clusters << s->cluster_bits,
+ .nb_bytes = 0,
+ },
};
qemu_co_queue_init(&allocation.dependent_requests);
@@ -4860,16 +4873,9 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts,
BlockDriverState *in_bs,
if (has_luks) {
g_autoptr(QCryptoBlockCreateOptions) create_opts = NULL;
- QDict *opts_qdict;
- QDict *cryptoopts;
+ QDict *cryptoopts = qcow2_extract_crypto_opts(opts, "luks", errp);
size_t headerlen;
- opts_qdict = qemu_opts_to_qdict(opts, NULL);
- qdict_extract_subqdict(opts_qdict, &cryptoopts, "encrypt.");
- qobject_unref(opts_qdict);
-
- qdict_put_str(cryptoopts, "format", "luks");
-
create_opts = block_crypto_create_opts_init(cryptoopts, errp);
qobject_unref(cryptoopts);
if (!create_opts) {
@@ -4981,7 +4987,6 @@ err:
static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVQcow2State *s = bs->opaque;
- bdi->unallocated_blocks_are_zero = true;
bdi->cluster_size = s->cluster_size;
bdi->vm_state_offset = qcow2_vm_state_offset(s);
return 0;
@@ -5273,6 +5278,7 @@ typedef enum Qcow2AmendOperation {
QCOW2_NO_OPERATION = 0,
QCOW2_UPGRADING,
+ QCOW2_UPDATING_ENCRYPTION,
QCOW2_CHANGING_REFCOUNT_ORDER,
QCOW2_DOWNGRADING,
} Qcow2AmendOperation;
@@ -5340,6 +5346,7 @@ static void qcow2_amend_helper_cb(BlockDriverState *bs,
static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
BlockDriverAmendStatusCB *status_cb,
void *cb_opaque,
+ bool force,
Error **errp)
{
BDRVQcow2State *s = bs->opaque;
@@ -5349,13 +5356,11 @@ static int qcow2_amend_options(BlockDriverState *bs,
QemuOpts *opts,
bool lazy_refcounts = s->use_lazy_refcounts;
bool data_file_raw = data_file_is_raw(bs);
const char *compat = NULL;
- uint64_t cluster_size = s->cluster_size;
- bool encrypt;
- int encformat;
int refcount_bits = s->refcount_bits;
int ret;
QemuOptDesc *desc = opts->list->desc;
Qcow2AmendHelperCBInfo helper_cb_info;
+ bool encryption_update = false;
while (desc && desc->name) {
if (!qemu_opt_find(opts, desc->name)) {
@@ -5376,44 +5381,24 @@ static int qcow2_amend_options(BlockDriverState *bs,
QemuOpts *opts,
error_setg(errp, "Unknown compatibility level %s", compat);
return -EINVAL;
}
- } else if (!strcmp(desc->name, BLOCK_OPT_PREALLOC)) {
- error_setg(errp, "Cannot change preallocation mode");
- return -ENOTSUP;
} else if (!strcmp(desc->name, BLOCK_OPT_SIZE)) {
new_size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
} else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FILE)) {
backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
} else if (!strcmp(desc->name, BLOCK_OPT_BACKING_FMT)) {
backing_format = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
- } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT)) {
- encrypt = qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT,
- !!s->crypto);
-
- if (encrypt != !!s->crypto) {
+ } else if (g_str_has_prefix(desc->name, "encrypt.")) {
+ if (!s->crypto) {
error_setg(errp,
- "Changing the encryption flag is not supported");
- return -ENOTSUP;
+ "Can't amend encryption options - encryption not
present");
+ return -EINVAL;
}
- } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT_FORMAT)) {
- encformat = qcow2_crypt_method_from_format(
- qemu_opt_get(opts, BLOCK_OPT_ENCRYPT_FORMAT));
-
- if (encformat != s->crypt_method_header) {
+ if (s->crypt_method_header != QCOW_CRYPT_LUKS) {
error_setg(errp,
- "Changing the encryption format is not supported");
- return -ENOTSUP;
- }
- } else if (g_str_has_prefix(desc->name, "encrypt.")) {
- error_setg(errp,
- "Changing the encryption parameters is not supported");
- return -ENOTSUP;
- } else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) {
- cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE,
- cluster_size);
- if (cluster_size != s->cluster_size) {
- error_setg(errp, "Changing the cluster size is not supported");
+ "Only LUKS encryption options can be amended");
return -ENOTSUP;
}
+ encryption_update = true;
} else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS,
lazy_refcounts);
@@ -5443,22 +5428,6 @@ static int qcow2_amend_options(BlockDriverState *bs,
QemuOpts *opts,
"images");
return -EINVAL;
}
- } else if (!strcmp(desc->name, BLOCK_OPT_COMPRESSION_TYPE)) {
- const char *ct_name =
- qemu_opt_get(opts, BLOCK_OPT_COMPRESSION_TYPE);
- int compression_type =
- qapi_enum_parse(&Qcow2CompressionType_lookup, ct_name, -1,
- NULL);
- if (compression_type == -1) {
- error_setg(errp, "Unknown compression type: %s", ct_name);
- return -ENOTSUP;
- }
-
- if (compression_type != s->compression_type) {
- error_setg(errp, "Changing the compression type "
- "is not supported");
- return -ENOTSUP;
- }
} else {
/* if this point is reached, this probably means a new option was
* added without having it covered here */
@@ -5472,7 +5441,8 @@ static int qcow2_amend_options(BlockDriverState *bs,
QemuOpts *opts,
.original_status_cb = status_cb,
.original_cb_opaque = cb_opaque,
.total_operations = (new_version != old_version)
- + (s->refcount_bits != refcount_bits)
+ + (s->refcount_bits != refcount_bits) +
+ (encryption_update == true)
};
/* Upgrade first (some features may require compat=1.1) */
@@ -5485,6 +5455,33 @@ static int qcow2_amend_options(BlockDriverState *bs,
QemuOpts *opts,
}
}
+ if (encryption_update) {
+ QDict *amend_opts_dict;
+ QCryptoBlockAmendOptions *amend_opts;
+
+ helper_cb_info.current_operation = QCOW2_UPDATING_ENCRYPTION;
+ amend_opts_dict = qcow2_extract_crypto_opts(opts, "luks", errp);
+ if (!amend_opts_dict) {
+ return -EINVAL;
+ }
+ amend_opts = block_crypto_amend_opts_init(amend_opts_dict, errp);
+ qobject_unref(amend_opts_dict);
+ if (!amend_opts) {
+ return -EINVAL;
+ }
+ ret = qcrypto_block_amend_options(s->crypto,
+ qcow2_crypto_hdr_read_func,
+ qcow2_crypto_hdr_write_func,
+ bs,
+ amend_opts,
+ force,
+ errp);
+ qapi_free_QCryptoBlockAmendOptions(amend_opts);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
if (s->refcount_bits != refcount_bits) {
int refcount_order = ctz32(refcount_bits);
@@ -5598,6 +5595,44 @@ static int qcow2_amend_options(BlockDriverState *bs,
QemuOpts *opts,
return 0;
}
+static int coroutine_fn qcow2_co_amend(BlockDriverState *bs,
+ BlockdevAmendOptions *opts,
+ bool force,
+ Error **errp)
+{
+ BlockdevAmendOptionsQcow2 *qopts = &opts->u.qcow2;
+ BDRVQcow2State *s = bs->opaque;
+ int ret = 0;
+
+ if (qopts->has_encrypt) {
+ if (!s->crypto) {
+ error_setg(errp, "image is not encrypted, can't amend");
+ return -EOPNOTSUPP;
+ }
+
+ if (qopts->encrypt->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
+ error_setg(errp,
+ "Amend can't be used to change the qcow2 encryption
format");
+ return -EOPNOTSUPP;
+ }
+
+ if (s->crypt_method_header != QCOW_CRYPT_LUKS) {
+ error_setg(errp,
+ "Only LUKS encryption options can be amended for qcow2
with blockdev-amend");
+ return -EOPNOTSUPP;
+ }
+
+ ret = qcrypto_block_amend_options(s->crypto,
+ qcow2_crypto_hdr_read_func,
+ qcow2_crypto_hdr_write_func,
+ bs,
+ qopts->encrypt,
+ force,
+ errp);
+ }
+ return ret;
+}
+
/*
* If offset or size are negative, respectively, they will not be included in
* the BLOCK_IMAGE_CORRUPTED event emitted.
@@ -5648,89 +5683,108 @@ void qcow2_signal_corruption(BlockDriverState *bs,
bool fatal, int64_t offset,
s->signaled_corruption = true;
}
+#define QCOW_COMMON_OPTIONS \
+ { \
+ .name = BLOCK_OPT_SIZE, \
+ .type = QEMU_OPT_SIZE, \
+ .help = "Virtual disk size" \
+ }, \
+ { \
+ .name = BLOCK_OPT_COMPAT_LEVEL, \
+ .type = QEMU_OPT_STRING, \
+ .help = "Compatibility level (v2 [0.10] or v3 [1.1])" \
+ }, \
+ { \
+ .name = BLOCK_OPT_BACKING_FILE, \
+ .type = QEMU_OPT_STRING, \
+ .help = "File name of a base image" \
+ }, \
+ { \
+ .name = BLOCK_OPT_BACKING_FMT, \
+ .type = QEMU_OPT_STRING, \
+ .help = "Image format of the base image" \
+ }, \
+ { \
+ .name = BLOCK_OPT_DATA_FILE, \
+ .type = QEMU_OPT_STRING, \
+ .help = "File name of an external data file" \
+ }, \
+ { \
+ .name = BLOCK_OPT_DATA_FILE_RAW, \
+ .type = QEMU_OPT_BOOL, \
+ .help = "The external data file must stay valid " \
+ "as a raw image" \
+ }, \
+ { \
+ .name = BLOCK_OPT_LAZY_REFCOUNTS, \
+ .type = QEMU_OPT_BOOL, \
+ .help = "Postpone refcount updates", \
+ .def_value_str = "off" \
+ }, \
+ { \
+ .name = BLOCK_OPT_REFCOUNT_BITS, \
+ .type = QEMU_OPT_NUMBER, \
+ .help = "Width of a reference count entry in bits", \
+ .def_value_str = "16" \
+ }
+
static QemuOptsList qcow2_create_opts = {
.name = "qcow2-create-opts",
.head = QTAILQ_HEAD_INITIALIZER(qcow2_create_opts.head),
.desc = {
- {
- .name = BLOCK_OPT_SIZE,
- .type = QEMU_OPT_SIZE,
- .help = "Virtual disk size"
- },
- {
- .name = BLOCK_OPT_COMPAT_LEVEL,
- .type = QEMU_OPT_STRING,
- .help = "Compatibility level (v2 [0.10] or v3 [1.1])"
- },
- {
- .name = BLOCK_OPT_BACKING_FILE,
- .type = QEMU_OPT_STRING,
- .help = "File name of a base image"
- },
- {
- .name = BLOCK_OPT_BACKING_FMT,
- .type = QEMU_OPT_STRING,
- .help = "Image format of the base image"
- },
- {
- .name = BLOCK_OPT_DATA_FILE,
- .type = QEMU_OPT_STRING,
- .help = "File name of an external data file"
- },
- {
- .name = BLOCK_OPT_DATA_FILE_RAW,
- .type = QEMU_OPT_BOOL,
- .help = "The external data file must stay valid as a raw image"
- },
- {
- .name = BLOCK_OPT_ENCRYPT,
- .type = QEMU_OPT_BOOL,
- .help = "Encrypt the image with format 'aes'. (Deprecated "
- "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)",
+ { \
+ .name = BLOCK_OPT_ENCRYPT, \
+ .type = QEMU_OPT_BOOL, \
+ .help = "Encrypt the image with format 'aes'. (Deprecated " \
+ "in favor of " BLOCK_OPT_ENCRYPT_FORMAT "=aes)", \
+ }, \
+ { \
+ .name = BLOCK_OPT_ENCRYPT_FORMAT, \
+ .type = QEMU_OPT_STRING, \
+ .help = "Encrypt the image, format choices: 'aes', 'luks'", \
+ }, \
+ BLOCK_CRYPTO_OPT_DEF_KEY_SECRET("encrypt.", \
+ "ID of secret providing qcow AES key or LUKS passphrase"), \
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG("encrypt."), \
+ BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE("encrypt."), \
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG("encrypt."), \
+ BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG("encrypt."), \
+ BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG("encrypt."), \
+ BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME("encrypt."), \
+ { \
+ .name = BLOCK_OPT_CLUSTER_SIZE, \
+ .type = QEMU_OPT_SIZE, \
+ .help = "qcow2 cluster size", \
+ .def_value_str = stringify(DEFAULT_CLUSTER_SIZE) \
+ }, \
+ { \
+ .name = BLOCK_OPT_PREALLOC, \
+ .type = QEMU_OPT_STRING, \
+ .help = "Preallocation mode (allowed values: off, " \
+ "metadata, falloc, full)" \
+ }, \
+ { \
+ .name = BLOCK_OPT_COMPRESSION_TYPE, \
+ .type = QEMU_OPT_STRING, \
+ .help = "Compression method used for image cluster " \
+ "compression", \
+ .def_value_str = "zlib" \
},
- {
- .name = BLOCK_OPT_ENCRYPT_FORMAT,
- .type = QEMU_OPT_STRING,
- .help = "Encrypt the image, format choices: 'aes', 'luks'",
- },
- BLOCK_CRYPTO_OPT_DEF_KEY_SECRET("encrypt.",
- "ID of secret providing qcow AES key or LUKS passphrase"),
- BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_ALG("encrypt."),
- BLOCK_CRYPTO_OPT_DEF_LUKS_CIPHER_MODE("encrypt."),
- BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_ALG("encrypt."),
- BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG("encrypt."),
- BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG("encrypt."),
+ QCOW_COMMON_OPTIONS,
+ { /* end of list */ }
+ }
+};
+
+static QemuOptsList qcow2_amend_opts = {
+ .name = "qcow2-amend-opts",
+ .head = QTAILQ_HEAD_INITIALIZER(qcow2_amend_opts.head),
+ .desc = {
+ BLOCK_CRYPTO_OPT_DEF_LUKS_STATE("encrypt."),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_KEYSLOT("encrypt."),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_OLD_SECRET("encrypt."),
+ BLOCK_CRYPTO_OPT_DEF_LUKS_NEW_SECRET("encrypt."),
BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME("encrypt."),
- {
- .name = BLOCK_OPT_CLUSTER_SIZE,
- .type = QEMU_OPT_SIZE,
- .help = "qcow2 cluster size",
- .def_value_str = stringify(DEFAULT_CLUSTER_SIZE)
- },
- {
- .name = BLOCK_OPT_PREALLOC,
- .type = QEMU_OPT_STRING,
- .help = "Preallocation mode (allowed values: off, metadata, "
- "falloc, full)"
- },
- {
- .name = BLOCK_OPT_LAZY_REFCOUNTS,
- .type = QEMU_OPT_BOOL,
- .help = "Postpone refcount updates",
- .def_value_str = "off"
- },
- {
- .name = BLOCK_OPT_REFCOUNT_BITS,
- .type = QEMU_OPT_NUMBER,
- .help = "Width of a reference count entry in bits",
- .def_value_str = "16"
- },
- {
- .name = BLOCK_OPT_COMPRESSION_TYPE,
- .type = QEMU_OPT_STRING,
- .help = "Compression method used for image cluster compression",
- .def_value_str = "zlib"
- },
+ QCOW_COMMON_OPTIONS,
{ /* end of list */ }
}
};
@@ -5791,10 +5845,12 @@ BlockDriver bdrv_qcow2 = {
.bdrv_inactivate = qcow2_inactivate,
.create_opts = &qcow2_create_opts,
+ .amend_opts = &qcow2_amend_opts,
.strong_runtime_opts = qcow2_strong_runtime_opts,
.mutable_opts = mutable_opts,
.bdrv_co_check = qcow2_co_check,
.bdrv_amend_options = qcow2_amend_options,
+ .bdrv_co_amend = qcow2_co_amend,
.bdrv_detach_aio_context = qcow2_detach_aio_context,
.bdrv_attach_aio_context = qcow2_attach_aio_context,
diff --git a/block/qed.c b/block/qed.c
index c0c65015c7..ece8b9bb60 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -849,56 +849,18 @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
* @s: QED state
* @pos: Byte position in device
* @qiov: Destination I/O vector
- * @backing_qiov: Possibly shortened copy of qiov, to be allocated here
- * @cb: Completion function
- * @opaque: User data for completion function
*
* This function reads qiov->size bytes starting at pos from the backing file.
* If there is no backing file then zeroes are read.
*/
static int coroutine_fn qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
- QEMUIOVector *qiov,
- QEMUIOVector **backing_qiov)
+ QEMUIOVector *qiov)
{
- uint64_t backing_length = 0;
- size_t size;
- int ret;
-
- /* If there is a backing file, get its length. Treat the absence of a
- * backing file like a zero length backing file.
- */
if (s->bs->backing) {
- int64_t l = bdrv_getlength(s->bs->backing->bs);
- if (l < 0) {
- return l;
- }
- backing_length = l;
- }
-
- /* Zero all sectors if reading beyond the end of the backing file */
- if (pos >= backing_length ||
- pos + qiov->size > backing_length) {
- qemu_iovec_memset(qiov, 0, 0, qiov->size);
- }
-
- /* Complete now if there are no backing file sectors to read */
- if (pos >= backing_length) {
- return 0;
- }
-
- /* If the read straddles the end of the backing file, shorten it */
- size = MIN((uint64_t)backing_length - pos, qiov->size);
-
- assert(*backing_qiov == NULL);
- *backing_qiov = g_new(QEMUIOVector, 1);
- qemu_iovec_init(*backing_qiov, qiov->niov);
- qemu_iovec_concat(*backing_qiov, qiov, 0, size);
-
- BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
- ret = bdrv_co_preadv(s->bs->backing, pos, size, *backing_qiov, 0);
- if (ret < 0) {
- return ret;
+ BLKDBG_EVENT(s->bs->file, BLKDBG_READ_BACKING_AIO);
+ return bdrv_co_preadv(s->bs->backing, pos, qiov->size, qiov, 0);
}
+ qemu_iovec_memset(qiov, 0, 0, qiov->size);
return 0;
}
@@ -915,7 +877,6 @@ static int coroutine_fn
qed_copy_from_backing_file(BDRVQEDState *s,
uint64_t offset)
{
QEMUIOVector qiov;
- QEMUIOVector *backing_qiov = NULL;
int ret;
/* Skip copy entirely if there is no work to do */
@@ -925,13 +886,7 @@ static int coroutine_fn
qed_copy_from_backing_file(BDRVQEDState *s,
qemu_iovec_init_buf(&qiov, qemu_blockalign(s->bs, len), len);
- ret = qed_read_backing_file(s, pos, &qiov, &backing_qiov);
-
- if (backing_qiov) {
- qemu_iovec_destroy(backing_qiov);
- g_free(backing_qiov);
- backing_qiov = NULL;
- }
+ ret = qed_read_backing_file(s, pos, &qiov);
if (ret) {
goto out;
@@ -1339,8 +1294,7 @@ static int coroutine_fn qed_aio_read_data(void *opaque,
int ret,
qemu_iovec_memset(&acb->cur_qiov, 0, 0, acb->cur_qiov.size);
r = 0;
} else if (ret != QED_CLUSTER_FOUND) {
- r = qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov,
- &acb->backing_qiov);
+ r = qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov);
} else {
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
r = bdrv_co_preadv(bs->file, offset, acb->cur_qiov.size,
@@ -1365,12 +1319,6 @@ static int coroutine_fn qed_aio_next_io(QEDAIOCB *acb)
while (1) {
trace_qed_aio_next_io(s, acb, 0, acb->cur_pos + acb->cur_qiov.size);
- if (acb->backing_qiov) {
- qemu_iovec_destroy(acb->backing_qiov);
- g_free(acb->backing_qiov);
- acb->backing_qiov = NULL;
- }
-
acb->qiov_offset += acb->cur_qiov.size;
acb->cur_pos += acb->cur_qiov.size;
qemu_iovec_reset(&acb->cur_qiov);
@@ -1514,7 +1462,6 @@ static int bdrv_qed_get_info(BlockDriverState *bs,
BlockDriverInfo *bdi)
memset(bdi, 0, sizeof(*bdi));
bdi->cluster_size = s->header.cluster_size;
bdi->is_dirty = s->header.features & QED_F_NEED_CHECK;
- bdi->unallocated_blocks_are_zero = true;
return 0;
}
diff --git a/block/qed.h b/block/qed.h
index 42c115d822..3d12bf78d4 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -140,7 +140,6 @@ typedef struct QEDAIOCB {
/* Current cluster scatter-gather list */
QEMUIOVector cur_qiov;
- QEMUIOVector *backing_qiov;
uint64_t cur_pos; /* position on block device, in bytes */
uint64_t cur_cluster; /* cluster offset in image file */
unsigned int cur_nclusters; /* number of clusters being accessed */
diff --git a/block/vdi.c b/block/vdi.c
index 2f506a01ba..c4527a9d8c 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -334,7 +334,6 @@ static int vdi_get_info(BlockDriverState *bs,
BlockDriverInfo *bdi)
logout("\n");
bdi->cluster_size = s->block_size;
bdi->vm_state_offset = 0;
- bdi->unallocated_blocks_are_zero = true;
return 0;
}
@@ -536,7 +535,7 @@ static int coroutine_fn
vdi_co_block_status(BlockDriverState *bs,
*pnum = MIN(s->block_size - index_in_block, bytes);
result = VDI_IS_ALLOCATED(bmap_entry);
if (!result) {
- return 0;
+ return BDRV_BLOCK_ZERO;
}
*map = s->header.offset_data + (uint64_t)bmap_entry * s->block_size +
diff --git a/block/vhdx.c b/block/vhdx.c
index fa9e544a5e..645dc4b4f4 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1164,9 +1164,6 @@ static int vhdx_get_info(BlockDriverState *bs,
BlockDriverInfo *bdi)
bdi->cluster_size = s->block_size;
- bdi->unallocated_blocks_are_zero =
- (s->params.data_bits & VHDX_PARAMS_HAS_PARENT) == 0;
-
return 0;
}
diff --git a/block/vpc.c b/block/vpc.c
index c055591641..01fcd37e3c 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -606,7 +606,6 @@ static int vpc_get_info(BlockDriverState *bs,
BlockDriverInfo *bdi)
bdi->cluster_size = s->block_size;
}
- bdi->unallocated_blocks_are_zero = true;
return 0;
}
@@ -745,7 +744,7 @@ static int coroutine_fn
vpc_co_block_status(BlockDriverState *bs,
image_offset = get_image_offset(bs, offset, false, NULL);
allocated = (image_offset != -1);
*pnum = 0;
- ret = 0;
+ ret = BDRV_BLOCK_ZERO;
do {
/* All sectors in a block are contiguous (without using the bitmap) */
diff --git a/block/vvfat.c b/block/vvfat.c
index c65a98e3ee..2eb8cbb19f 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -140,48 +140,16 @@ static inline void* array_insert(array_t* array,unsigned
int index,unsigned int
return array->pointer+index*array->item_size;
}
-/* this performs a "roll", so that the element which was at index_from becomes
- * index_to, but the order of all other elements is preserved. */
-static inline int array_roll(array_t* array,int index_to,int index_from,int
count)
-{
- char* buf;
- char* from;
- char* to;
- int is;
-
- if(!array ||
- index_to<0 || index_to>=array->next ||
- index_from<0 || index_from>=array->next)
- return -1;
-
- if(index_to==index_from)
- return 0;
-
- is=array->item_size;
- from=array->pointer+index_from*is;
- to=array->pointer+index_to*is;
- buf=g_malloc(is*count);
- memcpy(buf,from,is*count);
-
- if(index_to<index_from)
- memmove(to+is*count,to,from-to);
- else
- memmove(from,from+is*count,to-from);
-
- memcpy(to,buf,is*count);
-
- g_free(buf);
-
- return 0;
-}
-
static inline int array_remove_slice(array_t* array,int index, int count)
{
assert(index >=0);
assert(count > 0);
assert(index + count <= array->next);
- if(array_roll(array,array->next-1,index,count))
- return -1;
+
+ memmove(array->pointer + index * array->item_size,
+ array->pointer + (index + count) * array->item_size,
+ (array->next - index - count) * array->item_size);
+
array->next -= count;
return 0;
}
@@ -520,12 +488,31 @@ static void set_begin_of_direntry(direntry_t* direntry,
uint32_t begin)
direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
}
+static bool valid_filename(const unsigned char *name)
+{
+ unsigned char c;
+ if (!strcmp((const char*)name, ".") || !strcmp((const char*)name, "..")) {
+ return false;
+ }
+ for (; (c = *name); name++) {
+ if (!((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ c > 127 ||
+ strchr("$%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
static uint8_t to_valid_short_char(gunichar c)
{
c = g_unichar_toupper(c);
if ((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
- strchr("$%'-_@~`!(){}^#&", c) != 0) {
+ strchr("$%'-_@~`!(){}^#&", c) != NULL) {
return c;
} else {
return 0;
@@ -2098,6 +2085,10 @@ DLOG(fprintf(stderr, "check direntry %d:\n", i);
print_direntry(direntries + i))
}
lfn.checksum = 0x100; /* cannot use long name twice */
+ if (!valid_filename(lfn.name)) {
+ fprintf(stderr, "Invalid file name\n");
+ goto fail;
+ }
if (path_len + 1 + lfn.len >= PATH_MAX) {
fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
goto fail;
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0bfe46cff9..ac40d79bfa 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -413,7 +413,11 @@ static void save_window(CPUSPARCState *env)
save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
env->wim = new_wim;
#else
- save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
+ /*
+ * cansave is zero if the spill trap handler is triggered by `save` and
+ * nonzero if triggered by a `flushw`
+ */
+ save_window_offset(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
env->cansave++;
env->canrestore--;
#endif
diff --git a/configure b/configure
index 8a65240d4a..ee6c3c6792 100755
--- a/configure
+++ b/configure
@@ -1575,6 +1575,10 @@ for opt do
;;
--enable-vhost-user) vhost_user="yes"
;;
+ --disable-vhost-vdpa) vhost_vdpa="no"
+ ;;
+ --enable-vhost-vdpa) vhost_vdpa="yes"
+ ;;
--disable-vhost-kernel) vhost_kernel="no"
;;
--enable-vhost-kernel) vhost_kernel="yes"
@@ -1883,6 +1887,7 @@ disabled with --disable-FEATURE, default is enabled if
available:
vhost-crypto vhost-user-crypto backend support
vhost-kernel vhost kernel backend support
vhost-user vhost-user backend support
+ vhost-vdpa vhost-vdpa kernel backend support
spice spice
rbd rados block device (rbd)
libiscsi iscsi support
@@ -2394,6 +2399,10 @@ test "$vhost_user" = "" && vhost_user=yes
if test "$vhost_user" = "yes" && test "$mingw32" = "yes"; then
error_exit "vhost-user isn't available on win32"
fi
+test "$vhost_vdpa" = "" && vhost_vdpa=$linux
+if test "$vhost_vdpa" = "yes" && test "$linux" != "yes"; then
+ error_exit "vhost-vdpa is only available on Linux"
+fi
test "$vhost_kernel" = "" && vhost_kernel=$linux
if test "$vhost_kernel" = "yes" && test "$linux" != "yes"; then
error_exit "vhost-kernel is only available on Linux"
@@ -2422,6 +2431,11 @@ test "$vhost_user_fs" = "" && vhost_user_fs=$vhost_user
if test "$vhost_user_fs" = "yes" && test "$vhost_user" = "no"; then
error_exit "--enable-vhost-user-fs requires --enable-vhost-user"
fi
+#vhost-vdpa backends
+test "$vhost_net_vdpa" = "" && vhost_net_vdpa=$vhost_vdpa
+if test "$vhost_net_vdpa" = "yes" && test "$vhost_vdpa" = "no"; then
+ error_exit "--enable-vhost-net-vdpa requires --enable-vhost-vdpa"
+fi
# OR the vhost-kernel and vhost-user values for simplicity
if test "$vhost_net" = ""; then
@@ -3194,6 +3208,13 @@ if ! check_include "ifaddrs.h" ; then
have_ifaddrs_h=no
fi
+#########################################
+# libdrm check
+have_drm_h=no
+if check_include "libdrm/drm.h" ; then
+ have_drm_h=yes
+fi
+
##########################################
# VTE probe
@@ -5134,10 +5155,14 @@ extern int openpty(int *am, int *as, char *name, void
*termp, void *winp);
int main(void) { return openpty(0, 0, 0, 0, 0); }
EOF
-if ! compile_prog "" "" ; then
+have_openpty="no"
+if compile_prog "" "" ; then
+ have_openpty="yes"
+else
if compile_prog "" "-lutil" ; then
libs_softmmu="-lutil $libs_softmmu"
libs_tools="-lutil $libs_tools"
+ have_openpty="yes"
fi
fi
@@ -6936,6 +6961,7 @@ echo "vhost-scsi support $vhost_scsi"
echo "vhost-vsock support $vhost_vsock"
echo "vhost-user support $vhost_user"
echo "vhost-user-fs support $vhost_user_fs"
+echo "vhost-vdpa support $vhost_vdpa"
echo "Trace backends $trace_backends"
if have_backend "simple"; then
echo "Trace output file $trace_file-<pid>"
@@ -7377,9 +7403,15 @@ fi
if test "$have_ifaddrs_h" = "yes" ; then
echo "HAVE_IFADDRS_H=y" >> $config_host_mak
fi
+if test "$have_drm_h" = "yes" ; then
+ echo "HAVE_DRM_H=y" >> $config_host_mak
+fi
if test "$have_broken_size_max" = "yes" ; then
echo "HAVE_BROKEN_SIZE_MAX=y" >> $config_host_mak
fi
+if test "$have_openpty" = "yes" ; then
+ echo "HAVE_OPENPTY=y" >> $config_host_mak
+fi
# Work around a system header bug with some kernel/XFS header
# versions where they both try to define 'struct fsxattr':
@@ -7437,6 +7469,9 @@ fi
if test "$vhost_net_user" = "yes" ; then
echo "CONFIG_VHOST_NET_USER=y" >> $config_host_mak
fi
+if test "$vhost_net_vdpa" = "yes" ; then
+ echo "CONFIG_VHOST_NET_VDPA=y" >> $config_host_mak
+fi
if test "$vhost_crypto" = "yes" ; then
echo "CONFIG_VHOST_CRYPTO=y" >> $config_host_mak
fi
@@ -7452,6 +7487,9 @@ fi
if test "$vhost_user" = "yes" ; then
echo "CONFIG_VHOST_USER=y" >> $config_host_mak
fi
+if test "$vhost_vdpa" = "yes" ; then
+ echo "CONFIG_VHOST_VDPA=y" >> $config_host_mak
+fi
if test "$vhost_user_fs" = "yes" ; then
echo "CONFIG_VHOST_USER_FS=y" >> $config_host_mak
fi
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 4861db810c..564caa1094 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -32,6 +32,7 @@
#include "qemu/uuid.h"
#include "qemu/coroutine.h"
+#include "qemu/bitmap.h"
/*
* Reference for the LUKS format implemented here is
@@ -70,6 +71,9 @@ typedef struct QCryptoBlockLUKSKeySlot
QCryptoBlockLUKSKeySlot;
#define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL
+#define QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS 2000
+#define QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS 40
+
static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = {
'L', 'U', 'K', 'S', 0xBA, 0xBE
};
@@ -219,6 +223,9 @@ struct QCryptoBlockLUKS {
/* Hash algorithm used in pbkdf2 function */
QCryptoHashAlgorithm hash_alg;
+
+ /* Name of the secret that was used to open the image */
+ char *secret;
};
@@ -720,7 +727,7 @@ qcrypto_block_luks_store_key(QCryptoBlock *block,
Error **errp)
{
QCryptoBlockLUKS *luks = block->opaque;
- QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx];
+ QCryptoBlockLUKSKeySlot *slot;
g_autofree uint8_t *splitkey = NULL;
size_t splitkeylen;
g_autofree uint8_t *slotkey = NULL;
@@ -730,6 +737,8 @@ qcrypto_block_luks_store_key(QCryptoBlock *block,
uint64_t iters;
int ret = -1;
+ assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
+ slot = &luks->header.key_slots[slot_idx];
if (qcrypto_random_bytes(slot->salt,
QCRYPTO_BLOCK_LUKS_SALT_LEN,
errp) < 0) {
@@ -890,7 +899,7 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
Error **errp)
{
QCryptoBlockLUKS *luks = block->opaque;
- const QCryptoBlockLUKSKeySlot *slot = &luks->header.key_slots[slot_idx];
+ const QCryptoBlockLUKSKeySlot *slot;
g_autofree uint8_t *splitkey = NULL;
size_t splitkeylen;
g_autofree uint8_t *possiblekey = NULL;
@@ -900,6 +909,8 @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
g_autoptr(QCryptoIVGen) ivgen = NULL;
size_t niv;
+ assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
+ slot = &luks->header.key_slots[slot_idx];
if (slot->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {
return 0;
}
@@ -1069,6 +1080,126 @@ qcrypto_block_luks_find_key(QCryptoBlock *block,
return -1;
}
+/*
+ * Returns true if a slot i is marked as active
+ * (contains encrypted copy of the master key)
+ */
+static bool
+qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks,
+ unsigned int slot_idx)
+{
+ uint32_t val;
+
+ assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
+ val = luks->header.key_slots[slot_idx].active;
+ return val == QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
+}
+
+/*
+ * Returns the number of slots that are marked as active
+ * (slots that contain encrypted copy of the master key)
+ */
+static unsigned int
+qcrypto_block_luks_count_active_slots(const QCryptoBlockLUKS *luks)
+{
+ size_t i = 0;
+ unsigned int ret = 0;
+
+ for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
+ if (qcrypto_block_luks_slot_active(luks, i)) {
+ ret++;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Finds first key slot which is not active
+ * Returns the key slot index, or -1 if it doesn't exist
+ */
+static int
+qcrypto_block_luks_find_free_keyslot(const QCryptoBlockLUKS *luks)
+{
+ size_t i;
+
+ for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
+ if (!qcrypto_block_luks_slot_active(luks, i)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/*
+ * Erases an keyslot given its index
+ * Returns:
+ * 0 if the keyslot was erased successfully
+ * -1 if a error occurred while erasing the keyslot
+ *
+ */
+static int
+qcrypto_block_luks_erase_key(QCryptoBlock *block,
+ unsigned int slot_idx,
+ QCryptoBlockWriteFunc writefunc,
+ void *opaque,
+ Error **errp)
+{
+ QCryptoBlockLUKS *luks = block->opaque;
+ QCryptoBlockLUKSKeySlot *slot;
+ g_autofree uint8_t *garbagesplitkey = NULL;
+ size_t splitkeylen;
+ size_t i;
+ Error *local_err = NULL;
+ int ret;
+
+ assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
+ slot = &luks->header.key_slots[slot_idx];
+
+ splitkeylen = luks->header.master_key_len * slot->stripes;
+ assert(splitkeylen > 0);
+
+ garbagesplitkey = g_new0(uint8_t, splitkeylen);
+
+ /* Reset the key slot header */
+ memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN);
+ slot->iterations = 0;
+ slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
+
+ ret = qcrypto_block_luks_store_header(block, writefunc,
+ opaque, &local_err);
+
+ if (ret < 0) {
+ error_propagate(errp, local_err);
+ }
+ /*
+ * Now try to erase the key material, even if the header
+ * update failed
+ */
+ for (i = 0; i < QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS; i++) {
+ if (qcrypto_random_bytes(garbagesplitkey,
+ splitkeylen, &local_err) < 0) {
+ /*
+ * If we failed to get the random data, still write
+ * at least zeros to the key slot at least once
+ */
+ error_propagate(errp, local_err);
+
+ if (i > 0) {
+ return -1;
+ }
+ }
+ if (writefunc(block,
+ slot->key_offset_sector * QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
+ garbagesplitkey,
+ splitkeylen,
+ opaque,
+ &local_err) != splitkeylen) {
+ error_propagate(errp, local_err);
+ return -1;
+ }
+ }
+ return ret;
+}
static int
qcrypto_block_luks_open(QCryptoBlock *block,
@@ -1099,6 +1230,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
luks = g_new0(QCryptoBlockLUKS, 1);
block->opaque = luks;
+ luks->secret = g_strdup(options->u.luks.key_secret);
if (qcrypto_block_luks_load_header(block, readfunc, opaque, errp) < 0) {
goto fail;
@@ -1164,6 +1296,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
fail:
qcrypto_block_free_cipher(block);
qcrypto_ivgen_free(block->ivgen);
+ g_free(luks->secret);
g_free(luks);
return -1;
}
@@ -1204,7 +1337,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
if (!luks_opts.has_iter_time) {
- luks_opts.iter_time = 2000;
+ luks_opts.iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS;
}
if (!luks_opts.has_cipher_alg) {
luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256;
@@ -1244,6 +1377,8 @@ qcrypto_block_luks_create(QCryptoBlock *block,
optprefix ? optprefix : "");
goto error;
}
+ luks->secret = g_strdup(options->u.luks.key_secret);
+
password = qcrypto_secret_lookup_as_utf8(luks_opts.key_secret, errp);
if (!password) {
goto error;
@@ -1471,10 +1606,278 @@ qcrypto_block_luks_create(QCryptoBlock *block,
qcrypto_block_free_cipher(block);
qcrypto_ivgen_free(block->ivgen);
+ g_free(luks->secret);
g_free(luks);
return -1;
}
+static int
+qcrypto_block_luks_amend_add_keyslot(QCryptoBlock *block,
+ QCryptoBlockReadFunc readfunc,
+ QCryptoBlockWriteFunc writefunc,
+ void *opaque,
+ QCryptoBlockAmendOptionsLUKS *opts_luks,
+ bool force,
+ Error **errp)
+{
+ QCryptoBlockLUKS *luks = block->opaque;
+ uint64_t iter_time = opts_luks->has_iter_time ?
+ opts_luks->iter_time :
+ QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME_MS;
+ int keyslot;
+ g_autofree char *old_password = NULL;
+ g_autofree char *new_password = NULL;
+ g_autofree uint8_t *master_key = NULL;
+
+ char *secret = opts_luks->has_secret ? opts_luks->secret : luks->secret;
+
+ if (!opts_luks->has_new_secret) {
+ error_setg(errp, "'new-secret' is required to activate a keyslot");
+ return -1;
+ }
+ if (opts_luks->has_old_secret) {
+ error_setg(errp,
+ "'old-secret' must not be given when activating keyslots");
+ return -1;
+ }
+
+ if (opts_luks->has_keyslot) {
+ keyslot = opts_luks->keyslot;
+ if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) {
+ error_setg(errp,
+ "Invalid keyslot %u specified, must be between 0 and
%u",
+ keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1);
+ return -1;
+ }
+ } else {
+ keyslot = qcrypto_block_luks_find_free_keyslot(luks);
+ if (keyslot == -1) {
+ error_setg(errp,
+ "Can't add a keyslot - all keyslots are in use");
+ return -1;
+ }
+ }
+
+ if (!force && qcrypto_block_luks_slot_active(luks, keyslot)) {
+ error_setg(errp,
+ "Refusing to overwrite active keyslot %i - "
+ "please erase it first",
+ keyslot);
+ return -1;
+ }
+
+ /* Locate the password that will be used to retrieve the master key */
+ old_password = qcrypto_secret_lookup_as_utf8(secret, errp);
+ if (!old_password) {
+ return -1;
+ }
+
+ /* Retrieve the master key */
+ master_key = g_new0(uint8_t, luks->header.master_key_len);
+
+ if (qcrypto_block_luks_find_key(block, old_password, master_key,
+ readfunc, opaque, errp) < 0) {
+ error_append_hint(errp, "Failed to retrieve the master key");
+ return -1;
+ }
+
+ /* Locate the new password*/
+ new_password = qcrypto_secret_lookup_as_utf8(opts_luks->new_secret, errp);
+ if (!new_password) {
+ return -1;
+ }
+
+ /* Now set the new keyslots */
+ if (qcrypto_block_luks_store_key(block, keyslot, new_password, master_key,
+ iter_time, writefunc, opaque, errp)) {
+ error_append_hint(errp, "Failed to write to keyslot %i", keyslot);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+qcrypto_block_luks_amend_erase_keyslots(QCryptoBlock *block,
+ QCryptoBlockReadFunc readfunc,
+ QCryptoBlockWriteFunc writefunc,
+ void *opaque,
+ QCryptoBlockAmendOptionsLUKS
*opts_luks,
+ bool force,
+ Error **errp)
+{
+ QCryptoBlockLUKS *luks = block->opaque;
+ g_autofree uint8_t *tmpkey = NULL;
+ g_autofree char *old_password = NULL;
+
+ if (opts_luks->has_new_secret) {
+ error_setg(errp,
+ "'new-secret' must not be given when erasing keyslots");
+ return -1;
+ }
+ if (opts_luks->has_iter_time) {
+ error_setg(errp,
+ "'iter-time' must not be given when erasing keyslots");
+ return -1;
+ }
+ if (opts_luks->has_secret) {
+ error_setg(errp,
+ "'secret' must not be given when erasing keyslots");
+ return -1;
+ }
+
+ /* Load the old password if given */
+ if (opts_luks->has_old_secret) {
+ old_password = qcrypto_secret_lookup_as_utf8(opts_luks->old_secret,
+ errp);
+ if (!old_password) {
+ return -1;
+ }
+
+ /*
+ * Allocate a temporary key buffer that we will need when
+ * checking if slot matches the given old password
+ */
+ tmpkey = g_new0(uint8_t, luks->header.master_key_len);
+ }
+
+ /* Erase an explicitly given keyslot */
+ if (opts_luks->has_keyslot) {
+ int keyslot = opts_luks->keyslot;
+
+ if (keyslot < 0 || keyslot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) {
+ error_setg(errp,
+ "Invalid keyslot %i specified, must be between 0 and
%i",
+ keyslot, QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS - 1);
+ return -1;
+ }
+
+ if (opts_luks->has_old_secret) {
+ int rv = qcrypto_block_luks_load_key(block,
+ keyslot,
+ old_password,
+ tmpkey,
+ readfunc,
+ opaque,
+ errp);
+ if (rv == -1) {
+ return -1;
+ } else if (rv == 0) {
+ error_setg(errp,
+ "Given keyslot %i doesn't contain the given "
+ "old password for erase operation",
+ keyslot);
+ return -1;
+ }
+ }
+
+ if (!force && !qcrypto_block_luks_slot_active(luks, keyslot)) {
+ error_setg(errp,
+ "Given keyslot %i is already erased (inactive) ",
+ keyslot);
+ return -1;
+ }
+
+ if (!force && qcrypto_block_luks_count_active_slots(luks) == 1) {
+ error_setg(errp,
+ "Attempt to erase the only active keyslot %i "
+ "which will erase all the data in the image "
+ "irreversibly - refusing operation",
+ keyslot);
+ return -1;
+ }
+
+ if (qcrypto_block_luks_erase_key(block, keyslot,
+ writefunc, opaque, errp)) {
+ error_append_hint(errp, "Failed to erase keyslot %i", keyslot);
+ return -1;
+ }
+
+ /* Erase all keyslots that match the given old password */
+ } else if (opts_luks->has_old_secret) {
+
+ unsigned long slots_to_erase_bitmap = 0;
+ size_t i;
+ int slot_count;
+
+ assert(QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS <=
+ sizeof(slots_to_erase_bitmap) * 8);
+
+ for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
+ int rv = qcrypto_block_luks_load_key(block,
+ i,
+ old_password,
+ tmpkey,
+ readfunc,
+ opaque,
+ errp);
+ if (rv == -1) {
+ return -1;
+ } else if (rv == 1) {
+ bitmap_set(&slots_to_erase_bitmap, i, 1);
+ }
+ }
+
+ slot_count = bitmap_count_one(&slots_to_erase_bitmap,
+ QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
+ if (slot_count == 0) {
+ error_setg(errp,
+ "No keyslots match given (old) password for erase
operation");
+ return -1;
+ }
+
+ if (!force &&
+ slot_count == qcrypto_block_luks_count_active_slots(luks)) {
+ error_setg(errp,
+ "All the active keyslots match the (old) password that "
+ "was given and erasing them will erase all the data in "
+ "the image irreversibly - refusing operation");
+ return -1;
+ }
+
+ /* Now apply the update */
+ for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
+ if (!test_bit(i, &slots_to_erase_bitmap)) {
+ continue;
+ }
+ if (qcrypto_block_luks_erase_key(block, i, writefunc,
+ opaque, errp)) {
+ error_append_hint(errp, "Failed to erase keyslot %zu", i);
+ return -1;
+ }
+ }
+ } else {
+ error_setg(errp,
+ "To erase keyslot(s), either explicit keyslot index "
+ "or the password currently contained in them must be
given");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+qcrypto_block_luks_amend_options(QCryptoBlock *block,
+ QCryptoBlockReadFunc readfunc,
+ QCryptoBlockWriteFunc writefunc,
+ void *opaque,
+ QCryptoBlockAmendOptions *options,
+ bool force,
+ Error **errp)
+{
+ QCryptoBlockAmendOptionsLUKS *opts_luks = &options->u.luks;
+
+ switch (opts_luks->state) {
+ case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_ACTIVE:
+ return qcrypto_block_luks_amend_add_keyslot(block, readfunc,
+ writefunc, opaque,
+ opts_luks, force, errp);
+ case Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE_INACTIVE:
+ return qcrypto_block_luks_amend_erase_keyslots(block, readfunc,
+ writefunc, opaque,
+ opts_luks, force, errp);
+ default:
+ g_assert_not_reached();
+ }
+}
static int qcrypto_block_luks_get_info(QCryptoBlock *block,
QCryptoBlockInfo *info,
@@ -1523,7 +1926,11 @@ static int qcrypto_block_luks_get_info(QCryptoBlock
*block,
static void qcrypto_block_luks_cleanup(QCryptoBlock *block)
{
- g_free(block->opaque);
+ QCryptoBlockLUKS *luks = block->opaque;
+ if (luks) {
+ g_free(luks->secret);
+ g_free(luks);
+ }
}
@@ -1560,6 +1967,7 @@ qcrypto_block_luks_encrypt(QCryptoBlock *block,
const QCryptoBlockDriver qcrypto_block_driver_luks = {
.open = qcrypto_block_luks_open,
.create = qcrypto_block_luks_create,
+ .amend = qcrypto_block_luks_amend_options,
.get_info = qcrypto_block_luks_get_info,
.cleanup = qcrypto_block_luks_cleanup,
.decrypt = qcrypto_block_luks_decrypt,
diff --git a/crypto/block.c b/crypto/block.c
index 6f42b32f1e..eb057948b5 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -150,6 +150,35 @@
qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
return crypto != NULL;
}
+int qcrypto_block_amend_options(QCryptoBlock *block,
+ QCryptoBlockReadFunc readfunc,
+ QCryptoBlockWriteFunc writefunc,
+ void *opaque,
+ QCryptoBlockAmendOptions *options,
+ bool force,
+ Error **errp)
+{
+ if (options->format != block->format) {
+ error_setg(errp,
+ "Cannot amend encryption format");
+ return -1;
+ }
+
+ if (!block->driver->amend) {
+ error_setg(errp,
+ "Crypto format %s doesn't support format options amendment",
+ QCryptoBlockFormat_str(block->format));
+ return -1;
+ }
+
+ return block->driver->amend(block,
+ readfunc,
+ writefunc,
+ opaque,
+ options,
+ force,
+ errp);
+}
QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
Error **errp)
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
index 71c59cb542..3c7ccea504 100644
--- a/crypto/blockpriv.h
+++ b/crypto/blockpriv.h
@@ -62,6 +62,14 @@ struct QCryptoBlockDriver {
void *opaque,
Error **errp);
+ int (*amend)(QCryptoBlock *block,
+ QCryptoBlockReadFunc readfunc,
+ QCryptoBlockWriteFunc writefunc,
+ void *opaque,
+ QCryptoBlockAmendOptions *options,
+ bool force,
+ Error **errp);
+
int (*get_info)(QCryptoBlock *block,
QCryptoBlockInfo *info,
Error **errp);
diff --git a/docs/interop/index.rst b/docs/interop/index.rst
index 049387ac6d..006f986420 100644
--- a/docs/interop/index.rst
+++ b/docs/interop/index.rst
@@ -20,3 +20,4 @@ Contents:
qemu-ga
vhost-user
vhost-user-gpu
+ vhost-vdpa
diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index 688b7c6900..10e3e3475e 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -816,6 +816,7 @@ Protocol features
#define VHOST_USER_PROTOCOL_F_RESET_DEVICE 13
#define VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS 14
#define VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS 15
+ #define VHOST_USER_PROTOCOL_F_STATUS 16
Master message types
--------------------
@@ -1307,6 +1308,29 @@ Master message types
``VHOST_USER_ADD_MEM_REG`` message, this message is used to set and
update the memory tables of the slave device.
+``VHOST_USER_SET_STATUS``
+ :id: 39
+ :equivalent ioctl: VHOST_VDPA_SET_STATUS
+ :slave payload: N/A
+ :master payload: ``u64``
+
+ When the ``VHOST_USER_PROTOCOL_F_STATUS`` protocol feature has been
+ successfully negotiated, this message is submitted by the master to
+ notify the backend with updated device status as defined in the Virtio
+ specification.
+
+``VHOST_USER_GET_STATUS``
+ :id: 40
+ :equivalent ioctl: VHOST_VDPA_GET_STATUS
+ :slave payload: ``u64``
+ :master payload: N/A
+
+ When the ``VHOST_USER_PROTOCOL_F_STATUS`` protocol feature has been
+ successfully negotiated, this message is submitted by the master to
+ query the backend for its device status as defined in the Virtio
+ specification.
+
+
Slave message types
-------------------
diff --git a/docs/interop/vhost-vdpa.rst b/docs/interop/vhost-vdpa.rst
new file mode 100644
index 0000000000..0c70ba01bc
--- /dev/null
+++ b/docs/interop/vhost-vdpa.rst
@@ -0,0 +1,17 @@
+=====================
+Vhost-vdpa Protocol
+=====================
+
+Introduction
+=============
+vDPA(Virtual data path acceleration) device is a device that uses
+a datapath which complies with the virtio specifications with vendor
+specific control path. vDPA devices can be both physically located on
+the hardware or emulated by software.
+
+This document describes the vDPA support in qemu
+
+Here is the kernel commit here
+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4c8cf31885f69e86be0b5b9e6677a26797365e1d
+
+TODO : More information will add later
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
index 843ae71fc6..58a9aeb851 100644
--- a/docs/system/deprecated.rst
+++ b/docs/system/deprecated.rst
@@ -82,6 +82,15 @@ should specify an ``audiodev=`` property. Additionally,
when using
vnc, you should specify an ``audiodev=`` propery if you plan to
transmit audio through the VNC protocol.
+Creating sound card devices using ``-soundhw`` (since 5.1)
+''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+Sound card devices should be created using ``-device`` instead. The
+names are the same for most devices. The exceptions are ``hda`` which
+needs two devices (``-device intel-hda -device hda-duplex``) and
+``pcspk`` which can be activated using ``-machine
+pcspk-audiodev=<name>``.
+
``-mon ...,control=readline,pretty=on|off`` (since 4.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
@@ -404,6 +413,17 @@ The above, converted to the current supported format::
json:{"file.driver":"rbd", "file.pool":"rbd", "file.image":"name"}
+linux-user mode CPUs
+--------------------
+
+``tilegx`` CPUs (since 5.1.0)
+'''''''''''''''''''''''''''''
+
+The ``tilegx`` guest CPU support (which was only implemented in
+linux-user mode) is deprecated and will be removed in a future version
+of QEMU. Support for this CPU was removed from the upstream Linux
+kernel in 2018, and has also been dropped from glibc.
+
Related binaries
----------------
diff --git a/docs/system/target-i386-desc.rst.inc
b/docs/system/target-i386-desc.rst.inc
index 47a169e0ae..7d1fffacbe 100644
--- a/docs/system/target-i386-desc.rst.inc
+++ b/docs/system/target-i386-desc.rst.inc
@@ -31,6 +31,8 @@ The QEMU PC System emulator simulates the following
peripherals:
- CS4231A compatible sound card
+- PC speaker
+
- PCI UHCI, OHCI, EHCI or XHCI USB controller and a virtual USB-1.1
hub.
@@ -49,7 +51,7 @@ must be told to not have parallel ports to have working GUS.
.. parsed-literal::
- |qemu_system_x86| dos.img -soundhw gus -parallel none
+ |qemu_system_x86| dos.img -device gus -parallel none
Alternatively:
@@ -60,3 +62,12 @@ Alternatively:
Or some other unclaimed IRQ.
CS4231A is the chip used in Windows Sound System and GUSMAX products
+
+The PC speaker audio device can be configured using the pcspk-audiodev
+machine property, i.e.
+
+.. parsed-literal::
+
+ |qemu_system_x86| some.img \
+ -audiodev <backend>,id=<name> \
+ -machine pcspk-audiodev=<name>
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 7f0737488a..e33f5575e3 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -253,11 +253,14 @@ Command description:
.. program:: qemu-img-commands
-.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t
CACHE] -o OPTIONS FILENAME
+.. option:: amend [--object OBJECTDEF] [--image-opts] [-p] [-q] [-f FMT] [-t
CACHE] [--force] -o OPTIONS FILENAME
Amends the image format specific *OPTIONS* for the image file
*FILENAME*. Not all file formats support this operation.
+ --force allows some unsafe operations. Currently for -f luks, it allows to
+ erase the last encryption key, and to overwrite an active encryption key.
+
.. option:: bench [-c COUNT] [-d DEPTH] [-f FMT]
[--flush-interval=FLUSH_INTERVAL] [-i AIO] [-n] [--no-drain] [-o OFFSET]
[--pattern=PATTERN] [-q] [-s BUFFER_SIZE] [-S STEP_SIZE] [-t CACHE] [-w] [-U]
FILENAME
Run a simple sequential I/O benchmark on the specified image. If ``-w`` is
diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst
index 378594c422..824e713491 100644
--- a/docs/tools/virtiofsd.rst
+++ b/docs/tools/virtiofsd.rst
@@ -54,6 +54,11 @@ Options
* flock|no_flock -
Enable/disable flock. The default is ``no_flock``.
+ * modcaps=CAPLIST
+ Modify the list of capabilities allowed; CAPLIST is a colon separated
+ list of capabilities, each preceded by either + or -, e.g.
+ ''+sys_admin:-chown''.
+
* log_level=LEVEL -
Print only log messages matching LEVEL or more severe. LEVEL is one of
``err``, ``warn``, ``info``, or ``debug``. The default is ``info``.
diff --git a/exec.c b/exec.c
index 21926dc9c7..893636176e 100644
--- a/exec.c
+++ b/exec.c
@@ -4115,4 +4115,56 @@ void mtree_print_dispatch(AddressSpaceDispatch *d,
MemoryRegion *root)
}
}
+/*
+ * If positive, discarding RAM is disabled. If negative, discarding RAM is
+ * required to work and cannot be disabled.
+ */
+static int ram_block_discard_disabled;
+
+int ram_block_discard_disable(bool state)
+{
+ int old;
+
+ if (!state) {
+ atomic_dec(&ram_block_discard_disabled);
+ return 0;
+ }
+
+ do {
+ old = atomic_read(&ram_block_discard_disabled);
+ if (old < 0) {
+ return -EBUSY;
+ }
+ } while (atomic_cmpxchg(&ram_block_discard_disabled, old, old + 1) != old);
+ return 0;
+}
+
+int ram_block_discard_require(bool state)
+{
+ int old;
+
+ if (!state) {
+ atomic_inc(&ram_block_discard_disabled);
+ return 0;
+ }
+
+ do {
+ old = atomic_read(&ram_block_discard_disabled);
+ if (old > 0) {
+ return -EBUSY;
+ }
+ } while (atomic_cmpxchg(&ram_block_discard_disabled, old, old - 1) != old);
+ return 0;
+}
+
+bool ram_block_discard_is_disabled(void)
+{
+ return atomic_read(&ram_block_discard_disabled) > 0;
+}
+
+bool ram_block_discard_is_required(void)
+{
+ return atomic_read(&ram_block_discard_disabled) < 0;
+}
+
#endif
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index 6446034711..51b2f256ec 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -427,6 +427,9 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error
**errp)
FSL_IMX6UL_ENET2_TIMER_IRQ,
};
+ object_property_set_uint(OBJECT(&s->eth[i]),
+ s->phy_num[i],
+ "phy-num", &error_abort);
object_property_set_uint(OBJECT(&s->eth[i]),
FSL_IMX6UL_ETH_NUM_TX_RINGS,
"tx-ring-num", &error_abort);
@@ -607,10 +610,17 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error
**errp)
FSL_IMX6UL_OCRAM_ALIAS_ADDR, &s->ocram_alias);
}
+static Property fsl_imx6ul_properties[] = {
+ DEFINE_PROP_UINT32("fec1-phy-num", FslIMX6ULState, phy_num[0], 0),
+ DEFINE_PROP_UINT32("fec2-phy-num", FslIMX6ULState, phy_num[1], 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void fsl_imx6ul_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ device_class_set_props(dc, fsl_imx6ul_properties);
dc->realize = fsl_imx6ul_realize;
dc->desc = "i.MX6UL SOC";
/* Reason: Uses serial_hds and nd_table in realize() directly */
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
index 2f845cedfc..9033d3f8f3 100644
--- a/hw/arm/mcimx6ul-evk.c
+++ b/hw/arm/mcimx6ul-evk.c
@@ -40,6 +40,8 @@ static void mcimx6ul_evk_init(MachineState *machine)
s = FSL_IMX6UL(object_new(TYPE_FSL_IMX6UL));
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
+ object_property_set_uint(OBJECT(s), 2, "fec1-phy-num", &error_fatal);
+ object_property_set_uint(OBJECT(s), 1, "fec2-phy-num", &error_fatal);
qdev_realize(DEVICE(s), NULL, &error_fatal);
memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_MMDC_ADDR,
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index 105c5e63f2..ceee6aa48d 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -11,6 +11,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/module.h"
+#include "qemu/log.h"
#include "cpu.h"
#include "hw/arm/pxa.h"
#include "hw/sysbus.h"
@@ -166,7 +167,9 @@ static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr
offset,
case ICHP: /* Highest Priority register */
return pxa2xx_pic_highest(s);
default:
- printf("%s: Bad register offset " REG_FMT "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pxa2xx_pic_mem_read: bad register offset 0x%"
HWADDR_PRIx
+ "\n", offset);
return 0;
}
}
@@ -199,7 +202,9 @@ static void pxa2xx_pic_mem_write(void *opaque, hwaddr
offset,
s->priority[32 + ((offset - IPR32) >> 2)] = value & 0x8000003f;
break;
default:
- printf("%s: Bad register offset " REG_FMT "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "pxa2xx_pic_mem_write: bad register offset 0x%"
+ HWADDR_PRIx "\n", offset);
return;
}
pxa2xx_pic_update(opaque);
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index fc18212e68..f020aff974 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -23,36 +23,66 @@
#include "hw/ssi/ssi.h"
#include "hw/block/flash.h"
#include "qemu/timer.h"
+#include "qemu/log.h"
#include "hw/arm/sharpsl.h"
#include "ui/console.h"
#include "hw/audio/wm8750.h"
#include "audio/audio.h"
#include "hw/boards.h"
#include "hw/sysbus.h"
+#include "hw/misc/max111x.h"
#include "migration/vmstate.h"
#include "exec/address-spaces.h"
#include "cpu.h"
-#undef REG_FMT
-#define REG_FMT "0x%02lx"
+enum spitz_model_e { spitz, akita, borzoi, terrier };
+
+typedef struct {
+ MachineClass parent;
+ enum spitz_model_e model;
+ int arm_id;
+} SpitzMachineClass;
+
+typedef struct {
+ MachineState parent;
+ PXA2xxState *mpu;
+ DeviceState *mux;
+ DeviceState *lcdtg;
+ DeviceState *ads7846;
+ DeviceState *max1111;
+ DeviceState *scp0;
+ DeviceState *scp1;
+ DeviceState *misc_gpio;
+} SpitzMachineState;
+
+#define TYPE_SPITZ_MACHINE "spitz-common"
+#define SPITZ_MACHINE(obj) \
+ OBJECT_CHECK(SpitzMachineState, obj, TYPE_SPITZ_MACHINE)
+#define SPITZ_MACHINE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SpitzMachineClass, obj, TYPE_SPITZ_MACHINE)
+#define SPITZ_MACHINE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SpitzMachineClass, klass, TYPE_SPITZ_MACHINE)
+
+#define zaurus_printf(format, ...) \
+ fprintf(stderr, "%s: " format, __func__, ##__VA_ARGS__)
/* Spitz Flash */
-#define FLASH_BASE 0x0c000000
-#define FLASH_ECCLPLB 0x00 /* Line parity 7 - 0 bit */
-#define FLASH_ECCLPUB 0x04 /* Line parity 15 - 8 bit */
-#define FLASH_ECCCP 0x08 /* Column parity 5 - 0 bit */
-#define FLASH_ECCCNTR 0x0c /* ECC byte counter */
-#define FLASH_ECCCLRR 0x10 /* Clear ECC */
-#define FLASH_FLASHIO 0x14 /* Flash I/O */
-#define FLASH_FLASHCTL 0x18 /* Flash Control */
-
-#define FLASHCTL_CE0 (1 << 0)
-#define FLASHCTL_CLE (1 << 1)
-#define FLASHCTL_ALE (1 << 2)
-#define FLASHCTL_WP (1 << 3)
-#define FLASHCTL_CE1 (1 << 4)
-#define FLASHCTL_RYBY (1 << 5)
-#define FLASHCTL_NCE (FLASHCTL_CE0 | FLASHCTL_CE1)
+#define FLASH_BASE 0x0c000000
+#define FLASH_ECCLPLB 0x00 /* Line parity 7 - 0 bit */
+#define FLASH_ECCLPUB 0x04 /* Line parity 15 - 8 bit */
+#define FLASH_ECCCP 0x08 /* Column parity 5 - 0 bit */
+#define FLASH_ECCCNTR 0x0c /* ECC byte counter */
+#define FLASH_ECCCLRR 0x10 /* Clear ECC */
+#define FLASH_FLASHIO 0x14 /* Flash I/O */
+#define FLASH_FLASHCTL 0x18 /* Flash Control */
+
+#define FLASHCTL_CE0 (1 << 0)
+#define FLASHCTL_CLE (1 << 1)
+#define FLASHCTL_ALE (1 << 2)
+#define FLASHCTL_WP (1 << 3)
+#define FLASHCTL_CE1 (1 << 4)
+#define FLASHCTL_RYBY (1 << 5)
+#define FLASHCTL_NCE (FLASHCTL_CE0 | FLASHCTL_CE1)
#define TYPE_SL_NAND "sl-nand"
#define SL_NAND(obj) OBJECT_CHECK(SLNANDState, (obj), TYPE_SL_NAND)
@@ -74,12 +104,12 @@ static uint64_t sl_read(void *opaque, hwaddr addr,
unsigned size)
int ryby;
switch (addr) {
-#define BSHR(byte, from, to) ((s->ecc.lp[byte] >> (from - to)) & (1 << to))
+#define BSHR(byte, from, to) ((s->ecc.lp[byte] >> (from - to)) & (1 << to))
case FLASH_ECCLPLB:
return BSHR(0, 4, 0) | BSHR(0, 5, 2) | BSHR(0, 6, 4) | BSHR(0, 7, 6) |
BSHR(1, 4, 1) | BSHR(1, 5, 3) | BSHR(1, 6, 5) | BSHR(1, 7, 7);
-#define BSHL(byte, from, to) ((s->ecc.lp[byte] << (to - from)) & (1 << to))
+#define BSHL(byte, from, to) ((s->ecc.lp[byte] << (to - from)) & (1 << to))
case FLASH_ECCLPUB:
return BSHL(0, 0, 0) | BSHL(0, 1, 2) | BSHL(0, 2, 4) | BSHL(0, 3, 6) |
BSHL(1, 0, 1) | BSHL(1, 1, 3) | BSHL(1, 2, 5) | BSHL(1, 3, 7);
@@ -105,7 +135,9 @@ static uint64_t sl_read(void *opaque, hwaddr addr, unsigned
size)
return ecc_digest(&s->ecc, nand_getio(s->nand));
default:
- zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned
long)addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "sl_read: bad register offset 0x%02" HWADDR_PRIx "\n",
+ addr);
}
return 0;
}
@@ -136,7 +168,9 @@ static void sl_write(void *opaque, hwaddr addr,
break;
default:
- zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned
long)addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "sl_write: bad register offset 0x%02" HWADDR_PRIx "\n",
+ addr);
}
}
@@ -191,8 +225,8 @@ static void sl_nand_realize(DeviceState *dev, Error **errp)
/* Spitz Keyboard */
-#define SPITZ_KEY_STROBE_NUM 11
-#define SPITZ_KEY_SENSE_NUM 7
+#define SPITZ_KEY_STROBE_NUM 11
+#define SPITZ_KEY_SENSE_NUM 7
static const int spitz_gpio_key_sense[SPITZ_KEY_SENSE_NUM] = {
12, 17, 91, 34, 36, 38, 39
@@ -214,11 +248,11 @@ static int spitz_keymap[SPITZ_KEY_SENSE_NUM +
1][SPITZ_KEY_STROBE_NUM] = {
{ 0x52, 0x43, 0x01, 0x47, 0x49, -1 , -1 , -1 , -1 , -1 , -1 },
};
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |