Compare commits

..

75 Commits

Author SHA1 Message Date
Michael Roth
0d83fccb4f Update version for 2.7.1 release
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-23 09:38:06 -06:00
Ashijeet Acharya
4dde694191 ide: Fix memory leak in ide_register_restart_cb()
Fix a memory leak in ide_register_restart_cb() in hw/ide/core.c and add
idebus_unrealize() in hw/ide/qdev.c to have calls to
qemu_del_vm_change_state_handler() to deal with the dangling change
state handler during hot-unplugging ide devices which might lead to a
crash.

Signed-off-by: Ashijeet Acharya <ashijeetacharya@gmail.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1474995212-10580-1-git-send-email-ashijeetacharya@gmail.com
[Minor whitespace fix --js]
Signed-off-by: John Snow <jsnow@redhat.com>
(cherry picked from commit ca44141d5f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-21 10:49:48 -06:00
Marc-André Lureau
7d17d68971 portio: keep references on portio
The isa_register_portio_list() function allocates ioports
data/state. Let's keep the reference to this data on some owner.  This
isn't enough to fix leaks, but at least, ASAN stops complaining of
direct leaks. Further cleanup would require calling
portio_list_del/destroy().

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit e305a16510)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-21 10:08:19 -06:00
John Snow
345f1cd9f6 block-backend: Always notify on blk_eject
blk_eject is only used by scsi-disk and atapi, and in both cases we
only attempt to invoke blk_eject if we have a bona-fide change in
tray state.

The "issue" here is that the tray state does not generate a QMP event
unless there is a medium/BDS attached to the device, so if libvirt et al
are waiting for a tray event to occur from an empty-but-closed drive,
software opening that drive will not emit an event and libvirt will
wait forever.

Change this by modifying blk_eject to always emit an event, instead of
conditionally on a "real" backend eject.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1373264

Reported-by: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 1478553214-497-2-git-send-email-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
(cherry picked from commit c47ee043dc)

* dropped functional depedenecy on 2d76e724

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-21 09:59:57 -06:00
Mark Cave-Ayland
8d5f2a7570 dma-helpers: explicitly pass alignment into DMA helpers
The hard-coded default alignment is BDRV_SECTOR_SIZE, however this is not
necessarily the case for all platforms. Use this as the default alignment for
all current callers.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Eric Blake <eblake@redhat.com>
Acked-by: John Snow <jsnow@redhat.com>
Message-id: 1476445266-27503-2-git-send-email-mark.cave-ayland@ilande.co.uk
Signed-off-by: John Snow <jsnow@redhat.com>
(cherry picked from commit 99868af3d0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-21 09:27:59 -06:00
John Snow
5f20161cf3 atapi: classify read_cd as conditionally returning data
For the purposes of byte_count_limit verification, add a new flag that
identifies read_cd as sometimes returning data, then check the BCL in
its command handler after we know that it will indeed return data.

Reported-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-id: 1477970211-25754-2-git-send-email-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
(cherry picked from commit e7bd708ec8)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-20 19:33:05 -06:00
Stefan Hajnoczi
05838b4688 ui/gtk: fix "Copy" menu item segfault
The "Copy" menu item copies VTE terminal text to the clipboard.  This
only works with VTE terminals, not with graphics consoles.

Disable the menu item when the current notebook page isn't a VTE
terminal.

This patch fixes a segfault.  Reproducer: Start QEMU and click the Copy
menu item when the guest display is visible.

Reported-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Tested-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20161214142518.10504-1-stefanha@redhat.com
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit a08156321a)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-20 19:31:47 -06:00
Thorsten Kohfeldt
223d1a2da1 vfio/pci: Fix vfio_rtl8168_quirk_data_read address offset
Introductory comment for rtl8168 VFIO MSI-X quirk states:
At BAR2 offset 0x70 there is a dword data register,
         offset 0x74 is a dword address register.
vfio: vfio_bar_read(0000:05:00.0:BAR2+0x70, 4) = 0xfee00398 // read data

Thus, correct offset for data read is 0x70,
but function vfio_rtl8168_quirk_data_read() wrongfully uses offset 0x74.

Signed-off-by: Thorsten Kohfeldt <thorsten.kohfeldt@gmx.de>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
(cherry picked from commit 31e6a7b17b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-14 16:34:09 -06:00
7f7ac2141e msmouse: Fix segfault caused by free the chr before chardev cleanup.
Segfault happens when leaving qemu with msmouse backend:

 #0  0x00007fa8526ac975 in raise () at /lib64/libc.so.6
 #1  0x00007fa8526add8a in abort () at /lib64/libc.so.6
 #2  0x0000558be78846ab in error_exit (err=16, msg=0x558be799da10 ...
 #3  0x0000558be7884717 in qemu_mutex_destroy (mutex=0x558be93be750) at ...
 #4  0x0000558be7549951 in qemu_chr_free_common (chr=0x558be93be750) at ...
 #5  0x0000558be754999c in qemu_chr_free (chr=0x558be93be750) at ...
 #6  0x0000558be7549a20 in qemu_chr_delete (chr=0x558be93be750) at ...
 #7  0x0000558be754a8ef in qemu_chr_cleanup () at qemu-char.c:4643
 #8  0x0000558be755843e in main (argc=5, argv=0x7ffe925d7118, ...

The chr was freed by msmouse close callback before chardev cleanup,
Then qemu_mutex_destroy triggered raise().

Because freeing chr is handled by qemu_chr_free_common, Remove the free from
msmouse_chr_close to avoid double free.

Fixes: c1111a24a3
Cc: qemu-stable@nongnu.org
Signed-off-by: Lin Ma <lma@suse.com>
Message-Id: <20160915143158.4796-1-lma@suse.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 9e14037f05)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-14 16:34:09 -06:00
Paolo Bonzini
db1604cd60 Revert "megasas: remove useless check for cmd->frame"
This reverts commit 8cc46787b5.
It turns out that cmd->frame can be NULL and thus the commit
can cause a SIGSEGV

Reported-by: Holger Schranz <holger@fam-schranz.de>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 421cc3e7e8)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 18:15:33 -06:00
Eduardo Habkost
cc1fd25295 vl: Delay initialization of memory backends
Initialization of memory backends may take a while when
prealloc=yes is used, depending on their size. Initializing
memory backends before chardevs may delay the creation of monitor
sockets, and trigger timeouts on management software that waits
until the monitor socket is created by QEMU. See, for example,
the bug report at:
https://bugzilla.redhat.com/show_bug.cgi?id=1371211

In addition to that, allocating memory before calling
configure_accelerator() breaks the tcg_enabled() checks at
memory_region_init_*().

This patch fixes those problems by adding "memory-backend-*"
classes to the delayed-initialization list.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
(cherry picked from commit 6546d0dba6)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 18:13:21 -06:00
Eduardo Habkost
ee99e42be4 vhost-user-test: Use libqos instead of pxe-virtio.rom
vhost-user-test relies on iPXE just to initialize the virtio-net
device, and doesn't do any actual packet tx/rx testing.

In addition to that, the test relies on TCG, which is
imcompatible with vhost. The test only worked by accident: a bug
the memory backend initialization made memory regions not have
the DIRTY_MEMORY_CODE bit set in dirty_log_mask.

This changes vhost-user-test to initialize the virtio-net device
using libqos, and not use TCG nor pxe-virtio.rom.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
(cherry picked from commit cdafe92961)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 18:13:02 -06:00
Peter Xu
0ef167c907 intel_iommu: fix incorrect device invalidate
"mask" needs to be inverted before use.

Signed-off-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 6cb99acc28)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 18:06:43 -06:00
Adrian Bunk
248a780fd3 rules.mak: Use -r instead of -Wl, -r to fix building when PIE is default
Building qemu fails in distributions where gcc enables PIE by default
(e.g. Debian unstable) with:

/usr/bin/ld: -r and -pie may not be used together

Use -r instead of -Wl,-r to avoid gcc passing -pie to the linker
when PIE is enabled and a relocatable object is passed.

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Message-Id: <20161127162817.15144-1-bunk@stusta.de>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit c96f0ee6a6)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 18:05:55 -06:00
Peter Xu
80f630be21 pci-assign: sync MSI/MSI-X cap and table with PCIDevice
Since commit e1d4fb2d ("kvm-irqchip: x86: add msi route notify fn"),
kvm_irqchip_add_msi_route() starts to use pci_get_msi_message() to fetch
MSI info. This requires that we setup MSI related fields in PCIDevice.
For most devices, that won't be a problem, as long as we are using
general interfaces like msi_init()/msix_init().

However, for pci-assign devices, MSI/MSI-X is treated differently - PCI
assign devices are maintaining its own MSI table and cap information in
AssignedDevice struct. however that's not synced up with PCIDevice's
fields. That will leads to pci_get_msi_message() failed to find correct
MSI capability, even with an NULL msix_table.

A quick fix is to sync up the two places: both the capability bits and
table address for MSI/MSI-X.

Reported-by: Changlimin <changlimin@h3c.com>
Tested-by: Changlimin <changlimin@h3c.com>
Cc: qemu-stable@nongnu.org
Fixes: e1d4fb2d ("kvm-irqchip: x86: add msi route notify fn")
Signed-off-by: Peter Xu <peterx@redhat.com>

Message-Id: <1480042522-16551-1-git-send-email-peterx@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 64e184e260)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 18:04:19 -06:00
Zhuang Yanying
353801cde4 ivshmem: Fix 64 bit memory bar configuration
Device ivshmem property use64=0 is designed to make the device
expose a 32 bit shared memory BAR instead of 64 bit one.  The
default is a 64 bit BAR, except pc-1.2 and older retain a 32 bit
BAR.  A 32 bit BAR can support only up to 1 GiB of shared memory.

This worked as designed until commit 5400c02 accidentally flipped
its sense: since then, we misinterpret use64=0 as use64=1 and vice
versa.  Worse, the default got flipped as well.  Devices
ivshmem-plain and ivshmem-doorbell are not affected.

Fix by restoring the test of IVShmemState member not_legacy_32bit
that got messed up in commit 5400c02.  Also update its
initialization for devices ivhsmem-plain and ivshmem-doorbell.
Without that, they'd regress to 32 bit BARs.

Cc: qemu-stable@nongnu.org
Signed-off-by: Zhuang Yanying <ann.zhuangyanying@huawei.com>
Reviewed-by: Gonglei <arei.gonglei@huawei.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
(cherry picked from commit be4e0d7375)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:49:41 -06:00
Greg Kurz
c8a3159df4 vhost: drop legacy vring layout bits
The legacy vring layout is not used anymore as we use the separate
mappings even for legacy devices.
This patch simply removes it.

This also fixes a bug with virtio 1 devices when the vring descriptor table
is mapped at a higher address than the used vring because the following
function may return an insanely great value:

hwaddr virtio_queue_get_ring_size(VirtIODevice *vdev, int n)
{
    return vdev->vq[n].vring.used - vdev->vq[n].vring.desc +
           virtio_queue_get_used_size(vdev, n);
}

and the mapping fails.

Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 1cdce7c54d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:49:41 -06:00
Max Reitz
48fdfebab6 block/curl: Do not wait for data beyond EOF
libcurl will only give us as much data as there is, not more. The block
layer will deny requests beyond the end of file for us; but since this
block driver is still using a sector-based interface, we can still get
in trouble if the file size is not a multiple of 512.

While we have already made sure not to attempt transfers beyond the end
of the file, we are currently still trying to receive data from there if
the original request exceeds the file size. This patch fixes this issue
and invokes qemu_iovec_memset() on the iovec's tail.

Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20161025025431.24714-5-mreitz@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
(cherry picked from commit 4e504535c1)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:48:44 -06:00
Max Reitz
6eb194ddd7 block/curl: Remember all sockets
For some connection types (like FTP, generally), more than one socket
may be used (in FTP's case: control vs. data stream). As of commit
838ef60249 ("curl: Eliminate unnecessary
use of curl_multi_socket_all"), we have to remember all of the sockets
used by libcurl, but in fact we only did that for a single one. Since
one libcurl connection may use multiple sockets, however, we have to
remember them all.

Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20161025025431.24714-4-mreitz@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
(cherry picked from commit ff5ca1664a)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:48:44 -06:00
Max Reitz
7e278ef797 block/curl: Fix return value from curl_read_cb
While commit 38bbc0a580 is correct in that
the callback is supposed to return the number of bytes handled; what it
does not mention is that libcurl will throw an error if the callback did
not "handle" all of the data passed to it.

Therefore, if the callback receives some data that it cannot handle
(either because the receive buffer has not been set up yet or because it
would not fit into the receive buffer) and we have to ignore it, we
still have to report that the data has been handled.

Obviously, this should not happen normally. But it does happen at least
for FTP connections where some data (that we do not expect) may be
generated when the connection is established.

Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-id: 20161025025431.24714-3-mreitz@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
(cherry picked from commit 4e7676571b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:48:44 -06:00
Max Reitz
6a5ea68e9e block/curl: Use BDRV_SECTOR_SIZE
Currently, curl defines its own constant SECTOR_SIZE. There is no
advantage over using the global BDRV_SECTOR_SIZE, so drop it.

Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-id: 20161025025431.24714-2-mreitz@redhat.com
Signed-off-by: Jeff Cody <jcody@redhat.com>
(cherry picked from commit 9054d9f6b0)

Conflicts:
	block/curl.c

* drop context dep on fffb6e1 / aio_bh_schedule_oneshot

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:48:44 -06:00
Eric Blake
31454ebde5 block: Pass unaligned discard requests to drivers
Discard is advisory, so rounding the requests to alignment
boundaries is never semantically wrong from the data that
the guest sees.  But at least the Dell Equallogic iSCSI SANs
has an interesting property that its advertised discard
alignment is 15M, yet documents that discarding a sequence
of 1M slices will eventually result in the 15M page being
marked as discarded, and it is possible to observe which
pages have been discarded.

Between commits 9f1963b and b8d0a980, we converted the block
layer to a byte-based interface that ultimately ignores any
unaligned head or tail based on the driver's advertised
discard granularity, which means that qemu 2.7 refuses to
pass any discard request smaller than 15M down to the Dell
Equallogic hardware.  This is a slight regression in behavior
compared to earlier qemu, where a guest executing discards
in power-of-2 chunks used to be able to get every page
discarded, but is now left with various pages still allocated
because the guest requests did not align with the hardware's
15M pages.

Since the SCSI specification says nothing about a minimum
discard granularity, and only documents the preferred
alignment, it is best if the block layer gives the driver
every bit of information about discard requests, rather than
rounding it to alignment boundaries early.

Rework the block layer discard algorithm to mirror the write
zero algorithm: always peel off any unaligned head or tail
and manage that in isolation, then do the bulk of the request
on an aligned boundary.  The fallback when the driver returns
-ENOTSUP for an unaligned request is to silently ignore that
portion of the discard request; but for devices that can pass
the partial request all the way down to hardware, this can
result in the hardware coalescing requests and discarding
aligned pages after all.

Reported by: Peter Lieven <pl@kamp.de>
CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>

(cherry picked from commit 3482b9bc41)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:48:44 -06:00
Eric Blake
5e4eb851dd block: Return -ENOTSUP rather than assert on unaligned discards
Right now, the block layer rounds discard requests, so that
individual drivers are able to assert that discard requests
will never be unaligned.  But there are some ISCSI devices
that track and coalesce multiple unaligned requests, turning it
into an actual discard if the requests eventually cover an
entire page, which implies that it is better to always pass
discard requests as low down the stack as possible.

In isolation, this patch has no semantic effect, since the
block layer currently never passes an unaligned request through.
But the block layer already has code that silently ignores
drivers that return -ENOTSUP for a discard request that cannot
be honored (as well as drivers that return 0 even when nothing
was done).  But the next patch will update the block layer to
fragment discard requests, so that clients are guaranteed that
they are either dealing with an unaligned head or tail, or an
aligned core, making it similar to the block layer semantics of
write zero fragmentation.

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 49228d1e95)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:48:43 -06:00
Eric Blake
dd11d33deb block: Let write zeroes fallback work even with small max_transfer
Commit 443668ca rewrote the write_zeroes logic to guarantee that
an unaligned request never crosses a cluster boundary.  But
in the rewrite, the new code assumed that at most one iteration
would be needed to get to an alignment boundary.

However, it is easy to trigger an assertion failure: the Linux
kernel limits loopback devices to advertise a max_transfer of
only 64k.  Any operation that requires falling back to writes
rather than more efficient zeroing must obey max_transfer during
that fallback, which means an unaligned head may require multiple
iterations of the write fallbacks before reaching the aligned
boundaries, when layering a format with clusters larger than 64k
atop the protocol of file access to a loopback device.

Test case:

$ qemu-img create -f qcow2 -o cluster_size=1M file 10M
$ losetup /dev/loop2 /path/to/file
$ qemu-io -f qcow2 /dev/loop2
qemu-io> w 7m 1k
qemu-io> w -z 8003584 2093056

In fairness to Denis (as the original listed author of the culprit
commit), the faulty logic for at most one iteration is probably all
my fault in reworking his idea.  But the solution is to restore what
was in place prior to that commit: when dealing with an unaligned
head or tail, iterate as many times as necessary while fragmenting
the operation at max_transfer boundaries.

Reported-by: Ed Swierk <eswierk@skyportsystems.com>
CC: qemu-stable@nongnu.org
CC: Denis V. Lunev <den@openvz.org>
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit b2f95feec5)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:48:30 -06:00
Eric Blake
c4bf37e0b0 qcow2: Inform block layer about discard boundaries
At the qcow2 layer, discard is only possible on a per-cluster
basis; at the moment, qcow2 silently rounds any unaligned
requests to this granularity.  However, an upcoming patch will
fix a regression in the block layer ignoring too much of an
unaligned discard request, by changing the block layer to
break up a discard request at alignment boundaries; for that
to work, the block layer must know about our limits.

However, we can't go one step further by changing
qcow2_discard_clusters() to assert that requests are always
aligned, since that helper function is reached on paths
outside of the block layer.

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit ecdbead659)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-12 17:48:19 -06:00
Samuel Thibault
e9dbd28e2a slirp: Fix access to freed memory
if_start() goes through the slirp->if_fastq and slirp->if_batchq
list of pending messages, and accesses ifm->ifq_so->so_nqueued of its
elements if ifm->ifq_so != NULL.  When freeing a socket, we thus need
to make sure that any pending message for this socket does not refer
to the socket any more.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Tested-by: Brian Candler <b.candler@pobox.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit ea64d5f088)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-08 13:56:26 -06:00
Greg Kurz
92230a5963 vhost: adapt vhost_verify_ring_mappings() to virtio 1 ring layout
With virtio 1, the vring layout is split in 3 separate regions of
contiguous memory for the descriptor table, the available ring and the
used ring, as opposed with legacy virtio which uses a single region.

In case of memory re-mapping, the code ensures it doesn't affect the
vring mapping. This is done in vhost_verify_ring_mappings() which assumes
the device is legacy.

This patch changes vhost_verify_ring_mappings() to check the mappings of
each part of the vring separately.

This works for legacy mappings as well.

Cc: qemu-stable@nongnu.org
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit f1f9e6c596)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-08 13:53:11 -06:00
Kevin Wolf
48b3aa20ae block: Don't mark node clean after failed flush
Commit 3ff2f67a changed bdrv_co_flush() so that no flush is issues if
the image hasn't been dirtied since the last flush. This is not quite
correct: The condition should be that the image hasn't been dirtied
since the last _successful_ flush. This patch changes the logic
accordingly.

Without this fix, subsequent bdrv_co_flush() calls would return success
without actually doing anything even though the image is still dirty.
The difference is visible in some blkdebug test cases where error
messages incorrectly disappeared after commit 3ff2f67a.

Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-id: 1478300595-10090-1-git-send-email-kwolf@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit e6af1e0854)

Conflicts:
	block/io.c

* remove context dep on 9972354

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-08 13:50:54 -06:00
Michael S. Tsirkin
f1372d6e14 virtio-net: mark VIRTIO_NET_F_GSO as legacy
virtio 1.0 spec says this is a legacy feature bit,
hide it from guests in modern mode.

Note: for cross-version migration compatibility,
we keep the bit set in host_features.
The result will be that a guest migrating cross-version
will see host features change under it.
As guests only seem to read it once, this should
not be an issue. Meanwhile, will work to fix guests to
ignore this bit in virtio1 mode, too.

Cc: qemu-stable@nongnu.org
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
(cherry picked from commit 2a083ffd2e)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-08 13:50:54 -06:00
Michael S. Tsirkin
63087cd74b virtio: allow per-device-class legacy features
Legacy features are those that transitional devices only
expose on the legacy interface.
Allow different ones per device class.

Cc: qemu-stable@nongnu.org # dependency for the next patch
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
(cherry picked from commit 9b706dbbbb)

Conflicts:
	hw/virtio/virtio.c

* drop context dep on ff4c07df
* resolv func dep on ff4c07df creating vdc variable in
  virtio_device_class_init()

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-08 13:50:54 -06:00
David Gibson
9df69dcd14 target-ppc: Fix CPU migration from qemu-2.6 <-> later versions
When migration for target-ppc was converted to vmstate, several
VMSTATE_EQUAL() checks were foolishly included of things that really
should be internal state.  Specifically we verified equality of the
insns_flags and insns_flags2 fields, which are used within TCG to
determine which groups of instructions are available on this cpu
model.  Between qemu-2.6 and qemu-2.7 we made some changes to these
classes which broke migration.

This path fixes migration both forwards and backwards.  On migration
from 2.6 to later versions we import the fields into teporary
variables, which we then ignore.  In migration backwards, we populate
the temporary fields from the runtime fields, but mask out the bits
which were added after qemu-2.6, allowing the VMSTATE_EQUAL in
qemu-2.6 to accept the stream.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
(cherry picked from commit 16a2497bd4)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-12-02 09:38:26 -06:00
Daniel P. Berrange
95a0638043 net: fix sending of data with -net socket, listen backend
The use of -net socket,listen was broken in the following
commit

  commit 16a3df403b
  Author: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
  Date:   Fri May 13 15:35:19 2016 +0800

    net/net: Add SocketReadState for reuse codes

    This function is from net/socket.c, move it to net.c and net.h.
    Add SocketReadState to make others reuse net_fill_rstate().
    suggestion from jason.

This refactored the state out of NetSocketState into a
separate SocketReadState. This refactoring requires
that a callback is provided to be triggered upon
completion of a packet receive from the guest.

The patch only registered this callback in the codepaths
hit by -net socket,connect, not -net socket,listen. So
as a result packets sent by the guest in the latter case
get dropped on the floor.

This bug is hidden because net_fill_rstate() silently
does nothing if the callback is not set.

This patch adds in the middle callback registration
and also adds an assert so that QEMU aborts if there
are any other codepaths hit which are missing the
callback.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(cherry picked from commit e79cd40680)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-18 19:06:19 -06:00
Corey Minyard
1790a9d77d acpi/ipmi: Initialize the fwinfo before fetching it
The initialization was missed before, resulting in some
bad data in the smbus case.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 698ae42b91)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-18 19:05:21 -06:00
Alex Williamson
1b16ded6a5 memory: Don't use memcpy for ram_device regions
With a vfio assigned device we lay down a base MemoryRegion registered
as an IO region, giving us read & write accessors.  If the region
supports mmap, we lay down a higher priority sub-region MemoryRegion
on top of the base layer initialized as a RAM device pointer to the
mmap.  Finally, if we have any quirks for the device (ie. address
ranges that need additional virtualization support), we put another IO
sub-region on top of the mmap MemoryRegion.  When this is flattened,
we now potentially have sub-page mmap MemoryRegions exposed which
cannot be directly mapped through KVM.

This is as expected, but a subtle detail of this is that we end up
with two different access mechanisms through QEMU.  If we disable the
mmap MemoryRegion, we make use of the IO MemoryRegion and service
accesses using pread and pwrite to the vfio device file descriptor.
If the mmap MemoryRegion is enabled and results in one of these
sub-page gaps, QEMU handles the access as RAM, using memcpy to the
mmap.  Using either pread/pwrite or the mmap directly should be
correct, but using memcpy causes us problems.  I expect that not only
does memcpy not necessarily honor the original width and alignment in
performing a copy, but it potentially also uses processor instructions
not intended for MMIO spaces.  It turns out that this has been a
problem for Realtek NIC assignment, which has such a quirk that
creates a sub-page mmap MemoryRegion access.

To resolve this, we disable memory_access_is_direct() for ram_device
regions since QEMU assumes that it can use memcpy for those regions.
Instead we access through MemoryRegionOps, which replaces the memcpy
with simple de-references of standard sizes to the host memory.

With this patch we attempt to provide unrestricted access to the RAM
device, allowing byte through qword access as well as unaligned
access.  The assumption here is that accesses initiated by the VM are
driven by a device specific driver, which knows the device
capabilities.  If unaligned accesses are not supported by the device,
we don't want them to work in a VM by performing multiple aligned
accesses to compose the unaligned access.  A down-side of this
philosophy is that the xp command from the monitor attempts to use
the largest available access weidth, unaware of the underlying
device.  Using memcpy had this same restriction, but at least now an
operator can dump individual registers, even if blocks of device
memory may result in access widths beyond the capabilities of a
given device (RTL NICs only support up to dword).

Reported-by: Thorsten Kohfeldt <thorsten.kohfeldt@gmx.de>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 4a2e242bbb)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 18:19:01 -05:00
Alex Williamson
ca83f87a66 memory: Replace skip_dump flag with "ram_device"
Setting skip_dump on a MemoryRegion allows us to modify one specific
code path, but the restriction we're trying to address encompasses
more than that.  If we have a RAM MemoryRegion backed by a physical
device, it not only restricts our ability to dump that region, but
also affects how we should manipulate it.  Here we recognize that
MemoryRegions do not change to sometimes allow dumps and other times
not, so we replace setting the skip_dump flag with a new initializer
so that we know exactly the type of region to which we're applying
this behavior.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 21e00fa55f)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 18:19:01 -05:00
Prasad J Pandit
2817466c55 net: rtl8139: limit processing of ring descriptors
RTL8139 ethernet controller in C+ mode supports multiple
descriptor rings, each with maximum of 64 descriptors. While
processing transmit descriptor ring in 'rtl8139_cplus_transmit',
it does not limit the descriptor count and runs forever. Add
check to avoid it.

Reported-by: Andrew Henderson <hendersa@icculus.org>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(cherry picked from commit c7c3591669)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 18:19:01 -05:00
Alberto Garcia
e389e44a35 qemu-iotests: Test I/O in a single drive from a throttling group
iotest 093 contains a test that creates a throttling group with
several drives and performs I/O in all of them. This patch adds a new
test that creates a similar setup but only performs I/O in one of the
drives at the same time.

This is useful to test that the round robin algorithm is behaving
properly in these scenarios, and is specifically written using the
regression introduced in 27ccdd5259 as an example.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit a26ddb4396)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 18:19:00 -05:00
Alberto Garcia
b1fdc94193 throttle: Correct access to wrong BlockBackendPublic structures
In 27ccdd5259 the throttling fields were
moved from BlockDriverState to BlockBackend. However in a few cases
the code started using throttling fields from the active BlockBackend
instead of the round-robin token, making the algorithm behave
incorrectly.

This can cause starvation if there's a throttling group with several
drives but only one of them has I/O.

Cc: qemu-stable@nongnu.org
Reported-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 6bf77e1c2d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 18:19:00 -05:00
Thomas Huth
61781984db ppc/kvm: Mark 64kB page size support as disabled if not available
QEMU currently refuses to start with KVM-PR and only prints out

	qemu: fatal: Unknown MMU model 851972

when being started there. This is because commit 4322e8ced5
("ppc: Fix 64K pages support in full emulation") introduced a new
POWERPC_MMU_64K bit to indicate support for this page size, but
it never gets cleared on KVM-PR if the host kernel does not support
this. Thus we've got to turn off this bit in the mmu_model for KVM-PR.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 0d594f5565)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 18:19:00 -05:00
Paolo Bonzini
857efecf91 rbd: shift byte count as a 64-bit value
Otherwise, reads of more than 2GB fail.  Until commit
7bbca9e290, reads of 2^41
bytes succeeded at least theoretically.

In fact, pdiscard ought to receive a 64-bit integer as the
count for the same reason.

Reported by Coverity.

Fixes: 7bbca9e290
Cc: qemu-stable@nongnu.org
Cc: kwolf@redhat.com
Cc: eblake@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit e948f663e9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 18:19:00 -05:00
Markus Armbruster
99837b0d36 tests/test-qmp-input-strict: Cover missing struct members
These tests would have caught the bug fixed by the previous commit.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1475594630-24758-1-git-send-email-armbru@redhat.com>
(cherry picked from commit bce3035a44)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 18:19:00 -05:00
Marc-André Lureau
b34c7bd463 qapi: Fix crash when 'any' or 'null' parameter is missing
Unlike the other visit methods, visit_type_any() and visit_type_null()
neglect to check whether qmp_input_get_object() succeeded.  They crash
when it fails.  Reproducer:

{ "execute": "qom-set",
  "arguments": { "path": "/machine", "property": "rtc-time" } }

Will crash with:

qapi/qapi-visit-core.c:277: visit_type_any: Assertion `!err != !*obj'
failed

Broken in commit 5c678ee.  Fix by adding the missing error checks.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20160922203927.28241-3-marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Commit message rephrased]
Signed-off-by: Markus Armbruster <armbru@redhat.com>

(cherry picked from commit c489780203)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 18:18:54 -05:00
Marc-André Lureau
f3467f56c1 qmp: fix object-add assert() without props
Since commit ad739706bb, user_creatable_add_type() expects to be
given a qdict. However, if object-add is called without props, you reach
the assert: "qemu/qom/object_interfaces.c:115: user_creatable_add_type:
Assertion `qdict' failed.", because the qdict isn't created in this
case (it's optional).

Furthermore, qmp_input_visitor_new() is not meant to be called without a
dict, and a further commit will assert in this situation.

If none given, create an empty qdict in qmp to avoid the
user_creatable_add_type() assert(qdict).

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20160922203927.28241-2-marcandre.lureau@redhat.com>
Tested-by: Xiao Long Jiang <zxiaol@linux.vnet.ibm.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
(cherry picked from commit e64c75a975)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 17:24:25 -05:00
Daniel P. Berrange
5be5335661 char: fix missing return in error path for chardev TLS init
If the qio_channel_tls_new_(server|client) methods fail,
we disconnect the client. Unfortunately a missing return
means we then go on to try and run the TLS handshake on
a NULL I/O channel. This gives predictably segfaulty
results.

The main way to trigger this is to request a bogus TLS
priority string for the TLS credentials. e.g.

  -object tls-creds-x509,id=tls0,priority=wibble,...

Most other ways appear impossible to trigger except
perhaps if OOM conditions cause gnutls initialization
to fail.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 660a2d83e0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 17:16:58 -05:00
Emilio G. Cota
af29bd3193 qht: fix unlock-after-free segfault upon resizing
The old map's bucket locks are being unlocked *after*
that same old map has been passed to RCU for destruction.
This is a bug that can cause a segfault, since there's
no guarantee that the deletion will be deferred (e.g.
there may be no concurrent readers).

The segfault is easily triggered in RHEL6/CentOS6 with qht-test,
particularly on a single-core system or by pinning qht-test
to a single core.

Fix it by unlocking the map's bucket locks right after having
published the new map, and (crucially) before marking the map
for deletion via call_rcu().

While at it, expand qht_do_resize() to atomically do (1) a reset,
(2) a resize, or (3) a reset+resize. This simplifies the calling
code, since the new function (qht_do_resize_reset()) acquires
and releases the buckets' locks.

Note that no qht_do_reset inline is provided, since it would have
no users--qht_reset() already performs a reset without taking
ht->lock.

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Reported-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Emilio G. Cota <cota@braap.org>
Message-Id: <1475706880-10667-3-git-send-email-cota@braap.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 76b553b308)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 17:15:30 -05:00
Emilio G. Cota
f72ca1ac6f qht: simplify qht_reset_size
Sometimes gcc doesn't pick up the fact that 'new' is properly
set if 'resize == true', which may generate an unnecessary
build warning.

Fix it by removing 'resize' and directly checking that 'new'
is non-NULL.

Signed-off-by: Emilio G. Cota <cota@braap.org>
Message-Id: <1475706880-10667-2-git-send-email-cota@braap.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit f555a9d0b3)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 17:14:57 -05:00
Eric Blake
4d45fe11d1 migrate: Fix cpu-throttle-increment regression in HMP
Commit 69ef1f3 accidentally broke migrate_set_parameter's ability
to set the cpu-throttle-increment to anything other than the
default, because it forgot to parse the user's string into an
integer.

CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
(cherry picked from commit bb2b777cf9)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 17:10:51 -05:00
John Snow
4a25ab2a04 block-backend: remove blk_flush_all
We can teach Xen to drain and flush each device as it needs to, instead
of trying to flush ALL devices. This removes the last user of
blk_flush_all.

The function is therefore removed under the premise that any new uses
of blk_flush_all would be the wrong paradigm: either flush the single
device that requires flushing, or use an appropriate flush_all mechanism
from outside of the BlkBackend layer.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Acked-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 49137bf684)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 17:06:27 -05:00
John Snow
95200ebb50 qemu: use bdrv_flush_all for vm_stop et al
Reimplement bdrv_flush_all for vm_stop. In contrast to blk_flush_all,
bdrv_flush_all does not have device model restrictions. This allows
us to flush and halt unconditionally without error.

This allows us to do things like migrate when we have a device with
an open tray, but has a node that may need to be flushed, or nodes
that aren't currently attached to any device and need to be flushed.

Specifically, this allows us to migrate when we have a CDROM with
an open tray.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Acked-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 22af08eacf)
Conflicts:
	cpus.c

* drop context dependancy on 6d0ceb80

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 17:04:56 -05:00
John Snow
8e94512568 block: reintroduce bdrv_flush_all
Commit fe1a9cbc moved the flush_all routine from the bdrv layer to the
block-backend layer. In doing so, however, the semantics of the routine
changed slightly such that flush_all now used blk_flush instead of
bdrv_flush.

blk_flush can fail if the attached device model reports that it is not
"available," (i.e. the tray is open.) This changed the semantics of
flush_all such that it can now fail for e.g. open CDROM drives.

Reintroduce bdrv_flush_all to regain the old semantics without having to
alter the behavior of blk_flush or blk_flush_all, which are already
'doing the right thing.'

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Acked-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 4085f5c7a2)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 17:01:44 -05:00
Eric Blake
d40d148feb iscsi: Fix divide-by-zero regression on raw SG devices
When qemu uses iscsi devices in sg mode, iscsilun->block_size
is left at 0.  Prior to commits cf081fca and similar, when
block limits were tracked in sectors, this did not matter:
various block limits were just left at 0.  But when we started
scaling by block size, this caused SIGFPE.

Then, in a later patch, commit a5b8dd2c added an assertion to
bdrv_open_common() that request_alignment is always non-zero;
which was not true for SG mode.  Rather than relax that assertion,
we can just provide a sane value (we don't know of any SG device
with a block size smaller than qemu's default sizing of 512 bytes).

One possible solution for SG mode is to just blindly skip ALL
of iscsi_refresh_limits(), since we already short circuit so
many other things in sg mode.  But this patch takes a slightly
more conservative approach, and merely guarantees that scaling
will succeed, while still using multiples of the original size
where possible.  Resulting limits may still be zero in SG mode
(that is, we mostly only fix block_size used as a denominator
or which affect assertions, not all uses).

Reported-by: Holger Schranz <holger@fam-schranz.de>
Signed-off-by: Eric Blake <eblake@redhat.com>
CC: qemu-stable@nongnu.org

Message-Id: <1473283640-15756-1-git-send-email-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 95eaa78537)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:53:21 -05:00
Daniel P. Berrange
f9856029d5 qcow2: fix encryption during cow of sectors
Broken in previous commit:

  commit aaa4d20b49
  Author: Kevin Wolf <kwolf@redhat.com>
  Date:   Wed Jun 1 15:21:05 2016 +0200

      qcow2: Make copy_sectors() byte based

The copy_sectors() code was originally using the 'sector'
parameter for encryption, which was passed in by the caller
from the QCowL2Meta.offset field (aka the guest logical
offset).

After the change, the code is using 'cluster_offset' which
was passed in from QCow2L2Meta.alloc_offset field (aka the
host physical offset).

This would cause the data to be encrypted using an incorrect
initialization vector which will in turn cause later reads
to return garbage.

Although current qcow2 built-in encryption is blocked from
usage in the emulator, one could still hit this if writing
to the file via qemu-{img,io,nbd} commands.

Cc: qemu-stable@nongnu.org
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit bb9f8dd0e1)
Conflicts:
	tests/qemu-iotests/group

* drop context dependancy on non-2.7 iotest groups

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:51:20 -05:00
David Gibson
a3a254550b vfio/pci: Fix regression in MSI routing configuration
d1f6af6 "kvm-irqchip: simplify kvm_irqchip_add_msi_route" was a cleanup
of kvmchip routing configuration, that was mostly intended for x86.
However, it also contains a subtle change in behaviour which breaks EEH[1]
error recovery on certain VFIO passthrough devices on spapr guests.  So far
it's only been seen on a BCM5719 NIC on a POWER8 server, but there may be
other hardware with the same problem.  It's also possible there could be
circumstances where it causes a bug on x86 as well, though I don't know of
any obvious candidates.

Prior to d1f6af6, both vfio_msix_vector_do_use() and
vfio_add_kvm_msi_virq() used msg == NULL as a special flag to mark this
as the "dummy" vector used to make the host hardware state sync with the
guest expected hardware state in terms of MSI configuration.

Specifically that flag caused vfio_add_kvm_msi_virq() to become a no-op,
meaning the dummy irq would always be delivered via qemu. d1f6af6 changed
vfio_add_kvm_msi_virq() so it takes a vector number instead of the msg
parameter, and determines the correct message itself.  The test for !msg
was removed, and not replaced with anything there or in the caller.

With an spapr guest which has a VFIO device, if an EEH error occurs on the
host hardware, then the device will be isolated then reset.  This is a
combination of host and guest action, mediated by some EEH related
hypercalls.  I haven't fully traced the mechanics, but somehow installing
the kvm irqchip route for the dummy irq on the BCM5719 means that after EEH
reset and recovery, at least some irqs are no longer delivered to the
guest.

In particular, the guest never gets the link up event, and so the NIC is
effectively dead.

[1] EEH (Enhanced Error Handling) is an IBM POWER server specific PCI-*
    error reporting and recovery mechanism.  The concept is somewhat
    similar to PCI-E AER, but the details are different.

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1373802

Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Gavin Shan <gwshan@au1.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Cc: qemu-stable@nongnu.org
Fixes: d1f6af6a17 ("kvm-irqchip: simplify kvm_irqchip_add_msi_route")
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
(cherry picked from commit 6d17a018d0)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:47:51 -05:00
Cornelia Huck
533dedf059 s390x/css: handle cssid 255 correctly
The cssid 255 is reserved but still valid from an architectural
point of view. However, feeding a bogus schid of 0xffffffff into
the virtio hypercall will lead to a crash:

Stack trace of thread 138363:
        #0  0x00000000100d168c css_find_subch (qemu-system-s390x)
        #1  0x00000000100d3290 virtio_ccw_hcall_notify
        #2  0x00000000100cbf60 s390_virtio_hypercall
        #3  0x000000001010ff7a handle_hypercall
        #4  0x0000000010079ed4 kvm_cpu_exec (qemu-system-s390x)
        #5  0x00000000100609b4 qemu_kvm_cpu_thread_fn
        #6  0x000003ff8b887bb4 start_thread (libpthread.so.0)
        #7  0x000003ff8b78df0a thread_start (libc.so.6)

This is because the css array was only allocated for 0..254
instead of 0..255.

Let's fix this by bumping MAX_CSSID to 255 and fencing off the
reserved cssid of 255 during css image allocation.

Reported-by: Christian Borntraeger <borntraeger@de.ibm.com>
Tested-by: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
(cherry picked from commit 882b3b9769)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:36 -05:00
John Snow
54c26b7340 ahci: clear aiocb in ncq_cb
Similar to existing fixes for IDE (87ac25fd) and ATAPI (7f951b2d), the
AIOCB must be cleared in the callback. Otherwise, we may accidentally
try to reset a dangling pointer in bdrv_aio_cancel() from a port reset.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 1474575040-32079-2-git-send-email-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
(cherry picked from commit df403bc588)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:36 -05:00
Fam Zheng
f5436d1dab virtio-scsi: Don't abort when media is ejected
With an ejected block backend, blk_get_aio_context() would return
qemu_aio_context. In this case don't assert.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <1473848224-24809-3-git-send-email-famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 2a2d69f490)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:35 -05:00
Fam Zheng
3550eeafcd scsi-disk: Cleaning up around tray open state
Even if tray is not open, it can be empty (blk_is_inserted() == false).
Handle both cases correctly by replacing the s->tray_open checks with
blk_is_available(), which is an AND of the two.

Also simplify successive checks of them into blk_is_available(), in a
couple cases.

Signed-off-by: Fam Zheng <famz@redhat.com>
Message-Id: <1473848224-24809-2-git-send-email-famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit cd723b8560)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:35 -05:00
Fam Zheng
316c2c9448 iothread: Stop threads before main() quits
Right after main_loop ends, we release various things but keep iothread
alive. The latter is not prepared to the sudden change of resources.

Specifically, after bdrv_close_all(), virtio-scsi dataplane get a
surprise at the empty BlockBackend:

(gdb) bt
    at /usr/src/debug/qemu-2.6.0/hw/scsi/virtio-scsi.c:543
    at /usr/src/debug/qemu-2.6.0/hw/scsi/virtio-scsi.c:577

It is because the d->conf.blk->root is set to NULL, then
blk_get_aio_context() returns qemu_aio_context, whereas s->ctx is still
pointing to the iothread:

    hw/scsi/virtio-scsi.c:543:

    if (s->dataplane_started) {
        assert(blk_get_aio_context(d->conf.blk) == s->ctx);
    }

To fix this, let's stop iothreads before doing bdrv_close_all().

Cc: qemu-stable@nongnu.org
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1473326931-9699-1-git-send-email-famz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit dce8921b2b)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:35 -05:00
Daniel P. Berrange
98b4465f7d crypto: ensure XTS is only used with ciphers with 16 byte blocks
The XTS cipher mode needs to be used with a cipher which has
a block size of 16 bytes. If a mis-matching block size is used,
the code will either corrupt memory beyond the IV array, or
not fully encrypt/decrypt the IV.

This fixes a memory corruption crash when attempting to use
cast5-128 with xts, since the former has an 8 byte block size.

A test case is added to ensure the cipher creation fails with
such an invalid combination.

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
(cherry picked from commit a5d2f44d0d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:35 -05:00
Paolo Bonzini
8342e1240b scsi: mptconfig: fix misuse of MPTSAS_CONFIG_PACK
These issues cause respectively a QEMU crash and a leak of 2 bytes of
stack.  They were discovered by VictorV of 360 Marvel Team.

Reported-by: Tom Victor <i-tangtianwen@360.cm>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 65a8e1f641)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:35 -05:00
Prasad J Pandit
0b6ab25367 scsi: mptconfig: fix an assert expression
When LSI SAS1068 Host Bus emulator builds configuration page
headers, mptsas_config_pack() should assert that the size
fits in a byte.  However, the size is expressed in 32-bit
units, so up to 1020 bytes fit.  The assertion was only
allowing replies up to 252 bytes, so fix it.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1472645167-30765-2-git-send-email-ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit cf2bce203a)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:35 -05:00
Prasad J Pandit
742886578d vmw_pvscsi: check page count while initialising descriptor rings
Vmware Paravirtual SCSI emulation uses command descriptors to
process SCSI commands. These descriptors come with their ring
buffers. A guest could set the page count for these rings to
an arbitrary value, leading to infinite loop or OOB access.
Add check to avoid it.

Reported-by: Tom Victor <vv474172261@gmail.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1472626169-12989-1-git-send-email-ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 7f61f4690d)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:34 -05:00
Rony Weng
2f8e8c7396 scsi-disk: change disk serial length from 20 to 36
Openstack Cinder assigns volume a 36 characters uuid as serial.
QEMU will shrinks the uuid to 20 characters, which does not match
the original uuid.

Note that there is no limit to the length of the serial number in
the SCSI spec.  20 was copy-pasted from virtio-blk which in turn was
copy-pasted from ATA; 36 is even more arbitrary.  However, bumping it
up too much might cause issues (e.g. 252 seems to make sense because
then the maximum amount of returned data is 256; but who knows there's
no off-by-one somewhere for such a nicely rounded number).

Signed-off-by: Rony Weng <ronyweng@synology.com>
Message-Id: <1472457138-23386-1-git-send-email-ronyweng@synology.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 48b6206305)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:34 -05:00
069e885d83 qemu-char: avoid segfault if user lacks of permisson of a given logfile
Function qemu_chr_alloc returns NULL if it failed to open logfile by any reason,
says no write permission. For backends tty, stdio and msmouse, They need to
check this return value to avoid segfault in this case.

Signed-off-by: Lin Ma <lma@suse.com>
Cc: qemu-stable <qemu-stable@nongnu.org>
Message-Id: <20160914062250.22226-1-lma@suse.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 71200fb966)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:34 -05:00
Prasad J Pandit
bfb15f77bb scsi: pvscsi: limit process IO loop to ring size
Vmware Paravirtual SCSI emulator while processing IO requests
could run into an infinite loop if 'pvscsi_ring_pop_req_descr'
always returned positive value. Limit IO loop to the ring size.

Cc: qemu-stable@nongnu.org
Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1473845952-30785-1-git-send-email-ppandit@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit d251157ac1)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:34 -05:00
Li Qiang
c6a7b922f8 scsi: mptsas: use g_new0 to allocate MPTSASRequest object
When processing IO request in mptsas, it uses g_new to allocate
a 'req' object. If an error occurs before 'req->sreq' is
allocated, It could lead to an OOB write in mptsas_free_request
function. Use g_new0 to avoid it.

Reported-by: Li Qiang <liqiang6-s@360.cn>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-Id: <1473684251-17476-1-git-send-email-ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 670e56d3ed)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:34 -05:00
Greg Kurz
d06c61f310 9pfs: fix potential segfault during walk
If the call to fid_to_qid() returns an error, we will call v9fs_path_free()
on uninitialized paths.

It is a regression introduced by the following commit:

56f101ecce 9pfs: handle walk of ".." in the root directory

Let's fix this by initializing dpath and path before calling fid_to_qid().

Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
[groug: updated the changelog to indicate this is regression and to provide
        the offending commit SHA1]
Signed-off-by: Greg Kurz <groug@kaod.org>

(cherry picked from commit 13fd08e631)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:34 -05:00
Gonglei
91a2f46297 vnc: fix qemu crash because of SIGSEGV
The backtrace is:

0x00007f0b75cdf880 in pixman_image_get_stride () from /lib64/libpixman-1.so.0
0x00007f0b77bcb3cf in vnc_server_fb_stride (vd=0x7f0b7a1a2bb0) at ui/vnc.c:680
vnc_dpy_copy (dcl=0x7f0b7a1a2c00, src_x=224, src_y=263, dst_x=319, dst_y=363, w=1, h=1) at ui/vnc.c:915
0x00007f0b77bbcc35 in dpy_gfx_copy (con=0x7f0b7a146210, src_x=src_x@entry=224, src_y=src_y@entry=263, dst_x=dst_x@entry=319,
dst_y=dst_y@entry=363, w=1, h=1) at ui/console.c:1575
0x00007f0b77bbda4e in qemu_console_copy (con=<optimized out>, src_x=src_x@entry=224, src_y=src_y@entry=263, dst_x=dst_x@entry=319,
dst_y=dst_y@entry=363, w=<optimized out>, h=<optimized out>) at ui/console.c:2111
0x00007f0b77ac0980 in cirrus_do_copy (h=<optimized out>, w=<optimized out>, src=<optimized out>, dst=<optimized out>, s=0x7f0b7b086090) at hw/display/cirrus_vga.c:774
cirrus_bitblt_videotovideo_copy (s=0x7f0b7b086090) at hw/display/cirrus_vga.c:793
cirrus_bitblt_videotovideo (s=0x7f0b7b086090) at hw/display/cirrus_vga.c:915
cirrus_bitblt_start (s=0x7f0b7b086090) at hw/display/cirrus_vga.c:1056
0x00007f0b77965cfb in memory_region_write_accessor (mr=0x7f0b7b096e40, addr=320, value=<optimized out>, size=1, shift=<optimized out>,mask=<optimized out>, attrs=...) at /root/rpmbuild/BUILD/master/qemu/memory.c:525
0x00007f0b77963f59 in access_with_adjusted_size (addr=addr@entry=320, value=value@entry=0x7f0b69a268d8, size=size@entry=4,
access_size_min=<optimized out>, access_size_max=<optimized out>, access=access@entry=0x7f0b77965c80 <memory_region_write_accessor>,
mr=mr@entry=0x7f0b7b096e40, attrs=attrs@entry=...) at /root/rpmbuild/BUILD/master/qemu/memory.c:591
0x00007f0b77968315 in memory_region_dispatch_write (mr=mr@entry=0x7f0b7b096e40, addr=addr@entry=320, data=18446744073709551362,
size=size@entry=4, attrs=attrs@entry=...) at /root/rpmbuild/BUILD/master/qemu/memory.c:1262
0x00007f0b779256a9 in address_space_write_continue (mr=0x7f0b7b096e40, l=4, addr1=320, len=4, buf=0x7f0b77713028 "\002\377\377\377",
attrs=..., addr=4273930560, as=0x7f0b7827d280 <address_space_memory>) at /root/rpmbuild/BUILD/master/qemu/exec.c:2544
address_space_write (as=<optimized out>, addr=<optimized out>, attrs=..., buf=<optimized out>, len=<optimized out>) at /root/rpmbuild/BUILD/master/qemu/exec.c:2601
0x00007f0b77925c1d in address_space_rw (as=<optimized out>, addr=<optimized out>, attrs=..., attrs@entry=...,
buf=buf@entry=0x7f0b77713028 "\002\377\377\377", len=<optimized out>, is_write=<optimized out>) at /root/rpmbuild/BUILD/master/qemu/exec.c:2703
0x00007f0b77962f53 in kvm_cpu_exec (cpu=cpu@entry=0x7f0b79fcc2d0) at /root/rpmbuild/BUILD/master/qemu/kvm-all.c:1965
0x00007f0b77950cc6 in qemu_kvm_cpu_thread_fn (arg=0x7f0b79fcc2d0) at /root/rpmbuild/BUILD/master/qemu/cpus.c:1078
0x00007f0b744b3dc5 in start_thread (arg=0x7f0b69a27700) at pthread_create.c:308
0x00007f0b70d3d66d in clone () from /lib64/libc.so.6

The code path while meeting segfault:
 vnc_dpy_copy
   vnc_update_client
     vnc_disconnect_finish [while vnc_disconnect_start() is invoked because somethins wrong]
       vnc_update_server_surface
         vd->server = NULL;
   vnc_server_fb_stride
     pixman_image_get_stride(vd->server)

Let's add a non-NULL check before calling vnc_server_fb_stride() to avoid segmentation fault.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Daniel P. Berrange <berrange@redhat.com>
Reported-by: Yanying Zhuang <ann.zhuangyanying@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: 1472788698-120964-1-git-send-email-arei.gonglei@huawei.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 3e10c3ecfc)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:33 -05:00
Ladi Prosek
520d4b288f virtio-balloon: discard virtqueue element on reset
The one pending element is being freed but not discarded on device
reset, which causes svq->inuse to creep up, eventually hitting the
"Virtqueue size exceeded" error.

Properly discarding the element on device reset makes sure that its
buffers are unmapped and the inuse counter stays balanced.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Roman Kagan <rkagan@virtuozzo.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 104e70cae7)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:33 -05:00
Stefan Hajnoczi
4b6542dd17 virtio: zero vq->inuse in virtio_reset()
vq->inuse must be zeroed upon device reset like most other virtqueue
fields.

In theory, virtio_reset() just needs assert(vq->inuse == 0) since
devices must clean up in-flight requests during reset (requests cannot
not be leaked!).

In practice, it is difficult to achieve vq->inuse == 0 across reset
because balloon, blk, 9p, etc implement various different strategies for
cleaning up requests.  Most devices call g_free(elem) directly without
telling virtio.c that the VirtQueueElement is cleaned up.  Therefore
vq->inuse is not decremented during reset.

This patch zeroes vq->inuse and trusts that devices are not leaking
VirtQueueElements across reset.

I will send a follow-up series that refactors request life-cycle across
all devices and converts vq->inuse = 0 into assert(vq->inuse == 0) but
this more invasive approach is not appropriate for stable trees.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Cc: qemu-stable <qemu-stable@nongnu.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Ladi Prosek <lprosek@redhat.com>
(cherry picked from commit 4b7f91ed02)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2016-11-02 16:41:33 -05:00
Michael Roth
c1a77fd6fa Merge tag 'ppc-for-2.7-20161013' into stable-2.7-staging
qemu-2.7 (stable): ppc patch queue 2016-10-13

TCG for ppc does not properly implement hardware transactional memory.
It has a stub implementation in which transactions always fail.
Unfortunately in v2.7.0, HTM is advertised as being available to
guests, which means guests may incorrectly attempt to use it and hang.

This has been the case for a while, but has become more urgent with
recent (guest) Linux kernel versions which attempt to lazily enable
TM.  Under TCG that now triggers the problem regularly, instead of
just when running a TM aware userspace program.

The problem is already fixed in the 2.8/master branch, by correctly
advertising HTM as not being available with TCG.  This series
backports the relevant patches to the qemu-2.7 stable branch to fix
the problem there.

* tag 'ppc-for-2.7-20161013':
  ppc: Check the availability of transactional memory
  hw/ppc/spapr: Fix the selection of the processor features
  hw/ppc/spapr: Move code related to "ibm,pa-features" to a separate function
  linux-headers: update
2016-11-02 16:40:01 -05:00
Thomas Huth
2e68f28854 ppc: Check the availability of transactional memory
KVM-PR currently does not support transactional memory, and the
implementation in TCG is just a fake. We should not announce TM
support in the ibm,pa-features property when running on such a
system, so disable it by default and only enable it if the KVM
implementation supports it (i.e. recent versions of KVM-HV).
These changes are based on some earlier work from Anton Blanchard
(thanks!).

Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit bac3bf287a)
2016-10-13 12:58:06 +11:00
Thomas Huth
45a4f18e2e hw/ppc/spapr: Fix the selection of the processor features
The current code uses pa_features_206 for POWERPC_MMU_2_06, and
for everything else, it uses pa_features_207. This is bad in some
cases because there is also a "degraded" MMU version of ISA 2.06,
called POWERPC_MMU_2_06a, which should of course use the flags for
2.06 instead. And there is also the possibility that the user runs
the pseries machine with a POWER5+ or even 970 processor. In that
case we certainly do not want to set the flags for 2.07, and rather
simply skip the setting of the pa-features property instead.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 4cbec30d76)
2016-10-13 12:58:06 +11:00
Thomas Huth
5c17966605 hw/ppc/spapr: Move code related to "ibm,pa-features" to a separate function
The function spapr_populate_cpu_dt() has become quite big
already, and since we likely have to extend the pa-features
property for every new processor generation, it is nicer
if we put the related code into a separate function.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 230bf719d3)
2016-10-13 12:58:06 +11:00
Cornelia Huck
6ff3ab0d6b linux-headers: update
Update headers against 4.8-rc2.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2016-10-13 12:58:06 +11:00
595 changed files with 15848 additions and 26577 deletions

3
.gitignore vendored
View File

@@ -53,8 +53,7 @@
/qemu-bridge-helper
/qemu-monitor.texi
/qemu-monitor-info.texi
/qemu-version.h
/qemu-version.h.tmp
/qmp-commands.txt
/vscclient
/fsdev/virtfs-proxy-helper
*.[1-9]

View File

@@ -83,7 +83,6 @@ F: include/exec/cpu*.h
F: include/exec/exec-all.h
F: include/exec/helper*.h
F: include/exec/tb-hash.h
F: include/sysemu/cpus.h
FPU emulation
M: Aurelien Jarno <aurelien@aurel32.net>
@@ -172,7 +171,6 @@ L: qemu-ppc@nongnu.org
S: Maintained
F: target-ppc/
F: hw/ppc/
F: include/hw/ppc/
F: disas/ppc.c
S390
@@ -189,7 +187,6 @@ S: Odd Fixes
F: target-sh4/
F: hw/sh4/
F: disas/sh4.c
F: include/hw/sh4/
SPARC
M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
@@ -205,7 +202,6 @@ M: Guan Xuetao <gxt@mprc.pku.edu.cn>
S: Maintained
F: target-unicore32/
F: hw/unicore32/
F: include/hw/unicore32/
X86
M: Paolo Bonzini <pbonzini@redhat.com>
@@ -229,7 +225,6 @@ M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
S: Maintained
F: target-tricore/
F: hw/tricore/
F: include/hw/tricore/
Guest CPU Cores (KVM):
----------------------
@@ -461,6 +456,7 @@ S: Maintained
F: hw/*/xilinx_*
F: hw/*/cadence_*
F: hw/misc/zynq_slcr.c
F: include/hw/xilinx.h
X: hw/ssi/xilinx_*
Xilinx ZynqMP
@@ -469,7 +465,7 @@ M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/*/xlnx*.c
F: include/hw/*/xlnx*.h
F: include/hw/*/xlnx*.c
ARM ACPI Subsystem
M: Shannon Zhao <zhaoshenglong@huawei.com>
@@ -575,9 +571,6 @@ L: qemu-ppc@nongnu.org
S: Supported
F: hw/ppc/e500.[hc]
F: hw/ppc/e500plat.c
F: include/hw/ppc/ppc_e500.h
F: include/hw/pci-host/ppce500.h
F: pc-bios/u-boot.e500
mpc8544ds
M: Alexander Graf <agraf@suse.de>
@@ -595,8 +588,6 @@ F: hw/ppc/mac_newworld.c
F: hw/pci-host/uninorth.c
F: hw/pci-bridge/dec.[hc]
F: hw/misc/macio/
F: include/hw/ppc/mac_dbdma.h
F: hw/nvram/mac_nvram.c
Old World
M: Alexander Graf <agraf@suse.de>
@@ -624,14 +615,6 @@ F: include/hw/*/spapr*
F: hw/*/xics*
F: include/hw/*/xics*
F: pc-bios/spapr-rtas/*
F: pc-bios/spapr-rtas.bin
F: pc-bios/slof.bin
F: docs/specs/ppc-spapr-hcalls.txt
F: docs/specs/ppc-spapr-hotplug.txt
F: tests/spapr*
F: tests/libqos/*spapr*
F: tests/rtas*
F: tests/libqos/rtas*
virtex_ml507
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
@@ -683,9 +666,6 @@ F: hw/s390x/
F: include/hw/s390x/
F: pc-bios/s390-ccw/
F: hw/watchdog/wdt_diag288.c
F: include/hw/watchdog/wdt_diag288.h
F: pc-bios/s390-ccw.img
F: default-configs/s390x-softmmu.mak
T: git git://github.com/cohuck/qemu.git s390-next
T: git git://github.com/borntraeger/qemu.git s390-next
@@ -715,7 +695,7 @@ F: hw/i2c/smbus_ich9.c
F: hw/acpi/piix4.c
F: hw/acpi/ich9.c
F: include/hw/acpi/ich9.h
F: include/hw/acpi/piix4.h
F: include/hw/acpi/piix.h
F: hw/misc/sga.c
PC Chipset
@@ -735,10 +715,6 @@ F: hw/misc/pc-testdev.c
F: hw/timer/hpet*
F: hw/timer/i8254*
F: hw/timer/mc146818rtc*
F: include/hw/i2c/pm_smbus.h
F: include/hw/timer/hpet.h
F: include/hw/timer/i8254*
F: include/hw/timer/mc146818rtc*
Machine core
M: Eduardo Habkost <ehabkost@redhat.com>
@@ -821,15 +797,16 @@ F: hw/mem/*
F: hw/acpi/*
F: hw/smbios/*
F: hw/i386/acpi-build.[hc]
F: hw/i386/*dsl
F: hw/arm/virt-acpi-build.c
F: include/hw/arm/virt-acpi-build.h
F: scripts/acpi*py
ppc4xx
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc/ppc4*.c
F: include/hw/ppc/ppc4xx.h
ppce500
M: Alexander Graf <agraf@suse.de>
@@ -849,15 +826,13 @@ Network devices
M: Jason Wang <jasowang@redhat.com>
S: Odd Fixes
F: hw/net/
F: tests/virtio-net-test.c
T: git git://github.com/jasowang/qemu.git net
SCSI
M: Paolo Bonzini <pbonzini@redhat.com>
S: Supported
F: include/hw/scsi/*
F: include/hw/scsi*
F: hw/scsi/*
F: tests/virtio-scsi-test.c
T: git git://github.com/bonzini/qemu.git scsi-next
LSI53C895A
@@ -910,7 +885,6 @@ S: Supported
F: hw/*/virtio*
F: net/vhost-user.c
F: include/hw/virtio/
F: tests/virtio-balloon-test.c
virtio-9p
M: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
@@ -928,7 +902,7 @@ L: qemu-block@nongnu.org
S: Supported
F: hw/block/virtio-blk.c
F: hw/block/dataplane/*
F: tests/virtio-blk-test.c
F: hw/virtio/dataplane/*
T: git git://github.com/stefanha/qemu.git block
virtio-ccw
@@ -951,8 +925,6 @@ S: Supported
F: hw/char/virtio-serial-bus.c
F: hw/char/virtio-console.c
F: include/hw/virtio/virtio-serial.h
F: tests/virtio-console-test.c
F: tests/virtio-serial-test.c
virtio-rng
M: Amit Shah <amit.shah@redhat.com>
@@ -961,7 +933,6 @@ F: hw/virtio/virtio-rng.c
F: include/hw/virtio/virtio-rng.h
F: include/sysemu/rng*.h
F: backends/rng*.c
F: tests/virtio-rng-test.c
nvme
M: Keith Busch <keith.busch@intel.com>
@@ -1093,6 +1064,12 @@ S: Supported
F: qom/cpu.c
F: include/qom/cpu.h
ICC Bus
M: Igor Mammedov <imammedo@redhat.com>
S: Supported
F: include/hw/cpu/icc_bus.h
F: hw/cpu/icc_bus.c
Device Tree
M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
M: Alexander Graf <agraf@suse.de>
@@ -1260,6 +1237,7 @@ M: Markus Armbruster <armbru@redhat.com>
S: Supported
F: qmp.c
F: monitor.c
F: qmp-commands.hx
F: docs/*qmp-*
F: scripts/qmp/
T: git git://repo.or.cz/qemu/armbru.git qapi-next
@@ -1279,11 +1257,6 @@ F: net/slirp.c
F: include/net/slirp.h
T: git git://git.kiszka.org/qemu.git queues/slirp
Stubs
M: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
F: stubs/
Tracing
M: Stefan Hajnoczi <stefanha@redhat.com>
S: Maintained
@@ -1357,13 +1330,6 @@ F: include/qemu/throttle.h
F: util/throttle.c
L: qemu-block@nongnu.org
UUID
M: Fam Zheng <famz@redhat.com>
S: Supported
F: util/uuid.c
F: include/qemu/uuid.h
F: tests/test-uuid.c
Usermode Emulation
------------------
Overall
@@ -1614,7 +1580,7 @@ M: Kevin Wolf <kwolf@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/linux-aio.c
F: include/block/raw-aio.h
F: block/raw-aio.h
F: block/raw-posix.c
F: block/raw-win32.c
F: block/raw_bsd.c
@@ -1658,15 +1624,6 @@ L: qemu-block@nongnu.org
S: Supported
F: tests/image-fuzzer/
Replication
M: Wen Congyang <wency@cn.fujitsu.com>
M: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
S: Supported
F: replication*
F: block/replication.c
F: tests/test-replication.c
F: docs/block-replication.txt
Build and test automation
-------------------------
M: Alex Bennée <alex.bennee@linaro.org>

View File

@@ -76,8 +76,6 @@ GENERATED_HEADERS += trace/generated-ust-provider.h
GENERATED_SOURCES += trace/generated-ust.c
endif
GENERATED_HEADERS += module_block.h
# Don't try to regenerate Makefile or configure
# We don't generate any of them
Makefile: ;
@@ -94,6 +92,7 @@ HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 qemu-ga.8
DOCS+=qmp-commands.txt
ifdef CONFIG_VIRTFS
DOCS+=fsdev/virtfs-proxy-helper.1
endif
@@ -247,6 +246,9 @@ Makefile: $(version-obj-y) $(version-lobj-y)
libqemustub.a: $(stub-obj-y)
libqemuutil.a: $(util-obj-y)
block-modules = $(foreach o,$(block-obj-m),"$(basename $(subst /,-,$o))",) NULL
util/module.o-cflags = -D'CONFIG_BLOCK_MODULES=$(block-modules)'
######################################################################
qemu-img.o: qemu-img-cmds.h
@@ -310,7 +312,7 @@ $(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
qmp-commands.h qmp-marshal.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o "." $<, \
$(gen-out-type) -o "." -m $<, \
" GEN $@")
qmp-introspect.h qmp-introspect.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
@@ -351,11 +353,6 @@ ivshmem-client$(EXESUF): $(ivshmem-client-obj-y) libqemuutil.a libqemustub.a
ivshmem-server$(EXESUF): $(ivshmem-server-obj-y) libqemuutil.a libqemustub.a
$(call LINK, $^)
module_block.h: $(SRC_PATH)/scripts/modules/module_block.py config-host.mak
$(call quiet-command,$(PYTHON) $< $@ \
$(addprefix $(SRC_PATH)/,$(patsubst %.mo,%.c,$(block-obj-m))), \
" GEN $@")
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
@@ -435,7 +432,7 @@ endif
install-doc: $(DOCS)
$(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) qemu-doc.html qemu-tech.html "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) $(SRC_PATH)/docs/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
$(INSTALL_DATA) qmp-commands.txt "$(DESTDIR)$(qemu_docdir)"
ifdef CONFIG_POSIX
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
$(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1"
@@ -558,6 +555,9 @@ qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -q < $< > $@," GEN $@")
qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
@@ -669,40 +669,3 @@ endif
-include $(wildcard *.d tests/*.d)
include $(SRC_PATH)/tests/docker/Makefile.include
.PHONY: help
help:
@echo 'Generic targets:'
@echo ' all - Build all'
@echo ' dir/file.o - Build specified target only'
@echo ' install - Install QEMU, documentation and tools'
@echo ' ctags/TAGS - Generate tags file for editors'
@echo ' cscope - Generate cscope index'
@echo ''
@$(if $(TARGET_DIRS), \
echo 'Architecture specific targets:'; \
$(foreach t, $(TARGET_DIRS), \
printf " %-30s - Build for %s\\n" $(patsubst %,subdir-%,$(t)) $(t);) \
echo '')
@echo 'Cleaning targets:'
@echo ' clean - Remove most generated files but keep the config'
@echo ' distclean - Remove all generated files'
@echo ' dist - Build a distributable tarball'
@echo ''
@echo 'Test targets:'
@echo ' check - Run all tests (check-help for details)'
@echo ' docker - Help about targets running tests inside Docker containers'
@echo ''
@echo 'Documentation targets:'
@echo ' dvi html info pdf'
@echo ' - Build documentation in specified format'
@echo ''
ifdef CONFIG_WIN32
@echo 'Windows targets:'
@echo ' installer - Build NSIS-based installer for qemu-ga'
ifdef QEMU_GA_MSI_ENABLED
@echo ' msi - Build MSI-based installer for qemu-ga'
endif
@echo ''
endif
@echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'

View File

@@ -15,7 +15,6 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
block-obj-$(CONFIG_WIN32) += aio-win32.o
block-obj-y += block/
block-obj-y += qemu-io-cmds.o
block-obj-$(CONFIG_REPLICATION) += replication.o
block-obj-m = block/

View File

@@ -156,7 +156,7 @@ else
obj-y += hw/$(TARGET_BASE_ARCH)/
endif
GENERATED_HEADERS += hmp-commands.h hmp-commands-info.h
GENERATED_HEADERS += hmp-commands.h hmp-commands-info.h qmp-commands-old.h
endif # CONFIG_SOFTMMU
@@ -209,10 +209,13 @@ hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
clean: clean-target
qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
clean:
rm -f *.a *~ $(PROGS)
rm -f $(shell find . -name '*.[od]')
rm -f hmp-commands.h gdbstub-xml.c
rm -f hmp-commands.h qmp-commands-old.h gdbstub-xml.c
ifdef CONFIG_TRACE_SYSTEMTAP
rm -f *.stp
endif

View File

@@ -1 +1 @@
2.7.50
2.7.1

View File

@@ -235,6 +235,25 @@ void audio_init(void)
}
}
int qemu_uuid_parse(const char *str, uint8_t *uuid)
{
int ret;
if (strlen(str) != 36) {
return -1;
}
ret = sscanf(str, UUID_FMT, &uuid[0], &uuid[1], &uuid[2], &uuid[3],
&uuid[4], &uuid[5], &uuid[6], &uuid[7], &uuid[8], &uuid[9],
&uuid[10], &uuid[11], &uuid[12], &uuid[13], &uuid[14],
&uuid[15]);
if (ret != 16) {
return -1;
}
return 0;
}
void do_acpitable_option(const QemuOpts *opts)
{
#ifdef TARGET_I386

View File

@@ -41,9 +41,7 @@ static void rng_egd_request_entropy(RngBackend *b, RngRequest *req)
header[0] = 0x02;
header[1] = len;
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, header, sizeof(header));
qemu_chr_fe_write(s->chr, header, sizeof(header));
size -= len;
}

170
block.c
View File

@@ -25,9 +25,7 @@
#include "trace.h"
#include "block/block_int.h"
#include "block/blockjob.h"
#include "block/nbd.h"
#include "qemu/error-report.h"
#include "module_block.h"
#include "qemu/module.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qbool.h"
@@ -243,40 +241,17 @@ BlockDriverState *bdrv_new(void)
return bs;
}
static BlockDriver *bdrv_do_find_format(const char *format_name)
BlockDriver *bdrv_find_format(const char *format_name)
{
BlockDriver *drv1;
QLIST_FOREACH(drv1, &bdrv_drivers, list) {
if (!strcmp(drv1->format_name, format_name)) {
return drv1;
}
}
return NULL;
}
BlockDriver *bdrv_find_format(const char *format_name)
{
BlockDriver *drv1;
int i;
drv1 = bdrv_do_find_format(format_name);
if (drv1) {
return drv1;
}
/* The driver isn't registered, maybe we need to load a module */
for (i = 0; i < (int)ARRAY_SIZE(block_driver_modules); ++i) {
if (!strcmp(block_driver_modules[i].format_name, format_name)) {
block_module_load_one(block_driver_modules[i].library_name);
break;
}
}
return bdrv_do_find_format(format_name);
}
static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only)
{
static const char *whitelist_rw[] = {
@@ -485,19 +460,6 @@ static BlockDriver *find_hdev_driver(const char *filename)
return drv;
}
static BlockDriver *bdrv_do_find_protocol(const char *protocol)
{
BlockDriver *drv1;
QLIST_FOREACH(drv1, &bdrv_drivers, list) {
if (drv1->protocol_name && !strcmp(drv1->protocol_name, protocol)) {
return drv1;
}
}
return NULL;
}
BlockDriver *bdrv_find_protocol(const char *filename,
bool allow_protocol_prefix,
Error **errp)
@@ -506,7 +468,6 @@ BlockDriver *bdrv_find_protocol(const char *filename,
char protocol[128];
int len;
const char *p;
int i;
/* TODO Drivers without bdrv_file_open must be specified explicitly */
@@ -533,25 +494,15 @@ BlockDriver *bdrv_find_protocol(const char *filename,
len = sizeof(protocol) - 1;
memcpy(protocol, filename, len);
protocol[len] = '\0';
drv1 = bdrv_do_find_protocol(protocol);
if (drv1) {
return drv1;
}
for (i = 0; i < (int)ARRAY_SIZE(block_driver_modules); ++i) {
if (block_driver_modules[i].protocol_name &&
!strcmp(block_driver_modules[i].protocol_name, protocol)) {
block_module_load_one(block_driver_modules[i].library_name);
break;
QLIST_FOREACH(drv1, &bdrv_drivers, list) {
if (drv1->protocol_name &&
!strcmp(drv1->protocol_name, protocol)) {
return drv1;
}
}
drv1 = bdrv_do_find_protocol(protocol);
if (!drv1) {
error_setg(errp, "Unknown protocol '%s'", protocol);
}
return drv1;
error_setg(errp, "Unknown protocol '%s'", protocol);
return NULL;
}
/*
@@ -733,9 +684,6 @@ static void bdrv_temp_snapshot_options(int *child_flags, QDict *child_options,
qdict_set_default_str(child_options, BDRV_OPT_CACHE_DIRECT, "off");
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
/* Copy the read-only option from the parent */
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
/* aio=native doesn't work for cache.direct=off, so disable it for the
* temporary snapshot */
*child_flags &= ~BDRV_O_NATIVE_AIO;
@@ -758,9 +706,6 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
/* Inherit the read-only option from the parent if it's not set */
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
/* Our block drivers take care to send flushes and respect unmap policy,
* so we can default to enable both on lower layers regardless of the
* corresponding parent options. */
@@ -814,8 +759,7 @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
/* backing files always opened read-only */
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
flags &= ~BDRV_O_COPY_ON_READ;
flags &= ~(BDRV_O_RDWR | BDRV_O_COPY_ON_READ);
/* snapshot=on is handled on the top layer */
flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY);
@@ -862,14 +806,6 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) {
*flags |= BDRV_O_NOCACHE;
}
*flags &= ~BDRV_O_RDWR;
assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
if (!qemu_opt_get_bool(opts, BDRV_OPT_READ_ONLY, false)) {
*flags |= BDRV_O_RDWR;
}
}
static void update_options_from_flags(QDict *options, int flags)
@@ -882,10 +818,6 @@ static void update_options_from_flags(QDict *options, int flags)
qdict_put(options, BDRV_OPT_CACHE_NO_FLUSH,
qbool_from_bool(flags & BDRV_O_NO_FLUSH));
}
if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
qdict_put(options, BDRV_OPT_READ_ONLY,
qbool_from_bool(!(flags & BDRV_O_RDWR)));
}
}
static void bdrv_assign_node_name(BlockDriverState *bs,
@@ -949,11 +881,6 @@ static QemuOptsList bdrv_runtime_opts = {
.type = QEMU_OPT_BOOL,
.help = "Ignore flush requests",
},
{
.name = BDRV_OPT_READ_ONLY,
.type = QEMU_OPT_BOOL,
.help = "Node is opened in read-only mode",
},
{ /* end of list */ }
},
};
@@ -985,8 +912,6 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
goto fail_opts;
}
update_flags_from_options(&bs->open_flags, opts);
driver_name = qemu_opt_get(opts, "driver");
drv = bdrv_find_format(driver_name);
assert(drv != NULL);
@@ -1048,6 +973,9 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
bs->drv = drv;
bs->opaque = g_malloc0(drv->instance_size);
/* Apply cache mode options */
update_flags_from_options(&bs->open_flags, opts);
/* Open the image, either directly or using a protocol */
open_flags = bdrv_open_flags(bs, bs->open_flags);
if (drv->bdrv_file_open) {
@@ -1383,23 +1311,6 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
/* Otherwise we won't be able to commit due to check in bdrv_commit */
bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_COMMIT_TARGET,
bs->backing_blocker);
/*
* We do backup in 3 ways:
* 1. drive backup
* The target bs is new opened, and the source is top BDS
* 2. blockdev backup
* Both the source and the target are top BDSes.
* 3. internal backup(used for block replication)
* Both the source and the target are backing file
*
* In case 1 and 2, neither the source nor the target is the backing file.
* In case 3, we will block the top BDS, so there is only one block job
* for the top BDS and its backing chain.
*/
bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_SOURCE,
bs->backing_blocker);
bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_TARGET,
bs->backing_blocker);
out:
bdrv_refresh_limits(bs, NULL);
}
@@ -1698,25 +1609,6 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
goto fail;
}
/* Set the BDRV_O_RDWR and BDRV_O_ALLOW_RDWR flags.
* FIXME: we're parsing the QDict to avoid having to create a
* QemuOpts just for this, but neither option is optimal. */
if (g_strcmp0(qdict_get_try_str(options, BDRV_OPT_READ_ONLY), "on") &&
!qdict_get_try_bool(options, BDRV_OPT_READ_ONLY, false)) {
flags |= (BDRV_O_RDWR | BDRV_O_ALLOW_RDWR);
} else {
flags &= ~BDRV_O_RDWR;
}
if (flags & BDRV_O_SNAPSHOT) {
snapshot_options = qdict_new();
bdrv_temp_snapshot_options(&snapshot_flags, snapshot_options,
flags, options);
/* Let bdrv_backing_options() override "read-only" */
qdict_del(options, BDRV_OPT_READ_ONLY);
bdrv_backing_options(&flags, options, flags, options);
}
bs->open_flags = flags;
bs->options = options;
options = qdict_clone_shallow(options);
@@ -1741,6 +1633,18 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
/* Open image file without format layer */
if ((flags & BDRV_O_PROTOCOL) == 0) {
if (flags & BDRV_O_RDWR) {
flags |= BDRV_O_ALLOW_RDWR;
}
if (flags & BDRV_O_SNAPSHOT) {
snapshot_options = qdict_new();
bdrv_temp_snapshot_options(&snapshot_flags, snapshot_options,
flags, options);
bdrv_backing_options(&flags, options, flags, options);
}
bs->open_flags = flags;
file = bdrv_open_child(filename, options, "file", bs,
&child_file, true, &local_err);
if (local_err) {
@@ -1925,13 +1829,6 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
options = qdict_new();
}
/* Check if this BlockDriverState is already in the queue */
QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
if (bs == bs_entry->state.bs) {
break;
}
}
/*
* Precedence of options:
* 1. Explicitly passed in options (highest)
@@ -1952,11 +1849,7 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
}
/* Old explicitly set values (don't overwrite by inherited value) */
if (bs_entry) {
old_options = qdict_clone_shallow(bs_entry->state.explicit_options);
} else {
old_options = qdict_clone_shallow(bs->explicit_options);
}
old_options = qdict_clone_shallow(bs->explicit_options);
bdrv_join_options(bs, options, old_options);
QDECREF(old_options);
@@ -1995,13 +1888,8 @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
child->role, options, flags);
}
if (!bs_entry) {
bs_entry = g_new0(BlockReopenQueueEntry, 1);
QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
} else {
QDECREF(bs_entry->state.options);
QDECREF(bs_entry->state.explicit_options);
}
bs_entry = g_new0(BlockReopenQueueEntry, 1);
QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
bs_entry->state.bs = bs;
bs_entry->state.options = options;
@@ -2318,7 +2206,6 @@ static void bdrv_close(BlockDriverState *bs)
void bdrv_close_all(void)
{
block_job_cancel_sync_all();
nbd_export_close_all();
/* Drop references from requests still in flight, such as canceled block
* jobs whose AIO context has not been polled yet */
@@ -3059,6 +2946,11 @@ bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag)
return false;
}
int bdrv_is_snapshot(BlockDriverState *bs)
{
return !!(bs->open_flags & BDRV_O_SNAPSHOT);
}
/* backing_file can either be relative, or absolute, or a protocol. If it is
* relative, it must be relative to the chain. So, passing in bs->filename
* from a BDS as backing_file should not be done, as that may be relative to

View File

@@ -1,8 +1,8 @@
block-obj-y += raw_bsd.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o
block-obj-y += raw_bsd.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
block-obj-y += qed-check.o
block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o
block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
block-obj-y += quorum.o
block-obj-y += parallels.o blkdebug.o blkverify.o blkreplay.o
block-obj-y += block-backend.o snapshot.o qapi.o
@@ -22,14 +22,12 @@ block-obj-$(CONFIG_ARCHIPELAGO) += archipelago.o
block-obj-$(CONFIG_LIBSSH2) += ssh.o
block-obj-y += accounting.o dirty-bitmap.o
block-obj-y += write-threshold.o
block-obj-y += backup.o
block-obj-$(CONFIG_REPLICATION) += replication.o
block-obj-y += crypto.o
common-obj-y += stream.o
common-obj-y += backup.o
nfs.o-libs := $(LIBNFS_LIBS)
iscsi.o-cflags := $(LIBISCSI_CFLAGS)
iscsi.o-libs := $(LIBISCSI_LIBS)
curl.o-cflags := $(CURL_CFLAGS)
@@ -41,6 +39,7 @@ gluster.o-libs := $(GLUSTERFS_LIBS)
ssh.o-cflags := $(LIBSSH2_CFLAGS)
ssh.o-libs := $(LIBSSH2_LIBS)
archipelago.o-libs := $(ARCHIPELAGO_LIBS)
block-obj-m += dmg.o
dmg.o-libs := $(BZIP2_LIBS)
qcow.o-libs := -lz
linux-aio.o-libs := -laio

View File

@@ -17,7 +17,6 @@
#include "block/block.h"
#include "block/block_int.h"
#include "block/blockjob.h"
#include "block/block_backup.h"
#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qemu/ratelimit.h"
@@ -28,6 +27,13 @@
#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
#define SLICE_TIME 100000000ULL /* ns */
typedef struct CowRequest {
int64_t start;
int64_t end;
QLIST_ENTRY(CowRequest) list;
CoQueue wait_queue; /* coroutines blocked on this request */
} CowRequest;
typedef struct BackupBlockJob {
BlockJob common;
BlockBackend *target;
@@ -41,7 +47,6 @@ typedef struct BackupBlockJob {
uint64_t sectors_read;
unsigned long *done_bitmap;
int64_t cluster_size;
bool compress;
NotifierWithReturn before_write;
QLIST_HEAD(, CowRequest) inflight_reqs;
} BackupBlockJob;
@@ -149,8 +154,7 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
} else {
ret = blk_co_pwritev(job->target, start * job->cluster_size,
bounce_qiov.size, &bounce_qiov,
job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
bounce_qiov.size, &bounce_qiov, 0);
}
if (ret < 0) {
trace_backup_do_cow_write_fail(job, start, ret);
@@ -249,57 +253,6 @@ static void backup_attached_aio_context(BlockJob *job, AioContext *aio_context)
blk_set_aio_context(s->target, aio_context);
}
void backup_do_checkpoint(BlockJob *job, Error **errp)
{
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
int64_t len;
assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
if (backup_job->sync_mode != MIRROR_SYNC_MODE_NONE) {
error_setg(errp, "The backup job only supports block checkpoint in"
" sync=none mode");
return;
}
len = DIV_ROUND_UP(backup_job->common.len, backup_job->cluster_size);
bitmap_zero(backup_job->done_bitmap, len);
}
void backup_wait_for_overlapping_requests(BlockJob *job, int64_t sector_num,
int nb_sectors)
{
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
int64_t sectors_per_cluster = cluster_size_sectors(backup_job);
int64_t start, end;
assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
start = sector_num / sectors_per_cluster;
end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);
wait_for_overlapping_requests(backup_job, start, end);
}
void backup_cow_request_begin(CowRequest *req, BlockJob *job,
int64_t sector_num,
int nb_sectors)
{
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
int64_t sectors_per_cluster = cluster_size_sectors(backup_job);
int64_t start, end;
assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
start = sector_num / sectors_per_cluster;
end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);
cow_request_begin(req, backup_job, start, end);
}
void backup_cow_request_end(CowRequest *req)
{
cow_request_end(req);
}
static const BlockJobDriver backup_job_driver = {
.instance_size = sizeof(BackupBlockJob),
.job_type = BLOCK_JOB_TYPE_BACKUP,
@@ -524,7 +477,6 @@ static void coroutine_fn backup_run(void *opaque)
void backup_start(const char *job_id, BlockDriverState *bs,
BlockDriverState *target, int64_t speed,
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
bool compress,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
BlockCompletionFunc *cb, void *opaque,
@@ -555,12 +507,6 @@ void backup_start(const char *job_id, BlockDriverState *bs,
return;
}
if (compress && target->drv->bdrv_co_pwritev_compressed == NULL) {
error_setg(errp, "Compression is not supported for this drive %s",
bdrv_get_device_name(target));
return;
}
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
return;
}
@@ -609,7 +555,6 @@ void backup_start(const char *job_id, BlockDriverState *bs,
job->sync_mode = sync_mode;
job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
sync_bitmap : NULL;
job->compress = compress;
/* If there is no backing file on the target, we cannot rely on COW if our
* backup cluster size is smaller than the target cluster size. Even for

View File

@@ -409,22 +409,6 @@ bool bdrv_has_blk(BlockDriverState *bs)
return bdrv_first_blk(bs) != NULL;
}
/*
* Returns true if @bs has only BlockBackends as parents.
*/
bool bdrv_is_root_node(BlockDriverState *bs)
{
BdrvChild *c;
QLIST_FOREACH(c, &bs->parents, next_parent) {
if (c->role != &child_root) {
return false;
}
}
return true;
}
/*
* Return @blk's DriveInfo if any, else null.
*/
@@ -559,25 +543,6 @@ void *blk_get_attached_dev(BlockBackend *blk)
return blk->dev;
}
/*
* Return the BlockBackend which has the device model @dev attached if it
* exists, else null.
*
* @dev must not be null.
*/
BlockBackend *blk_by_dev(void *dev)
{
BlockBackend *blk = NULL;
assert(dev != NULL);
while ((blk = blk_all_next(blk)) != NULL) {
if (blk->dev == dev) {
return blk;
}
}
return NULL;
}
/*
* Set @blk's device model callbacks to @ops.
* @opaque is the opaque argument to pass to the callbacks.
@@ -762,6 +727,21 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
return 0;
}
static int blk_check_request(BlockBackend *blk, int64_t sector_num,
int nb_sectors)
{
if (sector_num < 0 || sector_num > INT64_MAX / BDRV_SECTOR_SIZE) {
return -EIO;
}
if (nb_sectors < 0 || nb_sectors > INT_MAX / BDRV_SECTOR_SIZE) {
return -EIO;
}
return blk_check_byte_request(blk, sector_num * BDRV_SECTOR_SIZE,
nb_sectors * BDRV_SECTOR_SIZE);
}
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
unsigned int bytes, QEMUIOVector *qiov,
BdrvRequestFlags flags)
@@ -1316,6 +1296,11 @@ void blk_eject(BlockBackend *blk, bool eject_flag)
if (bs) {
bdrv_eject(bs, eject_flag);
}
/* Whether or not we ejected on the backend,
* the frontend experienced a tray event. */
qapi_event_send_device_tray_moved(blk_name(blk),
eject_flag, &error_abort);
}
int blk_get_flags(BlockBackend *blk)
@@ -1504,11 +1489,15 @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
flags | BDRV_REQ_ZERO_WRITE);
}
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
int count)
int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
return blk_prw(blk, offset, (void *) buf, count, blk_write_entry,
BDRV_REQ_WRITE_COMPRESSED);
int ret = blk_check_request(blk, sector_num, nb_sectors);
if (ret < 0) {
return ret;
}
return bdrv_write_compressed(blk_bs(blk), sector_num, buf, nb_sectors);
}
int blk_truncate(BlockBackend *blk, int64_t offset)
@@ -1640,28 +1629,6 @@ int blk_commit_all(void)
return 0;
}
int blk_flush_all(void)
{
BlockBackend *blk = NULL;
int result = 0;
while ((blk = blk_all_next(blk)) != NULL) {
AioContext *aio_context = blk_get_aio_context(blk);
int ret;
aio_context_acquire(aio_context);
if (blk_is_inserted(blk)) {
ret = blk_flush(blk);
if (ret < 0 && !result) {
result = ret;
}
}
aio_context_release(aio_context);
}
return result;
}
/* throttling disk I/O limits */
void blk_set_io_limits(BlockBackend *blk, ThrottleConfig *cfg)

View File

@@ -83,7 +83,7 @@ static void commit_complete(BlockJob *job, void *opaque)
BlockDriverState *active = s->active;
BlockDriverState *top = blk_bs(s->top);
BlockDriverState *base = blk_bs(s->base);
BlockDriverState *overlay_bs = bdrv_find_overlay(active, top);
BlockDriverState *overlay_bs;
int ret = data->ret;
if (!block_job_is_cancelled(&s->common) && ret == 0) {
@@ -97,6 +97,7 @@ static void commit_complete(BlockJob *job, void *opaque)
if (s->base_flags != bdrv_get_flags(base)) {
bdrv_reopen(base, s->base_flags, NULL);
}
overlay_bs = bdrv_find_overlay(active, top);
if (overlay_bs && s->orig_overlay_flags != bdrv_get_flags(overlay_bs)) {
bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL);
}
@@ -242,14 +243,14 @@ void commit_start(const char *job_id, BlockDriverState *bs,
orig_overlay_flags = bdrv_get_flags(overlay_bs);
/* convert base & overlay_bs to r/w, if necessary */
if (!(orig_base_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, base, NULL,
orig_base_flags | BDRV_O_RDWR);
}
if (!(orig_overlay_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs, NULL,
orig_overlay_flags | BDRV_O_RDWR);
}
if (!(orig_base_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, base, NULL,
orig_base_flags | BDRV_O_RDWR);
}
if (reopen_queue) {
bdrv_reopen_multiple(reopen_queue, &local_err);
if (local_err != NULL) {

View File

@@ -33,7 +33,6 @@
#define BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG "ivgen-alg"
#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"
typedef struct BlockCrypto BlockCrypto;
@@ -184,11 +183,6 @@ static QemuOptsList block_crypto_create_opts_luks = {
.type = QEMU_OPT_STRING,
.help = "Name of encryption hash algorithm",
},
{
.name = BLOCK_CRYPTO_OPT_LUKS_ITER_TIME,
.type = QEMU_OPT_NUMBER,
.help = "Time to spend in PBKDF in milliseconds",
},
{ /* end of list */ }
},
};

View File

@@ -73,7 +73,6 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
#define CURL_NUM_STATES 8
#define CURL_NUM_ACB 8
#define SECTOR_SIZE 512
#define READ_AHEAD_DEFAULT (256 * 1024)
#define CURL_TIMEOUT_DEFAULT 5
#define CURL_TIMEOUT_MAX 10000
@@ -106,12 +105,17 @@ typedef struct CURLAIOCB {
size_t end;
} CURLAIOCB;
typedef struct CURLSocket {
int fd;
QLIST_ENTRY(CURLSocket) next;
} CURLSocket;
typedef struct CURLState
{
struct BDRVCURLState *s;
CURLAIOCB *acb[CURL_NUM_ACB];
CURL *curl;
curl_socket_t sock_fd;
QLIST_HEAD(, CURLSocket) sockets;
char *orig_buf;
size_t buf_start;
size_t buf_off;
@@ -165,10 +169,27 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
{
BDRVCURLState *s;
CURLState *state = NULL;
CURLSocket *socket;
curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
state->sock_fd = fd;
s = state->s;
QLIST_FOREACH(socket, &state->sockets, next) {
if (socket->fd == fd) {
if (action == CURL_POLL_REMOVE) {
QLIST_REMOVE(socket, next);
g_free(socket);
}
break;
}
}
if (!socket) {
socket = g_new0(CURLSocket, 1);
socket->fd = fd;
QLIST_INSERT_HEAD(&state->sockets, socket, next);
}
socket = NULL;
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, (int)fd);
switch (action) {
case CURL_POLL_IN:
@@ -214,12 +235,13 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
DPRINTF("CURL: Just reading %zd bytes\n", realsize);
if (!s || !s->orig_buf)
return 0;
if (!s || !s->orig_buf) {
goto read_end;
}
if (s->buf_off >= s->buf_len) {
/* buffer full, read nothing */
return 0;
goto read_end;
}
realsize = MIN(realsize, s->buf_len - s->buf_off);
memcpy(s->orig_buf + s->buf_off, ptr, realsize);
@@ -232,15 +254,26 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
continue;
if ((s->buf_off >= acb->end)) {
size_t request_length = acb->nb_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start,
acb->end - acb->start);
if (acb->end - acb->start < request_length) {
size_t offset = acb->end - acb->start;
qemu_iovec_memset(acb->qiov, offset, 0,
request_length - offset);
}
acb->common.cb(acb->common.opaque, 0);
qemu_aio_unref(acb);
s->acb[i] = NULL;
}
}
return realsize;
read_end:
/* curl will error out if we do not return this value */
return size * nmemb;
}
static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
@@ -248,6 +281,8 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
{
int i;
size_t end = start + len;
size_t clamped_end = MIN(end, s->len);
size_t clamped_len = clamped_end - start;
for (i=0; i<CURL_NUM_STATES; i++) {
CURLState *state = &s->states[i];
@@ -262,12 +297,15 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
// Does the existing buffer cover our section?
if ((start >= state->buf_start) &&
(start <= buf_end) &&
(end >= state->buf_start) &&
(end <= buf_end))
(clamped_end >= state->buf_start) &&
(clamped_end <= buf_end))
{
char *buf = state->orig_buf + (start - state->buf_start);
qemu_iovec_from_buf(acb->qiov, 0, buf, len);
qemu_iovec_from_buf(acb->qiov, 0, buf, clamped_len);
if (clamped_len < len) {
qemu_iovec_memset(acb->qiov, clamped_len, 0, len - clamped_len);
}
acb->common.cb(acb->common.opaque, 0);
return FIND_RET_OK;
@@ -277,13 +315,13 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
if (state->in_use &&
(start >= state->buf_start) &&
(start <= buf_fend) &&
(end >= state->buf_start) &&
(end <= buf_fend))
(clamped_end >= state->buf_start) &&
(clamped_end <= buf_fend))
{
int j;
acb->start = start - state->buf_start;
acb->end = acb->start + len;
acb->end = acb->start + clamped_len;
for (j=0; j<CURL_NUM_ACB; j++) {
if (!state->acb[j]) {
@@ -353,6 +391,7 @@ static void curl_multi_check_completion(BDRVCURLState *s)
static void curl_multi_do(void *arg)
{
CURLState *s = (CURLState *)arg;
CURLSocket *socket, *next_socket;
int running;
int r;
@@ -360,10 +399,13 @@ static void curl_multi_do(void *arg)
return;
}
do {
r = curl_multi_socket_action(s->s->multi, s->sock_fd, 0, &running);
} while(r == CURLM_CALL_MULTI_PERFORM);
/* Need to use _SAFE because curl_multi_socket_action() may trigger
* curl_sock_cb() which might modify this list */
QLIST_FOREACH_SAFE(socket, &s->sockets, next, next_socket) {
do {
r = curl_multi_socket_action(s->s->multi, socket->fd, 0, &running);
} while (r == CURLM_CALL_MULTI_PERFORM);
}
}
static void curl_multi_read(void *arg)
@@ -467,6 +509,7 @@ static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s)
#endif
}
QLIST_INIT(&state->sockets);
state->s = s;
return state;
@@ -476,6 +519,14 @@ static void curl_clean_state(CURLState *s)
{
if (s->s->multi)
curl_multi_remove_handle(s->s->multi, s->curl);
while (!QLIST_EMPTY(&s->sockets)) {
CURLSocket *socket = QLIST_FIRST(&s->sockets);
QLIST_REMOVE(socket, next);
g_free(socket);
}
s->in_use = 0;
}
@@ -675,28 +726,11 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s);
if (curl_easy_perform(state->curl))
goto out;
if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d);
if (d)
s->len = (size_t)d;
else if(!s->len)
goto out;
}
/* Prior CURL 7.19.4 return value of 0 could mean that the file size is not
* know or the size is zero. From 7.19.4 CURL returns -1 if size is not
* known and zero if it is realy zero-length file. */
#if LIBCURL_VERSION_NUM >= 0x071304
if (d < 0) {
pstrcpy(state->errmsg, CURL_ERROR_SIZE,
"Server didn't report file size.");
goto out;
}
#else
if (d <= 0) {
pstrcpy(state->errmsg, CURL_ERROR_SIZE,
"Unknown file size or zero-length file.");
goto out;
}
#endif
s->len = (size_t)d;
if ((!strncasecmp(s->url, "http://", strlen("http://"))
|| !strncasecmp(s->url, "https://", strlen("https://")))
&& !s->accept_range) {
@@ -742,12 +776,12 @@ static void curl_readv_bh_cb(void *p)
qemu_bh_delete(acb->bh);
acb->bh = NULL;
size_t start = acb->sector_num * SECTOR_SIZE;
size_t start = acb->sector_num * BDRV_SECTOR_SIZE;
size_t end;
// In case we have the requested data already (e.g. read-ahead),
// we can just call the callback and be done.
switch (curl_find_buf(s, start, acb->nb_sectors * SECTOR_SIZE, acb)) {
switch (curl_find_buf(s, start, acb->nb_sectors * BDRV_SECTOR_SIZE, acb)) {
case FIND_RET_OK:
qemu_aio_unref(acb);
// fall through
@@ -766,13 +800,13 @@ static void curl_readv_bh_cb(void *p)
}
acb->start = 0;
acb->end = (acb->nb_sectors * SECTOR_SIZE);
acb->end = MIN(acb->nb_sectors * BDRV_SECTOR_SIZE, s->len - start);
state->buf_off = 0;
g_free(state->orig_buf);
state->buf_start = start;
state->buf_len = acb->end + s->readahead_size;
end = MIN(start + state->buf_len, s->len) - 1;
state->buf_len = MIN(acb->end + s->readahead_size, s->len - start);
end = start + state->buf_len - 1;
state->orig_buf = g_try_malloc(state->buf_len);
if (state->buf_len && state->orig_buf == NULL) {
curl_clean_state(state);
@@ -783,8 +817,8 @@ static void curl_readv_bh_cb(void *p)
state->acb[0] = acb;
snprintf(state->range, 127, "%zd-%zd", start, end);
DPRINTF("CURL (AIO): Reading %d at %zd (%s)\n",
(acb->nb_sectors * SECTOR_SIZE), start, state->range);
DPRINTF("CURL (AIO): Reading %llu at %zd (%s)\n",
(acb->nb_sectors * BDRV_SECTOR_SIZE), start, state->range);
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
curl_multi_add_handle(s->multi, state->curl);

View File

@@ -30,8 +30,6 @@
#define GLUSTER_DEFAULT_PORT 24007
#define GLUSTER_DEBUG_DEFAULT 4
#define GLUSTER_DEBUG_MAX 9
#define GLUSTER_OPT_LOGFILE "logfile"
#define GLUSTER_LOGFILE_DEFAULT "-" /* handled in libgfapi as /dev/stderr */
#define GERR_INDEX_HINT "hint: check in 'server' array index '%d'\n"
@@ -46,7 +44,6 @@ typedef struct GlusterAIOCB {
typedef struct BDRVGlusterState {
struct glfs *glfs;
struct glfs_fd *fd;
char *logfile;
bool supports_seek_data;
int debug_level;
} BDRVGlusterState;
@@ -76,11 +73,6 @@ static QemuOptsList qemu_gluster_create_opts = {
.type = QEMU_OPT_NUMBER,
.help = "Gluster log level, valid range is 0-9",
},
{
.name = GLUSTER_OPT_LOGFILE,
.type = QEMU_OPT_STRING,
.help = "Logfile path of libgfapi",
},
{ /* end of list */ }
}
};
@@ -99,11 +91,6 @@ static QemuOptsList runtime_opts = {
.type = QEMU_OPT_NUMBER,
.help = "Gluster log level, valid range is 0-9",
},
{
.name = GLUSTER_OPT_LOGFILE,
.type = QEMU_OPT_STRING,
.help = "Logfile path of libgfapi",
},
{ /* end of list */ }
},
};
@@ -354,7 +341,7 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
}
}
ret = glfs_set_logging(glfs, gconf->logfile, gconf->debug_level);
ret = glfs_set_logging(glfs, "-", gconf->debug_level);
if (ret < 0) {
goto out;
}
@@ -589,9 +576,7 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
if (ret < 0) {
error_setg(errp, "invalid URI");
error_append_hint(errp, "Usage: file=gluster[+transport]://"
"[host[:port]]volume/path[?socket=...]"
"[,file.debug=N]"
"[,file.logfile=/path/filename.log]\n");
"[host[:port]]/volume/path[?socket=...]\n");
errno = -ret;
return NULL;
}
@@ -601,9 +586,7 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
error_append_hint(errp, "Usage: "
"-drive driver=qcow2,file.driver=gluster,"
"file.volume=testvol,file.path=/path/a.qcow2"
"[,file.debug=9]"
"[,file.logfile=/path/filename.log],"
"file.server.0.type=tcp,"
"[,file.debug=9],file.server.0.type=tcp,"
"file.server.0.host=1.2.3.4,"
"file.server.0.port=24007,"
"file.server.1.transport=unix,"
@@ -694,7 +677,7 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
BlockdevOptionsGluster *gconf = NULL;
QemuOpts *opts;
Error *local_err = NULL;
const char *filename, *logfile;
const char *filename;
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
@@ -717,13 +700,6 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
gconf = g_new0(BlockdevOptionsGluster, 1);
gconf->debug_level = s->debug_level;
gconf->has_debug_level = true;
logfile = qemu_opt_get(opts, GLUSTER_OPT_LOGFILE);
s->logfile = g_strdup(logfile ? logfile : GLUSTER_LOGFILE_DEFAULT);
gconf->logfile = g_strdup(s->logfile);
gconf->has_logfile = true;
s->glfs = qemu_gluster_init(gconf, filename, options, errp);
if (!s->glfs) {
ret = -errno;
@@ -762,7 +738,6 @@ out:
if (!ret) {
return ret;
}
g_free(s->logfile);
if (s->fd) {
glfs_close(s->fd);
}
@@ -794,8 +769,6 @@ static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
gconf = g_new0(BlockdevOptionsGluster, 1);
gconf->debug_level = s->debug_level;
gconf->has_debug_level = true;
gconf->logfile = g_strdup(s->logfile);
gconf->has_logfile = true;
reop_s->glfs = qemu_gluster_init(gconf, state->bs->filename, NULL, errp);
if (reop_s->glfs == NULL) {
ret = -errno;
@@ -941,12 +914,6 @@ static int qemu_gluster_create(const char *filename,
}
gconf->has_debug_level = true;
gconf->logfile = qemu_opt_get_del(opts, GLUSTER_OPT_LOGFILE);
if (!gconf->logfile) {
gconf->logfile = g_strdup(GLUSTER_LOGFILE_DEFAULT);
}
gconf->has_logfile = true;
glfs = qemu_gluster_init(gconf, filename, NULL, errp);
if (!glfs) {
ret = -errno;
@@ -1058,7 +1025,6 @@ static void qemu_gluster_close(BlockDriverState *bs)
{
BDRVGlusterState *s = bs->opaque;
g_free(s->logfile);
if (s->fd) {
glfs_close(s->fd);
s->fd = NULL;

View File

@@ -540,6 +540,17 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
return 0;
}
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
int nb_sectors)
{
if (nb_sectors < 0 || nb_sectors > BDRV_REQUEST_MAX_SECTORS) {
return -EIO;
}
return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
nb_sectors * BDRV_SECTOR_SIZE);
}
typedef struct RwCo {
BdrvChild *child;
int64_t offset;
@@ -886,19 +897,6 @@ emulate_flags:
return ret;
}
static int coroutine_fn
bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov)
{
BlockDriver *drv = bs->drv;
if (!drv->bdrv_co_pwritev_compressed) {
return -ENOTSUP;
}
return drv->bdrv_co_pwritev_compressed(bs, offset, bytes, qiov);
}
static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
int64_t offset, unsigned int bytes, QEMUIOVector *qiov)
{
@@ -1181,6 +1179,8 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
int max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT_MAX);
int alignment = MAX(bs->bl.pwrite_zeroes_alignment,
bs->bl.request_alignment);
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
MAX_WRITE_ZEROES_BOUNCE_BUFFER);
assert(alignment % bs->bl.request_alignment == 0);
head = offset % alignment;
@@ -1196,9 +1196,12 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
* boundaries.
*/
if (head) {
/* Make a small request up to the first aligned sector. */
num = MIN(count, alignment - head);
head = 0;
/* Make a small request up to the first aligned sector. For
* convenience, limit this request to max_transfer even if
* we don't need to fall back to writes. */
num = MIN(MIN(count, max_transfer), alignment - head);
head = (head + num) % alignment;
assert(num < max_write_zeroes);
} else if (tail && num > alignment) {
/* Shorten the request to the last aligned sector. */
num -= tail;
@@ -1224,8 +1227,6 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
if (ret == -ENOTSUP) {
/* Fall back to bounce buffer if write zeroes is unsupported */
int max_transfer = MIN_NON_ZERO(bs->bl.max_transfer,
MAX_WRITE_ZEROES_BOUNCE_BUFFER);
BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
if ((flags & BDRV_REQ_FUA) &&
@@ -1317,8 +1318,6 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
} else if (flags & BDRV_REQ_ZERO_WRITE) {
bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
} else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
ret = bdrv_driver_pwritev_compressed(bs, offset, bytes, qiov);
} else if (bytes <= max_transfer) {
bdrv_debug_event(bs, BLKDBG_PWRITEV);
ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags);
@@ -1619,6 +1618,31 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
BDRV_REQ_ZERO_WRITE | flags);
}
/*
* Flush ALL BDSes regardless of if they are reachable via a BlkBackend or not.
*/
int bdrv_flush_all(void)
{
BdrvNextIterator it;
BlockDriverState *bs = NULL;
int result = 0;
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
AioContext *aio_context = bdrv_get_aio_context(bs);
int ret;
aio_context_acquire(aio_context);
ret = bdrv_flush(bs);
if (ret < 0 && !result) {
result = ret;
}
aio_context_release(aio_context);
}
return result;
}
typedef struct BdrvCoGetBlockStatusData {
BlockDriverState *bs;
BlockDriverState *base;
@@ -1883,6 +1907,28 @@ int bdrv_is_allocated_above(BlockDriverState *top,
return 0;
}
int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BlockDriver *drv = bs->drv;
int ret;
if (!drv) {
return -ENOMEDIUM;
}
if (!drv->bdrv_write_compressed) {
return -ENOTSUP;
}
ret = bdrv_check_request(bs, sector_num, nb_sectors);
if (ret < 0) {
return ret;
}
assert(QLIST_EMPTY(&bs->dirty_bitmaps));
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
}
typedef struct BdrvVmstateCo {
BlockDriverState *bs;
QEMUIOVector *qiov;
@@ -2338,7 +2384,9 @@ flush_parent:
ret = bs->file ? bdrv_co_flush(bs->file->bs) : 0;
out:
/* Notify any pending flushes that we have completed */
bs->flushed_gen = current_gen;
if (ret == 0) {
bs->flushed_gen = current_gen;
}
bs->active_flush_req = NULL;
/* Return value is ignored - it's ok if wait queue is empty */
qemu_co_queue_next(&bs->flush_queue);
@@ -2389,7 +2437,7 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
{
BdrvTrackedRequest req;
int max_pdiscard, ret;
int head, align;
int head, tail, align;
if (!bs->drv) {
return -ENOMEDIUM;
@@ -2412,19 +2460,15 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
return 0;
}
/* Discard is advisory, so ignore any unaligned head or tail */
/* Discard is advisory, but some devices track and coalesce
* unaligned requests, so we must pass everything down rather than
* round here. Still, most devices will just silently ignore
* unaligned requests (by returning -ENOTSUP), so we must fragment
* the request accordingly. */
align = MAX(bs->bl.pdiscard_alignment, bs->bl.request_alignment);
assert(align % bs->bl.request_alignment == 0);
head = offset % align;
if (head) {
head = MIN(count, align - head);
count -= head;
offset += head;
}
count = QEMU_ALIGN_DOWN(count, align);
if (!count) {
return 0;
}
tail = (offset + count) % align;
tracked_request_begin(&req, bs, offset, count, BDRV_TRACKED_DISCARD);
@@ -2435,11 +2479,34 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset,
max_pdiscard = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_pdiscard, INT_MAX),
align);
assert(max_pdiscard);
assert(max_pdiscard >= bs->bl.request_alignment);
while (count > 0) {
int ret;
int num = MIN(count, max_pdiscard);
int num = count;
if (head) {
/* Make small requests to get to alignment boundaries. */
num = MIN(count, align - head);
if (!QEMU_IS_ALIGNED(num, bs->bl.request_alignment)) {
num %= bs->bl.request_alignment;
}
head = (head + num) % align;
assert(num < max_pdiscard);
} else if (tail) {
if (num > align) {
/* Shorten the request to the last aligned cluster. */
num -= tail;
} else if (!QEMU_IS_ALIGNED(tail, bs->bl.request_alignment) &&
tail > bs->bl.request_alignment) {
tail %= bs->bl.request_alignment;
num -= tail;
}
}
/* limit request size */
if (num > max_pdiscard) {
num = max_pdiscard;
}
if (bs->drv->bdrv_co_pdiscard) {
ret = bs->drv->bdrv_co_pdiscard(bs, offset, num);

View File

@@ -36,7 +36,7 @@
#include "block/block_int.h"
#include "block/scsi.h"
#include "qemu/iov.h"
#include "qemu/uuid.h"
#include "sysemu/sysemu.h"
#include "qmp-commands.h"
#include "qapi/qmp/qstring.h"
#include "crypto/secret.h"
@@ -1048,7 +1048,9 @@ coroutine_fn iscsi_co_pdiscard(BlockDriverState *bs, int64_t offset, int count)
struct IscsiTask iTask;
struct unmap_list list;
assert(is_byte_request_lun_aligned(offset, count, iscsilun));
if (!is_byte_request_lun_aligned(offset, count, iscsilun)) {
return -ENOTSUP;
}
if (!iscsilun->lbp.lbpu) {
/* UNMAP is not supported by the target */
@@ -2013,9 +2015,45 @@ static BlockDriver bdrv_iscsi = {
.bdrv_attach_aio_context = iscsi_attach_aio_context,
};
static QemuOptsList qemu_iscsi_opts = {
.name = "iscsi",
.head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
.desc = {
{
.name = "user",
.type = QEMU_OPT_STRING,
.help = "username for CHAP authentication to target",
},{
.name = "password",
.type = QEMU_OPT_STRING,
.help = "password for CHAP authentication to target",
},{
.name = "password-secret",
.type = QEMU_OPT_STRING,
.help = "ID of the secret providing password for CHAP "
"authentication to target",
},{
.name = "header-digest",
.type = QEMU_OPT_STRING,
.help = "HeaderDigest setting. "
"{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
},{
.name = "initiator-name",
.type = QEMU_OPT_STRING,
.help = "Initiator iqn name to use when connecting",
},{
.name = "timeout",
.type = QEMU_OPT_NUMBER,
.help = "Request timeout in seconds (default 0 = no timeout)",
},
{ /* end of list */ }
},
};
static void iscsi_block_init(void)
{
bdrv_register(&bdrv_iscsi);
qemu_add_opts(&qemu_iscsi_opts);
}
block_init(iscsi_block_init);

View File

@@ -59,6 +59,7 @@ struct LinuxAioState {
/* I/O completion processing */
QEMUBH *completion_bh;
struct io_event events[MAX_EVENTS];
int event_idx;
int event_max;
};
@@ -94,153 +95,64 @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
laiocb->ret = ret;
if (laiocb->co) {
/* Jump and continue completion for foreign requests, don't do
* anything for current request, it will be completed shortly. */
if (laiocb->co != qemu_coroutine_self()) {
qemu_coroutine_enter(laiocb->co);
}
qemu_coroutine_enter(laiocb->co);
} else {
laiocb->common.cb(laiocb->common.opaque, ret);
qemu_aio_unref(laiocb);
}
}
/**
* aio_ring buffer which is shared between userspace and kernel.
*
* This copied from linux/fs/aio.c, common header does not exist
* but AIO exists for ages so we assume ABI is stable.
*/
struct aio_ring {
unsigned id; /* kernel internal index number */
unsigned nr; /* number of io_events */
unsigned head; /* Written to by userland or by kernel. */
unsigned tail;
unsigned magic;
unsigned compat_features;
unsigned incompat_features;
unsigned header_length; /* size of aio_ring */
struct io_event io_events[0];
};
/**
* io_getevents_peek:
* @ctx: AIO context
* @events: pointer on events array, output value
* Returns the number of completed events and sets a pointer
* on events array. This function does not update the internal
* ring buffer, only reads head and tail. When @events has been
* processed io_getevents_commit() must be called.
*/
static inline unsigned int io_getevents_peek(io_context_t ctx,
struct io_event **events)
{
struct aio_ring *ring = (struct aio_ring *)ctx;
unsigned int head = ring->head, tail = ring->tail;
unsigned int nr;
nr = tail >= head ? tail - head : ring->nr - head;
*events = ring->io_events + head;
/* To avoid speculative loads of s->events[i] before observing tail.
Paired with smp_wmb() inside linux/fs/aio.c: aio_complete(). */
smp_rmb();
return nr;
}
/**
* io_getevents_commit:
* @ctx: AIO context
* @nr: the number of events on which head should be advanced
*
* Advances head of a ring buffer.
*/
static inline void io_getevents_commit(io_context_t ctx, unsigned int nr)
{
struct aio_ring *ring = (struct aio_ring *)ctx;
if (nr) {
ring->head = (ring->head + nr) % ring->nr;
}
}
/**
* io_getevents_advance_and_peek:
* @ctx: AIO context
* @events: pointer on events array, output value
* @nr: the number of events on which head should be advanced
*
* Advances head of a ring buffer and returns number of elements left.
*/
static inline unsigned int
io_getevents_advance_and_peek(io_context_t ctx,
struct io_event **events,
unsigned int nr)
{
io_getevents_commit(ctx, nr);
return io_getevents_peek(ctx, events);
}
/**
* qemu_laio_process_completions:
* @s: AIO state
*
* Fetches completed I/O requests and invokes their callbacks.
/* The completion BH fetches completed I/O requests and invokes their
* callbacks.
*
* The function is somewhat tricky because it supports nested event loops, for
* example when a request callback invokes aio_poll(). In order to do this,
* indices are kept in LinuxAioState. Function schedules BH completion so it
* can be called again in a nested event loop. When there are no events left
* to complete the BH is being canceled.
* the completion events array and index are kept in LinuxAioState. The BH
* reschedules itself as long as there are completions pending so it will
* either be called again in a nested event loop or will be called after all
* events have been completed. When there are no events left to complete, the
* BH returns without rescheduling.
*/
static void qemu_laio_process_completions(LinuxAioState *s)
{
struct io_event *events;
/* Reschedule so nested event loops see currently pending completions */
qemu_bh_schedule(s->completion_bh);
while ((s->event_max = io_getevents_advance_and_peek(s->ctx, &events,
s->event_idx))) {
for (s->event_idx = 0; s->event_idx < s->event_max; ) {
struct iocb *iocb = events[s->event_idx].obj;
struct qemu_laiocb *laiocb =
container_of(iocb, struct qemu_laiocb, iocb);
laiocb->ret = io_event_ret(&events[s->event_idx]);
/* Change counters one-by-one because we can be nested. */
s->io_q.in_flight--;
s->event_idx++;
qemu_laio_process_completion(laiocb);
}
}
qemu_bh_cancel(s->completion_bh);
/* If we are nested we have to notify the level above that we are done
* by setting event_max to zero, upper level will then jump out of it's
* own `for` loop. If we are the last all counters droped to zero. */
s->event_max = 0;
s->event_idx = 0;
}
static void qemu_laio_process_completions_and_submit(LinuxAioState *s)
{
qemu_laio_process_completions(s);
if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
ioq_submit(s);
}
}
static void qemu_laio_completion_bh(void *opaque)
{
LinuxAioState *s = opaque;
qemu_laio_process_completions_and_submit(s);
/* Fetch more completion events when empty */
if (s->event_idx == s->event_max) {
do {
struct timespec ts = { 0 };
s->event_max = io_getevents(s->ctx, MAX_EVENTS, MAX_EVENTS,
s->events, &ts);
} while (s->event_max == -EINTR);
s->event_idx = 0;
if (s->event_max <= 0) {
s->event_max = 0;
return; /* no more events */
}
s->io_q.in_flight -= s->event_max;
}
/* Reschedule so nested event loops see currently pending completions */
qemu_bh_schedule(s->completion_bh);
/* Process completion events */
while (s->event_idx < s->event_max) {
struct iocb *iocb = s->events[s->event_idx].obj;
struct qemu_laiocb *laiocb =
container_of(iocb, struct qemu_laiocb, iocb);
laiocb->ret = io_event_ret(&s->events[s->event_idx]);
s->event_idx++;
qemu_laio_process_completion(laiocb);
}
if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
ioq_submit(s);
}
qemu_bh_cancel(s->completion_bh);
}
static void qemu_laio_completion_cb(EventNotifier *e)
@@ -248,7 +160,7 @@ static void qemu_laio_completion_cb(EventNotifier *e)
LinuxAioState *s = container_of(e, LinuxAioState, e);
if (event_notifier_test_and_clear(&s->e)) {
qemu_laio_process_completions_and_submit(s);
qemu_laio_completion_bh(s);
}
}
@@ -324,19 +236,6 @@ static void ioq_submit(LinuxAioState *s)
QSIMPLEQ_SPLIT_AFTER(&s->io_q.pending, aiocb, next, &completed);
} while (ret == len && !QSIMPLEQ_EMPTY(&s->io_q.pending));
s->io_q.blocked = (s->io_q.in_queue > 0);
if (s->io_q.in_flight) {
/* We can try to complete something just right away if there are
* still requests in-flight. */
qemu_laio_process_completions(s);
/*
* Even we have completed everything (in_flight == 0), the queue can
* have still pended requests (in_queue > 0). We do not attempt to
* repeat submission to avoid IO hang. The reason is simple: s->e is
* still set and completion callback will be called shortly and all
* pended requests will be submitted from there.
*/
}
}
void laio_io_plug(BlockDriverState *bs, LinuxAioState *s)
@@ -394,7 +293,6 @@ int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
.co = qemu_coroutine_self(),
.nbytes = qiov->size,
.ctx = s,
.ret = -EINPROGRESS,
.is_read = (type == QEMU_AIO_READ),
.qiov = qiov,
};
@@ -404,9 +302,7 @@ int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
return ret;
}
if (laiocb.ret == -EINPROGRESS) {
qemu_coroutine_yield();
}
qemu_coroutine_yield();
return laiocb.ret;
}

View File

@@ -916,8 +916,7 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
BlockCompletionFunc *cb,
void *opaque, Error **errp,
const BlockJobDriver *driver,
bool is_none_mode, BlockDriverState *base,
bool auto_complete)
bool is_none_mode, BlockDriverState *base)
{
MirrorBlockJob *s;
@@ -953,9 +952,6 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
s->granularity = granularity;
s->buf_size = ROUND_UP(buf_size, granularity);
s->unmap = unmap;
if (auto_complete) {
s->should_complete = true;
}
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
if (!s->dirty_bitmap) {
@@ -994,15 +990,14 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
mirror_start_job(job_id, bs, target, replaces,
speed, granularity, buf_size, backing_mode,
on_source_error, on_target_error, unmap, cb, opaque, errp,
&mirror_job_driver, is_none_mode, base, false);
&mirror_job_driver, is_none_mode, base);
}
void commit_active_start(const char *job_id, BlockDriverState *bs,
BlockDriverState *base, int64_t speed,
BlockdevOnError on_error,
BlockCompletionFunc *cb,
void *opaque, Error **errp,
bool auto_complete)
void *opaque, Error **errp)
{
int64_t length, base_length;
int orig_base_flags;
@@ -1043,7 +1038,7 @@ void commit_active_start(const char *job_id, BlockDriverState *bs,
mirror_start_job(job_id, bs, base, NULL, speed, 0, 0,
MIRROR_LEAVE_BACKING_CHAIN,
on_error, on_error, false, cb, opaque, &local_err,
&commit_active_job_driver, false, base, auto_complete);
&commit_active_job_driver, false, base);
if (local_err) {
error_propagate(errp, local_err);
goto error_restore_flags;

View File

@@ -913,32 +913,75 @@ static int qcow_make_empty(BlockDriverState *bs)
return 0;
}
typedef struct QcowWriteCo {
BlockDriverState *bs;
int64_t sector_num;
const uint8_t *buf;
int nb_sectors;
int ret;
} QcowWriteCo;
static void qcow_write_co_entry(void *opaque)
{
QcowWriteCo *co = opaque;
QEMUIOVector qiov;
struct iovec iov = (struct iovec) {
.iov_base = (uint8_t*) co->buf,
.iov_len = co->nb_sectors * BDRV_SECTOR_SIZE,
};
qemu_iovec_init_external(&qiov, &iov, 1);
co->ret = qcow_co_writev(co->bs, co->sector_num, co->nb_sectors, &qiov);
}
/* Wrapper for non-coroutine contexts */
static int qcow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
Coroutine *co;
AioContext *aio_context = bdrv_get_aio_context(bs);
QcowWriteCo data = {
.bs = bs,
.sector_num = sector_num,
.buf = buf,
.nb_sectors = nb_sectors,
.ret = -EINPROGRESS,
};
co = qemu_coroutine_create(qcow_write_co_entry, &data);
qemu_coroutine_enter(co);
while (data.ret == -EINPROGRESS) {
aio_poll(aio_context, true);
}
return data.ret;
}
/* XXX: put compressed sectors first, then all the cluster aligned
tables to avoid losing bytes in alignment */
static coroutine_fn int
qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov)
static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
QEMUIOVector hd_qiov;
struct iovec iov;
z_stream strm;
int ret, out_len;
uint8_t *buf, *out_buf;
uint8_t *out_buf;
uint64_t cluster_offset;
buf = qemu_blockalign(bs, s->cluster_size);
if (bytes != s->cluster_size) {
if (bytes > s->cluster_size ||
offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
{
qemu_vfree(buf);
return -EINVAL;
}
if (nb_sectors != s->cluster_sectors) {
ret = -EINVAL;
/* Zero-pad last write if image size is not cluster aligned */
memset(buf + bytes, 0, s->cluster_size - bytes);
if (sector_num + nb_sectors == bs->total_sectors &&
nb_sectors < s->cluster_sectors) {
uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size);
memset(pad_buf, 0, s->cluster_size);
memcpy(pad_buf, buf, nb_sectors * BDRV_SECTOR_SIZE);
ret = qcow_write_compressed(bs, sector_num,
pad_buf, s->cluster_sectors);
qemu_vfree(pad_buf);
}
return ret;
}
qemu_iovec_to_buf(qiov, 0, buf, qiov->size);
out_buf = g_malloc(s->cluster_size);
@@ -969,35 +1012,27 @@ qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
/* could not compress: write normal cluster */
ret = qcow_co_writev(bs, offset >> BDRV_SECTOR_BITS,
bytes >> BDRV_SECTOR_BITS, qiov);
ret = qcow_write(bs, sector_num, buf, s->cluster_sectors);
if (ret < 0) {
goto fail;
}
goto success;
}
qemu_co_mutex_lock(&s->lock);
cluster_offset = get_cluster_offset(bs, offset, 2, out_len, 0, 0);
qemu_co_mutex_unlock(&s->lock);
if (cluster_offset == 0) {
ret = -EIO;
goto fail;
}
cluster_offset &= s->cluster_offset_mask;
} else {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
out_len, 0, 0);
if (cluster_offset == 0) {
ret = -EIO;
goto fail;
}
iov = (struct iovec) {
.iov_base = out_buf,
.iov_len = out_len,
};
qemu_iovec_init_external(&hd_qiov, &iov, 1);
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
if (ret < 0) {
goto fail;
cluster_offset &= s->cluster_offset_mask;
ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
if (ret < 0) {
goto fail;
}
}
success:
ret = 0;
fail:
qemu_vfree(buf);
g_free(out_buf);
return ret;
}
@@ -1050,7 +1085,7 @@ static BlockDriver bdrv_qcow = {
.bdrv_set_key = qcow_set_key,
.bdrv_make_empty = qcow_make_empty,
.bdrv_co_pwritev_compressed = qcow_co_pwritev_compressed,
.bdrv_write_compressed = qcow_write_compressed,
.bdrv_get_info = qcow_get_info,
.create_opts = &qcow_create_opts,

View File

@@ -83,9 +83,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
}
memset(new_l1_table, 0, align_offset(new_l1_size2, 512));
if (s->l1_size) {
memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
}
memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
/* write new table (align to cluster) */
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);

View File

@@ -1204,6 +1204,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
bs->bl.request_alignment = BDRV_SECTOR_SIZE;
}
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
bs->bl.pdiscard_alignment = s->cluster_size;
}
static int qcow2_set_key(BlockDriverState *bs, const char *key)
@@ -1804,10 +1805,7 @@ static size_t header_ext_add(char *buf, uint32_t magic, const void *s,
.magic = cpu_to_be32(magic),
.len = cpu_to_be32(len),
};
if (len) {
memcpy(buf + sizeof(QCowExtension), s, len);
}
memcpy(buf + sizeof(QCowExtension), s, len);
return ext_len;
}
@@ -2488,6 +2486,11 @@ static coroutine_fn int qcow2_co_pdiscard(BlockDriverState *bs,
int ret;
BDRVQcow2State *s = bs->opaque;
if (!QEMU_IS_ALIGNED(offset | count, s->cluster_size)) {
assert(count < s->cluster_size);
return -ENOTSUP;
}
qemu_co_mutex_lock(&s->lock);
ret = qcow2_discard_clusters(bs, offset, count >> BDRV_SECTOR_BITS,
QCOW2_DISCARD_REQUEST, false);
@@ -2536,39 +2539,84 @@ static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
return 0;
}
typedef struct Qcow2WriteCo {
BlockDriverState *bs;
int64_t sector_num;
const uint8_t *buf;
int nb_sectors;
int ret;
} Qcow2WriteCo;
static void qcow2_write_co_entry(void *opaque)
{
Qcow2WriteCo *co = opaque;
QEMUIOVector qiov;
uint64_t offset = co->sector_num * BDRV_SECTOR_SIZE;
uint64_t bytes = co->nb_sectors * BDRV_SECTOR_SIZE;
struct iovec iov = (struct iovec) {
.iov_base = (uint8_t*) co->buf,
.iov_len = bytes,
};
qemu_iovec_init_external(&qiov, &iov, 1);
co->ret = qcow2_co_pwritev(co->bs, offset, bytes, &qiov, 0);
}
/* Wrapper for non-coroutine contexts */
static int qcow2_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
Coroutine *co;
AioContext *aio_context = bdrv_get_aio_context(bs);
Qcow2WriteCo data = {
.bs = bs,
.sector_num = sector_num,
.buf = buf,
.nb_sectors = nb_sectors,
.ret = -EINPROGRESS,
};
co = qemu_coroutine_create(qcow2_write_co_entry, &data);
qemu_coroutine_enter(co);
while (data.ret == -EINPROGRESS) {
aio_poll(aio_context, true);
}
return data.ret;
}
/* XXX: put compressed sectors first, then all the cluster aligned
tables to avoid losing bytes in alignment */
static coroutine_fn int
qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov)
static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcow2State *s = bs->opaque;
QEMUIOVector hd_qiov;
struct iovec iov;
z_stream strm;
int ret, out_len;
uint8_t *buf, *out_buf;
uint8_t *out_buf;
uint64_t cluster_offset;
if (bytes == 0) {
if (nb_sectors == 0) {
/* align end of file to a sector boundary to ease reading with
sector based I/Os */
cluster_offset = bdrv_getlength(bs->file->bs);
return bdrv_truncate(bs->file->bs, cluster_offset);
}
buf = qemu_blockalign(bs, s->cluster_size);
if (bytes != s->cluster_size) {
if (bytes > s->cluster_size ||
offset + bytes != bs->total_sectors << BDRV_SECTOR_BITS)
{
qemu_vfree(buf);
return -EINVAL;
}
if (nb_sectors != s->cluster_sectors) {
ret = -EINVAL;
/* Zero-pad last write if image size is not cluster aligned */
memset(buf + bytes, 0, s->cluster_size - bytes);
if (sector_num + nb_sectors == bs->total_sectors &&
nb_sectors < s->cluster_sectors) {
uint8_t *pad_buf = qemu_blockalign(bs, s->cluster_size);
memset(pad_buf, 0, s->cluster_size);
memcpy(pad_buf, buf, nb_sectors * BDRV_SECTOR_SIZE);
ret = qcow2_write_compressed(bs, sector_num,
pad_buf, s->cluster_sectors);
qemu_vfree(pad_buf);
}
return ret;
}
qemu_iovec_to_buf(qiov, 0, buf, bytes);
out_buf = g_malloc(s->cluster_size);
@@ -2599,44 +2647,33 @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
/* could not compress: write normal cluster */
ret = qcow2_co_pwritev(bs, offset, bytes, qiov, 0);
ret = qcow2_write(bs, sector_num, buf, s->cluster_sectors);
if (ret < 0) {
goto fail;
}
} else {
cluster_offset = qcow2_alloc_compressed_cluster_offset(bs,
sector_num << 9, out_len);
if (!cluster_offset) {
ret = -EIO;
goto fail;
}
cluster_offset &= s->cluster_offset_mask;
ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);
if (ret < 0) {
goto fail;
}
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len);
if (ret < 0) {
goto fail;
}
goto success;
}
qemu_co_mutex_lock(&s->lock);
cluster_offset =
qcow2_alloc_compressed_cluster_offset(bs, offset, out_len);
if (!cluster_offset) {
qemu_co_mutex_unlock(&s->lock);
ret = -EIO;
goto fail;
}
cluster_offset &= s->cluster_offset_mask;
ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len);
qemu_co_mutex_unlock(&s->lock);
if (ret < 0) {
goto fail;
}
iov = (struct iovec) {
.iov_base = out_buf,
.iov_len = out_len,
};
qemu_iovec_init_external(&hd_qiov, &iov, 1);
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
ret = bdrv_co_pwritev(bs->file, cluster_offset, out_len, &hd_qiov, 0);
if (ret < 0) {
goto fail;
}
success:
ret = 0;
fail:
qemu_vfree(buf);
g_free(out_buf);
return ret;
}
@@ -3381,7 +3418,7 @@ BlockDriver bdrv_qcow2 = {
.bdrv_co_pwrite_zeroes = qcow2_co_pwrite_zeroes,
.bdrv_co_pdiscard = qcow2_co_pdiscard,
.bdrv_truncate = qcow2_truncate,
.bdrv_co_pwritev_compressed = qcow2_co_pwritev_compressed,
.bdrv_write_compressed = qcow2_write_compressed,
.bdrv_make_empty = qcow2_make_empty,
.bdrv_snapshot_create = qcow2_snapshot_create,

View File

@@ -530,6 +530,7 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
bool exact_size);
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
void qcow2_l2_cache_reset(BlockDriverState *bs);
int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
uint8_t *out_buf, const uint8_t *in_buf,

View File

@@ -737,7 +737,7 @@ static BlockAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs,
void *opaque)
{
return rbd_start_aio(bs, sector_num << BDRV_SECTOR_BITS, qiov,
nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
(int64_t) nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
RBD_AIO_READ);
}
@@ -749,7 +749,7 @@ static BlockAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
void *opaque)
{
return rbd_start_aio(bs, sector_num << BDRV_SECTOR_BITS, qiov,
nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
(int64_t) nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
RBD_AIO_WRITE);
}

View File

@@ -1,659 +0,0 @@
/*
* Replication Block filter
*
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
* Copyright (c) 2016 Intel Corporation
* Copyright (c) 2016 FUJITSU LIMITED
*
* Author:
* Wen Congyang <wency@cn.fujitsu.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "block/nbd.h"
#include "block/blockjob.h"
#include "block/block_int.h"
#include "block/block_backup.h"
#include "sysemu/block-backend.h"
#include "qapi/error.h"
#include "replication.h"
typedef struct BDRVReplicationState {
ReplicationMode mode;
int replication_state;
BdrvChild *active_disk;
BdrvChild *hidden_disk;
BdrvChild *secondary_disk;
char *top_id;
ReplicationState *rs;
Error *blocker;
int orig_hidden_flags;
int orig_secondary_flags;
int error;
} BDRVReplicationState;
enum {
BLOCK_REPLICATION_NONE, /* block replication is not started */
BLOCK_REPLICATION_RUNNING, /* block replication is running */
BLOCK_REPLICATION_FAILOVER, /* failover is running in background */
BLOCK_REPLICATION_FAILOVER_FAILED, /* failover failed */
BLOCK_REPLICATION_DONE, /* block replication is done */
};
static void replication_start(ReplicationState *rs, ReplicationMode mode,
Error **errp);
static void replication_do_checkpoint(ReplicationState *rs, Error **errp);
static void replication_get_error(ReplicationState *rs, Error **errp);
static void replication_stop(ReplicationState *rs, bool failover,
Error **errp);
#define REPLICATION_MODE "mode"
#define REPLICATION_TOP_ID "top-id"
static QemuOptsList replication_runtime_opts = {
.name = "replication",
.head = QTAILQ_HEAD_INITIALIZER(replication_runtime_opts.head),
.desc = {
{
.name = REPLICATION_MODE,
.type = QEMU_OPT_STRING,
},
{
.name = REPLICATION_TOP_ID,
.type = QEMU_OPT_STRING,
},
{ /* end of list */ }
},
};
static ReplicationOps replication_ops = {
.start = replication_start,
.checkpoint = replication_do_checkpoint,
.get_error = replication_get_error,
.stop = replication_stop,
};
static int replication_open(BlockDriverState *bs, QDict *options,
int flags, Error **errp)
{
int ret;
BDRVReplicationState *s = bs->opaque;
Error *local_err = NULL;
QemuOpts *opts = NULL;
const char *mode;
const char *top_id;
ret = -EINVAL;
opts = qemu_opts_create(&replication_runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
if (local_err) {
goto fail;
}
mode = qemu_opt_get(opts, REPLICATION_MODE);
if (!mode) {
error_setg(&local_err, "Missing the option mode");
goto fail;
}
if (!strcmp(mode, "primary")) {
s->mode = REPLICATION_MODE_PRIMARY;
} else if (!strcmp(mode, "secondary")) {
s->mode = REPLICATION_MODE_SECONDARY;
top_id = qemu_opt_get(opts, REPLICATION_TOP_ID);
s->top_id = g_strdup(top_id);
if (!s->top_id) {
error_setg(&local_err, "Missing the option top-id");
goto fail;
}
} else {
error_setg(&local_err,
"The option mode's value should be primary or secondary");
goto fail;
}
s->rs = replication_new(bs, &replication_ops);
ret = 0;
fail:
qemu_opts_del(opts);
error_propagate(errp, local_err);
return ret;
}
static void replication_close(BlockDriverState *bs)
{
BDRVReplicationState *s = bs->opaque;
if (s->replication_state == BLOCK_REPLICATION_RUNNING) {
replication_stop(s->rs, false, NULL);
}
if (s->mode == REPLICATION_MODE_SECONDARY) {
g_free(s->top_id);
}
replication_remove(s->rs);
}
static int64_t replication_getlength(BlockDriverState *bs)
{
return bdrv_getlength(bs->file->bs);
}
static int replication_get_io_status(BDRVReplicationState *s)
{
switch (s->replication_state) {
case BLOCK_REPLICATION_NONE:
return -EIO;
case BLOCK_REPLICATION_RUNNING:
return 0;
case BLOCK_REPLICATION_FAILOVER:
return s->mode == REPLICATION_MODE_PRIMARY ? -EIO : 0;
case BLOCK_REPLICATION_FAILOVER_FAILED:
return s->mode == REPLICATION_MODE_PRIMARY ? -EIO : 1;
case BLOCK_REPLICATION_DONE:
/*
* active commit job completes, and active disk and secondary_disk
* is swapped, so we can operate bs->file directly
*/
return s->mode == REPLICATION_MODE_PRIMARY ? -EIO : 0;
default:
abort();
}
}
static int replication_return_value(BDRVReplicationState *s, int ret)
{
if (s->mode == REPLICATION_MODE_SECONDARY) {
return ret;
}
if (ret < 0) {
s->error = ret;
ret = 0;
}
return ret;
}
static coroutine_fn int replication_co_readv(BlockDriverState *bs,
int64_t sector_num,
int remaining_sectors,
QEMUIOVector *qiov)
{
BDRVReplicationState *s = bs->opaque;
BdrvChild *child = s->secondary_disk;
BlockJob *job = NULL;
CowRequest req;
int ret;
if (s->mode == REPLICATION_MODE_PRIMARY) {
/* We only use it to forward primary write requests */
return -EIO;
}
ret = replication_get_io_status(s);
if (ret < 0) {
return ret;
}
if (child && child->bs) {
job = child->bs->job;
}
if (job) {
backup_wait_for_overlapping_requests(child->bs->job, sector_num,
remaining_sectors);
backup_cow_request_begin(&req, child->bs->job, sector_num,
remaining_sectors);
ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors,
qiov);
backup_cow_request_end(&req);
goto out;
}
ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors, qiov);
out:
return replication_return_value(s, ret);
}
static coroutine_fn int replication_co_writev(BlockDriverState *bs,
int64_t sector_num,
int remaining_sectors,
QEMUIOVector *qiov)
{
BDRVReplicationState *s = bs->opaque;
QEMUIOVector hd_qiov;
uint64_t bytes_done = 0;
BdrvChild *top = bs->file;
BdrvChild *base = s->secondary_disk;
BdrvChild *target;
int ret, n;
ret = replication_get_io_status(s);
if (ret < 0) {
goto out;
}
if (ret == 0) {
ret = bdrv_co_writev(top, sector_num,
remaining_sectors, qiov);
return replication_return_value(s, ret);
}
/*
* Failover failed, only write to active disk if the sectors
* have already been allocated in active disk/hidden disk.
*/
qemu_iovec_init(&hd_qiov, qiov->niov);
while (remaining_sectors > 0) {
ret = bdrv_is_allocated_above(top->bs, base->bs, sector_num,
remaining_sectors, &n);
if (ret < 0) {
goto out1;
}
qemu_iovec_reset(&hd_qiov);
qemu_iovec_concat(&hd_qiov, qiov, bytes_done, n * BDRV_SECTOR_SIZE);
target = ret ? top : base;
ret = bdrv_co_writev(target, sector_num, n, &hd_qiov);
if (ret < 0) {
goto out1;
}
remaining_sectors -= n;
sector_num += n;
bytes_done += n * BDRV_SECTOR_SIZE;
}
out1:
qemu_iovec_destroy(&hd_qiov);
out:
return ret;
}
static bool replication_recurse_is_first_non_filter(BlockDriverState *bs,
BlockDriverState *candidate)
{
return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
}
static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
{
Error *local_err = NULL;
int ret;
if (!s->secondary_disk->bs->job) {
error_setg(errp, "Backup job was cancelled unexpectedly");
return;
}
backup_do_checkpoint(s->secondary_disk->bs->job, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
ret = s->active_disk->bs->drv->bdrv_make_empty(s->active_disk->bs);
if (ret < 0) {
error_setg(errp, "Cannot make active disk empty");
return;
}
ret = s->hidden_disk->bs->drv->bdrv_make_empty(s->hidden_disk->bs);
if (ret < 0) {
error_setg(errp, "Cannot make hidden disk empty");
return;
}
}
static void reopen_backing_file(BDRVReplicationState *s, bool writable,
Error **errp)
{
BlockReopenQueue *reopen_queue = NULL;
int orig_hidden_flags, orig_secondary_flags;
int new_hidden_flags, new_secondary_flags;
Error *local_err = NULL;
if (writable) {
orig_hidden_flags = s->orig_hidden_flags =
bdrv_get_flags(s->hidden_disk->bs);
new_hidden_flags = (orig_hidden_flags | BDRV_O_RDWR) &
~BDRV_O_INACTIVE;
orig_secondary_flags = s->orig_secondary_flags =
bdrv_get_flags(s->secondary_disk->bs);
new_secondary_flags = (orig_secondary_flags | BDRV_O_RDWR) &
~BDRV_O_INACTIVE;
} else {
orig_hidden_flags = (s->orig_hidden_flags | BDRV_O_RDWR) &
~BDRV_O_INACTIVE;
new_hidden_flags = s->orig_hidden_flags;
orig_secondary_flags = (s->orig_secondary_flags | BDRV_O_RDWR) &
~BDRV_O_INACTIVE;
new_secondary_flags = s->orig_secondary_flags;
}
if (orig_hidden_flags != new_hidden_flags) {
reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs, NULL,
new_hidden_flags);
}
if (!(orig_secondary_flags & BDRV_O_RDWR)) {
reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs,
NULL, new_secondary_flags);
}
if (reopen_queue) {
bdrv_reopen_multiple(reopen_queue, &local_err);
error_propagate(errp, local_err);
}
}
static void backup_job_cleanup(BDRVReplicationState *s)
{
BlockDriverState *top_bs;
top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL);
if (!top_bs) {
return;
}
bdrv_op_unblock_all(top_bs, s->blocker);
error_free(s->blocker);
reopen_backing_file(s, false, NULL);
}
static void backup_job_completed(void *opaque, int ret)
{
BDRVReplicationState *s = opaque;
if (s->replication_state != BLOCK_REPLICATION_FAILOVER) {
/* The backup job is cancelled unexpectedly */
s->error = -EIO;
}
backup_job_cleanup(s);
}
static bool check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
{
BdrvChild *child;
/* The bs itself is the top_bs */
if (top_bs == bs) {
return true;
}
/* Iterate over top_bs's children */
QLIST_FOREACH(child, &top_bs->children, next) {
if (child->bs == bs || check_top_bs(child->bs, bs)) {
return true;
}
}
return false;
}
static void replication_start(ReplicationState *rs, ReplicationMode mode,
Error **errp)
{
BlockDriverState *bs = rs->opaque;
BDRVReplicationState *s;
BlockDriverState *top_bs;
int64_t active_length, hidden_length, disk_length;
AioContext *aio_context;
Error *local_err = NULL;
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
s = bs->opaque;
if (s->replication_state != BLOCK_REPLICATION_NONE) {
error_setg(errp, "Block replication is running or done");
aio_context_release(aio_context);
return;
}
if (s->mode != mode) {
error_setg(errp, "The parameter mode's value is invalid, needs %d,"
" but got %d", s->mode, mode);
aio_context_release(aio_context);
return;
}
switch (s->mode) {
case REPLICATION_MODE_PRIMARY:
break;
case REPLICATION_MODE_SECONDARY:
s->active_disk = bs->file;
if (!s->active_disk || !s->active_disk->bs ||
!s->active_disk->bs->backing) {
error_setg(errp, "Active disk doesn't have backing file");
aio_context_release(aio_context);
return;
}
s->hidden_disk = s->active_disk->bs->backing;
if (!s->hidden_disk->bs || !s->hidden_disk->bs->backing) {
error_setg(errp, "Hidden disk doesn't have backing file");
aio_context_release(aio_context);
return;
}
s->secondary_disk = s->hidden_disk->bs->backing;
if (!s->secondary_disk->bs || !bdrv_has_blk(s->secondary_disk->bs)) {
error_setg(errp, "The secondary disk doesn't have block backend");
aio_context_release(aio_context);
return;
}
/* verify the length */
active_length = bdrv_getlength(s->active_disk->bs);
hidden_length = bdrv_getlength(s->hidden_disk->bs);
disk_length = bdrv_getlength(s->secondary_disk->bs);
if (active_length < 0 || hidden_length < 0 || disk_length < 0 ||
active_length != hidden_length || hidden_length != disk_length) {
error_setg(errp, "Active disk, hidden disk, secondary disk's length"
" are not the same");
aio_context_release(aio_context);
return;
}
if (!s->active_disk->bs->drv->bdrv_make_empty ||
!s->hidden_disk->bs->drv->bdrv_make_empty) {
error_setg(errp,
"Active disk or hidden disk doesn't support make_empty");
aio_context_release(aio_context);
return;
}
/* reopen the backing file in r/w mode */
reopen_backing_file(s, true, &local_err);
if (local_err) {
error_propagate(errp, local_err);
aio_context_release(aio_context);
return;
}
/* start backup job now */
error_setg(&s->blocker,
"Block device is in use by internal backup job");
top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL);
if (!top_bs || !bdrv_is_root_node(top_bs) ||
!check_top_bs(top_bs, bs)) {
error_setg(errp, "No top_bs or it is invalid");
reopen_backing_file(s, false, NULL);
aio_context_release(aio_context);
return;
}
bdrv_op_block_all(top_bs, s->blocker);
bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker);
backup_start("replication-backup", s->secondary_disk->bs,
s->hidden_disk->bs, 0, MIRROR_SYNC_MODE_NONE, NULL, false,
BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
backup_job_completed, s, NULL, &local_err);
if (local_err) {
error_propagate(errp, local_err);
backup_job_cleanup(s);
aio_context_release(aio_context);
return;
}
break;
default:
aio_context_release(aio_context);
abort();
}
s->replication_state = BLOCK_REPLICATION_RUNNING;
if (s->mode == REPLICATION_MODE_SECONDARY) {
secondary_do_checkpoint(s, errp);
}
s->error = 0;
aio_context_release(aio_context);
}
static void replication_do_checkpoint(ReplicationState *rs, Error **errp)
{
BlockDriverState *bs = rs->opaque;
BDRVReplicationState *s;
AioContext *aio_context;
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
s = bs->opaque;
if (s->mode == REPLICATION_MODE_SECONDARY) {
secondary_do_checkpoint(s, errp);
}
aio_context_release(aio_context);
}
static void replication_get_error(ReplicationState *rs, Error **errp)
{
BlockDriverState *bs = rs->opaque;
BDRVReplicationState *s;
AioContext *aio_context;
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
s = bs->opaque;
if (s->replication_state != BLOCK_REPLICATION_RUNNING) {
error_setg(errp, "Block replication is not running");
aio_context_release(aio_context);
return;
}
if (s->error) {
error_setg(errp, "I/O error occurred");
aio_context_release(aio_context);
return;
}
aio_context_release(aio_context);
}
static void replication_done(void *opaque, int ret)
{
BlockDriverState *bs = opaque;
BDRVReplicationState *s = bs->opaque;
if (ret == 0) {
s->replication_state = BLOCK_REPLICATION_DONE;
/* refresh top bs's filename */
bdrv_refresh_filename(bs);
s->active_disk = NULL;
s->secondary_disk = NULL;
s->hidden_disk = NULL;
s->error = 0;
} else {
s->replication_state = BLOCK_REPLICATION_FAILOVER_FAILED;
s->error = -EIO;
}
}
static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
{
BlockDriverState *bs = rs->opaque;
BDRVReplicationState *s;
AioContext *aio_context;
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
s = bs->opaque;
if (s->replication_state != BLOCK_REPLICATION_RUNNING) {
error_setg(errp, "Block replication is not running");
aio_context_release(aio_context);
return;
}
switch (s->mode) {
case REPLICATION_MODE_PRIMARY:
s->replication_state = BLOCK_REPLICATION_DONE;
s->error = 0;
break;
case REPLICATION_MODE_SECONDARY:
/*
* This BDS will be closed, and the job should be completed
* before the BDS is closed, because we will access hidden
* disk, secondary disk in backup_job_completed().
*/
if (s->secondary_disk->bs->job) {
block_job_cancel_sync(s->secondary_disk->bs->job);
}
if (!failover) {
secondary_do_checkpoint(s, errp);
s->replication_state = BLOCK_REPLICATION_DONE;
aio_context_release(aio_context);
return;
}
s->replication_state = BLOCK_REPLICATION_FAILOVER;
commit_active_start("replication-commit", s->active_disk->bs,
s->secondary_disk->bs, 0, BLOCKDEV_ON_ERROR_REPORT,
replication_done,
bs, errp, true);
break;
default:
aio_context_release(aio_context);
abort();
}
aio_context_release(aio_context);
}
BlockDriver bdrv_replication = {
.format_name = "replication",
.protocol_name = "replication",
.instance_size = sizeof(BDRVReplicationState),
.bdrv_open = replication_open,
.bdrv_close = replication_close,
.bdrv_getlength = replication_getlength,
.bdrv_co_readv = replication_co_readv,
.bdrv_co_writev = replication_co_writev,
.is_filter = true,
.bdrv_recurse_is_first_non_filter = replication_recurse_is_first_non_filter,
.has_variable_length = true,
};
static void bdrv_replication_init(void)
{
bdrv_register(&bdrv_replication);
}
block_init(bdrv_replication_init);

View File

@@ -1049,7 +1049,7 @@ static int parse_vdiname(BDRVSheepdogState *s, const char *filename,
const char *host_spec, *vdi_spec;
int nr_sep, ret;
strstart(filename, "sheepdog:", &filename);
strstart(filename, "sheepdog:", (const char **)&filename);
p = q = g_strdup(filename);
/* count the number of separators */
@@ -2652,7 +2652,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
req.opcode = SD_OP_READ_VDIS;
req.data_length = max;
ret = do_req(fd, s->aio_context, &req,
ret = do_req(fd, s->aio_context, (SheepdogReq *)&req,
vdi_inuse, &wlen, &rlen);
closesocket(fd);
@@ -2820,8 +2820,9 @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
iov.iov_len = sizeof(zero);
discard_iov.iov = &iov;
discard_iov.niov = 1;
assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
assert((count & (BDRV_SECTOR_SIZE - 1)) == 0);
if (!QEMU_IS_ALIGNED(offset | count, BDRV_SECTOR_SIZE)) {
return -ENOTSUP;
}
acb = sd_aio_setup(bs, &discard_iov, offset >> BDRV_SECTOR_BITS,
count >> BDRV_SECTOR_BITS);
acb->aiocb_type = AIOCB_DISCARD_OBJ;

View File

@@ -168,6 +168,22 @@ static BlockBackend *throttle_group_next_blk(BlockBackend *blk)
return blk_by_public(next);
}
/*
* Return whether a BlockBackend has pending requests.
*
* This assumes that tg->lock is held.
*
* @blk: the BlockBackend
* @is_write: the type of operation (read/write)
* @ret: whether the BlockBackend has pending requests.
*/
static inline bool blk_has_pending_reqs(BlockBackend *blk,
bool is_write)
{
const BlockBackendPublic *blkp = blk_get_public(blk);
return blkp->pending_reqs[is_write];
}
/* Return the next BlockBackend in the round-robin sequence with pending I/O
* requests.
*
@@ -188,7 +204,7 @@ static BlockBackend *next_throttle_token(BlockBackend *blk, bool is_write)
/* get next bs round in round robin style */
token = throttle_group_next_blk(token);
while (token != start && !blkp->pending_reqs[is_write]) {
while (token != start && !blk_has_pending_reqs(token, is_write)) {
token = throttle_group_next_blk(token);
}
@@ -196,10 +212,13 @@ static BlockBackend *next_throttle_token(BlockBackend *blk, bool is_write)
* then decide the token is the current bs because chances are
* the current bs get the current request queued.
*/
if (token == start && !blkp->pending_reqs[is_write]) {
if (token == start && !blk_has_pending_reqs(token, is_write)) {
token = blk;
}
/* Either we return the original BB, or one with pending requests */
assert(token == blk || blk_has_pending_reqs(token, is_write));
return token;
}
@@ -257,7 +276,7 @@ static void schedule_next_request(BlockBackend *blk, bool is_write)
/* Check if there's any pending request to schedule next */
token = next_throttle_token(blk, is_write);
if (!blkp->pending_reqs[is_write]) {
if (!blk_has_pending_reqs(token, is_write)) {
return;
}
@@ -271,7 +290,7 @@ static void schedule_next_request(BlockBackend *blk, bool is_write)
qemu_co_queue_next(&blkp->throttled_reqs[is_write])) {
token = blk;
} else {
ThrottleTimers *tt = &blkp->throttle_timers;
ThrottleTimers *tt = &blk_get_public(token)->throttle_timers;
int64_t now = qemu_clock_get_ns(tt->clock_type);
timer_mod(tt->timers[is_write], now + 1);
tg->any_timer_armed[is_write] = true;

View File

@@ -58,7 +58,14 @@
#include "migration/migration.h"
#include "qemu/coroutine.h"
#include "qemu/cutils.h"
#include "qemu/uuid.h"
#if defined(CONFIG_UUID)
#include <uuid/uuid.h>
#else
/* TODO: move uuid emulation to some central place in QEMU. */
#include "sysemu/sysemu.h" /* UUID_FMT */
typedef unsigned char uuid_t[16];
#endif
/* Code configuration options. */
@@ -133,6 +140,28 @@
#define VDI_DISK_SIZE_MAX ((uint64_t)VDI_BLOCKS_IN_IMAGE_MAX * \
(uint64_t)DEFAULT_CLUSTER_SIZE)
#if !defined(CONFIG_UUID)
static inline void uuid_generate(uuid_t out)
{
memset(out, 0, sizeof(uuid_t));
}
static inline int uuid_is_null(const uuid_t uu)
{
uuid_t null_uuid = { 0 };
return memcmp(uu, null_uuid, sizeof(uuid_t)) == 0;
}
# if defined(CONFIG_VDI_DEBUG)
static inline void uuid_unparse(const uuid_t uu, char *out)
{
snprintf(out, 37, UUID_FMT,
uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7],
uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
}
# endif
#endif
typedef struct {
char text[0x40];
uint32_t signature;
@@ -153,10 +182,10 @@ typedef struct {
uint32_t block_extra; /* unused here */
uint32_t blocks_in_image;
uint32_t blocks_allocated;
QemuUUID uuid_image;
QemuUUID uuid_last_snap;
QemuUUID uuid_link;
QemuUUID uuid_parent;
uuid_t uuid_image;
uuid_t uuid_last_snap;
uuid_t uuid_link;
uuid_t uuid_parent;
uint64_t unused2[7];
} QEMU_PACKED VdiHeader;
@@ -177,6 +206,16 @@ typedef struct {
Error *migration_blocker;
} BDRVVdiState;
/* Change UUID from little endian (IPRT = VirtualBox format) to big endian
* format (network byte order, standard, see RFC 4122) and vice versa.
*/
static void uuid_convert(uuid_t uuid)
{
bswap32s((uint32_t *)&uuid[0]);
bswap16s((uint16_t *)&uuid[4]);
bswap16s((uint16_t *)&uuid[6]);
}
static void vdi_header_to_cpu(VdiHeader *header)
{
le32_to_cpus(&header->signature);
@@ -195,10 +234,10 @@ static void vdi_header_to_cpu(VdiHeader *header)
le32_to_cpus(&header->block_extra);
le32_to_cpus(&header->blocks_in_image);
le32_to_cpus(&header->blocks_allocated);
qemu_uuid_bswap(&header->uuid_image);
qemu_uuid_bswap(&header->uuid_last_snap);
qemu_uuid_bswap(&header->uuid_link);
qemu_uuid_bswap(&header->uuid_parent);
uuid_convert(header->uuid_image);
uuid_convert(header->uuid_last_snap);
uuid_convert(header->uuid_link);
uuid_convert(header->uuid_parent);
}
static void vdi_header_to_le(VdiHeader *header)
@@ -219,10 +258,10 @@ static void vdi_header_to_le(VdiHeader *header)
cpu_to_le32s(&header->block_extra);
cpu_to_le32s(&header->blocks_in_image);
cpu_to_le32s(&header->blocks_allocated);
qemu_uuid_bswap(&header->uuid_image);
qemu_uuid_bswap(&header->uuid_last_snap);
qemu_uuid_bswap(&header->uuid_link);
qemu_uuid_bswap(&header->uuid_parent);
uuid_convert(header->uuid_image);
uuid_convert(header->uuid_last_snap);
uuid_convert(header->uuid_link);
uuid_convert(header->uuid_parent);
}
#if defined(CONFIG_VDI_DEBUG)
@@ -430,11 +469,11 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
(uint64_t)header.blocks_in_image * header.block_size);
ret = -ENOTSUP;
goto fail;
} else if (!qemu_uuid_is_null(&header.uuid_link)) {
} else if (!uuid_is_null(header.uuid_link)) {
error_setg(errp, "unsupported VDI image (non-NULL link UUID)");
ret = -ENOTSUP;
goto fail;
} else if (!qemu_uuid_is_null(&header.uuid_parent)) {
} else if (!uuid_is_null(header.uuid_parent)) {
error_setg(errp, "unsupported VDI image (non-NULL parent UUID)");
ret = -ENOTSUP;
goto fail;
@@ -782,8 +821,8 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
if (image_type == VDI_TYPE_STATIC) {
header.blocks_allocated = blocks;
}
qemu_uuid_generate(&header.uuid_image);
qemu_uuid_generate(&header.uuid_last_snap);
uuid_generate(header.uuid_image);
uuid_generate(header.uuid_last_snap);
/* There is no need to set header.uuid_link or header.uuid_parent here. */
#if defined(CONFIG_VDI_DEBUG)
vdi_header_print(&header);

View File

@@ -21,6 +21,9 @@
#include "qemu/bswap.h"
#include "block/vhdx.h"
#include <uuid/uuid.h>
/*
* All the VHDX formats on disk are little endian - the following
* are helper import/export functions to correctly convert

View File

@@ -25,7 +25,8 @@
#include "qemu/bswap.h"
#include "block/vhdx.h"
#include "migration/migration.h"
#include "qemu/uuid.h"
#include <uuid/uuid.h>
/* Options for VHDX creation */
@@ -212,11 +213,11 @@ bool vhdx_checksum_is_valid(uint8_t *buf, size_t size, int crc_offset)
*/
void vhdx_guid_generate(MSGUID *guid)
{
QemuUUID uuid;
uuid_t uuid;
assert(guid != NULL);
qemu_uuid_generate(&uuid);
memcpy(guid, &uuid, sizeof(MSGUID));
uuid_generate(uuid);
memcpy(guid, uuid, sizeof(MSGUID));
}
/* Check for region overlaps inside the VHDX image */

View File

@@ -1645,11 +1645,56 @@ vmdk_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
return ret;
}
static int coroutine_fn
vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov)
typedef struct VmdkWriteCompressedCo {
BlockDriverState *bs;
int64_t sector_num;
const uint8_t *buf;
int nb_sectors;
int ret;
} VmdkWriteCompressedCo;
static void vmdk_co_write_compressed(void *opaque)
{
return vmdk_co_pwritev(bs, offset, bytes, qiov, 0);
VmdkWriteCompressedCo *co = opaque;
QEMUIOVector local_qiov;
uint64_t offset = co->sector_num * BDRV_SECTOR_SIZE;
uint64_t bytes = co->nb_sectors * BDRV_SECTOR_SIZE;
struct iovec iov = (struct iovec) {
.iov_base = (uint8_t*) co->buf,
.iov_len = bytes,
};
qemu_iovec_init_external(&local_qiov, &iov, 1);
co->ret = vmdk_pwritev(co->bs, offset, bytes, &local_qiov, false, false);
}
static int vmdk_write_compressed(BlockDriverState *bs,
int64_t sector_num,
const uint8_t *buf,
int nb_sectors)
{
BDRVVmdkState *s = bs->opaque;
if (s->num_extents == 1 && s->extents[0].compressed) {
Coroutine *co;
AioContext *aio_context = bdrv_get_aio_context(bs);
VmdkWriteCompressedCo data = {
.bs = bs,
.sector_num = sector_num,
.buf = buf,
.nb_sectors = nb_sectors,
.ret = -EINPROGRESS,
};
co = qemu_coroutine_create(vmdk_co_write_compressed, &data);
qemu_coroutine_enter(co);
while (data.ret == -EINPROGRESS) {
aio_poll(aio_context, true);
}
return data.ret;
} else {
return -ENOTSUP;
}
}
static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
@@ -2348,7 +2393,7 @@ static BlockDriver bdrv_vmdk = {
.bdrv_reopen_prepare = vmdk_reopen_prepare,
.bdrv_co_preadv = vmdk_co_preadv,
.bdrv_co_pwritev = vmdk_co_pwritev,
.bdrv_co_pwritev_compressed = vmdk_co_pwritev_compressed,
.bdrv_write_compressed = vmdk_write_compressed,
.bdrv_co_pwrite_zeroes = vmdk_co_pwrite_zeroes,
.bdrv_close = vmdk_close,
.bdrv_create = vmdk_create,

View File

@@ -30,7 +30,9 @@
#include "qemu/module.h"
#include "migration/migration.h"
#include "qemu/bswap.h"
#include "qemu/uuid.h"
#if defined(CONFIG_UUID)
#include <uuid/uuid.h>
#endif
/**************************************************************/
@@ -87,7 +89,7 @@ typedef struct vhd_footer {
uint32_t checksum;
/* UUID used to identify a parent hard disk (backing file) */
QemuUUID uuid;
uint8_t uuid[16];
uint8_t in_saved_state;
} QEMU_PACKED VHDFooter;
@@ -978,7 +980,9 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
footer->type = cpu_to_be32(disk_type);
qemu_uuid_generate(&footer->uuid);
#if defined(CONFIG_UUID)
uuid_generate(footer->uuid);
#endif
footer->checksum = cpu_to_be32(vpc_checksum(buf, HEADER_SIZE));

View File

@@ -2971,8 +2971,7 @@ static BlockDriver vvfat_write_target = {
static void vvfat_qcow_options(int *child_flags, QDict *child_options,
int parent_flags, QDict *parent_options)
{
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
*child_flags = BDRV_O_NO_FLUSH;
*child_flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH;
}
static const BdrvChildRole child_vvfat_qcow = {

View File

@@ -145,8 +145,7 @@ void qmp_nbd_server_start(SocketAddress *addr,
void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
Error **errp)
{
BlockDriverState *bs = NULL;
BlockBackend *on_eject_blk;
BlockBackend *blk;
NBDExport *exp;
if (!nbd_server) {
@@ -159,22 +158,26 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
return;
}
on_eject_blk = blk_by_name(device);
bs = bdrv_lookup_bs(device, device, errp);
if (!bs) {
blk = blk_by_name(device);
if (!blk) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", device);
return;
}
if (!blk_is_inserted(blk)) {
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
return;
}
if (!has_writable) {
writable = false;
}
if (bdrv_is_read_only(bs)) {
if (blk_is_read_only(blk)) {
writable = false;
}
exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY,
NULL, false, on_eject_blk, errp);
exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL,
errp);
if (!exp) {
return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -132,10 +132,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
if (job_id == NULL) {
job_id = bdrv_get_device_name(bs);
if (!*job_id) {
error_setg(errp, "An explicit job ID is required for this node");
return NULL;
}
}
if (!id_wellformed(job_id)) {

148
configure vendored
View File

@@ -212,6 +212,7 @@ sdlabi=""
virtfs=""
vnc="yes"
sparse="no"
uuid=""
vde=""
vnc_sasl=""
vnc_jpeg=""
@@ -228,7 +229,6 @@ xfs=""
vhost_net="no"
vhost_scsi="no"
vhost_vsock="no"
kvm="no"
rdma=""
gprof="no"
@@ -316,10 +316,10 @@ vte=""
virglrenderer=""
tpm="yes"
libssh2=""
vhdx=""
numa=""
tcmalloc="no"
jemalloc="no"
replication="yes"
# parse CC options first
for opt do
@@ -388,11 +388,7 @@ sdl2_config="${SDL2_CONFIG-${cross_prefix}sdl2-config}"
ARFLAGS="${ARFLAGS-rv}"
# default flags for all hosts
# We use -fwrapv to tell the compiler that we require a C dialect where
# left shift of signed integers is well defined and has the expected
# 2s-complement style results. (Both clang and gcc agree that it
# provides these semantics.)
QEMU_CFLAGS="-fno-strict-aliasing -fno-common -fwrapv $QEMU_CFLAGS"
QEMU_CFLAGS="-fno-strict-aliasing -fno-common $QEMU_CFLAGS"
QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
@@ -509,6 +505,8 @@ elif check_define __arm__ ; then
cpu="arm"
elif check_define __aarch64__ ; then
cpu="aarch64"
elif check_define __hppa__ ; then
cpu="hppa"
else
cpu=$(uname -m)
fi
@@ -676,7 +674,6 @@ Haiku)
kvm="yes"
vhost_net="yes"
vhost_scsi="yes"
vhost_vsock="yes"
QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES"
;;
esac
@@ -885,6 +882,10 @@ for opt do
;;
--disable-slirp) slirp="no"
;;
--disable-uuid) uuid="no"
;;
--enable-uuid) uuid="yes"
;;
--disable-vde) vde="no"
;;
--enable-vde) vde="yes"
@@ -1016,10 +1017,6 @@ for opt do
;;
--enable-vhost-scsi) vhost_scsi="yes"
;;
--disable-vhost-vsock) vhost_vsock="no"
;;
--enable-vhost-vsock) vhost_vsock="yes"
;;
--disable-opengl) opengl="no"
;;
--enable-opengl) opengl="yes"
@@ -1097,12 +1094,6 @@ for opt do
--disable-virtio-blk-data-plane|--enable-virtio-blk-data-plane)
echo "$0: $opt is obsolete, virtio-blk data-plane is always on" >&2
;;
--enable-vhdx|--disable-vhdx)
echo "$0: $opt is obsolete, VHDX driver is always built" >&2
;;
--enable-uuid|--disable-uuid)
echo "$0: $opt is obsolete, UUID support is always built" >&2
;;
--disable-gtk) gtk="no"
;;
--enable-gtk) gtk="yes"
@@ -1143,6 +1134,10 @@ for opt do
;;
--enable-libssh2) libssh2="yes"
;;
--enable-vhdx) vhdx="yes"
;;
--disable-vhdx) vhdx="no"
;;
--disable-numa) numa="no"
;;
--enable-numa) numa="yes"
@@ -1155,10 +1150,6 @@ for opt do
;;
--enable-jemalloc) jemalloc="yes"
;;
--disable-replication) replication="no"
;;
--enable-replication) replication="yes"
;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
@@ -1361,6 +1352,7 @@ disabled with --disable-FEATURE, default is enabled if available:
bluez bluez stack connectivity
kvm KVM acceleration support
rdma RDMA-based migration support
uuid uuid support
vde support for vde network
netmap support for netmap network
linux-aio Linux AIO support
@@ -1384,10 +1376,10 @@ disabled with --disable-FEATURE, default is enabled if available:
archipelago Archipelago backend
tpm TPM support
libssh2 ssh block device support
vhdx support for the Microsoft VHDX image format
numa libnuma support
tcmalloc tcmalloc support
jemalloc jemalloc support
replication replication support
NOTE: The object files are built at the place where configure is launched
EOF
@@ -1796,19 +1788,28 @@ fi
##########################################
# avx2 optimization requirement check
cat > $TMPC << EOF
if test "$static" = "no" ; then
cat > $TMPC << EOF
#pragma GCC push_options
#pragma GCC target("avx2")
#include <cpuid.h>
#include <immintrin.h>
static int bar(void *a) {
__m256i x = *(__m256i *)a;
return _mm256_testz_si256(x, x);
return _mm256_movemask_epi8(_mm256_cmpeq_epi8(*(__m256i *)a, (__m256i){0}));
}
int main(int argc, char *argv[]) { return bar(argv[0]); }
static void *bar_ifunc(void) {return (void*) bar;}
int foo(void *a) __attribute__((ifunc("bar_ifunc")));
int main(int argc, char *argv[]) { return foo(argv[0]);}
EOF
if compile_object "" ; then
avx2_opt="yes"
if compile_object "" ; then
if has readelf; then
if readelf --syms $TMPO 2>/dev/null |grep -q "IFUNC.*foo"; then
avx2_opt="yes"
fi
fi
fi
fi
#########################################
@@ -2655,6 +2656,47 @@ if compile_prog "" "" ; then
fnmatch="yes"
fi
##########################################
# uuid_generate() probe, used for vdi block driver
# Note that on some systems (notably MacOSX) no extra library
# need be linked to get the uuid functions.
if test "$uuid" != "no" ; then
uuid_libs="-luuid"
cat > $TMPC << EOF
#include <uuid/uuid.h>
int main(void)
{
uuid_t my_uuid;
uuid_generate(my_uuid);
return 0;
}
EOF
if compile_prog "" "" ; then
uuid="yes"
elif compile_prog "" "$uuid_libs" ; then
uuid="yes"
libs_softmmu="$uuid_libs $libs_softmmu"
libs_tools="$uuid_libs $libs_tools"
else
if test "$uuid" = "yes" ; then
feature_not_found "uuid" "Install libuuid devel"
fi
uuid=no
fi
fi
if test "$vhdx" = "yes" ; then
if test "$uuid" = "no" ; then
error_exit "uuid required for VHDX support"
fi
elif test "$vhdx" != "no" ; then
if test "$uuid" = "yes" ; then
vhdx=yes
else
vhdx=no
fi
fi
##########################################
# xfsctl() probe, used for raw-posix
if test "$xfs" != "no" ; then
@@ -2967,7 +3009,7 @@ fi
# g_test_trap_subprocess added in 2.38. Used by some tests.
glib_subprocess=yes
if test "$mingw32" = "yes" || ! $pkg_config --atleast-version=2.38 glib-2.0; then
if ! $pkg_config --atleast-version=2.38 glib-2.0; then
glib_subprocess=no
fi
@@ -4028,7 +4070,7 @@ EOF
if compile_prog "$vss_win32_include" "" ; then
guest_agent_with_vss="yes"
QEMU_CFLAGS="$QEMU_CFLAGS $vss_win32_include"
libs_qga="-lole32 -loleaut32 -lshlwapi -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga"
libs_qga="-lole32 -loleaut32 -lshlwapi -luuid -lstdc++ -Wl,--enable-stdcall-fixup $libs_qga"
qga_vss_provider="qga/vss-win32/qga-vss.dll qga/vss-win32/qga-vss.tlb"
else
if test "$vss_win32_sdk" != "" ; then
@@ -4149,18 +4191,6 @@ if compile_prog "" "" ; then
posix_madvise=yes
fi
##########################################
# check if we have posix_syslog
posix_syslog=no
cat > $TMPC << EOF
#include <syslog.h>
int main(void) { openlog("qemu", LOG_PID, LOG_DAEMON); syslog(LOG_INFO, "configure"); return 0; }
EOF
if compile_prog "" "" ; then
posix_syslog=yes
fi
##########################################
# check if trace backend exists
@@ -4531,6 +4561,7 @@ if test "$libnfs" != "no" ; then
if $pkg_config --atleast-version=1.9.3 libnfs; then
libnfs="yes"
libnfs_libs=$($pkg_config --libs libnfs)
LIBS="$LIBS $libnfs_libs"
else
if test "$libnfs" = "yes" ; then
feature_not_found "libnfs" "Install libnfs devel >= 1.9.3"
@@ -4836,10 +4867,10 @@ echo "preadv support $preadv"
echo "fdatasync $fdatasync"
echo "madvise $madvise"
echo "posix_madvise $posix_madvise"
echo "uuid support $uuid"
echo "libcap-ng support $cap_ng"
echo "vhost-net support $vhost_net"
echo "vhost-scsi support $vhost_scsi"
echo "vhost-vsock support $vhost_vsock"
echo "Trace backends $trace_backends"
if have_backend "simple"; then
echo "Trace output file $trace_file-<pid>"
@@ -4869,6 +4900,7 @@ echo "TPM support $tpm"
echo "libssh2 support $libssh2"
echo "TPM passthrough $tpm_passthrough"
echo "QOM debugging $qom_cast_debug"
echo "vhdx $vhdx"
echo "lzo support $lzo"
echo "snappy support $snappy"
echo "bzip2 support $bzip2"
@@ -4876,7 +4908,6 @@ echo "NUMA host support $numa"
echo "tcmalloc support $tcmalloc"
echo "jemalloc support $jemalloc"
echo "avx2 optimization $avx2_opt"
echo "replication support $replication"
if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -5025,6 +5056,9 @@ fi
if test "$fnmatch" = "yes" ; then
echo "CONFIG_FNMATCH=y" >> $config_host_mak
fi
if test "$uuid" = "yes" ; then
echo "CONFIG_UUID=y" >> $config_host_mak
fi
if test "$xfs" = "yes" ; then
echo "CONFIG_XFS=y" >> $config_host_mak
fi
@@ -5218,9 +5252,6 @@ fi
if test "$vhost_net" = "yes" ; then
echo "CONFIG_VHOST_NET_USED=y" >> $config_host_mak
fi
if test "$vhost_vsock" = "yes" ; then
echo "CONFIG_VHOST_VSOCK=y" >> $config_host_mak
fi
if test "$blobs" = "yes" ; then
echo "INSTALL_BLOBS=yes" >> $config_host_mak
fi
@@ -5298,8 +5329,7 @@ if test "$libiscsi" = "yes" ; then
fi
if test "$libnfs" = "yes" ; then
echo "CONFIG_LIBNFS=m" >> $config_host_mak
echo "LIBNFS_LIBS=$libnfs_libs" >> $config_host_mak
echo "CONFIG_LIBNFS=y" >> $config_host_mak
fi
if test "$seccomp" = "yes"; then
@@ -5391,6 +5421,10 @@ if test "$libssh2" = "yes" ; then
echo "LIBSSH2_LIBS=$libssh2_libs" >> $config_host_mak
fi
if test "$vhdx" = "yes" ; then
echo "CONFIG_VHDX=y" >> $config_host_mak
fi
# USB host support
if test "$libusb" = "yes"; then
echo "HOST_USB=libusb legacy" >> $config_host_mak
@@ -5434,13 +5468,6 @@ if have_backend "ftrace"; then
feature_not_found "ftrace(trace backend)" "ftrace requires Linux"
fi
fi
if have_backend "syslog"; then
if test "$posix_syslog" = "yes" ; then
echo "CONFIG_TRACE_SYSLOG=y" >> $config_host_mak
else
feature_not_found "syslog(trace backend)" "syslog not available"
fi
fi
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
if test "$rdma" = "yes" ; then
@@ -5451,10 +5478,6 @@ if test "$have_rtnetlink" = "yes" ; then
echo "CONFIG_RTNETLINK=y" >> $config_host_mak
fi
if test "$replication" = "yes" ; then
echo "CONFIG_REPLICATION=y" >> $config_host_mak
fi
# Hold two types of flag:
# CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on
# a thread we have a handle to
@@ -5841,6 +5864,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
cris)
disas_config "CRIS"
;;
hppa)
disas_config "HPPA"
;;
i386|x86_64|x32)
disas_config "I386"
;;

View File

@@ -147,8 +147,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
itb->tc_ptr, itb->pc, lookup_symbol(itb->pc));
#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)
&& qemu_log_in_addr_range(itb->pc)) {
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
#if defined(TARGET_I386)
log_cpu_state(cpu, CPU_DUMP_CCOP);
#elif defined(TARGET_M68K)
@@ -242,8 +241,7 @@ static bool tb_cmp(const void *p, const void *d)
if (tb->pc == desc->pc &&
tb->page_addr[0] == desc->phys_page1 &&
tb->cs_base == desc->cs_base &&
tb->flags == desc->flags &&
!atomic_read(&tb->invalid)) {
tb->flags == desc->flags) {
/* check next page if needed */
if (tb->page_addr[1] == -1) {
return true;
@@ -261,7 +259,7 @@ static bool tb_cmp(const void *p, const void *d)
return false;
}
static TranslationBlock *tb_htable_lookup(CPUState *cpu,
static TranslationBlock *tb_find_physical(CPUState *cpu,
target_ulong pc,
target_ulong cs_base,
uint32_t flags)
@@ -280,48 +278,72 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu,
return qht_lookup(&tcg_ctx.tb_ctx.htable, tb_cmp, &desc, h);
}
static inline TranslationBlock *tb_find(CPUState *cpu,
TranslationBlock *last_tb,
int tb_exit)
static TranslationBlock *tb_find_slow(CPUState *cpu,
target_ulong pc,
target_ulong cs_base,
uint32_t flags)
{
TranslationBlock *tb;
tb = tb_find_physical(cpu, pc, cs_base, flags);
if (tb) {
goto found;
}
#ifdef CONFIG_USER_ONLY
/* mmap_lock is needed by tb_gen_code, and mmap_lock must be
* taken outside tb_lock. Since we're momentarily dropping
* tb_lock, there's a chance that our desired tb has been
* translated.
*/
tb_unlock();
mmap_lock();
tb_lock();
tb = tb_find_physical(cpu, pc, cs_base, flags);
if (tb) {
mmap_unlock();
goto found;
}
#endif
/* if no translated code available, then translate it now */
tb = tb_gen_code(cpu, pc, cs_base, flags, 0);
#ifdef CONFIG_USER_ONLY
mmap_unlock();
#endif
found:
/* we add the TB in the virtual pc hash table */
cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
return tb;
}
static inline TranslationBlock *tb_find_fast(CPUState *cpu,
TranslationBlock **last_tb,
int tb_exit)
{
CPUArchState *env = (CPUArchState *)cpu->env_ptr;
TranslationBlock *tb;
target_ulong cs_base, pc;
uint32_t flags;
bool have_tb_lock = false;
/* we record a subset of the CPU state. It will
always be the same before a given translated block
is executed. */
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
tb = atomic_rcu_read(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]);
tb_lock();
tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
tb->flags != flags)) {
tb = tb_htable_lookup(cpu, pc, cs_base, flags);
if (!tb) {
/* mmap_lock is needed by tb_gen_code, and mmap_lock must be
* taken outside tb_lock. As system emulation is currently
* single threaded the locks are NOPs.
*/
mmap_lock();
tb_lock();
have_tb_lock = true;
/* There's a chance that our desired tb has been translated while
* taking the locks so we check again inside the lock.
*/
tb = tb_htable_lookup(cpu, pc, cs_base, flags);
if (!tb) {
/* if no translated code available, then translate it now */
tb = tb_gen_code(cpu, pc, cs_base, flags, 0);
}
mmap_unlock();
}
/* We add the TB in the virtual pc hash table for the fast lookup */
atomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
tb = tb_find_slow(cpu, pc, cs_base, flags);
}
if (cpu->tb_flushed) {
/* Ensure that no TB jump will be modified as the
* translation buffer has been flushed.
*/
*last_tb = NULL;
cpu->tb_flushed = false;
}
#ifndef CONFIG_USER_ONLY
/* We don't take care of direct jumps when address mapping changes in
@@ -329,25 +351,14 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
* spanning two pages because the mapping for the second page can change.
*/
if (tb->page_addr[1] != -1) {
last_tb = NULL;
*last_tb = NULL;
}
#endif
/* See if we can patch the calling TB. */
if (last_tb && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
if (!have_tb_lock) {
tb_lock();
have_tb_lock = true;
}
/* Check if translation buffer has been flushed */
if (cpu->tb_flushed) {
cpu->tb_flushed = false;
} else if (!tb->invalid) {
tb_add_jump(last_tb, tb_exit, tb);
}
}
if (have_tb_lock) {
tb_unlock();
if (*last_tb && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
tb_add_jump(*last_tb, tb_exit, tb);
}
tb_unlock();
return tb;
}
@@ -426,7 +437,8 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
} else if (replay_has_exception()
&& cpu->icount_decr.u16.low + cpu->icount_extra == 0) {
/* try to cause an exception pending in the log */
cpu_exec_nocache(cpu, 1, tb_find(cpu, NULL, 0), true);
TranslationBlock *last_tb = NULL; /* Avoid chaining TBs */
cpu_exec_nocache(cpu, 1, tb_find_fast(cpu, &last_tb, 0), true);
*ret = -1;
return true;
#endif
@@ -606,10 +618,10 @@ int cpu_exec(CPUState *cpu)
break;
}
atomic_mb_set(&cpu->tb_flushed, false); /* reset before first TB lookup */
cpu->tb_flushed = false; /* reset before first TB lookup */
for(;;) {
cpu_handle_interrupt(cpu, &last_tb);
tb = tb_find(cpu, last_tb, tb_exit);
tb = tb_find_fast(cpu, &last_tb, tb_exit);
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit, &sc);
/* Try to align the host and virtual clocks
if the guest is in advance */

28
cpus.c
View File

@@ -191,12 +191,8 @@ int64_t cpu_icount_to_ns(int64_t icount)
return icount << icount_time_shift;
}
/* return the time elapsed in VM between vm_start and vm_stop. Unless
* icount is active, cpu_get_ticks() uses units of the host CPU cycle
* counter.
*
* Caller must hold the BQL
*/
/* return the host CPU cycle counter and handle stop/restart */
/* Caller must hold the BQL */
int64_t cpu_get_ticks(void)
{
int64_t ticks;
@@ -223,19 +219,17 @@ int64_t cpu_get_ticks(void)
static int64_t cpu_get_clock_locked(void)
{
int64_t time;
int64_t ticks;
time = timers_state.cpu_clock_offset;
ticks = timers_state.cpu_clock_offset;
if (timers_state.cpu_ticks_enabled) {
time += get_clock();
ticks += get_clock();
}
return time;
return ticks;
}
/* Return the monotonic time elapsed in VM, i.e.,
* the time between vm_start and vm_stop
*/
/* return the host CPU monotonic timer and handle stop/restart */
int64_t cpu_get_clock(void)
{
int64_t ti;
@@ -250,7 +244,7 @@ int64_t cpu_get_clock(void)
}
/* enable cpu_get_ticks()
* Caller must hold BQL which serves as mutex for vm_clock_seqlock.
* Caller must hold BQL which server as mutex for vm_clock_seqlock.
*/
void cpu_enable_ticks(void)
{
@@ -266,7 +260,7 @@ void cpu_enable_ticks(void)
/* disable cpu_get_ticks() : the clock is stopped. You must not call
* cpu_get_ticks() after that.
* Caller must hold BQL which serves as mutex for vm_clock_seqlock.
* Caller must hold BQL which server as mutex for vm_clock_seqlock.
*/
void cpu_disable_ticks(void)
{
@@ -751,7 +745,7 @@ static int do_vm_stop(RunState state)
}
bdrv_drain_all();
ret = blk_flush_all();
ret = bdrv_flush_all();
return ret;
}
@@ -1494,7 +1488,7 @@ int vm_stop_force_state(RunState state)
bdrv_drain_all();
/* Make sure to return an error if the flush in a previous vm_stop()
* failed. */
return blk_flush_all();
return bdrv_flush_all();
}
}

View File

@@ -543,8 +543,10 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
#undef MMUSUFFIX
#define MMUSUFFIX _cmmu
#undef GETPC
#define GETPC() ((uintptr_t)0)
#undef GETPC_ADJ
#define GETPC_ADJ 0
#undef GETRA
#define GETRA() ((uintptr_t)0)
#define SOFTMMU_CODE_ACCESS
#define SHIFT 0

View File

@@ -29,7 +29,10 @@
#include "crypto/pbkdf.h"
#include "crypto/secret.h"
#include "crypto/random.h"
#include "qemu/uuid.h"
#ifdef CONFIG_UUID
#include <uuid/uuid.h>
#endif
#include "qemu/coroutine.h"
@@ -874,12 +877,18 @@ qcrypto_block_luks_open(QCryptoBlock *block,
}
static void
qcrypto_block_luks_uuid_gen(uint8_t *uuidstr)
static int
qcrypto_block_luks_uuid_gen(uint8_t *uuidstr, Error **errp)
{
QemuUUID uuid;
qemu_uuid_generate(&uuid);
qemu_uuid_unparse(&uuid, (char *)uuidstr);
#ifdef CONFIG_UUID
uuid_t uuid;
uuid_generate(uuid);
uuid_unparse(uuid, (char *)uuidstr);
return 0;
#else
error_setg(errp, "Unable to generate uuids on this platform");
return -1;
#endif
}
static int
@@ -908,12 +917,8 @@ qcrypto_block_luks_create(QCryptoBlock *block,
const char *hash_alg;
char *cipher_mode_spec = NULL;
QCryptoCipherAlgorithm ivcipheralg = 0;
uint64_t iters;
memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
if (!luks_opts.has_iter_time) {
luks_opts.iter_time = 2000;
}
if (!luks_opts.has_cipher_alg) {
luks_opts.cipher_alg = QCRYPTO_CIPHER_ALG_AES_256;
}
@@ -956,7 +961,10 @@ qcrypto_block_luks_create(QCryptoBlock *block,
* it out to disk
*/
luks->header.version = QCRYPTO_BLOCK_LUKS_VERSION;
qcrypto_block_luks_uuid_gen(luks->header.uuid);
if (qcrypto_block_luks_uuid_gen(luks->header.uuid,
errp) < 0) {
goto error;
}
cipher_alg = qcrypto_block_luks_cipher_alg_lookup(luks_opts.cipher_alg,
errp);
@@ -1056,40 +1064,26 @@ qcrypto_block_luks_create(QCryptoBlock *block,
/* Determine how many iterations we need to hash the master
* key, in order to have 1 second of compute time used
*/
iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg,
masterkey, luks->header.key_bytes,
luks->header.master_key_salt,
QCRYPTO_BLOCK_LUKS_SALT_LEN,
QCRYPTO_BLOCK_LUKS_DIGEST_LEN,
&local_err);
luks->header.master_key_iterations =
qcrypto_pbkdf2_count_iters(luks_opts.hash_alg,
masterkey, luks->header.key_bytes,
luks->header.master_key_salt,
QCRYPTO_BLOCK_LUKS_SALT_LEN,
&local_err);
if (local_err) {
error_propagate(errp, local_err);
goto error;
}
if (iters > (ULLONG_MAX / luks_opts.iter_time)) {
error_setg_errno(errp, ERANGE,
"PBKDF iterations %llu too large to scale",
(unsigned long long)iters);
goto error;
}
/* iter_time was in millis, but count_iters reported for secs */
iters = iters * luks_opts.iter_time / 1000;
/* Why /= 8 ? That matches cryptsetup, but there's no
* explanation why they chose /= 8... Probably so that
* if all 8 keyslots are active we only spend 1 second
* in total time to check all keys */
iters /= 8;
if (iters > UINT32_MAX) {
error_setg_errno(errp, ERANGE,
"PBKDF iterations %llu larger than %u",
(unsigned long long)iters, UINT32_MAX);
goto error;
}
iters = MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS);
luks->header.master_key_iterations = iters;
luks->header.master_key_iterations /= 8;
luks->header.master_key_iterations = MAX(
luks->header.master_key_iterations,
QCRYPTO_BLOCK_LUKS_MIN_MASTER_KEY_ITERS);
/* Hash the master key, saving the result in the LUKS
* header. This hash is used when opening the encrypted
@@ -1137,36 +1131,22 @@ qcrypto_block_luks_create(QCryptoBlock *block,
/* Again we determine how many iterations are required to
* hash the user password while consuming 1 second of compute
* time */
iters = qcrypto_pbkdf2_count_iters(luks_opts.hash_alg,
(uint8_t *)password, strlen(password),
luks->header.key_slots[0].salt,
QCRYPTO_BLOCK_LUKS_SALT_LEN,
luks->header.key_bytes,
&local_err);
luks->header.key_slots[0].iterations =
qcrypto_pbkdf2_count_iters(luks_opts.hash_alg,
(uint8_t *)password, strlen(password),
luks->header.key_slots[0].salt,
QCRYPTO_BLOCK_LUKS_SALT_LEN,
&local_err);
if (local_err) {
error_propagate(errp, local_err);
goto error;
}
if (iters > (ULLONG_MAX / luks_opts.iter_time)) {
error_setg_errno(errp, ERANGE,
"PBKDF iterations %llu too large to scale",
(unsigned long long)iters);
goto error;
}
/* iter_time was in millis, but count_iters reported for secs */
iters = iters * luks_opts.iter_time / 1000;
if (iters > UINT32_MAX) {
error_setg_errno(errp, ERANGE,
"PBKDF iterations %llu larger than %u",
(unsigned long long)iters, UINT32_MAX);
goto error;
}
luks->header.key_slots[0].iterations =
MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS);
/* Why /= 2 ? That matches cryptsetup, but there's no
* explanation why they chose /= 2... */
luks->header.key_slots[0].iterations /= 2;
luks->header.key_slots[0].iterations = MAX(
luks->header.key_slots[0].iterations,
QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS);
/* Generate a key that we'll use to encrypt the master

View File

@@ -59,8 +59,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
!qcrypto_block_drivers[options->format]) {
error_setg(errp, "Unsupported block driver %s",
QCryptoBlockFormat_lookup[options->format]);
error_setg(errp, "Unsupported block driver %d", options->format);
g_free(block);
return NULL;
}
@@ -89,8 +88,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
!qcrypto_block_drivers[options->format]) {
error_setg(errp, "Unsupported block driver %s",
QCryptoBlockFormat_lookup[options->format]);
error_setg(errp, "Unsupported block driver %d", options->format);
g_free(block);
return NULL;
}

View File

@@ -244,8 +244,7 @@ static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
if (cipher->mode != QCRYPTO_CIPHER_MODE_CBC &&
cipher->mode != QCRYPTO_CIPHER_MODE_ECB &&
cipher->mode != QCRYPTO_CIPHER_MODE_XTS) {
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_lookup[cipher->mode]);
error_setg(errp, "Unsupported cipher mode %d", cipher->mode);
return -1;
}
@@ -377,8 +376,7 @@ static int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher,
QCryptoCipherBuiltin *ctxt;
if (cipher->mode != QCRYPTO_CIPHER_MODE_ECB) {
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_lookup[cipher->mode]);
error_setg(errp, "Unsupported cipher mode %d", cipher->mode);
return -1;
}
@@ -444,8 +442,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
break;
default:
error_setg(errp,
"Unsupported cipher algorithm %s",
QCryptoCipherAlgorithm_lookup[cipher->alg]);
"Unsupported cipher algorithm %d", cipher->alg);
goto error;
}

View File

@@ -70,8 +70,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
gcrymode = GCRY_CIPHER_MODE_CBC;
break;
default:
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_lookup[mode]);
error_setg(errp, "Unsupported cipher mode %d", mode);
return NULL;
}
@@ -121,8 +120,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
break;
default:
error_setg(errp, "Unsupported cipher algorithm %s",
QCryptoCipherAlgorithm_lookup[alg]);
error_setg(errp, "Unsupported cipher algorithm %d", alg);
return NULL;
}

View File

@@ -227,8 +227,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
case QCRYPTO_CIPHER_MODE_XTS:
break;
default:
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_lookup[mode]);
error_setg(errp, "Unsupported cipher mode %d", mode);
return NULL;
}
@@ -358,8 +357,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
break;
default:
error_setg(errp, "Unsupported cipher algorithm %s",
QCryptoCipherAlgorithm_lookup[alg]);
error_setg(errp, "Unsupported cipher algorithm %d", alg);
goto error;
}
@@ -431,8 +429,8 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
break;
default:
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_lookup[cipher->mode]);
error_setg(errp, "Unsupported cipher algorithm %d",
cipher->alg);
return -1;
}
return 0;
@@ -471,8 +469,8 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
break;
default:
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_lookup[cipher->mode]);
error_setg(errp, "Unsupported cipher algorithm %d",
cipher->alg);
return -1;
}
return 0;

View File

@@ -59,7 +59,8 @@
#if (defined(CONFIG_GCRYPT) && \
(!defined(CONFIG_GNUTLS) || \
(LIBGNUTLS_VERSION_NUMBER < 0x020c00)) && \
!defined(GNUTLS_VERSION_NUMBER) || \
(GNUTLS_VERSION_NUMBER < 0x020c00)) && \
(!defined(GCRYPT_VERSION_NUMBER) || \
(GCRYPT_VERSION_NUMBER < 0x010600)))
#define QCRYPTO_INIT_GCRYPT_THREADS

View File

@@ -28,11 +28,7 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
switch (hash) {
case QCRYPTO_HASH_ALG_MD5:
case QCRYPTO_HASH_ALG_SHA1:
case QCRYPTO_HASH_ALG_SHA224:
case QCRYPTO_HASH_ALG_SHA256:
case QCRYPTO_HASH_ALG_SHA384:
case QCRYPTO_HASH_ALG_SHA512:
case QCRYPTO_HASH_ALG_RIPEMD160:
return true;
default:
return false;
@@ -42,33 +38,20 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
const uint8_t *key, size_t nkey,
const uint8_t *salt, size_t nsalt,
uint64_t iterations,
unsigned int iterations,
uint8_t *out, size_t nout,
Error **errp)
{
static const int hash_map[QCRYPTO_HASH_ALG__MAX] = {
[QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5,
[QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1,
[QCRYPTO_HASH_ALG_SHA224] = GCRY_MD_SHA224,
[QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256,
[QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384,
[QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512,
[QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160,
};
int ret;
if (iterations > ULONG_MAX) {
error_setg_errno(errp, ERANGE,
"PBKDF iterations %llu must be less than %lu",
(long long unsigned)iterations, ULONG_MAX);
return -1;
}
if (hash >= G_N_ELEMENTS(hash_map) ||
hash_map[hash] == GCRY_MD_NONE) {
error_setg_errno(errp, ENOSYS,
"PBKDF does not support hash algorithm %s",
QCryptoHashAlgorithm_lookup[hash]);
error_setg(errp, "Unexpected hash algorithm %d", hash);
return -1;
}

View File

@@ -20,7 +20,6 @@
#include "qemu/osdep.h"
#include <nettle/pbkdf2.h>
#include <nettle/hmac.h>
#include "qapi/error.h"
#include "crypto/pbkdf.h"
@@ -29,11 +28,7 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
{
switch (hash) {
case QCRYPTO_HASH_ALG_SHA1:
case QCRYPTO_HASH_ALG_SHA224:
case QCRYPTO_HASH_ALG_SHA256:
case QCRYPTO_HASH_ALG_SHA384:
case QCRYPTO_HASH_ALG_SHA512:
case QCRYPTO_HASH_ALG_RIPEMD160:
return true;
default:
return false;
@@ -43,74 +38,28 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
const uint8_t *key, size_t nkey,
const uint8_t *salt, size_t nsalt,
uint64_t iterations,
unsigned int iterations,
uint8_t *out, size_t nout,
Error **errp)
{
union {
struct hmac_md5_ctx md5;
struct hmac_sha1_ctx sha1;
struct hmac_sha224_ctx sha224;
struct hmac_sha256_ctx sha256;
struct hmac_sha384_ctx sha384;
struct hmac_sha512_ctx sha512;
struct hmac_ripemd160_ctx ripemd160;
} ctx;
if (iterations > UINT_MAX) {
error_setg_errno(errp, ERANGE,
"PBKDF iterations %llu must be less than %u",
(long long unsigned)iterations, UINT_MAX);
return -1;
}
switch (hash) {
case QCRYPTO_HASH_ALG_MD5:
hmac_md5_set_key(&ctx.md5, nkey, key);
PBKDF2(&ctx.md5, hmac_md5_update, hmac_md5_digest,
MD5_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
break;
case QCRYPTO_HASH_ALG_SHA1:
hmac_sha1_set_key(&ctx.sha1, nkey, key);
PBKDF2(&ctx.sha1, hmac_sha1_update, hmac_sha1_digest,
SHA1_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
break;
case QCRYPTO_HASH_ALG_SHA224:
hmac_sha224_set_key(&ctx.sha224, nkey, key);
PBKDF2(&ctx.sha224, hmac_sha224_update, hmac_sha224_digest,
SHA224_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
pbkdf2_hmac_sha1(nkey, key,
iterations,
nsalt, salt,
nout, out);
break;
case QCRYPTO_HASH_ALG_SHA256:
hmac_sha256_set_key(&ctx.sha256, nkey, key);
PBKDF2(&ctx.sha256, hmac_sha256_update, hmac_sha256_digest,
SHA256_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
break;
case QCRYPTO_HASH_ALG_SHA384:
hmac_sha384_set_key(&ctx.sha384, nkey, key);
PBKDF2(&ctx.sha384, hmac_sha384_update, hmac_sha384_digest,
SHA384_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
break;
case QCRYPTO_HASH_ALG_SHA512:
hmac_sha512_set_key(&ctx.sha512, nkey, key);
PBKDF2(&ctx.sha512, hmac_sha512_update, hmac_sha512_digest,
SHA512_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
break;
case QCRYPTO_HASH_ALG_RIPEMD160:
hmac_ripemd160_set_key(&ctx.ripemd160, nkey, key);
PBKDF2(&ctx.ripemd160, hmac_ripemd160_update, hmac_ripemd160_digest,
RIPEMD160_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
pbkdf2_hmac_sha256(nkey, key,
iterations,
nsalt, salt,
nout, out);
break;
default:
error_setg_errno(errp, ENOSYS,
"PBKDF does not support hash algorithm %s",
QCryptoHashAlgorithm_lookup[hash]);
"PBKDF does not support hash algorithm %d", hash);
return -1;
}
return 0;

View File

@@ -32,7 +32,7 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash G_GNUC_UNUSED,
size_t nkey G_GNUC_UNUSED,
const uint8_t *salt G_GNUC_UNUSED,
size_t nsalt G_GNUC_UNUSED,
uint64_t iterations G_GNUC_UNUSED,
unsigned int iterations G_GNUC_UNUSED,
uint8_t *out G_GNUC_UNUSED,
size_t nout G_GNUC_UNUSED,
Error **errp)

View File

@@ -62,33 +62,29 @@ static int qcrypto_pbkdf2_get_thread_cpu(unsigned long long *val_ms,
#endif
}
uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash,
const uint8_t *key, size_t nkey,
const uint8_t *salt, size_t nsalt,
size_t nout,
Error **errp)
int qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash,
const uint8_t *key, size_t nkey,
const uint8_t *salt, size_t nsalt,
Error **errp)
{
uint64_t ret = -1;
uint8_t *out;
uint64_t iterations = (1 << 15);
uint8_t out[32];
long long int iterations = (1 << 15);
unsigned long long delta_ms, start_ms, end_ms;
out = g_new(uint8_t, nout);
while (1) {
if (qcrypto_pbkdf2_get_thread_cpu(&start_ms, errp) < 0) {
goto cleanup;
return -1;
}
if (qcrypto_pbkdf2(hash,
key, nkey,
salt, nsalt,
iterations,
out, nout,
out, sizeof(out),
errp) < 0) {
goto cleanup;
return -1;
}
if (qcrypto_pbkdf2_get_thread_cpu(&end_ms, errp) < 0) {
goto cleanup;
return -1;
}
delta_ms = end_ms - start_ms;
@@ -104,10 +100,11 @@ uint64_t qcrypto_pbkdf2_count_iters(QCryptoHashAlgorithm hash,
iterations = iterations * 1000 / delta_ms;
ret = iterations;
if (iterations > INT32_MAX) {
error_setg(errp, "Iterations %lld too large for a 32-bit int",
iterations);
return -1;
}
cleanup:
memset(out, 0, nout);
g_free(out);
return ret;
return iterations;
}

View File

@@ -615,7 +615,7 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
}
if (cert != NULL && key != NULL) {
#if LIBGNUTLS_VERSION_NUMBER >= 0x030111
#if GNUTLS_VERSION_NUMBER >= 0x030111
char *password = NULL;
if (creds->passwordid) {
password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
@@ -630,7 +630,7 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
password,
0);
g_free(password);
#else /* LIBGNUTLS_VERSION_NUMBER < 0x030111 */
#else /* GNUTLS_VERSION_NUMBER < 0x030111 */
if (creds->passwordid) {
error_setg(errp, "PKCS8 decryption requires GNUTLS >= 3.1.11");
goto cleanup;
@@ -638,7 +638,7 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
ret = gnutls_certificate_set_x509_key_file(creds->data,
cert, key,
GNUTLS_X509_FMT_PEM);
#endif
#endif /* GNUTLS_VERSION_NUMBER < 0x030111 */
if (ret < 0) {
error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
cert, key, gnutls_strerror(ret));

View File

@@ -351,22 +351,16 @@ qcrypto_tls_session_check_credentials(QCryptoTLSSession *session,
{
if (object_dynamic_cast(OBJECT(session->creds),
TYPE_QCRYPTO_TLS_CREDS_ANON)) {
trace_qcrypto_tls_session_check_creds(session, "nop");
return 0;
} else if (object_dynamic_cast(OBJECT(session->creds),
TYPE_QCRYPTO_TLS_CREDS_X509)) {
if (session->creds->verifyPeer) {
int ret = qcrypto_tls_session_check_certificate(session,
errp);
trace_qcrypto_tls_session_check_creds(session,
ret == 0 ? "pass" : "fail");
return ret;
return qcrypto_tls_session_check_certificate(session,
errp);
} else {
trace_qcrypto_tls_session_check_creds(session, "skip");
return 0;
}
} else {
trace_qcrypto_tls_session_check_creds(session, "error");
error_setg(errp, "Unexpected credential type %s",
object_get_typename(OBJECT(session->creds)));
return -1;

View File

@@ -17,4 +17,3 @@ qcrypto_tls_creds_x509_load_cert_list(void *creds, const char *file) "TLS creds
# crypto/tlssession.c
qcrypto_tls_session_new(void *session, void *creds, const char *hostname, const char *aclname, int endpoint) "TLS session new session=%p creds=%p hostname=%s aclname=%s endpoint=%d"
qcrypto_tls_session_check_creds(void *session, const char *status) "TLS session check creds session=%p status=%s"

View File

@@ -3,6 +3,7 @@
include pci.mak
include usb.mak
CONFIG_VGA=y
CONFIG_ISA_MMIO=y
CONFIG_NAND=y
CONFIG_ECC=y
CONFIG_SERIAL=y

View File

@@ -30,12 +30,14 @@ CONFIG_I8257=y
CONFIG_IDE_ISA=y
CONFIG_IDE_PIIX=y
CONFIG_NE2000_ISA=y
CONFIG_PIIX_PCI=y
CONFIG_HPET=y
CONFIG_APPLESMC=y
CONFIG_I8259=y
CONFIG_PFLASH_CFI01=y
CONFIG_TPM_TIS=$(CONFIG_TPM)
CONFIG_MC146818RTC=y
CONFIG_PAM=y
CONFIG_PCI_PIIX=y
CONFIG_WDT_IB700=y
CONFIG_XEN_I386=$(CONFIG_XEN)

View File

@@ -3,6 +3,7 @@
include pci.mak
include sound.mak
include usb.mak
CONFIG_ISA_MMIO=y
CONFIG_ESCC=y
CONFIG_M48T59=y
CONFIG_SERIAL=y

View File

@@ -4,6 +4,7 @@ include pci.mak
include sound.mak
include usb.mak
CONFIG_VIRTIO_VGA=y
CONFIG_ISA_MMIO=y
CONFIG_ESCC=y
CONFIG_M48T59=y
CONFIG_SERIAL=y

View File

@@ -2,6 +2,7 @@
include pci.mak
include usb.mak
CONFIG_ISA_MMIO=y
CONFIG_M48T59=y
CONFIG_PTIMER=y
CONFIG_SERIAL=y

View File

@@ -30,12 +30,14 @@ CONFIG_I8257=y
CONFIG_IDE_ISA=y
CONFIG_IDE_PIIX=y
CONFIG_NE2000_ISA=y
CONFIG_PIIX_PCI=y
CONFIG_HPET=y
CONFIG_APPLESMC=y
CONFIG_I8259=y
CONFIG_PFLASH_CFI01=y
CONFIG_TPM_TIS=$(CONFIG_TPM)
CONFIG_MC146818RTC=y
CONFIG_PAM=y
CONFIG_PCI_PIIX=y
CONFIG_WDT_IB700=y
CONFIG_XEN_I386=$(CONFIG_XEN)

View File

@@ -310,6 +310,8 @@ void disas(FILE *out, void *code, unsigned long size)
print_insn = print_insn_m68k;
#elif defined(__s390__)
print_insn = print_insn_s390;
#elif defined(__hppa__)
print_insn = print_insn_hppa;
#elif defined(__ia64__)
print_insn = print_insn_ia64;
#endif

View File

@@ -9,6 +9,7 @@ libvixldir = $(SRC_PATH)/disas/libvixl
# versions do not.
arm-a64.o-cflags := -I$(libvixldir) -Wno-sign-compare
common-obj-$(CONFIG_CRIS_DIS) += cris.o
common-obj-$(CONFIG_HPPA_DIS) += hppa.o
common-obj-$(CONFIG_I386_DIS) += i386.o
common-obj-$(CONFIG_IA64_DIS) += ia64.o
common-obj-$(CONFIG_M68K_DIS) += m68k.o

View File

@@ -24,6 +24,7 @@
#include "qemu/osdep.h"
#include "disas/bfd.h"
#define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
#define ARM_EXT_V1 0
#define ARM_EXT_V2 0
@@ -72,6 +73,15 @@ static void floatformat_to_double (unsigned char *data, double *dest)
/* End of qemu specific additions. */
/* FIXME: Belongs in global header. */
#ifndef strneq
#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
#endif
#ifndef NUM_ELEM
#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
#endif
struct opcode32
{
unsigned long arch; /* Architecture defining this insn. */
@@ -1518,6 +1528,7 @@ static const char *const iwmmxt_cregnames[] =
/* Default to GCC register name set. */
static unsigned int regname_selected = 1;
#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
#define arm_regnames regnames[regname_selected].reg_names
static bfd_boolean force_thumb = false;

2832
disas/hppa.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -264,6 +264,12 @@ sh_dsp_reg_nums;
be some confusion between DSP and FPU etc. */
#define SH_ARCH_UNKNOWN_ARCH 0xffffffff
/* These are defined in bfd/cpu-sh.c . */
unsigned int sh_get_arch_from_bfd_mach (unsigned long mach);
unsigned int sh_get_arch_up_from_bfd_mach (unsigned long mach);
unsigned long sh_get_bfd_mach_from_arch_set (unsigned int arch_set);
/* bfd_boolean sh_merge_bfd_arch (bfd *ibfd, bfd *obfd); */
/* Below are the 'architecture sets'.
They describe the following inheritance graph:

View File

@@ -73,6 +73,7 @@ typedef struct {
AioContext *ctx;
BlockAIOCB *acb;
QEMUSGList *sg;
uint32_t align;
uint64_t offset;
DMADirection dir;
int sg_cur_index;
@@ -160,8 +161,9 @@ static void dma_blk_cb(void *opaque, int ret)
return;
}
if (dbs->iov.size & ~BDRV_SECTOR_MASK) {
qemu_iovec_discard_back(&dbs->iov, dbs->iov.size & ~BDRV_SECTOR_MASK);
if (!QEMU_IS_ALIGNED(dbs->iov.size, dbs->align)) {
qemu_iovec_discard_back(&dbs->iov,
QEMU_ALIGN_DOWN(dbs->iov.size, dbs->align));
}
dbs->acb = dbs->io_func(dbs->offset, &dbs->iov,
@@ -199,7 +201,7 @@ static const AIOCBInfo dma_aiocb_info = {
};
BlockAIOCB *dma_blk_io(AioContext *ctx,
QEMUSGList *sg, uint64_t offset,
QEMUSGList *sg, uint64_t offset, uint32_t align,
DMAIOFunc *io_func, void *io_func_opaque,
BlockCompletionFunc *cb,
void *opaque, DMADirection dir)
@@ -212,6 +214,7 @@ BlockAIOCB *dma_blk_io(AioContext *ctx,
dbs->sg = sg;
dbs->ctx = ctx;
dbs->offset = offset;
dbs->align = align;
dbs->sg_cur_index = 0;
dbs->sg_cur_byte = 0;
dbs->dir = dir;
@@ -234,11 +237,11 @@ BlockAIOCB *dma_blk_read_io_func(int64_t offset, QEMUIOVector *iov,
}
BlockAIOCB *dma_blk_read(BlockBackend *blk,
QEMUSGList *sg, uint64_t offset,
QEMUSGList *sg, uint64_t offset, uint32_t align,
void (*cb)(void *opaque, int ret), void *opaque)
{
return dma_blk_io(blk_get_aio_context(blk),
sg, offset, dma_blk_read_io_func, blk, cb, opaque,
return dma_blk_io(blk_get_aio_context(blk), sg, offset, align,
dma_blk_read_io_func, blk, cb, opaque,
DMA_DIRECTION_FROM_DEVICE);
}
@@ -252,11 +255,11 @@ BlockAIOCB *dma_blk_write_io_func(int64_t offset, QEMUIOVector *iov,
}
BlockAIOCB *dma_blk_write(BlockBackend *blk,
QEMUSGList *sg, uint64_t offset,
QEMUSGList *sg, uint64_t offset, uint32_t align,
void (*cb)(void *opaque, int ret), void *opaque)
{
return dma_blk_io(blk_get_aio_context(blk),
sg, offset, dma_blk_write_io_func, blk, cb, opaque,
return dma_blk_io(blk_get_aio_context(blk), sg, offset, align,
dma_blk_write_io_func, blk, cb, opaque,
DMA_DIRECTION_TO_DEVICE);
}

View File

@@ -1,239 +0,0 @@
Block replication
----------------------------------------
Copyright Fujitsu, Corp. 2016
Copyright (c) 2016 Intel Corporation
Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
This work is licensed under the terms of the GNU GPL, version 2 or later.
See the COPYING file in the top-level directory.
Block replication is used for continuous checkpoints. It is designed
for COLO (COarse-grain LOck-stepping) where the Secondary VM is running.
It can also be applied for FT/HA (Fault-tolerance/High Assurance) scenario,
where the Secondary VM is not running.
This document gives an overview of block replication's design.
== Background ==
High availability solutions such as micro checkpoint and COLO will do
consecutive checkpoints. The VM state of the Primary and Secondary VM is
identical right after a VM checkpoint, but becomes different as the VM
executes till the next checkpoint. To support disk contents checkpoint,
the modified disk contents in the Secondary VM must be buffered, and are
only dropped at next checkpoint time. To reduce the network transportation
effort during a vmstate checkpoint, the disk modification operations of
the Primary disk are asynchronously forwarded to the Secondary node.
== Workflow ==
The following is the image of block replication workflow:
+----------------------+ +------------------------+
|Primary Write Requests| |Secondary Write Requests|
+----------------------+ +------------------------+
| |
| (4)
| V
| /-------------\
| Copy and Forward | |
|---------(1)----------+ | Disk Buffer |
| | | |
| (3) \-------------/
| speculative ^
| write through (2)
| | |
V V |
+--------------+ +----------------+
| Primary Disk | | Secondary Disk |
+--------------+ +----------------+
1) Primary write requests will be copied and forwarded to Secondary
QEMU.
2) Before Primary write requests are written to Secondary disk, the
original sector content will be read from Secondary disk and
buffered in the Disk buffer, but it will not overwrite the existing
sector content (it could be from either "Secondary Write Requests" or
previous COW of "Primary Write Requests") in the Disk buffer.
3) Primary write requests will be written to Secondary disk.
4) Secondary write requests will be buffered in the Disk buffer and it
will overwrite the existing sector content in the buffer.
== Architecture ==
We are going to implement block replication from many basic
blocks that are already in QEMU.
virtio-blk ||
^ || .----------
| || | Secondary
1 Quorum || '----------
/ \ ||
/ \ ||
Primary 2 filter
disk ^ virtio-blk
| ^
3 NBD -------> 3 NBD |
client || server 2 filter
|| ^ ^
--------. || | |
Primary | || Secondary disk <--------- hidden-disk 5 <--------- active-disk 4
--------' || | backing ^ backing
|| | |
|| | |
|| '-------------------------'
|| drive-backup sync=none 6
1) The disk on the primary is represented by a block device with two
children, providing replication between a primary disk and the host that
runs the secondary VM. The read pattern (fifo) for quorum can be extended
to make the primary always read from the local disk instead of going through
NBD.
2) The new block filter (the name is replication) will control the block
replication.
3) The secondary disk receives writes from the primary VM through QEMU's
embedded NBD server (speculative write-through).
4) The disk on the secondary is represented by a custom block device
(called active-disk). It should start as an empty disk, and the format
should support bdrv_make_empty() and backing file.
5) The hidden-disk is created automatically. It buffers the original content
that is modified by the primary VM. It should also start as an empty disk,
and the driver supports bdrv_make_empty() and backing file.
6) The drive-backup job (sync=none) is run to allow hidden-disk to buffer
any state that would otherwise be lost by the speculative write-through
of the NBD server into the secondary disk. So before block replication,
the primary disk and secondary disk should contain the same data.
== Failure Handling ==
There are 7 internal errors when block replication is running:
1. I/O error on primary disk
2. Forwarding primary write requests failed
3. Backup failed
4. I/O error on secondary disk
5. I/O error on active disk
6. Making active disk or hidden disk empty failed
7. Doing failover failed
In case 1 and 5, we just report the error to the disk layer. In case 2, 3,
4 and 6, we just report block replication's error to FT/HA manager (which
decides when to do a new checkpoint, when to do failover).
In case 7, if active commit failed, we use replication failover failed state
in Secondary's write operation (what decides which target to write).
== New block driver interface ==
We add four block driver interfaces to control block replication:
a. replication_start_all()
Start block replication, called in migration/checkpoint thread.
We must call block_replication_start_all() in secondary QEMU before
calling block_replication_start_all() in primary QEMU. The caller
must hold the I/O mutex lock if it is in migration/checkpoint
thread.
b. replication_do_checkpoint_all()
This interface is called after all VM state is transferred to
Secondary QEMU. The Disk buffer will be dropped in this interface.
The caller must hold the I/O mutex lock if it is in migration/checkpoint
thread.
c. replication_get_error_all()
This interface is called to check if error happened in replication.
The caller must hold the I/O mutex lock if it is in migration/checkpoint
thread.
d. replication_stop_all()
It is called on failover. We will flush the Disk buffer into
Secondary Disk and stop block replication. The vm should be stopped
before calling it if you use this API to shutdown the guest, or other
things except failover. The caller must hold the I/O mutex lock if it is
in migration/checkpoint thread.
== Usage ==
Primary:
-drive if=xxx,driver=quorum,read-pattern=fifo,id=colo1,vote-threshold=1,\
children.0.file.filename=1.raw,\
children.0.driver=raw
Run qmp command in primary qemu:
{ 'execute': 'human-monitor-command',
'arguments': {
'command-line': 'drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=xxxx,file.port=xxxx,file.export=colo1,node-name=nbd_client1'
}
}
{ 'execute': 'x-blockdev-change',
'arguments': {
'parent': 'colo1',
'node': 'nbd_client1'
}
}
Note:
1. There should be only one NBD Client for each primary disk.
2. host is the secondary physical machine's hostname or IP
3. Each disk must have its own export name.
4. It is all a single argument to -drive and you should ignore the
leading whitespace.
5. The qmp command line must be run after running qmp command line in
secondary qemu.
6. After failover we need remove children.1 (replication driver).
Secondary:
-drive if=none,driver=raw,file.filename=1.raw,id=colo1 \
-drive if=xxx,id=topxxx,driver=replication,mode=secondary,top-id=topxxx\
file.file.filename=active_disk.qcow2,\
file.driver=qcow2,\
file.backing.file.filename=hidden_disk.qcow2,\
file.backing.driver=qcow2,\
file.backing.backing=colo1
Then run qmp command in secondary qemu:
{ 'execute': 'nbd-server-start',
'arguments': {
'addr': {
'type': 'inet',
'data': {
'host': 'xxx',
'port': 'xxx'
}
}
}
}
{ 'execute': 'nbd-server-add',
'arguments': {
'device': 'colo1',
'writable': true
}
}
Note:
1. The export name in secondary QEMU command line is the secondary
disk's id.
2. The export name for the same disk must be the same
3. The qmp command nbd-server-start and nbd-server-add must be run
before running the qmp command migrate on primary QEMU
4. Active disk, hidden disk and nbd target's length should be the
same.
5. It is better to put active disk and hidden disk in ramdisk.
6. It is all a single argument to -drive, and you should ignore
the leading whitespace.
After Failover:
Primary:
The secondary host is down, so we should run the following qmp command
to remove the nbd child from the quorum:
{ 'execute': 'x-blockdev-change',
'arguments': {
'parent': 'colo1',
'child': 'children.1'
}
}
{ 'execute': 'human-monitor-command',
'arguments': {
'command-line': 'drive_del xxxx'
}
}
Note: there is no qmp command to remove the blockdev now
Secondary:
The primary host is down, so we should do the following thing:
{ 'execute': 'nbd-server-stop' }
TODO:
1. Continuous block replication
2. Shared disk

View File

@@ -964,9 +964,9 @@ Example:
Used to generate the marshaling/dispatch functions for the commands
defined in the schema. The generated code implements
qmp_marshal_COMMAND() (registered automatically), and declares
qmp_COMMAND() that the user must implement. The following files are
generated:
qmp_marshal_COMMAND() (mentioned in qmp-commands.hx, and registered
automatically), and declares qmp_COMMAND() that the user must
implement. The following files are generated:
$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
QMP command defined in the schema. Functions

View File

@@ -37,7 +37,7 @@ do not matter; as soon as all previous critical sections have finished,
there cannot be any readers who hold references to the data structure,
and these can now be safely reclaimed (e.g., freed or unref'ed).
Here is a picture:
Here is a picutre:
thread 1 thread 2 thread 3
------------------- ------------------------ -------------------

View File

@@ -235,10 +235,7 @@ consider the following values:
- Water leaks from the bucket at a rate of 100 IOPS.
- Water can be added to the bucket at a rate of 2000 IOPS.
- The size of the bucket is 2000 x 60 = 120000
- If 'iops-total-max-length' is unset then it defaults to 1 and the
size of the bucket is 2000.
- If 'iops-total-max' is unset then 'iops-total-max-length' must be
unset as well. In this case the bucket size is 100.
- If 'iops-total-max' is unset then the bucket size is 100 x 60.
The bucket is initially empty, therefore water can be added until it's
full at a rate of 2000 IOPS (the burst rate). Once the bucket is full

View File

@@ -192,18 +192,6 @@ After running qemu by root user, you can get the trace:
Restriction: "ftrace" backend is restricted to Linux only.
=== Syslog ===
The "syslog" backend sends trace events using the POSIX syslog API. The log
is opened specifying the LOG_DAEMON facility and LOG_PID option (so events
are tagged with the pid of the particular QEMU process that generated
them). All events are logged at LOG_INFO level.
NOTE: syslog may squash duplicate consecutive trace events and apply rate
limiting.
Restriction: "syslog" backend is restricted to POSIX compliant OS.
==== Monitor commands ====
* trace-file on|off|flush|set <path>

View File

@@ -119,6 +119,17 @@ There are a few things to be noticed:
5. Printing to the terminal is discouraged for QMP commands, we do it here
because it's the easiest way to demonstrate a QMP command
Now a little hack is needed. As we're still using the old QMP server we need
to add the new command to its internal dispatch table. This step won't be
required in the near future. Open the qmp-commands.hx file and add the
following at the bottom:
{
.name = "hello-world",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_hello_world,
},
You're done. Now build qemu, run it as suggested in the "Testing" section,
and then type the following QMP command:
@@ -163,6 +174,21 @@ There are two important details to be noticed:
2. The C implementation signature must follow the schema's argument ordering,
which is defined by the "data" member
The last step is to update the qmp-commands.hx file:
{
.name = "hello-world",
.args_type = "message:s?",
.mhandler.cmd_new = qmp_marshal_hello_world,
},
Notice that the "args_type" member got our "message" argument. The character
"s" stands for "string" and "?" means it's optional. This too must be ordered
according to the C implementation and schema file. You can look for more
examples in the qmp-commands.hx file if you need to define more arguments.
Again, this step won't be required in the future.
Time to test our new version of the "hello-world" command. Build qemu, run it as
described in the "Testing" section and then send two commands:
@@ -311,7 +337,7 @@ we should add it to the hmp-commands.hx file:
.args_type = "message:s?",
.params = "hello-world [message]",
.help = "Print message to the standard output",
.cmd = hmp_hello_world,
.mhandler.cmd = hmp_hello_world,
},
STEXI
@@ -428,6 +454,14 @@ There are a number of things to be noticed:
6. You have to include the "qmp-commands.h" header file in qemu-timer.c,
otherwise qemu won't build
The last step is to add the correspoding entry in the qmp-commands.hx file:
{
.name = "query-alarm-clock",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_query_alarm_clock,
},
Time to test the new command. Build qemu, run it as described in the "Testing"
section and try this:
@@ -484,7 +518,7 @@ in the monitor.c file. The entry for the "info alarmclock" follows:
.args_type = "",
.params = "",
.help = "show information about the alarm clock",
.cmd = hmp_info_alarm_clock,
.mhandler.info = hmp_info_alarm_clock,
},
To test this, run qemu and type "info alarmclock" in the user monitor.
@@ -566,6 +600,14 @@ iteration of the loop. That's because the alarm timer method in use is the
first element of the alarm_timers array. Also notice that QAPI lists are handled
by hand and we return the head of the list.
To test this you have to add the corresponding qmp-commands.hx entry:
{
.name = "query-alarm-methods",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_query_alarm_methods,
},
Now Build qemu, run it as explained in the "Testing" section and try our new
command:

14
exec.c
View File

@@ -598,14 +598,11 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx)
}
#endif
static bool cpu_index_auto_assigned;
static int cpu_get_free_index(void)
{
CPUState *some_cpu;
int cpu_index = 0;
cpu_index_auto_assigned = true;
CPU_FOREACH(some_cpu) {
cpu_index++;
}
@@ -617,15 +614,14 @@ void cpu_exec_exit(CPUState *cpu)
CPUClass *cc = CPU_GET_CLASS(cpu);
cpu_list_lock();
if (!QTAILQ_IN_USE(cpu, node)) {
if (cpu->node.tqe_prev == NULL) {
/* there is nothing to undo since cpu_exec_init() hasn't been called */
cpu_list_unlock();
return;
}
assert(!(cpu_index_auto_assigned && cpu != QTAILQ_LAST(&cpus, CPUTailQ)));
QTAILQ_REMOVE(&cpus, cpu, node);
cpu->node.tqe_prev = NULL;
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
cpu_list_unlock();
@@ -667,8 +663,6 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
if (cpu->cpu_index == UNASSIGNED_CPU_INDEX) {
cpu->cpu_index = cpu_get_free_index();
assert(cpu->cpu_index != UNASSIGNED_CPU_INDEX);
} else {
assert(!cpu_index_auto_assigned);
}
QTAILQ_INSERT_TAIL(&cpus, cpu, node);
cpu_list_unlock();
@@ -1621,8 +1615,10 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
if (new_block->host) {
qemu_ram_setup_dump(new_block->host, new_block->max_length);
qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_HUGEPAGE);
/* MADV_DONTFORK is also needed by KVM in absence of synchronous MMU */
qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_DONTFORK);
if (kvm_enabled()) {
kvm_setup_guest_memory(new_block->host, new_block->max_length);
}
}
}

View File

@@ -4814,10 +4814,6 @@ int32_t floatx80_to_int32(floatx80 a, float_status *status)
int32_t aExp, shiftCount;
uint64_t aSig;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return 1 << 31;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -4846,10 +4842,6 @@ int32_t floatx80_to_int32_round_to_zero(floatx80 a, float_status *status)
uint64_t aSig, savedASig;
int32_t z;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return 1 << 31;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -4896,10 +4888,6 @@ int64_t floatx80_to_int64(floatx80 a, float_status *status)
int32_t aExp, shiftCount;
uint64_t aSig, aSigExtra;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return 1ULL << 63;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -4941,10 +4929,6 @@ int64_t floatx80_to_int64_round_to_zero(floatx80 a, float_status *status)
uint64_t aSig;
int64_t z;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return 1ULL << 63;
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -4987,10 +4971,6 @@ float32 floatx80_to_float32(floatx80 a, float_status *status)
int32_t aExp;
uint64_t aSig;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return float32_default_nan(status);
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -5019,10 +4999,6 @@ float64 floatx80_to_float64(floatx80 a, float_status *status)
int32_t aExp;
uint64_t aSig, zSig;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return float64_default_nan(status);
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -5051,10 +5027,6 @@ float128 floatx80_to_float128(floatx80 a, float_status *status)
int aExp;
uint64_t aSig, zSig0, zSig1;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return float128_default_nan(status);
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -5080,10 +5052,6 @@ floatx80 floatx80_round_to_int(floatx80 a, float_status *status)
uint64_t lastBitMask, roundBitsMask;
floatx80 z;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
aExp = extractFloatx80Exp( a );
if ( 0x403E <= aExp ) {
if ( ( aExp == 0x7FFF ) && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) {
@@ -5311,10 +5279,6 @@ floatx80 floatx80_add(floatx80 a, floatx80 b, float_status *status)
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
aSign = extractFloatx80Sign( a );
bSign = extractFloatx80Sign( b );
if ( aSign == bSign ) {
@@ -5336,10 +5300,6 @@ floatx80 floatx80_sub(floatx80 a, floatx80 b, float_status *status)
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
aSign = extractFloatx80Sign( a );
bSign = extractFloatx80Sign( b );
if ( aSign == bSign ) {
@@ -5363,10 +5323,6 @@ floatx80 floatx80_mul(floatx80 a, floatx80 b, float_status *status)
int32_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig0, zSig1;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -5424,10 +5380,6 @@ floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status)
uint64_t aSig, bSig, zSig0, zSig1;
uint64_t rem0, rem1, rem2, term0, term1, term2;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -5509,10 +5461,6 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status)
uint64_t aSig0, aSig1, bSig;
uint64_t q, term0, term1, alternateASig0, alternateASig1;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
aSig0 = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -5608,10 +5556,6 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *status)
uint64_t aSig0, aSig1, zSig0, zSig1, doubleZSig0;
uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
aSig0 = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
@@ -5676,11 +5620,10 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *status)
int floatx80_eq(floatx80 a, floatx80 b, float_status *status)
{
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
|| (extractFloatx80Exp(a) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(a) << 1))
|| (extractFloatx80Exp(b) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(b) << 1))
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
) {
float_raise(float_flag_invalid, status);
return 0;
@@ -5706,11 +5649,10 @@ int floatx80_le(floatx80 a, floatx80 b, float_status *status)
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
|| (extractFloatx80Exp(a) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(a) << 1))
|| (extractFloatx80Exp(b) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(b) << 1))
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
) {
float_raise(float_flag_invalid, status);
return 0;
@@ -5740,11 +5682,10 @@ int floatx80_lt(floatx80 a, floatx80 b, float_status *status)
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
|| (extractFloatx80Exp(a) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(a) << 1))
|| (extractFloatx80Exp(b) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(b) << 1))
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
) {
float_raise(float_flag_invalid, status);
return 0;
@@ -5771,11 +5712,10 @@ int floatx80_lt(floatx80 a, floatx80 b, float_status *status)
*----------------------------------------------------------------------------*/
int floatx80_unordered(floatx80 a, floatx80 b, float_status *status)
{
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
|| (extractFloatx80Exp(a) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(a) << 1))
|| (extractFloatx80Exp(b) == 0x7FFF
&& (uint64_t) (extractFloatx80Frac(b) << 1))
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
) {
float_raise(float_flag_invalid, status);
return 1;
@@ -5793,10 +5733,6 @@ int floatx80_unordered(floatx80 a, floatx80 b, float_status *status)
int floatx80_eq_quiet(floatx80 a, floatx80 b, float_status *status)
{
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return 0;
}
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
@@ -5828,10 +5764,6 @@ int floatx80_le_quiet(floatx80 a, floatx80 b, float_status *status)
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return 0;
}
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
@@ -5868,10 +5800,6 @@ int floatx80_lt_quiet(floatx80 a, floatx80 b, float_status *status)
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return 0;
}
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
@@ -5905,10 +5833,6 @@ int floatx80_lt_quiet(floatx80 a, floatx80 b, float_status *status)
*----------------------------------------------------------------------------*/
int floatx80_unordered_quiet(floatx80 a, floatx80 b, float_status *status)
{
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return 1;
}
if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
&& (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
|| ( ( extractFloatx80Exp( b ) == 0x7FFF )
@@ -7450,10 +7374,6 @@ static inline int floatx80_compare_internal(floatx80 a, floatx80 b,
{
flag aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
return float_relation_unordered;
}
if (( ( extractFloatx80Exp( a ) == 0x7fff ) &&
( extractFloatx80Frac( a )<<1 ) ) ||
( ( extractFloatx80Exp( b ) == 0x7fff ) &&
@@ -7725,10 +7645,6 @@ floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status)
int32_t aExp;
uint64_t aSig;
if (floatx80_invalid_encoding(a)) {
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );

View File

@@ -25,6 +25,11 @@ void v9fs_string_free(V9fsString *str)
str->size = 0;
}
void v9fs_string_null(V9fsString *str)
{
v9fs_string_free(str);
}
void GCC_FMT_ATTR(2, 3)
v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
{

View File

@@ -77,6 +77,7 @@ static inline void v9fs_string_init(V9fsString *str)
str->size = 0;
}
extern void v9fs_string_free(V9fsString *str);
extern void v9fs_string_null(V9fsString *str);
extern void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...);
extern void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs);

View File

@@ -402,9 +402,7 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
}
}
#else
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, buf, len);
qemu_chr_fe_write(s->chr, buf, len);
#endif
}

View File

@@ -18,7 +18,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the version of QEMU",
.cmd = hmp_info_version,
.mhandler.cmd = hmp_info_version,
},
STEXI
@@ -32,7 +32,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the network state",
.cmd = hmp_info_network,
.mhandler.cmd = hmp_info_network,
},
STEXI
@@ -46,7 +46,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the character devices",
.cmd = hmp_info_chardev,
.mhandler.cmd = hmp_info_chardev,
},
STEXI
@@ -61,7 +61,7 @@ ETEXI
.params = "[-n] [-v] [device]",
.help = "show info of one block device or all block devices "
"(-n: show named nodes; -v: show details)",
.cmd = hmp_info_block,
.mhandler.cmd = hmp_info_block,
},
STEXI
@@ -75,7 +75,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show block device statistics",
.cmd = hmp_info_blockstats,
.mhandler.cmd = hmp_info_blockstats,
},
STEXI
@@ -89,7 +89,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show progress of ongoing block device operations",
.cmd = hmp_info_block_jobs,
.mhandler.cmd = hmp_info_block_jobs,
},
STEXI
@@ -103,7 +103,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the cpu registers",
.cmd = hmp_info_registers,
.mhandler.cmd = hmp_info_registers,
},
STEXI
@@ -118,7 +118,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show local apic state",
.cmd = hmp_info_local_apic,
.mhandler.cmd = hmp_info_local_apic,
},
#endif
@@ -134,7 +134,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show io apic state",
.cmd = hmp_info_io_apic,
.mhandler.cmd = hmp_info_io_apic,
},
#endif
@@ -149,7 +149,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show infos for each CPU",
.cmd = hmp_info_cpus,
.mhandler.cmd = hmp_info_cpus,
},
STEXI
@@ -163,7 +163,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the command line history",
.cmd = hmp_info_history,
.mhandler.cmd = hmp_info_history,
},
STEXI
@@ -180,11 +180,11 @@ ETEXI
.params = "",
.help = "show the interrupts statistics (if available)",
#ifdef TARGET_SPARC
.cmd = sun4m_hmp_info_irq,
.mhandler.cmd = sun4m_hmp_info_irq,
#elif defined(TARGET_LM32)
.cmd = lm32_hmp_info_irq,
.mhandler.cmd = lm32_hmp_info_irq,
#else
.cmd = hmp_info_irq,
.mhandler.cmd = hmp_info_irq,
#endif
},
@@ -200,11 +200,11 @@ ETEXI
.params = "",
.help = "show i8259 (PIC) state",
#ifdef TARGET_SPARC
.cmd = sun4m_hmp_info_pic,
.mhandler.cmd = sun4m_hmp_info_pic,
#elif defined(TARGET_LM32)
.cmd = lm32_hmp_info_pic,
.mhandler.cmd = lm32_hmp_info_pic,
#else
.cmd = hmp_info_pic,
.mhandler.cmd = hmp_info_pic,
#endif
},
#endif
@@ -220,7 +220,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show PCI info",
.cmd = hmp_info_pci,
.mhandler.cmd = hmp_info_pci,
},
STEXI
@@ -236,7 +236,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show virtual to physical memory mappings",
.cmd = hmp_info_tlb,
.mhandler.cmd = hmp_info_tlb,
},
#endif
@@ -252,7 +252,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the active virtual memory mappings",
.cmd = hmp_info_mem,
.mhandler.cmd = hmp_info_mem,
},
#endif
@@ -267,7 +267,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show memory tree",
.cmd = hmp_info_mtree,
.mhandler.cmd = hmp_info_mtree,
},
STEXI
@@ -281,7 +281,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show dynamic compiler info",
.cmd = hmp_info_jit,
.mhandler.cmd = hmp_info_jit,
},
STEXI
@@ -295,7 +295,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show dynamic compiler opcode counters",
.cmd = hmp_info_opcount,
.mhandler.cmd = hmp_info_opcount,
},
STEXI
@@ -309,7 +309,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show KVM information",
.cmd = hmp_info_kvm,
.mhandler.cmd = hmp_info_kvm,
},
STEXI
@@ -323,7 +323,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show NUMA information",
.cmd = hmp_info_numa,
.mhandler.cmd = hmp_info_numa,
},
STEXI
@@ -337,7 +337,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show guest USB devices",
.cmd = hmp_info_usb,
.mhandler.cmd = hmp_info_usb,
},
STEXI
@@ -351,7 +351,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show host USB devices",
.cmd = hmp_info_usbhost,
.mhandler.cmd = hmp_info_usbhost,
},
STEXI
@@ -365,7 +365,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show profiling information",
.cmd = hmp_info_profile,
.mhandler.cmd = hmp_info_profile,
},
STEXI
@@ -379,7 +379,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show capture information",
.cmd = hmp_info_capture,
.mhandler.cmd = hmp_info_capture,
},
STEXI
@@ -393,7 +393,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the currently saved VM snapshots",
.cmd = hmp_info_snapshots,
.mhandler.cmd = hmp_info_snapshots,
},
STEXI
@@ -407,7 +407,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the current VM status (running|paused)",
.cmd = hmp_info_status,
.mhandler.cmd = hmp_info_status,
},
STEXI
@@ -421,7 +421,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show which guest mouse is receiving events",
.cmd = hmp_info_mice,
.mhandler.cmd = hmp_info_mice,
},
STEXI
@@ -435,7 +435,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the vnc server status",
.cmd = hmp_info_vnc,
.mhandler.cmd = hmp_info_vnc,
},
STEXI
@@ -450,7 +450,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the spice server status",
.cmd = hmp_info_spice,
.mhandler.cmd = hmp_info_spice,
},
#endif
@@ -465,7 +465,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the current VM name",
.cmd = hmp_info_name,
.mhandler.cmd = hmp_info_name,
},
STEXI
@@ -479,7 +479,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the current VM UUID",
.cmd = hmp_info_uuid,
.mhandler.cmd = hmp_info_uuid,
},
STEXI
@@ -493,7 +493,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show CPU statistics",
.cmd = hmp_info_cpustats,
.mhandler.cmd = hmp_info_cpustats,
},
STEXI
@@ -508,7 +508,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show user network stack connection states",
.cmd = hmp_info_usernet,
.mhandler.cmd = hmp_info_usernet,
},
#endif
@@ -523,7 +523,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show migration status",
.cmd = hmp_info_migrate,
.mhandler.cmd = hmp_info_migrate,
},
STEXI
@@ -537,7 +537,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show current migration capabilities",
.cmd = hmp_info_migrate_capabilities,
.mhandler.cmd = hmp_info_migrate_capabilities,
},
STEXI
@@ -551,7 +551,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show current migration parameters",
.cmd = hmp_info_migrate_parameters,
.mhandler.cmd = hmp_info_migrate_parameters,
},
STEXI
@@ -565,7 +565,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show current migration xbzrle cache size",
.cmd = hmp_info_migrate_cache_size,
.mhandler.cmd = hmp_info_migrate_cache_size,
},
STEXI
@@ -579,7 +579,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show balloon information",
.cmd = hmp_info_balloon,
.mhandler.cmd = hmp_info_balloon,
},
STEXI
@@ -593,7 +593,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show device tree",
.cmd = hmp_info_qtree,
.mhandler.cmd = hmp_info_qtree,
},
STEXI
@@ -607,7 +607,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show qdev device model list",
.cmd = hmp_info_qdm,
.mhandler.cmd = hmp_info_qdm,
},
STEXI
@@ -621,7 +621,7 @@ ETEXI
.args_type = "path:s?",
.params = "[path]",
.help = "show QOM composition tree",
.cmd = hmp_info_qom_tree,
.mhandler.cmd = hmp_info_qom_tree,
},
STEXI
@@ -635,7 +635,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show roms",
.cmd = hmp_info_roms,
.mhandler.cmd = hmp_info_roms,
},
STEXI
@@ -650,7 +650,7 @@ ETEXI
.params = "[name] [vcpu]",
.help = "show available trace-events & their state "
"(name: event name pattern; vcpu: vCPU to query, default is any)",
.cmd = hmp_info_trace_events,
.mhandler.cmd = hmp_info_trace_events,
.command_completion = info_trace_events_completion,
},
@@ -665,7 +665,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show the TPM device",
.cmd = hmp_info_tpm,
.mhandler.cmd = hmp_info_tpm,
},
STEXI
@@ -679,7 +679,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show memory backends",
.cmd = hmp_info_memdev,
.mhandler.cmd = hmp_info_memdev,
},
STEXI
@@ -693,7 +693,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show memory devices",
.cmd = hmp_info_memory_devices,
.mhandler.cmd = hmp_info_memory_devices,
},
STEXI
@@ -707,7 +707,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "show iothreads",
.cmd = hmp_info_iothreads,
.mhandler.cmd = hmp_info_iothreads,
},
STEXI
@@ -721,7 +721,7 @@ ETEXI
.args_type = "name:s",
.params = "name",
.help = "Show rocker switch",
.cmd = hmp_rocker,
.mhandler.cmd = hmp_rocker,
},
STEXI
@@ -735,7 +735,7 @@ ETEXI
.args_type = "name:s",
.params = "name",
.help = "Show rocker ports",
.cmd = hmp_rocker_ports,
.mhandler.cmd = hmp_rocker_ports,
},
STEXI
@@ -749,7 +749,7 @@ ETEXI
.args_type = "name:s,tbl_id:i?",
.params = "name [tbl_id]",
.help = "Show rocker OF-DPA flow tables",
.cmd = hmp_rocker_of_dpa_flows,
.mhandler.cmd = hmp_rocker_of_dpa_flows,
},
STEXI
@@ -763,7 +763,7 @@ ETEXI
.args_type = "name:s,type:i?",
.params = "name [type]",
.help = "Show rocker OF-DPA groups",
.cmd = hmp_rocker_of_dpa_groups,
.mhandler.cmd = hmp_rocker_of_dpa_groups,
},
STEXI
@@ -778,7 +778,7 @@ ETEXI
.args_type = "addr:l",
.params = "address",
.help = "Display the value of a storage key",
.cmd = hmp_info_skeys,
.mhandler.cmd = hmp_info_skeys,
},
#endif
@@ -793,7 +793,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "Display the latest dump status",
.cmd = hmp_info_dump,
.mhandler.cmd = hmp_info_dump,
},
STEXI
@@ -807,7 +807,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "Show information about hotpluggable CPUs",
.cmd = hmp_hotpluggable_cpus,
.mhandler.cmd = hmp_hotpluggable_cpus,
},
STEXI

View File

@@ -14,7 +14,7 @@ ETEXI
.args_type = "name:S?",
.params = "[cmd]",
.help = "show the help",
.cmd = do_help_cmd,
.mhandler.cmd = do_help_cmd,
},
STEXI
@@ -28,7 +28,7 @@ ETEXI
.args_type = "device:B",
.params = "device|all",
.help = "commit changes to the disk images (if -snapshot is used) or backing files",
.cmd = hmp_commit,
.mhandler.cmd = hmp_commit,
},
STEXI
@@ -47,7 +47,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "quit the emulator",
.cmd = hmp_quit,
.mhandler.cmd = hmp_quit,
},
STEXI
@@ -61,7 +61,7 @@ ETEXI
.args_type = "device:B,size:o",
.params = "device size",
.help = "resize a block image",
.cmd = hmp_block_resize,
.mhandler.cmd = hmp_block_resize,
},
STEXI
@@ -78,7 +78,7 @@ ETEXI
.args_type = "device:B,speed:o?,base:s?",
.params = "device [speed [base]]",
.help = "copy data from a backing file into a block device",
.cmd = hmp_block_stream,
.mhandler.cmd = hmp_block_stream,
},
STEXI
@@ -92,7 +92,7 @@ ETEXI
.args_type = "device:B,speed:o",
.params = "device speed",
.help = "set maximum speed for a background block operation",
.cmd = hmp_block_job_set_speed,
.mhandler.cmd = hmp_block_job_set_speed,
},
STEXI
@@ -107,7 +107,7 @@ ETEXI
.params = "[-f] device",
.help = "stop an active background block operation (use -f"
"\n\t\t\t if the operation is currently paused)",
.cmd = hmp_block_job_cancel,
.mhandler.cmd = hmp_block_job_cancel,
},
STEXI
@@ -121,7 +121,7 @@ ETEXI
.args_type = "device:B",
.params = "device",
.help = "stop an active background block operation",
.cmd = hmp_block_job_complete,
.mhandler.cmd = hmp_block_job_complete,
},
STEXI
@@ -136,7 +136,7 @@ ETEXI
.args_type = "device:B",
.params = "device",
.help = "pause an active background block operation",
.cmd = hmp_block_job_pause,
.mhandler.cmd = hmp_block_job_pause,
},
STEXI
@@ -150,7 +150,7 @@ ETEXI
.args_type = "device:B",
.params = "device",
.help = "resume a paused background block operation",
.cmd = hmp_block_job_resume,
.mhandler.cmd = hmp_block_job_resume,
},
STEXI
@@ -164,7 +164,7 @@ ETEXI
.args_type = "force:-f,device:B",
.params = "[-f] device",
.help = "eject a removable medium (use -f to force it)",
.cmd = hmp_eject,
.mhandler.cmd = hmp_eject,
},
STEXI
@@ -178,7 +178,7 @@ ETEXI
.args_type = "id:B",
.params = "device",
.help = "remove host block device",
.cmd = hmp_drive_del,
.mhandler.cmd = hmp_drive_del,
},
STEXI
@@ -197,7 +197,7 @@ ETEXI
.args_type = "device:B,target:F,arg:s?,read-only-mode:s?",
.params = "device filename [format [read-only-mode]]",
.help = "change a removable medium, optional format",
.cmd = hmp_change,
.mhandler.cmd = hmp_change,
},
STEXI
@@ -256,7 +256,7 @@ ETEXI
.args_type = "filename:F",
.params = "filename",
.help = "save screen into PPM image 'filename'",
.cmd = hmp_screendump,
.mhandler.cmd = hmp_screendump,
},
STEXI
@@ -270,7 +270,7 @@ ETEXI
.args_type = "filename:F",
.params = "filename",
.help = "output logs to 'filename'",
.cmd = hmp_logfile,
.mhandler.cmd = hmp_logfile,
},
STEXI
@@ -285,7 +285,7 @@ ETEXI
.params = "name on|off [vcpu]",
.help = "changes status of a specific trace event "
"(vcpu: vCPU to set, default is all)",
.cmd = hmp_trace_event,
.mhandler.cmd = hmp_trace_event,
.command_completion = trace_event_completion,
},
@@ -301,7 +301,7 @@ ETEXI
.args_type = "op:s?,arg:F?",
.params = "on|off|flush|set [arg]",
.help = "open, close, or flush trace file, or set a new file name",
.cmd = hmp_trace_file,
.mhandler.cmd = hmp_trace_file,
},
STEXI
@@ -316,7 +316,7 @@ ETEXI
.args_type = "items:s",
.params = "item1[,...]",
.help = "activate logging of the specified items",
.cmd = hmp_log,
.mhandler.cmd = hmp_log,
},
STEXI
@@ -330,7 +330,7 @@ ETEXI
.args_type = "name:s?",
.params = "[tag|id]",
.help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created",
.cmd = hmp_savevm,
.mhandler.cmd = hmp_savevm,
},
STEXI
@@ -347,7 +347,7 @@ ETEXI
.args_type = "name:s",
.params = "tag|id",
.help = "restore a VM snapshot from its tag or id",
.cmd = hmp_loadvm,
.mhandler.cmd = hmp_loadvm,
.command_completion = loadvm_completion,
},
@@ -363,7 +363,7 @@ ETEXI
.args_type = "name:s",
.params = "tag|id",
.help = "delete a VM snapshot from its tag or id",
.cmd = hmp_delvm,
.mhandler.cmd = hmp_delvm,
.command_completion = delvm_completion,
},
@@ -378,7 +378,7 @@ ETEXI
.args_type = "option:s?",
.params = "[on|off]",
.help = "run emulation in singlestep mode or switch to normal mode",
.cmd = hmp_singlestep,
.mhandler.cmd = hmp_singlestep,
},
STEXI
@@ -393,7 +393,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "stop emulation",
.cmd = hmp_stop,
.mhandler.cmd = hmp_stop,
},
STEXI
@@ -407,7 +407,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "resume emulation",
.cmd = hmp_cont,
.mhandler.cmd = hmp_cont,
},
STEXI
@@ -421,7 +421,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "wakeup guest from suspend",
.cmd = hmp_system_wakeup,
.mhandler.cmd = hmp_system_wakeup,
},
STEXI
@@ -435,7 +435,7 @@ ETEXI
.args_type = "device:s?",
.params = "[device]",
.help = "start gdbserver on given device (default 'tcp::1234'), stop with 'none'",
.cmd = hmp_gdbserver,
.mhandler.cmd = hmp_gdbserver,
},
STEXI
@@ -449,7 +449,7 @@ ETEXI
.args_type = "fmt:/,addr:l",
.params = "/fmt addr",
.help = "virtual memory dump starting at 'addr'",
.cmd = hmp_memory_dump,
.mhandler.cmd = hmp_memory_dump,
},
STEXI
@@ -463,7 +463,7 @@ ETEXI
.args_type = "fmt:/,addr:l",
.params = "/fmt addr",
.help = "physical memory dump starting at 'addr'",
.cmd = hmp_physical_memory_dump,
.mhandler.cmd = hmp_physical_memory_dump,
},
STEXI
@@ -530,7 +530,7 @@ ETEXI
.args_type = "fmt:/,val:l",
.params = "/fmt expr",
.help = "print expression value (use $reg for CPU register access)",
.cmd = do_print,
.mhandler.cmd = do_print,
},
STEXI
@@ -545,7 +545,7 @@ ETEXI
.args_type = "fmt:/,addr:i,index:i.",
.params = "/fmt addr",
.help = "I/O port read",
.cmd = hmp_ioport_read,
.mhandler.cmd = hmp_ioport_read,
},
STEXI
@@ -559,7 +559,7 @@ ETEXI
.args_type = "fmt:/,addr:i,val:i",
.params = "/fmt addr value",
.help = "I/O port write",
.cmd = hmp_ioport_write,
.mhandler.cmd = hmp_ioport_write,
},
STEXI
@@ -573,7 +573,7 @@ ETEXI
.args_type = "keys:s,hold-time:i?",
.params = "keys [hold_ms]",
.help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
.cmd = hmp_sendkey,
.mhandler.cmd = hmp_sendkey,
.command_completion = sendkey_completion,
},
@@ -596,7 +596,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "reset the system",
.cmd = hmp_system_reset,
.mhandler.cmd = hmp_system_reset,
},
STEXI
@@ -610,7 +610,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "send system power down event",
.cmd = hmp_system_powerdown,
.mhandler.cmd = hmp_system_powerdown,
},
STEXI
@@ -624,7 +624,7 @@ ETEXI
.args_type = "start:i,size:i",
.params = "addr size",
.help = "compute the checksum of a memory region",
.cmd = hmp_sum,
.mhandler.cmd = hmp_sum,
},
STEXI
@@ -638,7 +638,7 @@ ETEXI
.args_type = "devname:s",
.params = "device",
.help = "add USB device (e.g. 'host:bus.addr' or 'host:vendor_id:product_id')",
.cmd = hmp_usb_add,
.mhandler.cmd = hmp_usb_add,
},
STEXI
@@ -653,7 +653,7 @@ ETEXI
.args_type = "devname:s",
.params = "device",
.help = "remove USB device 'bus.addr'",
.cmd = hmp_usb_del,
.mhandler.cmd = hmp_usb_del,
},
STEXI
@@ -669,7 +669,7 @@ ETEXI
.args_type = "device:O",
.params = "driver[,prop=value][,...]",
.help = "add device, like -device on the command line",
.cmd = hmp_device_add,
.mhandler.cmd = hmp_device_add,
.command_completion = device_add_completion,
},
@@ -684,7 +684,7 @@ ETEXI
.args_type = "id:s",
.params = "device",
.help = "remove device",
.cmd = hmp_device_del,
.mhandler.cmd = hmp_device_del,
.command_completion = device_del_completion,
},
@@ -700,7 +700,7 @@ ETEXI
.args_type = "index:i",
.params = "index",
.help = "set the default CPU",
.cmd = hmp_cpu,
.mhandler.cmd = hmp_cpu,
},
STEXI
@@ -714,7 +714,7 @@ ETEXI
.args_type = "dx_str:s,dy_str:s,dz_str:s?",
.params = "dx dy [dz]",
.help = "send mouse move events",
.cmd = hmp_mouse_move,
.mhandler.cmd = hmp_mouse_move,
},
STEXI
@@ -729,7 +729,7 @@ ETEXI
.args_type = "button_state:i",
.params = "state",
.help = "change mouse button state (1=L, 2=M, 4=R)",
.cmd = hmp_mouse_button,
.mhandler.cmd = hmp_mouse_button,
},
STEXI
@@ -743,7 +743,7 @@ ETEXI
.args_type = "index:i",
.params = "index",
.help = "set which mouse device receives events",
.cmd = hmp_mouse_set,
.mhandler.cmd = hmp_mouse_set,
},
STEXI
@@ -761,7 +761,7 @@ ETEXI
.args_type = "path:F,freq:i?,bits:i?,nchannels:i?",
.params = "path [frequency [bits [channels]]]",
.help = "capture audio to a wave file (default frequency=44100 bits=16 channels=2)",
.cmd = hmp_wavcapture,
.mhandler.cmd = hmp_wavcapture,
},
STEXI
@item wavcapture @var{filename} [@var{frequency} [@var{bits} [@var{channels}]]]
@@ -782,7 +782,7 @@ ETEXI
.args_type = "n:i",
.params = "capture index",
.help = "stop capture",
.cmd = hmp_stopcapture,
.mhandler.cmd = hmp_stopcapture,
},
STEXI
@item stopcapture @var{index}
@@ -798,7 +798,7 @@ ETEXI
.args_type = "val:l,size:i,filename:s",
.params = "addr size file",
.help = "save to disk virtual memory dump starting at 'addr' of size 'size'",
.cmd = hmp_memsave,
.mhandler.cmd = hmp_memsave,
},
STEXI
@@ -812,7 +812,7 @@ ETEXI
.args_type = "val:l,size:i,filename:s",
.params = "addr size file",
.help = "save to disk physical memory dump starting at 'addr' of size 'size'",
.cmd = hmp_pmemsave,
.mhandler.cmd = hmp_pmemsave,
},
STEXI
@@ -826,7 +826,7 @@ ETEXI
.args_type = "bootdevice:s",
.params = "bootdevice",
.help = "define new values for the boot device list",
.cmd = hmp_boot_set,
.mhandler.cmd = hmp_boot_set,
},
STEXI
@@ -844,7 +844,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "inject an NMI",
.cmd = hmp_nmi,
.mhandler.cmd = hmp_nmi,
},
STEXI
@item nmi @var{cpu}
@@ -858,7 +858,7 @@ ETEXI
.args_type = "device:s,data:s",
.params = "device data",
.help = "Write to a ring buffer character device",
.cmd = hmp_ringbuf_write,
.mhandler.cmd = hmp_ringbuf_write,
.command_completion = ringbuf_write_completion,
},
@@ -875,7 +875,7 @@ ETEXI
.args_type = "device:s,size:i",
.params = "device size",
.help = "Read from a ring buffer character device",
.cmd = hmp_ringbuf_read,
.mhandler.cmd = hmp_ringbuf_read,
.command_completion = ringbuf_write_completion,
},
@@ -901,7 +901,7 @@ ETEXI
" full copy of disk\n\t\t\t -i for migration without "
"shared storage with incremental copy of disk "
"(base image shared between src and destination)",
.cmd = hmp_migrate,
.mhandler.cmd = hmp_migrate,
},
@@ -918,7 +918,7 @@ ETEXI
.args_type = "",
.params = "",
.help = "cancel the current VM migration",
.cmd = hmp_migrate_cancel,
.mhandler.cmd = hmp_migrate_cancel,
},
STEXI
@@ -933,7 +933,7 @@ ETEXI
.args_type = "uri:s",
.params = "uri",
.help = "Continue an incoming migration from an -incoming defer",
.cmd = hmp_migrate_incoming,
.mhandler.cmd = hmp_migrate_incoming,
},
STEXI
@@ -954,7 +954,7 @@ ETEXI
"The cache size affects the number of cache misses."
"In case of a high cache miss ratio you need to increase"
" the cache size",
.cmd = hmp_migrate_set_cache_size,
.mhandler.cmd = hmp_migrate_set_cache_size,
},
STEXI
@@ -969,7 +969,7 @@ ETEXI
.params = "value",
.help = "set maximum speed (in bytes) for migrations. "
"Defaults to MB if no size suffix is specified, ie. B/K/M/G/T",
.cmd = hmp_migrate_set_speed,
.mhandler.cmd = hmp_migrate_set_speed,
},
STEXI
@@ -983,7 +983,7 @@ ETEXI
.args_type = "value:T",
.params = "value",
.help = "set maximum tolerated downtime (in seconds) for migrations",
.cmd = hmp_migrate_set_downtime,
.mhandler.cmd = hmp_migrate_set_downtime,
},
STEXI
@@ -997,7 +997,7 @@ ETEXI
.args_type = "capability:s,state:b",
.params = "capability state",
.help = "Enable/Disable the usage of a capability for migration",
.cmd = hmp_migrate_set_capability,
.mhandler.cmd = hmp_migrate_set_capability,
.command_completion = migrate_set_capability_completion,
},
@@ -1012,7 +1012,7 @@ ETEXI
.args_type = "parameter:s,value:s",
.params = "parameter value",
.help = "Set the parameter for migration",
.cmd = hmp_migrate_set_parameter,
.mhandler.cmd = hmp_migrate_set_parameter,
.command_completion = migrate_set_parameter_completion,
},
@@ -1029,7 +1029,7 @@ ETEXI
.help = "Followup to a migration command to switch the migration"
" to postcopy mode. The postcopy-ram capability must "
"be set before the original migration command.",
.cmd = hmp_migrate_start_postcopy,
.mhandler.cmd = hmp_migrate_start_postcopy,
},
STEXI
@@ -1044,7 +1044,7 @@ ETEXI
.args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
.params = "protocol hostname port tls-port cert-subject",
.help = "set migration information for remote display",
.cmd = hmp_client_migrate_info,
.mhandler.cmd = hmp_client_migrate_info,
},
STEXI
@@ -1067,7 +1067,7 @@ ETEXI
"-s: dump in kdump-compressed format, with snappy compression.\n\t\t\t"
"begin: the starting physical address.\n\t\t\t"
"length: the memory size, in bytes.",
.cmd = hmp_dump_guest_memory,
.mhandler.cmd = hmp_dump_guest_memory,
},
@@ -1094,7 +1094,7 @@ ETEXI
.args_type = "filename:F",
.params = "",
.help = "Save guest storage keys into file 'filename'.\n",
.cmd = hmp_dump_skeys,
.mhandler.cmd = hmp_dump_skeys,
},
#endif
@@ -1116,7 +1116,7 @@ ETEXI
"The default format is qcow2. The -n flag requests QEMU\n\t\t\t"
"to reuse the image found in new-image-file, instead of\n\t\t\t"
"recreating it from scratch.",
.cmd = hmp_snapshot_blkdev,
.mhandler.cmd = hmp_snapshot_blkdev,
},
STEXI
@@ -1132,7 +1132,7 @@ ETEXI
.help = "take an internal snapshot of device.\n\t\t\t"
"The format of the image used by device must\n\t\t\t"
"support it, such as qcow2.\n\t\t\t",
.cmd = hmp_snapshot_blkdev_internal,
.mhandler.cmd = hmp_snapshot_blkdev_internal,
},
STEXI
@@ -1150,7 +1150,7 @@ ETEXI
"the snapshot matching both id and name.\n\t\t\t"
"The format of the image used by device must\n\t\t\t"
"support it, such as qcow2.\n\t\t\t",
.cmd = hmp_snapshot_delete_blkdev_internal,
.mhandler.cmd = hmp_snapshot_delete_blkdev_internal,
},
STEXI
@@ -1171,7 +1171,7 @@ ETEXI
"in new-image-file, instead of recreating it from scratch.\n\t\t\t"
"The -f flag requests QEMU to copy the whole disk,\n\t\t\t"
"so that the result does not need a backing file.\n\t\t\t",
.cmd = hmp_drive_mirror,
.mhandler.cmd = hmp_drive_mirror,
},
STEXI
@item drive_mirror
@@ -1182,8 +1182,8 @@ ETEXI
{
.name = "drive_backup",
.args_type = "reuse:-n,full:-f,compress:-c,device:B,target:s,format:s?",
.params = "[-n] [-f] [-c] device target [format]",
.args_type = "reuse:-n,full:-f,device:B,target:s,format:s?",
.params = "[-n] [-f] device target [format]",
.help = "initiates a point-in-time\n\t\t\t"
"copy for a device. The device's contents are\n\t\t\t"
"copied to the new image file, excluding data that\n\t\t\t"
@@ -1191,10 +1191,8 @@ ETEXI
"The -n flag requests QEMU to reuse the image found\n\t\t\t"
"in new-image-file, instead of recreating it from scratch.\n\t\t\t"
"The -f flag requests QEMU to copy the whole disk,\n\t\t\t"
"so that the result does not need a backing file.\n\t\t\t"
"The -c flag requests QEMU to compress backup data\n\t\t\t"
"(if the target format supports it).\n\t\t\t",
.cmd = hmp_drive_backup,
"so that the result does not need a backing file.\n\t\t\t",
.mhandler.cmd = hmp_drive_backup,
},
STEXI
@item drive_backup
@@ -1212,7 +1210,7 @@ ETEXI
"[,snapshot=on|off][,cache=on|off]\n"
"[,readonly=on|off][,copy-on-read=on|off]",
.help = "add drive to PCI storage controller",
.cmd = hmp_drive_add,
.mhandler.cmd = hmp_drive_add,
},
STEXI
@@ -1236,7 +1234,7 @@ ETEXI
"<error_status> = error string or 32bit\n\t\t\t"
"<tlb header> = 32bit x 4\n\t\t\t"
"<tlb header prefix> = 32bit x 4",
.cmd = hmp_pcie_aer_inject_error,
.mhandler.cmd = hmp_pcie_aer_inject_error,
},
STEXI
@@ -1250,7 +1248,7 @@ ETEXI
.args_type = "device:s,opts:s?",
.params = "tap|user|socket|vde|netmap|bridge|vhost-user|dump [options]",
.help = "add host VLAN client",
.cmd = hmp_host_net_add,
.mhandler.cmd = hmp_host_net_add,
.command_completion = host_net_add_completion,
},
@@ -1265,7 +1263,7 @@ ETEXI
.args_type = "vlan_id:i,device:s",
.params = "vlan_id name",
.help = "remove host VLAN client",
.cmd = hmp_host_net_remove,
.mhandler.cmd = hmp_host_net_remove,
.command_completion = host_net_remove_completion,
},
@@ -1280,7 +1278,7 @@ ETEXI
.args_type = "netdev:O",
.params = "[user|tap|socket|vde|bridge|hubport|netmap|vhost-user],id=str[,prop=value][,...]",
.help = "add host network device",
.cmd = hmp_netdev_add,
.mhandler.cmd = hmp_netdev_add,
.command_completion = netdev_add_completion,
},
@@ -1295,7 +1293,7 @@ ETEXI
.args_type = "id:s",
.params = "id",
.help = "remove host network device",
.cmd = hmp_netdev_del,
.mhandler.cmd = hmp_netdev_del,
.command_completion = netdev_del_completion,
},
@@ -1310,7 +1308,7 @@ ETEXI
.args_type = "object:O",
.params = "[qom-type=]type,id=str[,prop=value][,...]",
.help = "create QOM object",
.cmd = hmp_object_add,
.mhandler.cmd = hmp_object_add,
.command_completion = object_add_completion,
},
@@ -1325,7 +1323,7 @@ ETEXI
.args_type = "id:s",
.params = "id",
.help = "destroy QOM object",
.cmd = hmp_object_del,
.mhandler.cmd = hmp_object_del,
.command_completion = object_del_completion,
},
@@ -1341,7 +1339,7 @@ ETEXI
.args_type = "arg1:s,arg2:s?,arg3:s?",
.params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
.help = "redirect TCP or UDP connections from host to guest (requires -net user)",
.cmd = hmp_hostfwd_add,
.mhandler.cmd = hmp_hostfwd_add,
},
#endif
STEXI
@@ -1356,7 +1354,7 @@ ETEXI
.args_type = "arg1:s,arg2:s?,arg3:s?",
.params = "[vlan_id name] [tcp|udp]:[hostaddr]:hostport",
.help = "remove host-to-guest TCP or UDP redirection",
.cmd = hmp_hostfwd_remove,
.mhandler.cmd = hmp_hostfwd_remove,
},
#endif
@@ -1371,7 +1369,7 @@ ETEXI
.args_type = "value:M",
.params = "target",
.help = "request VM to change its memory allocation (in MB)",
.cmd = hmp_balloon,
.mhandler.cmd = hmp_balloon,
},
STEXI
@@ -1385,7 +1383,7 @@ ETEXI
.args_type = "name:s,up:b",
.params = "name on|off",
.help = "change the link status of a network adapter",
.cmd = hmp_set_link,
.mhandler.cmd = hmp_set_link,
.command_completion = set_link_completion,
},
@@ -1400,7 +1398,7 @@ ETEXI
.args_type = "action:s",
.params = "[reset|shutdown|poweroff|pause|debug|none]",
.help = "change watchdog action",
.cmd = hmp_watchdog_action,
.mhandler.cmd = hmp_watchdog_action,
.command_completion = watchdog_action_completion,
},
@@ -1415,7 +1413,7 @@ ETEXI
.args_type = "aclname:s",
.params = "aclname",
.help = "list rules in the access control list",
.cmd = hmp_acl_show,
.mhandler.cmd = hmp_acl_show,
},
STEXI
@@ -1432,7 +1430,7 @@ ETEXI
.args_type = "aclname:s,policy:s",
.params = "aclname allow|deny",
.help = "set default access control list policy",
.cmd = hmp_acl_policy,
.mhandler.cmd = hmp_acl_policy,
},
STEXI
@@ -1448,7 +1446,7 @@ ETEXI
.args_type = "aclname:s,match:s,policy:s,index:i?",
.params = "aclname match allow|deny [index]",
.help = "add a match rule to the access control list",
.cmd = hmp_acl_add,
.mhandler.cmd = hmp_acl_add,
},
STEXI
@@ -1467,7 +1465,7 @@ ETEXI
.args_type = "aclname:s,match:s",
.params = "aclname match",
.help = "remove a match rule from the access control list",
.cmd = hmp_acl_remove,
.mhandler.cmd = hmp_acl_remove,
},
STEXI
@@ -1481,7 +1479,7 @@ ETEXI
.args_type = "aclname:s",
.params = "aclname",
.help = "reset the access control list",
.cmd = hmp_acl_reset,
.mhandler.cmd = hmp_acl_reset,
},
STEXI
@@ -1496,7 +1494,7 @@ ETEXI
.args_type = "all:-a,writable:-w,uri:s",
.params = "nbd_server_start [-a] [-w] host:port",
.help = "serve block devices on the given host and port",
.cmd = hmp_nbd_server_start,
.mhandler.cmd = hmp_nbd_server_start,
},
STEXI
@item nbd_server_start @var{host}:@var{port}
@@ -1512,7 +1510,7 @@ ETEXI
.args_type = "writable:-w,device:B",
.params = "nbd_server_add [-w] device",
.help = "export a block device via NBD",
.cmd = hmp_nbd_server_add,
.mhandler.cmd = hmp_nbd_server_add,
},
STEXI
@item nbd_server_add @var{device}
@@ -1527,7 +1525,7 @@ ETEXI
.args_type = "",
.params = "nbd_server_stop",
.help = "stop serving block devices using the NBD protocol",
.cmd = hmp_nbd_server_stop,
.mhandler.cmd = hmp_nbd_server_stop,
},
STEXI
@item nbd_server_stop
@@ -1543,7 +1541,7 @@ ETEXI
.args_type = "broadcast:-b,cpu_index:i,bank:i,status:l,mcg_status:l,addr:l,misc:l",
.params = "[-b] cpu bank status mcgstatus addr misc",
.help = "inject a MCE on the given CPU [and broadcast to other CPUs with -b option]",
.cmd = hmp_mce,
.mhandler.cmd = hmp_mce,
},
#endif
@@ -1558,7 +1556,7 @@ ETEXI
.args_type = "fdname:s",
.params = "getfd name",
.help = "receive a file descriptor via SCM rights and assign it a name",
.cmd = hmp_getfd,
.mhandler.cmd = hmp_getfd,
},
STEXI
@@ -1574,7 +1572,7 @@ ETEXI
.args_type = "fdname:s",
.params = "closefd name",
.help = "close a file descriptor previously passed via SCM rights",
.cmd = hmp_closefd,
.mhandler.cmd = hmp_closefd,
},
STEXI
@@ -1590,7 +1588,7 @@ ETEXI
.args_type = "device:B,password:s",
.params = "block_passwd device password",
.help = "set the password of encrypted block devices",
.cmd = hmp_block_passwd,
.mhandler.cmd = hmp_block_passwd,
},
STEXI
@@ -1604,7 +1602,7 @@ ETEXI
.args_type = "device:B,bps:l,bps_rd:l,bps_wr:l,iops:l,iops_rd:l,iops_wr:l",
.params = "device bps bps_rd bps_wr iops iops_rd iops_wr",
.help = "change I/O throttle limits for a block drive",
.cmd = hmp_block_set_io_throttle,
.mhandler.cmd = hmp_block_set_io_throttle,
},
STEXI
@@ -1618,7 +1616,7 @@ ETEXI
.args_type = "protocol:s,password:s,connected:s?",
.params = "protocol password action-if-connected",
.help = "set spice/vnc password",
.cmd = hmp_set_password,
.mhandler.cmd = hmp_set_password,
},
STEXI
@@ -1637,7 +1635,7 @@ ETEXI
.args_type = "protocol:s,time:s",
.params = "protocol time",
.help = "set spice/vnc password expire-time",
.cmd = hmp_expire_password,
.mhandler.cmd = hmp_expire_password,
},
STEXI
@@ -1668,7 +1666,7 @@ ETEXI
.args_type = "args:s",
.params = "args",
.help = "add chardev",
.cmd = hmp_chardev_add,
.mhandler.cmd = hmp_chardev_add,
.command_completion = chardev_add_completion,
},
@@ -1684,7 +1682,7 @@ ETEXI
.args_type = "id:s",
.params = "id",
.help = "remove chardev",
.cmd = hmp_chardev_remove,
.mhandler.cmd = hmp_chardev_remove,
.command_completion = chardev_remove_completion,
},
@@ -1700,7 +1698,7 @@ ETEXI
.args_type = "device:B,command:s",
.params = "[device] \"[command]\"",
.help = "run a qemu-io command on a block device",
.cmd = hmp_qemu_io,
.mhandler.cmd = hmp_qemu_io,
},
STEXI
@@ -1715,7 +1713,7 @@ ETEXI
.args_type = "id:i",
.params = "id",
.help = "add cpu",
.cmd = hmp_cpu_add,
.mhandler.cmd = hmp_cpu_add,
},
STEXI
@@ -1729,7 +1727,7 @@ ETEXI
.args_type = "path:s?",
.params = "path",
.help = "list QOM properties",
.cmd = hmp_qom_list,
.mhandler.cmd = hmp_qom_list,
},
STEXI
@@ -1742,7 +1740,7 @@ ETEXI
.args_type = "path:s,property:s,value:s",
.params = "path property value",
.help = "set QOM property",
.cmd = hmp_qom_set,
.mhandler.cmd = hmp_qom_set,
},
STEXI
@@ -1755,8 +1753,8 @@ ETEXI
.args_type = "item:s?",
.params = "[subcommand]",
.help = "show various information about the system state",
.cmd = hmp_info_help,
.sub_table = info_cmds,
.mhandler.cmd = hmp_info_help,
.sub_table = info_cmds,
},
STEXI

61
hmp.c
View File

@@ -1109,19 +1109,8 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
const char *format = qdict_get_try_str(qdict, "format");
bool reuse = qdict_get_try_bool(qdict, "reuse", false);
bool full = qdict_get_try_bool(qdict, "full", false);
bool compress = qdict_get_try_bool(qdict, "compress", false);
enum NewImageMode mode;
Error *err = NULL;
DriveBackup backup = {
.device = (char *)device,
.target = (char *)filename,
.has_format = !!format,
.format = (char *)format,
.sync = full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
.has_mode = true,
.mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS,
.has_compress = !!compress,
.compress = compress,
};
if (!filename) {
error_setg(&err, QERR_MISSING_PARAMETER, "target");
@@ -1129,7 +1118,16 @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
return;
}
qmp_drive_backup(&backup, &err);
if (reuse) {
mode = NEW_IMAGE_MODE_EXISTING;
} else {
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
}
qmp_drive_backup(false, NULL, device, filename, !!format, format,
full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP,
true, mode, false, 0, false, NULL,
false, 0, false, 0, &err);
hmp_handle_error(mon, &err);
}
@@ -1286,6 +1284,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
break;
case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
has_cpu_throttle_increment = true;
use_int_value = true;
break;
case MIGRATION_PARAMETER_TLS_CREDS:
has_tls_creds = true;
@@ -1376,7 +1375,7 @@ void hmp_eject(Monitor *mon, const QDict *qdict)
const char *device = qdict_get_str(qdict, "device");
Error *err = NULL;
qmp_eject(true, device, false, NULL, true, force, &err);
qmp_eject(device, true, force, &err);
hmp_handle_error(mon, &err);
}
@@ -1422,9 +1421,8 @@ void hmp_change(Monitor *mon, const QDict *qdict)
}
}
qmp_blockdev_change_medium(true, device, false, NULL, target,
!!arg, arg, !!read_only, read_only_mode,
&err);
qmp_blockdev_change_medium(device, target, !!arg, arg,
!!read_only, read_only_mode, &err);
if (err &&
error_get_class(err) == ERROR_CLASS_DEVICE_ENCRYPTED) {
error_free(err);
@@ -1924,32 +1922,23 @@ void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
void hmp_qemu_io(Monitor *mon, const QDict *qdict)
{
BlockBackend *blk;
BlockBackend *local_blk = NULL;
AioContext *aio_context;
const char* device = qdict_get_str(qdict, "device");
const char* command = qdict_get_str(qdict, "command");
Error *err = NULL;
blk = blk_by_name(device);
if (!blk) {
BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
if (bs) {
blk = local_blk = blk_new();
blk_insert_bs(blk, bs);
} else {
goto fail;
}
if (blk) {
AioContext *aio_context = blk_get_aio_context(blk);
aio_context_acquire(aio_context);
qemuio_command(blk, command);
aio_context_release(aio_context);
} else {
error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", device);
}
aio_context = blk_get_aio_context(blk);
aio_context_acquire(aio_context);
qemuio_command(blk, command);
aio_context_release(aio_context);
fail:
blk_unref(local_blk);
hmp_handle_error(mon, &err);
}

View File

@@ -1060,10 +1060,13 @@ static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
const char *name, V9fsPath *target)
{
if (dir_path) {
v9fs_path_sprintf(target, "%s/%s", dir_path->data, name);
v9fs_string_sprintf((V9fsString *)target, "%s/%s",
dir_path->data, name);
} else {
v9fs_path_sprintf(target, "%s", name);
v9fs_string_sprintf((V9fsString *)target, "%s", name);
}
/* Bump the size for including terminating NULL */
target->size++;
return 0;
}

View File

@@ -294,7 +294,8 @@ static int v9fs_receive_status(V9fsProxy *proxy,
* This request read by proxy helper process
* returns 0 on success and -errno on error
*/
static int v9fs_request(V9fsProxy *proxy, int type, void *response, ...)
static int v9fs_request(V9fsProxy *proxy, int type,
void *response, const char *fmt, ...)
{
dev_t rdev;
va_list ap;
@@ -316,7 +317,7 @@ static int v9fs_request(V9fsProxy *proxy, int type, void *response, ...)
}
iovec = &proxy->out_iovec;
reply = &proxy->in_iovec;
va_start(ap, response);
va_start(ap, fmt);
switch (type) {
case T_OPEN:
path = va_arg(ap, V9fsString *);
@@ -604,7 +605,7 @@ close_error:
static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
{
int retval;
retval = v9fs_request(fs_ctx->private, T_LSTAT, stbuf, fs_path);
retval = v9fs_request(fs_ctx->private, T_LSTAT, stbuf, "s", fs_path);
if (retval < 0) {
errno = -retval;
return -1;
@@ -616,7 +617,8 @@ static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
char *buf, size_t bufsz)
{
int retval;
retval = v9fs_request(fs_ctx->private, T_READLINK, buf, fs_path, bufsz);
retval = v9fs_request(fs_ctx->private, T_READLINK, buf, "sd",
fs_path, bufsz);
if (retval < 0) {
errno = -retval;
return -1;
@@ -637,7 +639,7 @@ static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
int flags, V9fsFidOpenState *fs)
{
fs->fd = v9fs_request(ctx->private, T_OPEN, NULL, fs_path, flags);
fs->fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, flags);
if (fs->fd < 0) {
errno = -fs->fd;
fs->fd = -1;
@@ -651,7 +653,7 @@ static int proxy_opendir(FsContext *ctx,
int serrno, fd;
fs->dir.stream = NULL;
fd = v9fs_request(ctx->private, T_OPEN, NULL, fs_path, O_DIRECTORY);
fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, O_DIRECTORY);
if (fd < 0) {
errno = -fd;
return -1;
@@ -733,8 +735,8 @@ static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
int retval;
retval = v9fs_request(fs_ctx->private, T_CHMOD, NULL, fs_path,
credp->fc_mode);
retval = v9fs_request(fs_ctx->private, T_CHMOD, NULL, "sd",
fs_path, credp->fc_mode);
if (retval < 0) {
errno = -retval;
}
@@ -750,8 +752,8 @@ static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
retval = v9fs_request(fs_ctx->private, T_MKNOD, NULL, &fullname,
credp->fc_mode, credp->fc_rdev,
retval = v9fs_request(fs_ctx->private, T_MKNOD, NULL, "sdqdd",
&fullname, credp->fc_mode, credp->fc_rdev,
credp->fc_uid, credp->fc_gid);
v9fs_string_free(&fullname);
if (retval < 0) {
@@ -770,13 +772,14 @@ static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
retval = v9fs_request(fs_ctx->private, T_MKDIR, NULL, &fullname,
retval = v9fs_request(fs_ctx->private, T_MKDIR, NULL, "sddd", &fullname,
credp->fc_mode, credp->fc_uid, credp->fc_gid);
v9fs_string_free(&fullname);
if (retval < 0) {
errno = -retval;
retval = -1;
}
v9fs_string_free(&fullname);
return retval;
}
@@ -801,8 +804,9 @@ static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
fs->fd = v9fs_request(fs_ctx->private, T_CREATE, NULL, &fullname, flags,
credp->fc_mode, credp->fc_uid, credp->fc_gid);
fs->fd = v9fs_request(fs_ctx->private, T_CREATE, NULL, "sdddd",
&fullname, flags, credp->fc_mode,
credp->fc_uid, credp->fc_gid);
v9fs_string_free(&fullname);
if (fs->fd < 0) {
errno = -fs->fd;
@@ -823,8 +827,8 @@ static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
v9fs_string_sprintf(&target, "%s", oldpath);
retval = v9fs_request(fs_ctx->private, T_SYMLINK, NULL, &target, &fullname,
credp->fc_uid, credp->fc_gid);
retval = v9fs_request(fs_ctx->private, T_SYMLINK, NULL, "ssdd",
&target, &fullname, credp->fc_uid, credp->fc_gid);
v9fs_string_free(&fullname);
v9fs_string_free(&target);
if (retval < 0) {
@@ -843,7 +847,7 @@ static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
v9fs_string_init(&newpath);
v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
retval = v9fs_request(ctx->private, T_LINK, NULL, oldpath, &newpath);
retval = v9fs_request(ctx->private, T_LINK, NULL, "ss", oldpath, &newpath);
v9fs_string_free(&newpath);
if (retval < 0) {
errno = -retval;
@@ -856,7 +860,7 @@ static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
{
int retval;
retval = v9fs_request(ctx->private, T_TRUNCATE, NULL, fs_path, size);
retval = v9fs_request(ctx->private, T_TRUNCATE, NULL, "sq", fs_path, size);
if (retval < 0) {
errno = -retval;
return -1;
@@ -875,7 +879,8 @@ static int proxy_rename(FsContext *ctx, const char *oldpath,
v9fs_string_sprintf(&oldname, "%s", oldpath);
v9fs_string_sprintf(&newname, "%s", newpath);
retval = v9fs_request(ctx->private, T_RENAME, NULL, &oldname, &newname);
retval = v9fs_request(ctx->private, T_RENAME, NULL, "ss",
&oldname, &newname);
v9fs_string_free(&oldname);
v9fs_string_free(&newname);
if (retval < 0) {
@@ -887,8 +892,8 @@ static int proxy_rename(FsContext *ctx, const char *oldpath,
static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
int retval;
retval = v9fs_request(fs_ctx->private, T_CHOWN, NULL, fs_path,
credp->fc_uid, credp->fc_gid);
retval = v9fs_request(fs_ctx->private, T_CHOWN, NULL, "sdd",
fs_path, credp->fc_uid, credp->fc_gid);
if (retval < 0) {
errno = -retval;
}
@@ -899,7 +904,8 @@ static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
const struct timespec *buf)
{
int retval;
retval = v9fs_request(s->private, T_UTIME, NULL, fs_path,
retval = v9fs_request(s->private, T_UTIME, NULL, "sqqqq",
fs_path,
buf[0].tv_sec, buf[0].tv_nsec,
buf[1].tv_sec, buf[1].tv_nsec);
if (retval < 0) {
@@ -914,7 +920,7 @@ static int proxy_remove(FsContext *ctx, const char *path)
V9fsString name;
v9fs_string_init(&name);
v9fs_string_sprintf(&name, "%s", path);
retval = v9fs_request(ctx->private, T_REMOVE, NULL, &name);
retval = v9fs_request(ctx->private, T_REMOVE, NULL, "s", &name);
v9fs_string_free(&name);
if (retval < 0) {
errno = -retval;
@@ -943,7 +949,7 @@ static int proxy_fsync(FsContext *ctx, int fid_type,
static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
{
int retval;
retval = v9fs_request(s->private, T_STATFS, stbuf, fs_path);
retval = v9fs_request(s->private, T_STATFS, stbuf, "s", fs_path);
if (retval < 0) {
errno = -retval;
return -1;
@@ -959,8 +965,8 @@ static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
v9fs_string_init(&xname);
v9fs_string_sprintf(&xname, "%s", name);
retval = v9fs_request(ctx->private, T_LGETXATTR, value, size, fs_path,
&xname);
retval = v9fs_request(ctx->private, T_LGETXATTR, value, "dss", size,
fs_path, &xname);
v9fs_string_free(&xname);
if (retval < 0) {
errno = -retval;
@@ -972,7 +978,8 @@ static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
void *value, size_t size)
{
int retval;
retval = v9fs_request(ctx->private, T_LLISTXATTR, value, size, fs_path);
retval = v9fs_request(ctx->private, T_LLISTXATTR, value, "ds", size,
fs_path);
if (retval < 0) {
errno = -retval;
}
@@ -993,8 +1000,8 @@ static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
xvalue.data = g_malloc(size);
memcpy(xvalue.data, value, size);
retval = v9fs_request(ctx->private, T_LSETXATTR, value, fs_path, &xname,
&xvalue, size, flags);
retval = v9fs_request(ctx->private, T_LSETXATTR, value, "sssdd",
fs_path, &xname, &xvalue, size, flags);
v9fs_string_free(&xname);
v9fs_string_free(&xvalue);
if (retval < 0) {
@@ -1011,7 +1018,8 @@ static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
v9fs_string_init(&xname);
v9fs_string_sprintf(&xname, "%s", name);
retval = v9fs_request(ctx->private, T_LREMOVEXATTR, NULL, fs_path, &xname);
retval = v9fs_request(ctx->private, T_LREMOVEXATTR, NULL, "ss",
fs_path, &xname);
v9fs_string_free(&xname);
if (retval < 0) {
errno = -retval;
@@ -1023,10 +1031,13 @@ static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
const char *name, V9fsPath *target)
{
if (dir_path) {
v9fs_path_sprintf(target, "%s/%s", dir_path->data, name);
v9fs_string_sprintf((V9fsString *)target, "%s/%s",
dir_path->data, name);
} else {
v9fs_path_sprintf(target, "%s", name);
v9fs_string_sprintf((V9fsString *)target, "%s", name);
}
/* Bump the size for including terminating NULL */
target->size++;
return 0;
}
@@ -1075,7 +1086,7 @@ static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path,
errno = ENOTTY;
return -1;
}
err = v9fs_request(fs_ctx->private, T_GETVERSION, st_gen, path);
err = v9fs_request(fs_ctx->private, T_GETVERSION, st_gen, "s", path);
if (err < 0) {
errno = -err;
err = -1;

View File

@@ -12,7 +12,6 @@
*/
#include "qemu/osdep.h"
#include <glib/gprintf.h>
#include "hw/virtio/virtio.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
@@ -180,20 +179,6 @@ void v9fs_path_free(V9fsPath *path)
path->size = 0;
}
void GCC_FMT_ATTR(2, 3)
v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...)
{
va_list ap;
v9fs_path_free(path);
va_start(ap, fmt);
/* Bump the size for including terminating NULL */
path->size = g_vasprintf(&path->data, fmt, ap) + 1;
va_end(ap);
}
void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs)
{
v9fs_path_free(lhs);
@@ -825,15 +810,15 @@ static int stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name,
v9stat->mtime = stbuf->st_mtime;
v9stat->length = stbuf->st_size;
v9fs_string_free(&v9stat->uid);
v9fs_string_free(&v9stat->gid);
v9fs_string_free(&v9stat->muid);
v9fs_string_null(&v9stat->uid);
v9fs_string_null(&v9stat->gid);
v9fs_string_null(&v9stat->muid);
v9stat->n_uid = stbuf->st_uid;
v9stat->n_gid = stbuf->st_gid;
v9stat->n_muid = 0;
v9fs_string_free(&v9stat->extension);
v9fs_string_null(&v9stat->extension);
if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
err = v9fs_co_readlink(pdu, name, &v9stat->extension);
@@ -932,8 +917,10 @@ static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, int len)
V9fsPath str;
v9fs_path_init(&str);
v9fs_path_copy(&str, dst);
v9fs_path_sprintf(dst, "%s%s", src->data, str.data + len);
v9fs_string_sprintf((V9fsString *)dst, "%s%s", src->data, str.data+len);
v9fs_path_free(&str);
/* +1 to include terminating NULL */
dst->size++;
}
static inline bool is_ro_export(FsContext *ctx)

View File

@@ -327,7 +327,6 @@ static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu)
extern void v9fs_reclaim_fd(V9fsPDU *pdu);
extern void v9fs_path_init(V9fsPath *path);
extern void v9fs_path_free(V9fsPath *path);
extern void v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...);
extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs);
extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
const char *name, V9fsPath *path);

View File

@@ -226,7 +226,7 @@ static void build_extop_package(GArray *package, uint8_t op)
build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
}
void build_append_int_noprefix(GArray *table, uint64_t value, int size)
static void build_append_int_noprefix(GArray *table, uint64_t value, int size)
{
int i;

View File

@@ -99,6 +99,7 @@ void build_acpi_ipmi_devices(Aml *scope, BusState *bus)
ii = IPMI_INTERFACE(obj);
iic = IPMI_INTERFACE_GET_CLASS(obj);
memset(&info, 0, sizeof(info));
iic->get_fwinfo(ii, &info);
aml_append(scope, aml_ipmi_device(&info));
}

View File

@@ -17,4 +17,4 @@ obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o

View File

@@ -1,197 +0,0 @@
/*
* OpenPOWER Palmetto BMC
*
* Andrew Jeffery <andrew@aj.id.au>
*
* Copyright 2016 IBM Corp.
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/arm/arm.h"
#include "hw/arm/aspeed_soc.h"
#include "hw/boards.h"
#include "qemu/log.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
static struct arm_boot_info aspeed_board_binfo = {
.board_id = -1, /* device-tree-only board */
.nb_cpus = 1,
};
typedef struct AspeedBoardState {
AspeedSoCState soc;
MemoryRegion ram;
} AspeedBoardState;
typedef struct AspeedBoardConfig {
const char *soc_name;
uint32_t hw_strap1;
} AspeedBoardConfig;
enum {
PALMETTO_BMC,
AST2500_EVB,
};
#define PALMETTO_BMC_HW_STRAP1 ( \
SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) | \
SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
SCU_AST2400_HW_STRAP_ACPI_DIS | \
SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(AST2400_CLK_48M_IN) | \
SCU_HW_STRAP_VGA_CLASS_CODE | \
SCU_HW_STRAP_LPC_RESET_PIN | \
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN) | \
SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(AST2400_CPU_AHB_RATIO_2_1) | \
SCU_HW_STRAP_SPI_WIDTH | \
SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
#define AST2500_EVB_HW_STRAP1 (( \
AST2500_HW_STRAP1_DEFAULTS | \
SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \
SCU_AST2500_HW_STRAP_UART_DEBUG | \
SCU_AST2500_HW_STRAP_DDR4_ENABLE | \
SCU_HW_STRAP_MAC1_RGMII | \
SCU_HW_STRAP_MAC0_RGMII) & \
~SCU_HW_STRAP_2ND_BOOT_WDT)
static const AspeedBoardConfig aspeed_boards[] = {
[PALMETTO_BMC] = { "ast2400-a0", PALMETTO_BMC_HW_STRAP1 },
[AST2500_EVB] = { "ast2500-a1", AST2500_EVB_HW_STRAP1 },
};
static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
Error **errp)
{
int i ;
for (i = 0; i < s->num_cs; ++i) {
AspeedSMCFlash *fl = &s->flashes[i];
DriveInfo *dinfo = drive_get_next(IF_MTD);
qemu_irq cs_line;
/*
* FIXME: check that we are not using a flash module exceeding
* the controller segment size
*/
fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
if (dinfo) {
qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
errp);
}
qdev_init_nofail(fl->flash);
cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
}
}
static void aspeed_board_init(MachineState *machine,
const AspeedBoardConfig *cfg)
{
AspeedBoardState *bmc;
AspeedSoCClass *sc;
bmc = g_new0(AspeedBoardState, 1);
object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc),
&error_abort);
sc = ASPEED_SOC_GET_CLASS(&bmc->soc);
object_property_set_int(OBJECT(&bmc->soc), ram_size, "ram-size",
&error_abort);
object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
&error_abort);
object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
&error_abort);
/*
* Allocate RAM after the memory controller has checked the size
* was valid. If not, a default value is used.
*/
ram_size = object_property_get_int(OBJECT(&bmc->soc), "ram-size",
&error_abort);
memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
memory_region_add_subregion(get_system_memory(), sc->info->sdram_base,
&bmc->ram);
object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
&error_abort);
aspeed_board_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
aspeed_board_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
aspeed_board_binfo.kernel_filename = machine->kernel_filename;
aspeed_board_binfo.initrd_filename = machine->initrd_filename;
aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
aspeed_board_binfo.ram_size = ram_size;
aspeed_board_binfo.loader_start = sc->info->sdram_base;
arm_load_kernel(ARM_CPU(first_cpu), &aspeed_board_binfo);
}
static void palmetto_bmc_init(MachineState *machine)
{
aspeed_board_init(machine, &aspeed_boards[PALMETTO_BMC]);
}
static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "OpenPOWER Palmetto BMC (ARM926EJ-S)";
mc->init = palmetto_bmc_init;
mc->max_cpus = 1;
mc->no_sdcard = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_parallel = 1;
}
static const TypeInfo palmetto_bmc_type = {
.name = MACHINE_TYPE_NAME("palmetto-bmc"),
.parent = TYPE_MACHINE,
.class_init = palmetto_bmc_class_init,
};
static void ast2500_evb_init(MachineState *machine)
{
aspeed_board_init(machine, &aspeed_boards[AST2500_EVB]);
}
static void ast2500_evb_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "Aspeed AST2500 EVB (ARM1176)";
mc->init = ast2500_evb_init;
mc->max_cpus = 1;
mc->no_sdcard = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_parallel = 1;
}
static const TypeInfo ast2500_evb_type = {
.name = MACHINE_TYPE_NAME("ast2500-evb"),
.parent = TYPE_MACHINE,
.class_init = ast2500_evb_class_init,
};
static void aspeed_machine_init(void)
{
type_register_static(&palmetto_bmc_type);
type_register_static(&ast2500_evb_type);
}
type_init(aspeed_machine_init)

View File

@@ -1,5 +1,5 @@
/*
* ASPEED SoC family
* AST2400 SoC
*
* Andrew Jeffery <andrew@aj.id.au>
* Jeremy Kerr <jk@ozlabs.org>
@@ -15,68 +15,58 @@
#include "qemu-common.h"
#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/arm/aspeed_soc.h"
#include "hw/arm/ast2400.h"
#include "hw/char/serial.h"
#include "qemu/log.h"
#include "hw/i2c/aspeed_i2c.h"
#define ASPEED_SOC_UART_5_BASE 0x00184000
#define ASPEED_SOC_IOMEM_SIZE 0x00200000
#define ASPEED_SOC_IOMEM_BASE 0x1E600000
#define ASPEED_SOC_FMC_BASE 0x1E620000
#define ASPEED_SOC_SPI_BASE 0x1E630000
#define ASPEED_SOC_VIC_BASE 0x1E6C0000
#define ASPEED_SOC_SDMC_BASE 0x1E6E0000
#define ASPEED_SOC_SCU_BASE 0x1E6E2000
#define ASPEED_SOC_TIMER_BASE 0x1E782000
#define ASPEED_SOC_I2C_BASE 0x1E78A000
#define AST2400_UART_5_BASE 0x00184000
#define AST2400_IOMEM_SIZE 0x00200000
#define AST2400_IOMEM_BASE 0x1E600000
#define AST2400_SMC_BASE AST2400_IOMEM_BASE /* Legacy SMC */
#define AST2400_FMC_BASE 0X1E620000
#define AST2400_SPI_BASE 0X1E630000
#define AST2400_VIC_BASE 0x1E6C0000
#define AST2400_SCU_BASE 0x1E6E2000
#define AST2400_TIMER_BASE 0x1E782000
#define AST2400_I2C_BASE 0x1E78A000
#define ASPEED_SOC_FMC_FLASH_BASE 0x20000000
#define ASPEED_SOC_SPI_FLASH_BASE 0x30000000
#define AST2400_FMC_FLASH_BASE 0x20000000
#define AST2400_SPI_FLASH_BASE 0x30000000
static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
#define AST2400_SDRAM_BASE 0x40000000
#define AST2500_SDRAM_BASE 0x80000000
static const AspeedSoCInfo aspeed_socs[] = {
{ "ast2400-a0", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
{ "ast2400", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
{ "ast2500-a1", "arm1176", AST2500_A1_SILICON_REV, AST2500_SDRAM_BASE },
};
/*
* IO handlers: simply catch any reads/writes to IO addresses that aren't
* handled by a device mapping.
*/
static uint64_t aspeed_soc_io_read(void *p, hwaddr offset, unsigned size)
static uint64_t ast2400_io_read(void *p, hwaddr offset, unsigned size)
{
qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
__func__, offset, size);
return 0;
}
static void aspeed_soc_io_write(void *opaque, hwaddr offset, uint64_t value,
static void ast2400_io_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
__func__, offset, value, size);
}
static const MemoryRegionOps aspeed_soc_io_ops = {
.read = aspeed_soc_io_read,
.write = aspeed_soc_io_write,
static const MemoryRegionOps ast2400_io_ops = {
.read = ast2400_io_read,
.write = ast2400_io_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void aspeed_soc_init(Object *obj)
static void ast2400_init(Object *obj)
{
AspeedSoCState *s = ASPEED_SOC(obj);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
AST2400State *s = AST2400(obj);
s->cpu = cpu_arm_init(sc->info->cpu_model);
s->cpu = cpu_arm_init("arm926");
object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
@@ -94,7 +84,7 @@ static void aspeed_soc_init(Object *obj)
object_property_add_child(obj, "scu", OBJECT(&s->scu), NULL);
qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
sc->info->silicon_rev);
AST2400_A0_SILICON_REV);
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
"hw-strap1", &error_abort);
object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
@@ -107,27 +97,19 @@ static void aspeed_soc_init(Object *obj)
object_initialize(&s->spi, sizeof(s->spi), "aspeed.smc.spi");
object_property_add_child(obj, "spi", OBJECT(&s->spi), NULL);
qdev_set_parent_bus(DEVICE(&s->spi), sysbus_get_default());
object_initialize(&s->sdmc, sizeof(s->sdmc), TYPE_ASPEED_SDMC);
object_property_add_child(obj, "sdmc", OBJECT(&s->sdmc), NULL);
qdev_set_parent_bus(DEVICE(&s->sdmc), sysbus_get_default());
qdev_prop_set_uint32(DEVICE(&s->sdmc), "silicon-rev",
sc->info->silicon_rev);
object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
"ram-size", &error_abort);
}
static void aspeed_soc_realize(DeviceState *dev, Error **errp)
static void ast2400_realize(DeviceState *dev, Error **errp)
{
int i;
AspeedSoCState *s = ASPEED_SOC(dev);
AST2400State *s = AST2400(dev);
Error *err = NULL, *local_err = NULL;
/* IO space */
memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
"aspeed_soc.io", ASPEED_SOC_IOMEM_SIZE);
memory_region_add_subregion_overlap(get_system_memory(),
ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
memory_region_init_io(&s->iomem, NULL, &ast2400_io_ops, NULL,
"ast2400.io", AST2400_IOMEM_SIZE);
memory_region_add_subregion_overlap(get_system_memory(), AST2400_IOMEM_BASE,
&s->iomem, -1);
/* VIC */
object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
@@ -135,7 +117,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, AST2400_VIC_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
@@ -147,7 +129,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, ASPEED_SOC_TIMER_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, AST2400_TIMER_BASE);
for (i = 0; i < ARRAY_SIZE(timer_irqs); i++) {
qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->vic), timer_irqs[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
@@ -159,12 +141,12 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, ASPEED_SOC_SCU_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, AST2400_SCU_BASE);
/* UART - attach an 8250 to the IO space as our UART5 */
if (serial_hds[0]) {
qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]);
serial_mm_init(&s->iomem, ASPEED_SOC_UART_5_BASE, 2,
serial_mm_init(&s->iomem, AST2400_UART_5_BASE, 2,
uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
}
@@ -174,7 +156,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, ASPEED_SOC_I2C_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, AST2400_I2C_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
qdev_get_gpio_in(DEVICE(&s->vic), 12));
@@ -186,8 +168,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, ASPEED_SOC_FMC_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, ASPEED_SOC_FMC_FLASH_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, AST2400_FMC_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, AST2400_FMC_FLASH_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->smc), 0,
qdev_get_gpio_in(DEVICE(&s->vic), 19));
@@ -199,25 +181,15 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, ASPEED_SOC_SPI_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, ASPEED_SOC_SPI_FLASH_BASE);
/* SDMC - SDRAM Memory Controller */
object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, AST2400_SPI_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, AST2400_SPI_FLASH_BASE);
}
static void aspeed_soc_class_init(ObjectClass *oc, void *data)
static void ast2400_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
sc->info = (AspeedSoCInfo *) data;
dc->realize = aspeed_soc_realize;
dc->realize = ast2400_realize;
/*
* Reason: creates an ARM CPU, thus use after free(), see
@@ -226,29 +198,17 @@ static void aspeed_soc_class_init(ObjectClass *oc, void *data)
dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo aspeed_soc_type_info = {
.name = TYPE_ASPEED_SOC,
.parent = TYPE_DEVICE,
.instance_init = aspeed_soc_init,
.instance_size = sizeof(AspeedSoCState),
.class_size = sizeof(AspeedSoCClass),
.abstract = true,
static const TypeInfo ast2400_type_info = {
.name = TYPE_AST2400,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(AST2400State),
.instance_init = ast2400_init,
.class_init = ast2400_class_init,
};
static void aspeed_soc_register_types(void)
static void ast2400_register_types(void)
{
int i;
type_register_static(&aspeed_soc_type_info);
for (i = 0; i < ARRAY_SIZE(aspeed_socs); ++i) {
TypeInfo ti = {
.name = aspeed_socs[i].name,
.parent = TYPE_ASPEED_SOC,
.class_init = aspeed_soc_class_init,
.class_data = (void *) &aspeed_socs[i],
};
type_register(&ti);
}
type_register_static(&ast2400_type_info);
}
type_init(aspeed_soc_register_types)
type_init(ast2400_register_types)

View File

@@ -837,7 +837,7 @@ static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
s->freq = freq;
bh = qemu_bh_new(mv88w8618_timer_tick, s);
s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
s->ptimer = ptimer_init(bh);
}
static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,

View File

@@ -769,16 +769,14 @@ static void omap_sti_fifo_write(void *opaque, hwaddr addr,
if (ch == STI_TRACE_CONTROL_CHANNEL) {
/* Flush channel <i>value</i>. */
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, (const uint8_t *) "\r", 1);
qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
} else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
if (value == 0xc0 || value == 0xc3) {
/* Open channel <i>ch</i>. */
} else if (value == 0x00)
qemu_chr_fe_write_all(s->chr, (const uint8_t *) "\n", 1);
qemu_chr_fe_write(s->chr, (const uint8_t *) "\n", 1);
else
qemu_chr_fe_write_all(s->chr, &byte, 1);
qemu_chr_fe_write(s->chr, &byte, 1);
}
}

102
hw/arm/palmetto-bmc.c Normal file
View File

@@ -0,0 +1,102 @@
/*
* OpenPOWER Palmetto BMC
*
* Andrew Jeffery <andrew@aj.id.au>
*
* Copyright 2016 IBM Corp.
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/arm/arm.h"
#include "hw/arm/ast2400.h"
#include "hw/boards.h"
#include "qemu/log.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
static struct arm_boot_info palmetto_bmc_binfo = {
.loader_start = AST2400_SDRAM_BASE,
.board_id = 0,
.nb_cpus = 1,
};
typedef struct PalmettoBMCState {
AST2400State soc;
MemoryRegion ram;
} PalmettoBMCState;
static void palmetto_bmc_init_flashes(AspeedSMCState *s, const char *flashtype,
Error **errp)
{
int i ;
for (i = 0; i < s->num_cs; ++i) {
AspeedSMCFlash *fl = &s->flashes[i];
DriveInfo *dinfo = drive_get_next(IF_MTD);
qemu_irq cs_line;
/*
* FIXME: check that we are not using a flash module exceeding
* the controller segment size
*/
fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
if (dinfo) {
qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
errp);
}
qdev_init_nofail(fl->flash);
cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
}
}
static void palmetto_bmc_init(MachineState *machine)
{
PalmettoBMCState *bmc;
bmc = g_new0(PalmettoBMCState, 1);
object_initialize(&bmc->soc, (sizeof(bmc->soc)), TYPE_AST2400);
object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc),
&error_abort);
memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
memory_region_add_subregion(get_system_memory(), AST2400_SDRAM_BASE,
&bmc->ram);
object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
&error_abort);
object_property_set_int(OBJECT(&bmc->soc), 0x120CE416, "hw-strap1",
&error_abort);
object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
&error_abort);
palmetto_bmc_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
palmetto_bmc_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
palmetto_bmc_binfo.kernel_filename = machine->kernel_filename;
palmetto_bmc_binfo.initrd_filename = machine->initrd_filename;
palmetto_bmc_binfo.kernel_cmdline = machine->kernel_cmdline;
palmetto_bmc_binfo.ram_size = ram_size;
arm_load_kernel(ARM_CPU(first_cpu), &palmetto_bmc_binfo);
}
static void palmetto_bmc_machine_init(MachineClass *mc)
{
mc->desc = "OpenPOWER Palmetto BMC";
mc->init = palmetto_bmc_init;
mc->max_cpus = 1;
mc->no_sdcard = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_sdcard = 1;
mc->no_parallel = 1;
}
DEFINE_MACHINE("palmetto-bmc", palmetto_bmc_machine_init);

View File

@@ -1903,9 +1903,7 @@ static void pxa2xx_fir_write(void *opaque, hwaddr addr,
else
ch = ~value;
if (s->chr && s->enable && (s->control[0] & (1 << 3))) /* TXE */
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
qemu_chr_fe_write(s->chr, &ch, 1);
break;
case ICSR0:
s->status[0] &= ~(value & 0x66);

View File

@@ -1108,9 +1108,7 @@ static void strongarm_uart_tx(void *opaque)
if (s->utcr3 & UTCR3_LBM) /* loopback */ {
strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
} else if (s->chr) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &s->tx_fifo[s->tx_start], 1);
qemu_chr_fe_write(s->chr, &s->tx_fifo[s->tx_start], 1);
}
s->tx_start = (s->tx_start + 1) % 8;

View File

@@ -53,7 +53,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
uint16_t i;
for (i = 0; i < smp_cpus; i++) {
Aml *dev = aml_device("C%.03X", i);
Aml *dev = aml_device("C%03x", i);
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
aml_append(scope, dev);

View File

@@ -332,8 +332,6 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
qdev_set_nic_properties(DEVICE(&s->gem[i]), nd);
}
object_property_set_int(OBJECT(&s->gem[i]), 2, "num-priority-queues",
&error_abort);
object_property_set_bool(OBJECT(&s->gem[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);

View File

@@ -52,8 +52,8 @@ typedef struct {
unsigned int pit_count;
unsigned int samples;
unsigned int play_pos;
uint8_t data_on;
uint8_t dummy_refresh_clock;
int data_on;
int dummy_refresh_clock;
} PCSpkState;
static const char *s_spk = "pcspk";
@@ -187,18 +187,6 @@ static void pcspk_realizefn(DeviceState *dev, Error **errp)
pcspk_state = s;
}
static const VMStateDescription vmstate_spk = {
.name = "pcspk",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT8(data_on, PCSpkState),
VMSTATE_UINT8(dummy_refresh_clock, PCSpkState),
VMSTATE_END_OF_LIST()
}
};
static Property pcspk_properties[] = {
DEFINE_PROP_UINT32("iobase", PCSpkState, iobase, -1),
DEFINE_PROP_END_OF_LIST(),
@@ -210,7 +198,6 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data)
dc->realize = pcspk_realizefn;
set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->vmsd = &vmstate_spk;
dc->props = pcspk_properties;
/* Reason: realize sets global pcspk_state */
dc->cannot_instantiate_with_device_add_yet = true;

View File

@@ -1189,9 +1189,9 @@ static Property m25p80_properties[] = {
};
static const VMStateDescription vmstate_m25p80 = {
.name = "m25p80",
.version_id = 0,
.minimum_version_id = 0,
.name = "xilinx_spi",
.version_id = 3,
.minimum_version_id = 1,
.pre_save = m25p80_pre_save,
.fields = (VMStateField[]) {
VMSTATE_UINT8(state, Flash),
@@ -1200,19 +1200,20 @@ static const VMStateDescription vmstate_m25p80 = {
VMSTATE_UINT32(pos, Flash),
VMSTATE_UINT8(needed_bytes, Flash),
VMSTATE_UINT8(cmd_in_progress, Flash),
VMSTATE_UNUSED(4),
VMSTATE_UINT32(cur_addr, Flash),
VMSTATE_BOOL(write_enable, Flash),
VMSTATE_BOOL(reset_enable, Flash),
VMSTATE_UINT8(ear, Flash),
VMSTATE_BOOL(four_bytes_address_mode, Flash),
VMSTATE_UINT32(nonvolatile_cfg, Flash),
VMSTATE_UINT32(volatile_cfg, Flash),
VMSTATE_UINT32(enh_volatile_cfg, Flash),
VMSTATE_BOOL(quad_enable, Flash),
VMSTATE_UINT8(spansion_cr1nv, Flash),
VMSTATE_UINT8(spansion_cr2nv, Flash),
VMSTATE_UINT8(spansion_cr3nv, Flash),
VMSTATE_UINT8(spansion_cr4nv, Flash),
VMSTATE_BOOL_V(reset_enable, Flash, 2),
VMSTATE_UINT8_V(ear, Flash, 2),
VMSTATE_BOOL_V(four_bytes_address_mode, Flash, 2),
VMSTATE_UINT32_V(nonvolatile_cfg, Flash, 2),
VMSTATE_UINT32_V(volatile_cfg, Flash, 2),
VMSTATE_UINT32_V(enh_volatile_cfg, Flash, 2),
VMSTATE_BOOL_V(quad_enable, Flash, 3),
VMSTATE_UINT8_V(spansion_cr1nv, Flash, 3),
VMSTATE_UINT8_V(spansion_cr2nv, Flash, 3),
VMSTATE_UINT8_V(spansion_cr3nv, Flash, 3),
VMSTATE_UINT8_V(spansion_cr4nv, Flash, 3),
VMSTATE_END_OF_LIST()
}
};

View File

@@ -258,8 +258,10 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
req->has_sg = true;
dma_acct_start(n->conf.blk, &req->acct, &req->qsg, acct);
req->aiocb = is_write ?
dma_blk_write(n->conf.blk, &req->qsg, data_offset, nvme_rw_cb, req) :
dma_blk_read(n->conf.blk, &req->qsg, data_offset, nvme_rw_cb, req);
dma_blk_write(n->conf.blk, &req->qsg, data_offset, BDRV_SECTOR_SIZE,
nvme_rw_cb, req) :
dma_blk_read(n->conf.blk, &req->qsg, data_offset, BDRV_SECTOR_SIZE,
nvme_rw_cb, req);
return NVME_NO_COMPLETE;
}

View File

@@ -992,7 +992,7 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
vdc->load = virtio_blk_load_device;
}
static const TypeInfo virtio_blk_info = {
static const TypeInfo virtio_device_info = {
.name = TYPE_VIRTIO_BLK,
.parent = TYPE_VIRTIO_DEVICE,
.instance_size = sizeof(VirtIOBlock),
@@ -1002,7 +1002,7 @@ static const TypeInfo virtio_blk_info = {
static void virtio_register_types(void)
{
type_register_static(&virtio_blk_info);
type_register_static(&virtio_device_info);
}
type_init(virtio_register_types)

Some files were not shown because too many files have changed in this diff Show More