Compare commits
50 Commits
pull-ui-20
...
v2.5.1
Author | SHA1 | Date | |
---|---|---|---|
|
a58047f7fb | ||
|
5f409b108f | ||
|
078de11898 | ||
|
acea76c162 | ||
|
80b6e5723f | ||
|
9bddb45dbc | ||
|
e3a2cdfcb5 | ||
|
4dcd2f13b1 | ||
|
38e09211b6 | ||
|
d0ee85b4e4 | ||
|
4f046a6ba1 | ||
|
b47809c6b3 | ||
|
24fe899c3c | ||
|
aaf4fb6afb | ||
|
a2ae168821 | ||
|
bad094d524 | ||
|
4b0b1ec8e0 | ||
|
cab1cc7245 | ||
|
9ae02175b4 | ||
|
30929793b0 | ||
|
c5c9841ce8 | ||
|
6b62303eb8 | ||
|
c06f342009 | ||
|
cb873eaa6d | ||
|
4853a5a80f | ||
|
a375e0b03e | ||
|
a38a283fc7 | ||
|
225d50fbb1 | ||
|
020282d3e6 | ||
|
091af18104 | ||
|
d98392379a | ||
|
643c8d8ec1 | ||
|
3ede27db32 | ||
|
9849b1912f | ||
|
fe90bdc25b | ||
|
aaa5271327 | ||
|
abda95cb01 | ||
|
6a49a71cc6 | ||
|
e1a8a09124 | ||
|
7a2c1c8e66 | ||
|
702a8d165c | ||
|
3e96d5dcf2 | ||
|
16a2875735 | ||
|
4588b0d856 | ||
|
ff083d3c3b | ||
|
4d59e78dfe | ||
|
52a7b27947 | ||
|
d4aed70099 | ||
|
42ae4a3c61 | ||
|
0d335804e3 |
37
MAINTAINERS
37
MAINTAINERS
@@ -273,12 +273,9 @@ F: */xen*
|
||||
F: hw/char/xen_console.c
|
||||
F: hw/display/xenfb.c
|
||||
F: hw/net/xen_nic.c
|
||||
F: hw/block/xen_*
|
||||
F: hw/xen/
|
||||
F: hw/xenpv/
|
||||
F: hw/i386/xen/
|
||||
F: include/hw/xen/
|
||||
F: include/sysemu/xen-mapcache.h
|
||||
|
||||
Hosts:
|
||||
------
|
||||
@@ -590,7 +587,7 @@ F: hw/ppc/prep.c
|
||||
F: hw/pci-host/prep.[hc]
|
||||
F: hw/isa/pc87312.[hc]
|
||||
|
||||
sPAPR
|
||||
sPAPR (pseries)
|
||||
M: David Gibson <david@gibson.dropbear.id.au>
|
||||
M: Alexander Graf <agraf@suse.de>
|
||||
L: qemu-ppc@nongnu.org
|
||||
@@ -944,13 +941,6 @@ M: Jiri Pirko <jiri@resnulli.us>
|
||||
S: Maintained
|
||||
F: hw/net/rocker/
|
||||
|
||||
NVDIMM
|
||||
M: Xiao Guangrong <guangrong.xiao@linux.intel.com>
|
||||
S: Maintained
|
||||
F: hw/acpi/nvdimm.c
|
||||
F: hw/mem/nvdimm.c
|
||||
F: include/hw/mem/nvdimm.h
|
||||
|
||||
Subsystems
|
||||
----------
|
||||
Audio
|
||||
@@ -1039,8 +1029,7 @@ Device Tree
|
||||
M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
|
||||
M: Alexander Graf <agraf@suse.de>
|
||||
S: Maintained
|
||||
F: device_tree.c
|
||||
F: include/sysemu/device_tree.h
|
||||
F: device_tree.[ch]
|
||||
|
||||
Error reporting
|
||||
M: Markus Armbruster <armbru@redhat.com>
|
||||
@@ -1119,9 +1108,8 @@ F: net/netmap.c
|
||||
Network Block Device (NBD)
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Odd Fixes
|
||||
F: block/nbd*
|
||||
F: nbd/
|
||||
F: include/block/nbd*
|
||||
F: block/nbd.c
|
||||
F: nbd.*
|
||||
F: qemu-nbd.c
|
||||
T: git git://github.com/bonzini/qemu.git nbd-next
|
||||
|
||||
@@ -1204,7 +1192,6 @@ SLIRP
|
||||
M: Jan Kiszka <jan.kiszka@siemens.com>
|
||||
S: Maintained
|
||||
F: slirp/
|
||||
F: net/slirp.c
|
||||
T: git git://git.kiszka.org/qemu.git queues/slirp
|
||||
|
||||
Tracing
|
||||
@@ -1256,21 +1243,6 @@ S: Odd fixes
|
||||
F: util/buffer.c
|
||||
F: include/qemu/buffer.h
|
||||
|
||||
I/O Channels
|
||||
M: Daniel P. Berrange <berrange@redhat.com>
|
||||
S: Maintained
|
||||
F: io/
|
||||
F: include/io/
|
||||
F: tests/test-io-*
|
||||
|
||||
Sockets
|
||||
M: Daniel P. Berrange <berrange@redhat.com>
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Maintained
|
||||
F: include/qemu/sockets.h
|
||||
F: util/qemu-sockets.c
|
||||
|
||||
Usermode Emulation
|
||||
------------------
|
||||
Overall
|
||||
@@ -1511,7 +1483,6 @@ M: Denis V. Lunev <den@openvz.org>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: block/parallels.c
|
||||
F: docs/specs/parallels.txt
|
||||
|
||||
qed
|
||||
M: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
|
7
Makefile
7
Makefile
@@ -159,7 +159,6 @@ dummy := $(call unnest-vars,, \
|
||||
crypto-obj-y \
|
||||
crypto-aes-obj-y \
|
||||
qom-obj-y \
|
||||
io-obj-y \
|
||||
common-obj-y \
|
||||
common-obj-m)
|
||||
|
||||
@@ -179,7 +178,6 @@ SOFTMMU_SUBDIR_RULES=$(filter %-softmmu,$(SUBDIR_RULES))
|
||||
|
||||
$(SOFTMMU_SUBDIR_RULES): $(block-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): $(crypto-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): $(io-obj-y)
|
||||
$(SOFTMMU_SUBDIR_RULES): config-all-devices.mak
|
||||
|
||||
subdir-%:
|
||||
@@ -240,7 +238,7 @@ qemu-io$(EXESUF): qemu-io.o $(block-obj-y) $(crypto-obj-y) $(qom-obj-y) libqemuu
|
||||
|
||||
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
|
||||
|
||||
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/9p-marshal.o fsdev/9p-iov-marshal.o libqemuutil.a libqemustub.a
|
||||
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o libqemuutil.a libqemustub.a
|
||||
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
|
||||
|
||||
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
|
||||
@@ -271,8 +269,7 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
|
||||
|
||||
qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
|
||||
$(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
|
||||
$(SRC_PATH)/qapi/event.json $(SRC_PATH)/qapi/introspect.json \
|
||||
$(SRC_PATH)/qapi/crypto.json
|
||||
$(SRC_PATH)/qapi/event.json $(SRC_PATH)/qapi/introspect.json
|
||||
|
||||
qapi-types.c qapi-types.h :\
|
||||
$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
|
||||
|
@@ -8,8 +8,7 @@ util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
|
||||
# block-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
block-obj-y = async.o thread-pool.o
|
||||
block-obj-y += nbd/
|
||||
block-obj-y += block.o blockjob.o
|
||||
block-obj-y += nbd.o block.o blockjob.o
|
||||
block-obj-y += main-loop.o iohandler.o qemu-timer.o
|
||||
block-obj-$(CONFIG_POSIX) += aio-posix.o
|
||||
block-obj-$(CONFIG_WIN32) += aio-win32.o
|
||||
@@ -29,11 +28,6 @@ crypto-aes-obj-y = crypto/
|
||||
|
||||
qom-obj-y = qom/
|
||||
|
||||
#######################################################################
|
||||
# io-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
io-obj-y = io/
|
||||
|
||||
######################################################################
|
||||
# Target independent part of system emulation. The long term path is to
|
||||
# suppress *all* target specific code in case of system emulation, i.e. a
|
||||
|
@@ -176,7 +176,6 @@ dummy := $(call unnest-vars,.., \
|
||||
crypto-obj-y \
|
||||
crypto-aes-obj-y \
|
||||
qom-obj-y \
|
||||
io-obj-y \
|
||||
common-obj-y \
|
||||
common-obj-m)
|
||||
target-obj-y := $(target-obj-y-save)
|
||||
@@ -186,7 +185,6 @@ all-obj-y += $(qom-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
|
||||
all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
|
||||
|
||||
$(QEMU_PROG_BUILD): config-devices.mak
|
||||
|
||||
|
@@ -258,7 +258,9 @@ void do_acpitable_option(const QemuOpts *opts)
|
||||
|
||||
acpi_table_add(opts, &err);
|
||||
if (err) {
|
||||
error_reportf_err(err, "Wrong acpi table provided: ");
|
||||
error_report("Wrong acpi table provided: %s",
|
||||
error_get_pretty(err));
|
||||
error_free(err);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
@@ -1806,6 +1806,9 @@ static void audio_init (void)
|
||||
atexit (audio_atexit);
|
||||
|
||||
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
|
||||
if (!s->ts) {
|
||||
hw_error("Could not create audio timer\n");
|
||||
}
|
||||
|
||||
audio_process_options ("AUDIO", audio_options);
|
||||
|
||||
@@ -1856,8 +1859,12 @@ static void audio_init (void)
|
||||
|
||||
if (!done) {
|
||||
done = !audio_driver_init (s, &no_audio_driver);
|
||||
assert(done);
|
||||
dolog("warning: Using timer based audio emulation\n");
|
||||
if (!done) {
|
||||
hw_error("Could not initialize audio subsystem\n");
|
||||
}
|
||||
else {
|
||||
dolog ("warning: Using timer based audio emulation\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (conf.period.hertz <= 0) {
|
||||
|
@@ -32,10 +32,6 @@
|
||||
#define AUDIO_CAP "coreaudio"
|
||||
#include "audio_int.h"
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
#define MAC_OS_X_VERSION_10_6 1060
|
||||
#endif
|
||||
|
||||
static int isAtexit;
|
||||
|
||||
typedef struct {
|
||||
@@ -49,233 +45,11 @@ typedef struct coreaudioVoiceOut {
|
||||
AudioDeviceID outputDeviceID;
|
||||
UInt32 audioDevicePropertyBufferFrameSize;
|
||||
AudioStreamBasicDescription outputStreamBasicDescription;
|
||||
AudioDeviceIOProcID ioprocid;
|
||||
int live;
|
||||
int decr;
|
||||
int rpos;
|
||||
} coreaudioVoiceOut;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
/* The APIs used here only become available from 10.6 */
|
||||
|
||||
static OSStatus coreaudio_get_voice(AudioDeviceID *id)
|
||||
{
|
||||
UInt32 size = sizeof(*id);
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioHardwarePropertyDefaultOutputDevice,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
return AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||
&addr,
|
||||
0,
|
||||
NULL,
|
||||
&size,
|
||||
id);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
|
||||
AudioValueRange *framerange)
|
||||
{
|
||||
UInt32 size = sizeof(*framerange);
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyBufferFrameSizeRange,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
return AudioObjectGetPropertyData(id,
|
||||
&addr,
|
||||
0,
|
||||
NULL,
|
||||
&size,
|
||||
framerange);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
|
||||
{
|
||||
UInt32 size = sizeof(*framesize);
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyBufferFrameSize,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
return AudioObjectGetPropertyData(id,
|
||||
&addr,
|
||||
0,
|
||||
NULL,
|
||||
&size,
|
||||
framesize);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
|
||||
{
|
||||
UInt32 size = sizeof(*framesize);
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyBufferFrameSize,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
return AudioObjectSetPropertyData(id,
|
||||
&addr,
|
||||
0,
|
||||
NULL,
|
||||
size,
|
||||
framesize);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
|
||||
AudioStreamBasicDescription *d)
|
||||
{
|
||||
UInt32 size = sizeof(*d);
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyStreamFormat,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
return AudioObjectGetPropertyData(id,
|
||||
&addr,
|
||||
0,
|
||||
NULL,
|
||||
&size,
|
||||
d);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
|
||||
AudioStreamBasicDescription *d)
|
||||
{
|
||||
UInt32 size = sizeof(*d);
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyStreamFormat,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
return AudioObjectSetPropertyData(id,
|
||||
&addr,
|
||||
0,
|
||||
NULL,
|
||||
size,
|
||||
d);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
|
||||
{
|
||||
UInt32 size = sizeof(*result);
|
||||
AudioObjectPropertyAddress addr = {
|
||||
kAudioDevicePropertyDeviceIsRunning,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
return AudioObjectGetPropertyData(id,
|
||||
&addr,
|
||||
0,
|
||||
NULL,
|
||||
&size,
|
||||
result);
|
||||
}
|
||||
#else
|
||||
/* Legacy versions of functions using deprecated APIs */
|
||||
|
||||
static OSStatus coreaudio_get_voice(AudioDeviceID *id)
|
||||
{
|
||||
UInt32 size = sizeof(*id);
|
||||
|
||||
return AudioHardwareGetProperty(
|
||||
kAudioHardwarePropertyDefaultOutputDevice,
|
||||
&size,
|
||||
id);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
|
||||
AudioValueRange *framerange)
|
||||
{
|
||||
UInt32 size = sizeof(*framerange);
|
||||
|
||||
return AudioDeviceGetProperty(
|
||||
id,
|
||||
0,
|
||||
0,
|
||||
kAudioDevicePropertyBufferFrameSizeRange,
|
||||
&size,
|
||||
framerange);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
|
||||
{
|
||||
UInt32 size = sizeof(*framesize);
|
||||
|
||||
return AudioDeviceGetProperty(
|
||||
id,
|
||||
0,
|
||||
false,
|
||||
kAudioDevicePropertyBufferFrameSize,
|
||||
&size,
|
||||
framesize);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
|
||||
{
|
||||
UInt32 size = sizeof(*framesize);
|
||||
|
||||
return AudioDeviceSetProperty(
|
||||
id,
|
||||
NULL,
|
||||
0,
|
||||
false,
|
||||
kAudioDevicePropertyBufferFrameSize,
|
||||
size,
|
||||
framesize);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
|
||||
AudioStreamBasicDescription *d)
|
||||
{
|
||||
UInt32 size = sizeof(*d);
|
||||
|
||||
return AudioDeviceGetProperty(
|
||||
id,
|
||||
0,
|
||||
false,
|
||||
kAudioDevicePropertyStreamFormat,
|
||||
&size,
|
||||
d);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
|
||||
AudioStreamBasicDescription *d)
|
||||
{
|
||||
UInt32 size = sizeof(*d);
|
||||
|
||||
return AudioDeviceSetProperty(
|
||||
id,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
kAudioDevicePropertyStreamFormat,
|
||||
size,
|
||||
d);
|
||||
}
|
||||
|
||||
static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
|
||||
{
|
||||
UInt32 size = sizeof(*result);
|
||||
|
||||
return AudioDeviceGetProperty(
|
||||
id,
|
||||
0,
|
||||
0,
|
||||
kAudioDevicePropertyDeviceIsRunning,
|
||||
&size,
|
||||
result);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void coreaudio_logstatus (OSStatus status)
|
||||
{
|
||||
const char *str = "BUG";
|
||||
@@ -370,7 +144,10 @@ static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
|
||||
{
|
||||
OSStatus status;
|
||||
UInt32 result = 0;
|
||||
status = coreaudio_get_isrunning(outputDeviceID, &result);
|
||||
UInt32 propertySize = sizeof(outputDeviceID);
|
||||
status = AudioDeviceGetProperty(
|
||||
outputDeviceID, 0, 0,
|
||||
kAudioDevicePropertyDeviceIsRunning, &propertySize, &result);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr(status,
|
||||
"Could not determine whether Device is playing\n");
|
||||
@@ -511,6 +288,7 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
{
|
||||
OSStatus status;
|
||||
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
|
||||
UInt32 propertySize;
|
||||
int err;
|
||||
const char *typ = "playback";
|
||||
AudioValueRange frameRange;
|
||||
@@ -525,7 +303,12 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
|
||||
audio_pcm_init_info (&hw->info, as);
|
||||
|
||||
status = coreaudio_get_voice(&core->outputDeviceID);
|
||||
/* open default output device */
|
||||
propertySize = sizeof(core->outputDeviceID);
|
||||
status = AudioHardwareGetProperty(
|
||||
kAudioHardwarePropertyDefaultOutputDevice,
|
||||
&propertySize,
|
||||
&core->outputDeviceID);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr2 (status, typ,
|
||||
"Could not get default output Device\n");
|
||||
@@ -537,8 +320,14 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
}
|
||||
|
||||
/* get minimum and maximum buffer frame sizes */
|
||||
status = coreaudio_get_framesizerange(core->outputDeviceID,
|
||||
&frameRange);
|
||||
propertySize = sizeof(frameRange);
|
||||
status = AudioDeviceGetProperty(
|
||||
core->outputDeviceID,
|
||||
0,
|
||||
0,
|
||||
kAudioDevicePropertyBufferFrameSizeRange,
|
||||
&propertySize,
|
||||
&frameRange);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr2 (status, typ,
|
||||
"Could not get device buffer frame range\n");
|
||||
@@ -558,8 +347,15 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
}
|
||||
|
||||
/* set Buffer Frame Size */
|
||||
status = coreaudio_set_framesize(core->outputDeviceID,
|
||||
&core->audioDevicePropertyBufferFrameSize);
|
||||
propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
|
||||
status = AudioDeviceSetProperty(
|
||||
core->outputDeviceID,
|
||||
NULL,
|
||||
0,
|
||||
false,
|
||||
kAudioDevicePropertyBufferFrameSize,
|
||||
propertySize,
|
||||
&core->audioDevicePropertyBufferFrameSize);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr2 (status, typ,
|
||||
"Could not set device buffer frame size %" PRIu32 "\n",
|
||||
@@ -568,8 +364,14 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
}
|
||||
|
||||
/* get Buffer Frame Size */
|
||||
status = coreaudio_get_framesize(core->outputDeviceID,
|
||||
&core->audioDevicePropertyBufferFrameSize);
|
||||
propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
|
||||
status = AudioDeviceGetProperty(
|
||||
core->outputDeviceID,
|
||||
0,
|
||||
false,
|
||||
kAudioDevicePropertyBufferFrameSize,
|
||||
&propertySize,
|
||||
&core->audioDevicePropertyBufferFrameSize);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr2 (status, typ,
|
||||
"Could not get device buffer frame size\n");
|
||||
@@ -578,8 +380,14 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
hw->samples = conf->nbuffers * core->audioDevicePropertyBufferFrameSize;
|
||||
|
||||
/* get StreamFormat */
|
||||
status = coreaudio_get_streamformat(core->outputDeviceID,
|
||||
&core->outputStreamBasicDescription);
|
||||
propertySize = sizeof(core->outputStreamBasicDescription);
|
||||
status = AudioDeviceGetProperty(
|
||||
core->outputDeviceID,
|
||||
0,
|
||||
false,
|
||||
kAudioDevicePropertyStreamFormat,
|
||||
&propertySize,
|
||||
&core->outputStreamBasicDescription);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr2 (status, typ,
|
||||
"Could not get Device Stream properties\n");
|
||||
@@ -589,8 +397,15 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
|
||||
/* set Samplerate */
|
||||
core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
|
||||
status = coreaudio_set_streamformat(core->outputDeviceID,
|
||||
&core->outputStreamBasicDescription);
|
||||
propertySize = sizeof(core->outputStreamBasicDescription);
|
||||
status = AudioDeviceSetProperty(
|
||||
core->outputDeviceID,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
kAudioDevicePropertyStreamFormat,
|
||||
propertySize,
|
||||
&core->outputStreamBasicDescription);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
|
||||
as->freq);
|
||||
@@ -599,12 +414,8 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
}
|
||||
|
||||
/* set Callback */
|
||||
core->ioprocid = NULL;
|
||||
status = AudioDeviceCreateIOProcID(core->outputDeviceID,
|
||||
audioDeviceIOProc,
|
||||
hw,
|
||||
&core->ioprocid);
|
||||
if (status != kAudioHardwareNoError || core->ioprocid == NULL) {
|
||||
status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
|
||||
core->outputDeviceID = kAudioDeviceUnknown;
|
||||
return -1;
|
||||
@@ -612,10 +423,10 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
|
||||
|
||||
/* start Playback */
|
||||
if (!isPlaying(core->outputDeviceID)) {
|
||||
status = AudioDeviceStart(core->outputDeviceID, core->ioprocid);
|
||||
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr2 (status, typ, "Could not start playback\n");
|
||||
AudioDeviceDestroyIOProcID(core->outputDeviceID, core->ioprocid);
|
||||
AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc);
|
||||
core->outputDeviceID = kAudioDeviceUnknown;
|
||||
return -1;
|
||||
}
|
||||
@@ -633,15 +444,15 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
|
||||
if (!isAtexit) {
|
||||
/* stop playback */
|
||||
if (isPlaying(core->outputDeviceID)) {
|
||||
status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
|
||||
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr (status, "Could not stop playback\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* remove callback */
|
||||
status = AudioDeviceDestroyIOProcID(core->outputDeviceID,
|
||||
core->ioprocid);
|
||||
status = AudioDeviceRemoveIOProc(core->outputDeviceID,
|
||||
audioDeviceIOProc);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr (status, "Could not remove IOProc\n");
|
||||
}
|
||||
@@ -664,7 +475,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
|
||||
case VOICE_ENABLE:
|
||||
/* start playback */
|
||||
if (!isPlaying(core->outputDeviceID)) {
|
||||
status = AudioDeviceStart(core->outputDeviceID, core->ioprocid);
|
||||
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr (status, "Could not resume playback\n");
|
||||
}
|
||||
@@ -675,8 +486,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
|
||||
/* stop playback */
|
||||
if (!isAtexit) {
|
||||
if (isPlaying(core->outputDeviceID)) {
|
||||
status = AudioDeviceStop(core->outputDeviceID,
|
||||
core->ioprocid);
|
||||
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr (status, "Could not pause playback\n");
|
||||
}
|
||||
|
@@ -566,7 +566,6 @@ static CharDriverState *chr_baum_init(const char *id,
|
||||
ChardevReturn *ret,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.braille);
|
||||
BaumDriverState *baum;
|
||||
CharDriverState *chr;
|
||||
brlapi_handle_t *handle;
|
||||
@@ -577,12 +576,8 @@ static CharDriverState *chr_baum_init(const char *id,
|
||||
#endif
|
||||
int tty;
|
||||
|
||||
chr = qemu_chr_alloc(common, errp);
|
||||
if (!chr) {
|
||||
return NULL;
|
||||
}
|
||||
baum = g_malloc0(sizeof(BaumDriverState));
|
||||
baum->chr = chr;
|
||||
baum->chr = chr = qemu_chr_alloc();
|
||||
|
||||
chr->opaque = baum;
|
||||
chr->chr_write = baum_write;
|
||||
|
@@ -68,13 +68,9 @@ static CharDriverState *qemu_chr_open_msmouse(const char *id,
|
||||
ChardevReturn *ret,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.msmouse);
|
||||
CharDriverState *chr;
|
||||
|
||||
chr = qemu_chr_alloc(common, errp);
|
||||
if (!chr) {
|
||||
return NULL;
|
||||
}
|
||||
chr = qemu_chr_alloc();
|
||||
chr->chr_write = msmouse_chr_write;
|
||||
chr->chr_close = msmouse_chr_close;
|
||||
chr->explicit_be_open = true;
|
||||
|
@@ -23,7 +23,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/accounting.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/timer.h"
|
||||
|
@@ -50,7 +50,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -60,6 +59,7 @@
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qemu/atomic.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <xseg/xseg.h>
|
||||
#include <xseg/protocol.h>
|
||||
|
||||
|
@@ -11,7 +11,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "trace.h"
|
||||
#include "block/block.h"
|
||||
|
104
block/blkdebug.c
104
block/blkdebug.c
@@ -22,7 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "block/block_int.h"
|
||||
@@ -37,7 +36,7 @@ typedef struct BDRVBlkdebugState {
|
||||
int state;
|
||||
int new_state;
|
||||
|
||||
QLIST_HEAD(, BlkdebugRule) rules[BLKDBG__MAX];
|
||||
QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
|
||||
QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
|
||||
QLIST_HEAD(, BlkdebugSuspendedReq) suspended_reqs;
|
||||
} BDRVBlkdebugState;
|
||||
@@ -65,7 +64,7 @@ enum {
|
||||
};
|
||||
|
||||
typedef struct BlkdebugRule {
|
||||
BlkdebugEvent event;
|
||||
BlkDebugEvent event;
|
||||
int action;
|
||||
int state;
|
||||
union {
|
||||
@@ -144,12 +143,69 @@ static QemuOptsList *config_groups[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static int get_event_by_name(const char *name, BlkdebugEvent *event)
|
||||
static const char *event_names[BLKDBG_EVENT_MAX] = {
|
||||
[BLKDBG_L1_UPDATE] = "l1_update",
|
||||
[BLKDBG_L1_GROW_ALLOC_TABLE] = "l1_grow.alloc_table",
|
||||
[BLKDBG_L1_GROW_WRITE_TABLE] = "l1_grow.write_table",
|
||||
[BLKDBG_L1_GROW_ACTIVATE_TABLE] = "l1_grow.activate_table",
|
||||
|
||||
[BLKDBG_L2_LOAD] = "l2_load",
|
||||
[BLKDBG_L2_UPDATE] = "l2_update",
|
||||
[BLKDBG_L2_UPDATE_COMPRESSED] = "l2_update_compressed",
|
||||
[BLKDBG_L2_ALLOC_COW_READ] = "l2_alloc.cow_read",
|
||||
[BLKDBG_L2_ALLOC_WRITE] = "l2_alloc.write",
|
||||
|
||||
[BLKDBG_READ_AIO] = "read_aio",
|
||||
[BLKDBG_READ_BACKING_AIO] = "read_backing_aio",
|
||||
[BLKDBG_READ_COMPRESSED] = "read_compressed",
|
||||
|
||||
[BLKDBG_WRITE_AIO] = "write_aio",
|
||||
[BLKDBG_WRITE_COMPRESSED] = "write_compressed",
|
||||
|
||||
[BLKDBG_VMSTATE_LOAD] = "vmstate_load",
|
||||
[BLKDBG_VMSTATE_SAVE] = "vmstate_save",
|
||||
|
||||
[BLKDBG_COW_READ] = "cow_read",
|
||||
[BLKDBG_COW_WRITE] = "cow_write",
|
||||
|
||||
[BLKDBG_REFTABLE_LOAD] = "reftable_load",
|
||||
[BLKDBG_REFTABLE_GROW] = "reftable_grow",
|
||||
[BLKDBG_REFTABLE_UPDATE] = "reftable_update",
|
||||
|
||||
[BLKDBG_REFBLOCK_LOAD] = "refblock_load",
|
||||
[BLKDBG_REFBLOCK_UPDATE] = "refblock_update",
|
||||
[BLKDBG_REFBLOCK_UPDATE_PART] = "refblock_update_part",
|
||||
[BLKDBG_REFBLOCK_ALLOC] = "refblock_alloc",
|
||||
[BLKDBG_REFBLOCK_ALLOC_HOOKUP] = "refblock_alloc.hookup",
|
||||
[BLKDBG_REFBLOCK_ALLOC_WRITE] = "refblock_alloc.write",
|
||||
[BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS] = "refblock_alloc.write_blocks",
|
||||
[BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE] = "refblock_alloc.write_table",
|
||||
[BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE] = "refblock_alloc.switch_table",
|
||||
|
||||
[BLKDBG_CLUSTER_ALLOC] = "cluster_alloc",
|
||||
[BLKDBG_CLUSTER_ALLOC_BYTES] = "cluster_alloc_bytes",
|
||||
[BLKDBG_CLUSTER_FREE] = "cluster_free",
|
||||
|
||||
[BLKDBG_FLUSH_TO_OS] = "flush_to_os",
|
||||
[BLKDBG_FLUSH_TO_DISK] = "flush_to_disk",
|
||||
|
||||
[BLKDBG_PWRITEV_RMW_HEAD] = "pwritev_rmw.head",
|
||||
[BLKDBG_PWRITEV_RMW_AFTER_HEAD] = "pwritev_rmw.after_head",
|
||||
[BLKDBG_PWRITEV_RMW_TAIL] = "pwritev_rmw.tail",
|
||||
[BLKDBG_PWRITEV_RMW_AFTER_TAIL] = "pwritev_rmw.after_tail",
|
||||
[BLKDBG_PWRITEV] = "pwritev",
|
||||
[BLKDBG_PWRITEV_ZERO] = "pwritev_zero",
|
||||
[BLKDBG_PWRITEV_DONE] = "pwritev_done",
|
||||
|
||||
[BLKDBG_EMPTY_IMAGE_PREPARE] = "empty_image_prepare",
|
||||
};
|
||||
|
||||
static int get_event_by_name(const char *name, BlkDebugEvent *event)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BLKDBG__MAX; i++) {
|
||||
if (!strcmp(BlkdebugEvent_lookup[i], name)) {
|
||||
for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
|
||||
if (!strcmp(event_names[i], name)) {
|
||||
*event = i;
|
||||
return 0;
|
||||
}
|
||||
@@ -168,7 +224,7 @@ static int add_rule(void *opaque, QemuOpts *opts, Error **errp)
|
||||
struct add_rule_data *d = opaque;
|
||||
BDRVBlkdebugState *s = d->s;
|
||||
const char* event_name;
|
||||
BlkdebugEvent event;
|
||||
BlkDebugEvent event;
|
||||
struct BlkdebugRule *rule;
|
||||
|
||||
/* Find the right event for the rule */
|
||||
@@ -508,7 +564,7 @@ static void blkdebug_close(BlockDriverState *bs)
|
||||
BlkdebugRule *rule, *next;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BLKDBG__MAX; i++) {
|
||||
for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
|
||||
QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
|
||||
remove_rule(rule);
|
||||
}
|
||||
@@ -571,13 +627,13 @@ static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
|
||||
return injected;
|
||||
}
|
||||
|
||||
static void blkdebug_debug_event(BlockDriverState *bs, BlkdebugEvent event)
|
||||
static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event)
|
||||
{
|
||||
BDRVBlkdebugState *s = bs->opaque;
|
||||
struct BlkdebugRule *rule, *next;
|
||||
bool injected;
|
||||
|
||||
assert((int)event >= 0 && event < BLKDBG__MAX);
|
||||
assert((int)event >= 0 && event < BLKDBG_EVENT_MAX);
|
||||
|
||||
injected = false;
|
||||
s->new_state = s->state;
|
||||
@@ -592,7 +648,7 @@ static int blkdebug_debug_breakpoint(BlockDriverState *bs, const char *event,
|
||||
{
|
||||
BDRVBlkdebugState *s = bs->opaque;
|
||||
struct BlkdebugRule *rule;
|
||||
BlkdebugEvent blkdebug_event;
|
||||
BlkDebugEvent blkdebug_event;
|
||||
|
||||
if (get_event_by_name(event, &blkdebug_event) < 0) {
|
||||
return -ENOENT;
|
||||
@@ -634,7 +690,7 @@ static int blkdebug_debug_remove_breakpoint(BlockDriverState *bs,
|
||||
BlkdebugRule *rule, *next;
|
||||
int i, ret = -ENOENT;
|
||||
|
||||
for (i = 0; i < BLKDBG__MAX; i++) {
|
||||
for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
|
||||
QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
|
||||
if (rule->action == ACTION_SUSPEND &&
|
||||
!strcmp(rule->options.suspend.tag, tag)) {
|
||||
@@ -675,15 +731,17 @@ static int blkdebug_truncate(BlockDriverState *bs, int64_t offset)
|
||||
return bdrv_truncate(bs->file->bs, offset);
|
||||
}
|
||||
|
||||
static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
static void blkdebug_refresh_filename(BlockDriverState *bs)
|
||||
{
|
||||
QDict *opts;
|
||||
const QDictEntry *e;
|
||||
bool force_json = false;
|
||||
|
||||
for (e = qdict_first(options); e; e = qdict_next(options, e)) {
|
||||
for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) {
|
||||
if (strcmp(qdict_entry_key(e), "config") &&
|
||||
strcmp(qdict_entry_key(e), "x-image"))
|
||||
strcmp(qdict_entry_key(e), "x-image") &&
|
||||
strcmp(qdict_entry_key(e), "image") &&
|
||||
strncmp(qdict_entry_key(e), "image.", strlen("image.")))
|
||||
{
|
||||
force_json = true;
|
||||
break;
|
||||
@@ -699,7 +757,7 @@ static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
if (!force_json && bs->file->bs->exact_filename[0]) {
|
||||
snprintf(bs->exact_filename, sizeof(bs->exact_filename),
|
||||
"blkdebug:%s:%s",
|
||||
qdict_get_try_str(options, "config") ?: "",
|
||||
qdict_get_try_str(bs->options, "config") ?: "",
|
||||
bs->file->bs->exact_filename);
|
||||
}
|
||||
|
||||
@@ -709,8 +767,11 @@ static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
QINCREF(bs->file->bs->full_open_options);
|
||||
qdict_put_obj(opts, "image", QOBJECT(bs->file->bs->full_open_options));
|
||||
|
||||
for (e = qdict_first(options); e; e = qdict_next(options, e)) {
|
||||
if (strcmp(qdict_entry_key(e), "x-image")) {
|
||||
for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) {
|
||||
if (strcmp(qdict_entry_key(e), "x-image") &&
|
||||
strcmp(qdict_entry_key(e), "image") &&
|
||||
strncmp(qdict_entry_key(e), "image.", strlen("image.")))
|
||||
{
|
||||
qobject_incref(qdict_entry_value(e));
|
||||
qdict_put_obj(opts, qdict_entry_key(e), qdict_entry_value(e));
|
||||
}
|
||||
@@ -719,12 +780,6 @@ static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
bs->full_open_options = opts;
|
||||
}
|
||||
|
||||
static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state,
|
||||
BlockReopenQueue *queue, Error **errp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_blkdebug = {
|
||||
.format_name = "blkdebug",
|
||||
.protocol_name = "blkdebug",
|
||||
@@ -733,7 +788,6 @@ static BlockDriver bdrv_blkdebug = {
|
||||
.bdrv_parse_filename = blkdebug_parse_filename,
|
||||
.bdrv_file_open = blkdebug_open,
|
||||
.bdrv_close = blkdebug_close,
|
||||
.bdrv_reopen_prepare = blkdebug_reopen_prepare,
|
||||
.bdrv_getlength = blkdebug_getlength,
|
||||
.bdrv_truncate = blkdebug_truncate,
|
||||
.bdrv_refresh_filename = blkdebug_refresh_filename,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <stdarg.h>
|
||||
#include "qemu/sockets.h" /* for EINPROGRESS on Windows */
|
||||
#include "block/block_int.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
@@ -307,7 +307,7 @@ static void blkverify_attach_aio_context(BlockDriverState *bs,
|
||||
bdrv_attach_aio_context(s->test_file->bs, new_context);
|
||||
}
|
||||
|
||||
static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
static void blkverify_refresh_filename(BlockDriverState *bs)
|
||||
{
|
||||
BDRVBlkverifyState *s = bs->opaque;
|
||||
|
||||
|
@@ -10,7 +10,6 @@
|
||||
* or later. See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/blockjob.h"
|
||||
@@ -458,6 +457,14 @@ bool blk_dev_has_removable_media(BlockBackend *blk)
|
||||
return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Does @blk's attached device model have a tray?
|
||||
*/
|
||||
bool blk_dev_has_tray(BlockBackend *blk)
|
||||
{
|
||||
return blk->dev_ops && blk->dev_ops->is_tray_open;
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify @blk's attached device model of a media eject request.
|
||||
* If @force is true, the medium is about to be yanked out forcefully.
|
||||
@@ -474,7 +481,7 @@ void blk_dev_eject_request(BlockBackend *blk, bool force)
|
||||
*/
|
||||
bool blk_dev_is_tray_open(BlockBackend *blk)
|
||||
{
|
||||
if (blk->dev_ops && blk->dev_ops->is_tray_open) {
|
||||
if (blk_dev_has_tray(blk)) {
|
||||
return blk->dev_ops->is_tray_open(blk->dev_opaque);
|
||||
}
|
||||
return false;
|
||||
@@ -1024,21 +1031,11 @@ int blk_get_max_transfer_length(BlockBackend *blk)
|
||||
}
|
||||
}
|
||||
|
||||
int blk_get_max_iov(BlockBackend *blk)
|
||||
{
|
||||
return blk->bs->bl.max_iov;
|
||||
}
|
||||
|
||||
void blk_set_guest_block_size(BlockBackend *blk, int align)
|
||||
{
|
||||
blk->guest_block_size = align;
|
||||
}
|
||||
|
||||
void *blk_try_blockalign(BlockBackend *blk, size_t size)
|
||||
{
|
||||
return qemu_try_blockalign(blk ? blk->bs : NULL, size);
|
||||
}
|
||||
|
||||
void *blk_blockalign(BlockBackend *blk, size_t size)
|
||||
{
|
||||
return qemu_blockalign(blk ? blk->bs : NULL, size);
|
||||
|
@@ -22,7 +22,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
|
@@ -21,7 +21,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
|
@@ -12,7 +12,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "trace.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/blockjob.h"
|
||||
|
@@ -21,7 +21,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "block/block_int.h"
|
||||
|
@@ -21,7 +21,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/bswap.h"
|
||||
|
@@ -7,7 +7,6 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include <glusterfs/api/glfs.h>
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/uri.h"
|
||||
|
20
block/io.c
20
block/io.c
@@ -22,7 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "trace.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "block/blockjob.h"
|
||||
@@ -167,13 +166,9 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
bs->bl.max_transfer_length = bs->file->bs->bl.max_transfer_length;
|
||||
bs->bl.min_mem_alignment = bs->file->bs->bl.min_mem_alignment;
|
||||
bs->bl.opt_mem_alignment = bs->file->bs->bl.opt_mem_alignment;
|
||||
bs->bl.max_iov = bs->file->bs->bl.max_iov;
|
||||
} else {
|
||||
bs->bl.min_mem_alignment = 512;
|
||||
bs->bl.opt_mem_alignment = getpagesize();
|
||||
|
||||
/* Safe default since most protocols use readv()/writev()/etc */
|
||||
bs->bl.max_iov = IOV_MAX;
|
||||
}
|
||||
|
||||
if (bs->backing) {
|
||||
@@ -194,9 +189,6 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
bs->bl.min_mem_alignment =
|
||||
MAX(bs->bl.min_mem_alignment,
|
||||
bs->backing->bs->bl.min_mem_alignment);
|
||||
bs->bl.max_iov =
|
||||
MIN(bs->bl.max_iov,
|
||||
bs->backing->bs->bl.max_iov);
|
||||
}
|
||||
|
||||
/* Then let the driver override it */
|
||||
@@ -1301,7 +1293,6 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
|
||||
if (bs->read_only) {
|
||||
return -EPERM;
|
||||
}
|
||||
assert(!(bs->open_flags & BDRV_O_INACTIVE));
|
||||
|
||||
ret = bdrv_check_byte_request(bs, offset, bytes);
|
||||
if (ret < 0) {
|
||||
@@ -1891,8 +1882,7 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
|
||||
merge = 1;
|
||||
}
|
||||
|
||||
if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 >
|
||||
bs->bl.max_iov) {
|
||||
if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) {
|
||||
merge = 0;
|
||||
}
|
||||
|
||||
@@ -2463,7 +2453,6 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
|
||||
} else if (bs->read_only) {
|
||||
return -EPERM;
|
||||
}
|
||||
assert(!(bs->open_flags & BDRV_O_INACTIVE));
|
||||
|
||||
/* Do nothing if disabled. */
|
||||
if (!(bs->open_flags & BDRV_O_UNMAP)) {
|
||||
@@ -2625,11 +2614,10 @@ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
|
||||
bdrv_co_ioctl_entry(&data);
|
||||
} else {
|
||||
Coroutine *co = qemu_coroutine_create(bdrv_co_ioctl_entry);
|
||||
|
||||
qemu_coroutine_enter(co, &data);
|
||||
while (data.ret == -EINPROGRESS) {
|
||||
aio_poll(bdrv_get_aio_context(bs), true);
|
||||
}
|
||||
}
|
||||
while (data.ret == -EINPROGRESS) {
|
||||
aio_poll(bdrv_get_aio_context(bs), true);
|
||||
}
|
||||
return data.ret;
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "config-host.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include <math.h>
|
||||
@@ -1243,13 +1243,8 @@ static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
|
||||
iscsilun->lbprz = !!rc16->lbprz;
|
||||
iscsilun->use_16_for_rw = (rc16->returned_lba > 0xffffffff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION
|
||||
&& task->sense.key == SCSI_SENSE_UNIT_ATTENTION) {
|
||||
break;
|
||||
}
|
||||
/* Fall through and try READ CAPACITY(10) instead. */
|
||||
break;
|
||||
case TYPE_ROM:
|
||||
task = iscsi_readcapacity10_sync(iscsilun->iscsi, iscsilun->lun, 0, 0);
|
||||
if (task != NULL && task->status == SCSI_STATUS_GOOD) {
|
||||
@@ -1275,7 +1270,7 @@ static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
|
||||
&& retries-- > 0);
|
||||
|
||||
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
|
||||
error_setg(errp, "iSCSI: failed to send readcapacity10/16 command");
|
||||
error_setg(errp, "iSCSI: failed to send readcapacity10 command.");
|
||||
} else if (!iscsilun->block_size ||
|
||||
iscsilun->block_size % BDRV_SECTOR_SIZE) {
|
||||
error_setg(errp, "iSCSI: the target returned an invalid "
|
||||
|
@@ -7,7 +7,6 @@
|
||||
* 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/aio.h"
|
||||
#include "qemu/queue.h"
|
||||
|
@@ -11,7 +11,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "trace.h"
|
||||
#include "block/blockjob.h"
|
||||
#include "block/block_int.h"
|
||||
@@ -19,7 +18,6 @@
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/ratelimit.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define SLICE_TIME 100000000ULL /* ns */
|
||||
#define MAX_IN_FLIGHT 16
|
||||
@@ -162,15 +160,13 @@ static void mirror_read_complete(void *opaque, int ret)
|
||||
static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||
{
|
||||
BlockDriverState *source = s->common.bs;
|
||||
int nb_sectors, sectors_per_chunk, nb_chunks, max_iov;
|
||||
int nb_sectors, sectors_per_chunk, nb_chunks;
|
||||
int64_t end, sector_num, next_chunk, next_sector, hbitmap_next_sector;
|
||||
uint64_t delay_ns = 0;
|
||||
MirrorOp *op;
|
||||
int pnum;
|
||||
int64_t ret;
|
||||
|
||||
max_iov = MIN(source->bl.max_iov, s->target->bl.max_iov);
|
||||
|
||||
s->sector_num = hbitmap_iter_next(&s->hbi);
|
||||
if (s->sector_num < 0) {
|
||||
bdrv_dirty_iter_init(s->dirty_bitmap, &s->hbi);
|
||||
@@ -251,7 +247,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
|
||||
trace_mirror_break_buf_busy(s, nb_chunks, s->in_flight);
|
||||
break;
|
||||
}
|
||||
if (max_iov < nb_chunks + added_chunks) {
|
||||
if (IOV_MAX < nb_chunks + added_chunks) {
|
||||
trace_mirror_break_iov_max(s, nb_chunks, added_chunks);
|
||||
break;
|
||||
}
|
||||
@@ -374,22 +370,11 @@ static void mirror_exit(BlockJob *job, void *opaque)
|
||||
if (s->to_replace) {
|
||||
to_replace = s->to_replace;
|
||||
}
|
||||
|
||||
/* This was checked in mirror_start_job(), but meanwhile one of the
|
||||
* nodes could have been newly attached to a BlockBackend. */
|
||||
if (to_replace->blk && s->target->blk) {
|
||||
error_report("block job: Can't create node with two BlockBackends");
|
||||
data->ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bdrv_get_flags(s->target) != bdrv_get_flags(to_replace)) {
|
||||
bdrv_reopen(s->target, bdrv_get_flags(to_replace), NULL);
|
||||
}
|
||||
bdrv_replace_in_backing_chain(to_replace, s->target);
|
||||
}
|
||||
|
||||
out:
|
||||
if (s->to_replace) {
|
||||
bdrv_op_unblock_all(s->to_replace, s->replace_blocker);
|
||||
error_free(s->replace_blocker);
|
||||
@@ -655,7 +640,7 @@ static void mirror_complete(BlockJob *job, Error **errp)
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
ret = bdrv_open_backing_file(s->target, NULL, "backing", &local_err);
|
||||
ret = bdrv_open_backing_file(s->target, NULL, &local_err);
|
||||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
@@ -720,7 +705,6 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
|
||||
bool is_none_mode, BlockDriverState *base)
|
||||
{
|
||||
MirrorBlockJob *s;
|
||||
BlockDriverState *replaced_bs;
|
||||
|
||||
if (granularity == 0) {
|
||||
granularity = bdrv_get_default_bitmap_granularity(target);
|
||||
@@ -744,21 +728,6 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
|
||||
buf_size = DEFAULT_MIRROR_BUF_SIZE;
|
||||
}
|
||||
|
||||
/* We can't support this case as long as the block layer can't handle
|
||||
* multiple BlockBackends per BlockDriverState. */
|
||||
if (replaces) {
|
||||
replaced_bs = bdrv_lookup_bs(replaces, replaces, errp);
|
||||
if (replaced_bs == NULL) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
replaced_bs = bs;
|
||||
}
|
||||
if (replaced_bs->blk && target->blk) {
|
||||
error_setg(errp, "Can't create node with two BlockBackends");
|
||||
return;
|
||||
}
|
||||
|
||||
s = block_job_create(driver, bs, speed, cb, opaque, errp);
|
||||
if (!s) {
|
||||
return;
|
||||
|
@@ -26,7 +26,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "nbd-client.h"
|
||||
#include "qemu/sockets.h"
|
||||
|
||||
|
13
block/nbd.c
13
block/nbd.c
@@ -26,7 +26,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/nbd-client.h"
|
||||
#include "qemu/uri.h"
|
||||
#include "block/block_int.h"
|
||||
@@ -37,6 +36,8 @@
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define EN_OPTSTR ":exportname="
|
||||
|
||||
@@ -341,13 +342,13 @@ static void nbd_attach_aio_context(BlockDriverState *bs,
|
||||
nbd_client_attach_aio_context(bs, new_context);
|
||||
}
|
||||
|
||||
static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
static void nbd_refresh_filename(BlockDriverState *bs)
|
||||
{
|
||||
QDict *opts = qdict_new();
|
||||
const char *path = qdict_get_try_str(options, "path");
|
||||
const char *host = qdict_get_try_str(options, "host");
|
||||
const char *port = qdict_get_try_str(options, "port");
|
||||
const char *export = qdict_get_try_str(options, "export");
|
||||
const char *path = qdict_get_try_str(bs->options, "path");
|
||||
const char *host = qdict_get_try_str(bs->options, "host");
|
||||
const char *port = qdict_get_try_str(bs->options, "port");
|
||||
const char *export = qdict_get_try_str(bs->options, "export");
|
||||
|
||||
qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("nbd")));
|
||||
|
||||
|
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "config-host.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include "qemu-common.h"
|
||||
|
@@ -10,7 +10,6 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/block_int.h"
|
||||
|
||||
#define NULL_OPT_LATENCY "latency-ns"
|
||||
|
@@ -27,7 +27,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
@@ -62,7 +61,7 @@ typedef struct ParallelsHeader {
|
||||
typedef enum ParallelsPreallocMode {
|
||||
PRL_PREALLOC_MODE_FALLOCATE = 0,
|
||||
PRL_PREALLOC_MODE_TRUNCATE = 1,
|
||||
PRL_PREALLOC_MODE__MAX = 2,
|
||||
PRL_PREALLOC_MODE_MAX = 2,
|
||||
} ParallelsPreallocMode;
|
||||
|
||||
static const char *prealloc_mode_lookup[] = {
|
||||
@@ -661,7 +660,7 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
s->prealloc_size = MAX(s->tracks, s->prealloc_size >> BDRV_SECTOR_BITS);
|
||||
buf = qemu_opt_get_del(opts, PARALLELS_OPT_PREALLOC_MODE);
|
||||
s->prealloc_mode = qapi_enum_parse(prealloc_mode_lookup, buf,
|
||||
PRL_PREALLOC_MODE__MAX, PRL_PREALLOC_MODE_FALLOCATE, &local_err);
|
||||
PRL_PREALLOC_MODE_MAX, PRL_PREALLOC_MODE_FALLOCATE, &local_err);
|
||||
g_free(buf);
|
||||
if (local_err != NULL) {
|
||||
goto fail_options;
|
||||
|
25
block/qapi.c
25
block/qapi.c
@@ -22,7 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/qapi.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/throttle-groups.h"
|
||||
@@ -246,18 +245,15 @@ void bdrv_query_image_info(BlockDriverState *bs,
|
||||
info->has_backing_filename = true;
|
||||
bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err);
|
||||
if (err) {
|
||||
/* Can't reconstruct the full backing filename, so we must omit
|
||||
* this field and apply a Best Effort to this query. */
|
||||
error_propagate(errp, err);
|
||||
qapi_free_ImageInfo(info);
|
||||
g_free(backing_filename2);
|
||||
backing_filename2 = NULL;
|
||||
error_free(err);
|
||||
err = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Always report the full_backing_filename if present, even if it's the
|
||||
* same as backing_filename. That they are same is useful info. */
|
||||
if (backing_filename2) {
|
||||
info->full_backing_filename = g_strdup(backing_filename2);
|
||||
if (strcmp(backing_filename, backing_filename2) != 0) {
|
||||
info->full_backing_filename =
|
||||
g_strdup(backing_filename2);
|
||||
info->has_full_backing_filename = true;
|
||||
}
|
||||
|
||||
@@ -592,7 +588,7 @@ static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation,
|
||||
int i = 0;
|
||||
|
||||
for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) {
|
||||
QType type = qobject_type(entry->value);
|
||||
qtype_code type = qobject_type(entry->value);
|
||||
bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
|
||||
const char *format = composite ? "%*s[%i]:\n" : "%*s[%i]: ";
|
||||
|
||||
@@ -610,7 +606,7 @@ static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation,
|
||||
const QDictEntry *entry;
|
||||
|
||||
for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) {
|
||||
QType type = qobject_type(entry->value);
|
||||
qtype_code type = qobject_type(entry->value);
|
||||
bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
|
||||
const char *format = composite ? "%*s%s:\n" : "%*s%s: ";
|
||||
char key[strlen(entry->key) + 1];
|
||||
@@ -680,10 +676,7 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f,
|
||||
|
||||
if (info->has_backing_filename) {
|
||||
func_fprintf(f, "backing file: %s", info->backing_filename);
|
||||
if (!info->has_full_backing_filename) {
|
||||
func_fprintf(f, " (cannot determine actual path)");
|
||||
} else if (strcmp(info->backing_filename,
|
||||
info->full_backing_filename) != 0) {
|
||||
if (info->has_full_backing_filename) {
|
||||
func_fprintf(f, " (actual path: %s)", info->full_backing_filename);
|
||||
}
|
||||
func_fprintf(f, "\n");
|
||||
|
@@ -21,7 +21,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
/* Needed for CONFIG_MADVISE */
|
||||
#include "qemu/osdep.h"
|
||||
#include "config-host.h"
|
||||
|
||||
#if defined(CONFIG_MADVISE) || defined(CONFIG_POSIX_MADVISE)
|
||||
#include <sys/mman.h>
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "block/block_int.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/osdep.h"
|
||||
#include "qcow2.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
@@ -22,7 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#include "qemu-common.h"
|
||||
@@ -1642,8 +1641,7 @@ fail:
|
||||
static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
int l1_size, int64_t *visited_l1_entries,
|
||||
int64_t l1_entries,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque)
|
||||
BlockDriverAmendStatusCB *status_cb)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
bool is_active_l1 = (l1_table == s->l1_table);
|
||||
@@ -1669,7 +1667,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
/* unallocated */
|
||||
(*visited_l1_entries)++;
|
||||
if (status_cb) {
|
||||
status_cb(bs, *visited_l1_entries, l1_entries, cb_opaque);
|
||||
status_cb(bs, *visited_l1_entries, l1_entries);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1806,7 +1804,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
||||
|
||||
(*visited_l1_entries)++;
|
||||
if (status_cb) {
|
||||
status_cb(bs, *visited_l1_entries, l1_entries, cb_opaque);
|
||||
status_cb(bs, *visited_l1_entries, l1_entries);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1830,8 +1828,7 @@ fail:
|
||||
* qcow2 version which doesn't yet support metadata zero clusters.
|
||||
*/
|
||||
int qcow2_expand_zero_clusters(BlockDriverState *bs,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque)
|
||||
BlockDriverAmendStatusCB *status_cb)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t *l1_table = NULL;
|
||||
@@ -1848,7 +1845,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
|
||||
|
||||
ret = expand_zero_clusters_in_l1(bs, s->l1_table, s->l1_size,
|
||||
&visited_l1_entries, l1_entries,
|
||||
status_cb, cb_opaque);
|
||||
status_cb);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -1884,7 +1881,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
|
||||
|
||||
ret = expand_zero_clusters_in_l1(bs, l1_table, s->snapshots[i].l1_size,
|
||||
&visited_l1_entries, l1_entries,
|
||||
status_cb, cb_opaque);
|
||||
status_cb);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@@ -22,7 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/qcow2.h"
|
||||
@@ -1346,9 +1345,6 @@ static int inc_refcounts(BlockDriverState *bs,
|
||||
if (refcount == s->refcount_max) {
|
||||
fprintf(stderr, "ERROR: overflow cluster offset=0x%" PRIx64
|
||||
"\n", cluster_offset);
|
||||
fprintf(stderr, "Use qemu-img amend to increase the refcount entry "
|
||||
"width or qemu-img convert to create a clean copy if the "
|
||||
"image cannot be opened for writing\n");
|
||||
res->corruptions++;
|
||||
continue;
|
||||
}
|
||||
@@ -2471,450 +2467,3 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A pointer to a function of this type is given to walk_over_reftable(). That
|
||||
* function will create refblocks and pass them to a RefblockFinishOp once they
|
||||
* are completed (@refblock). @refblock_empty is set if the refblock is
|
||||
* completely empty.
|
||||
*
|
||||
* Along with the refblock, a corresponding reftable entry is passed, in the
|
||||
* reftable @reftable (which may be reallocated) at @reftable_index.
|
||||
*
|
||||
* @allocated should be set to true if a new cluster has been allocated.
|
||||
*/
|
||||
typedef int (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable,
|
||||
uint64_t reftable_index, uint64_t *reftable_size,
|
||||
void *refblock, bool refblock_empty,
|
||||
bool *allocated, Error **errp);
|
||||
|
||||
/**
|
||||
* This "operation" for walk_over_reftable() allocates the refblock on disk (if
|
||||
* it is not empty) and inserts its offset into the new reftable. The size of
|
||||
* this new reftable is increased as required.
|
||||
*/
|
||||
static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable,
|
||||
uint64_t reftable_index, uint64_t *reftable_size,
|
||||
void *refblock, bool refblock_empty, bool *allocated,
|
||||
Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int64_t offset;
|
||||
|
||||
if (!refblock_empty && reftable_index >= *reftable_size) {
|
||||
uint64_t *new_reftable;
|
||||
uint64_t new_reftable_size;
|
||||
|
||||
new_reftable_size = ROUND_UP(reftable_index + 1,
|
||||
s->cluster_size / sizeof(uint64_t));
|
||||
if (new_reftable_size > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) {
|
||||
error_setg(errp,
|
||||
"This operation would make the refcount table grow "
|
||||
"beyond the maximum size supported by QEMU, aborting");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
new_reftable = g_try_realloc(*reftable, new_reftable_size *
|
||||
sizeof(uint64_t));
|
||||
if (!new_reftable) {
|
||||
error_setg(errp, "Failed to increase reftable buffer size");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(new_reftable + *reftable_size, 0,
|
||||
(new_reftable_size - *reftable_size) * sizeof(uint64_t));
|
||||
|
||||
*reftable = new_reftable;
|
||||
*reftable_size = new_reftable_size;
|
||||
}
|
||||
|
||||
if (!refblock_empty && !(*reftable)[reftable_index]) {
|
||||
offset = qcow2_alloc_clusters(bs, s->cluster_size);
|
||||
if (offset < 0) {
|
||||
error_setg_errno(errp, -offset, "Failed to allocate refblock");
|
||||
return offset;
|
||||
}
|
||||
(*reftable)[reftable_index] = offset;
|
||||
*allocated = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This "operation" for walk_over_reftable() writes the refblock to disk at the
|
||||
* offset specified by the new reftable's entry. It does not modify the new
|
||||
* reftable or change any refcounts.
|
||||
*/
|
||||
static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
|
||||
uint64_t reftable_index, uint64_t *reftable_size,
|
||||
void *refblock, bool refblock_empty, bool *allocated,
|
||||
Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int64_t offset;
|
||||
int ret;
|
||||
|
||||
if (reftable_index < *reftable_size && (*reftable)[reftable_index]) {
|
||||
offset = (*reftable)[reftable_index];
|
||||
|
||||
ret = qcow2_pre_write_overlap_check(bs, 0, offset, s->cluster_size);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Overlap check failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, offset, refblock, s->cluster_size);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to write refblock");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
assert(refblock_empty);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function walks over the existing reftable and every referenced refblock;
|
||||
* if @new_set_refcount is non-NULL, it is called for every refcount entry to
|
||||
* create an equal new entry in the passed @new_refblock. Once that
|
||||
* @new_refblock is completely filled, @operation will be called.
|
||||
*
|
||||
* @status_cb and @cb_opaque are used for the amend operation's status callback.
|
||||
* @index is the index of the walk_over_reftable() calls and @total is the total
|
||||
* number of walk_over_reftable() calls per amend operation. Both are used for
|
||||
* calculating the parameters for the status callback.
|
||||
*
|
||||
* @allocated is set to true if a new cluster has been allocated.
|
||||
*/
|
||||
static int walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable,
|
||||
uint64_t *new_reftable_index,
|
||||
uint64_t *new_reftable_size,
|
||||
void *new_refblock, int new_refblock_size,
|
||||
int new_refcount_bits,
|
||||
RefblockFinishOp *operation, bool *allocated,
|
||||
Qcow2SetRefcountFunc *new_set_refcount,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque, int index, int total,
|
||||
Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
uint64_t reftable_index;
|
||||
bool new_refblock_empty = true;
|
||||
int refblock_index;
|
||||
int new_refblock_index = 0;
|
||||
int ret;
|
||||
|
||||
for (reftable_index = 0; reftable_index < s->refcount_table_size;
|
||||
reftable_index++)
|
||||
{
|
||||
uint64_t refblock_offset = s->refcount_table[reftable_index]
|
||||
& REFT_OFFSET_MASK;
|
||||
|
||||
status_cb(bs, (uint64_t)index * s->refcount_table_size + reftable_index,
|
||||
(uint64_t)total * s->refcount_table_size, cb_opaque);
|
||||
|
||||
if (refblock_offset) {
|
||||
void *refblock;
|
||||
|
||||
if (offset_into_cluster(s, refblock_offset)) {
|
||||
qcow2_signal_corruption(bs, true, -1, -1, "Refblock offset %#"
|
||||
PRIx64 " unaligned (reftable index: %#"
|
||||
PRIx64 ")", refblock_offset,
|
||||
reftable_index);
|
||||
error_setg(errp,
|
||||
"Image is corrupt (unaligned refblock offset)");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = qcow2_cache_get(bs, s->refcount_block_cache, refblock_offset,
|
||||
&refblock);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to retrieve refblock");
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (refblock_index = 0; refblock_index < s->refcount_block_size;
|
||||
refblock_index++)
|
||||
{
|
||||
uint64_t refcount;
|
||||
|
||||
if (new_refblock_index >= new_refblock_size) {
|
||||
/* new_refblock is now complete */
|
||||
ret = operation(bs, new_reftable, *new_reftable_index,
|
||||
new_reftable_size, new_refblock,
|
||||
new_refblock_empty, allocated, errp);
|
||||
if (ret < 0) {
|
||||
qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
(*new_reftable_index)++;
|
||||
new_refblock_index = 0;
|
||||
new_refblock_empty = true;
|
||||
}
|
||||
|
||||
refcount = s->get_refcount(refblock, refblock_index);
|
||||
if (new_refcount_bits < 64 && refcount >> new_refcount_bits) {
|
||||
uint64_t offset;
|
||||
|
||||
qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
|
||||
|
||||
offset = ((reftable_index << s->refcount_block_bits)
|
||||
+ refblock_index) << s->cluster_bits;
|
||||
|
||||
error_setg(errp, "Cannot decrease refcount entry width to "
|
||||
"%i bits: Cluster at offset %#" PRIx64 " has a "
|
||||
"refcount of %" PRIu64, new_refcount_bits,
|
||||
offset, refcount);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (new_set_refcount) {
|
||||
new_set_refcount(new_refblock, new_refblock_index++,
|
||||
refcount);
|
||||
} else {
|
||||
new_refblock_index++;
|
||||
}
|
||||
new_refblock_empty = new_refblock_empty && refcount == 0;
|
||||
}
|
||||
|
||||
qcow2_cache_put(bs, s->refcount_block_cache, &refblock);
|
||||
} else {
|
||||
/* No refblock means every refcount is 0 */
|
||||
for (refblock_index = 0; refblock_index < s->refcount_block_size;
|
||||
refblock_index++)
|
||||
{
|
||||
if (new_refblock_index >= new_refblock_size) {
|
||||
/* new_refblock is now complete */
|
||||
ret = operation(bs, new_reftable, *new_reftable_index,
|
||||
new_reftable_size, new_refblock,
|
||||
new_refblock_empty, allocated, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
(*new_reftable_index)++;
|
||||
new_refblock_index = 0;
|
||||
new_refblock_empty = true;
|
||||
}
|
||||
|
||||
if (new_set_refcount) {
|
||||
new_set_refcount(new_refblock, new_refblock_index++, 0);
|
||||
} else {
|
||||
new_refblock_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_refblock_index > 0) {
|
||||
/* Complete the potentially existing partially filled final refblock */
|
||||
if (new_set_refcount) {
|
||||
for (; new_refblock_index < new_refblock_size;
|
||||
new_refblock_index++)
|
||||
{
|
||||
new_set_refcount(new_refblock, new_refblock_index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
ret = operation(bs, new_reftable, *new_reftable_index,
|
||||
new_reftable_size, new_refblock, new_refblock_empty,
|
||||
allocated, errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
(*new_reftable_index)++;
|
||||
}
|
||||
|
||||
status_cb(bs, (uint64_t)(index + 1) * s->refcount_table_size,
|
||||
(uint64_t)total * s->refcount_table_size, cb_opaque);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque, Error **errp)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
Qcow2GetRefcountFunc *new_get_refcount;
|
||||
Qcow2SetRefcountFunc *new_set_refcount;
|
||||
void *new_refblock = qemu_blockalign(bs->file->bs, s->cluster_size);
|
||||
uint64_t *new_reftable = NULL, new_reftable_size = 0;
|
||||
uint64_t *old_reftable, old_reftable_size, old_reftable_offset;
|
||||
uint64_t new_reftable_index = 0;
|
||||
uint64_t i;
|
||||
int64_t new_reftable_offset = 0, allocated_reftable_size = 0;
|
||||
int new_refblock_size, new_refcount_bits = 1 << refcount_order;
|
||||
int old_refcount_order;
|
||||
int walk_index = 0;
|
||||
int ret;
|
||||
bool new_allocation;
|
||||
|
||||
assert(s->qcow_version >= 3);
|
||||
assert(refcount_order >= 0 && refcount_order <= 6);
|
||||
|
||||
/* see qcow2_open() */
|
||||
new_refblock_size = 1 << (s->cluster_bits - (refcount_order - 3));
|
||||
|
||||
new_get_refcount = get_refcount_funcs[refcount_order];
|
||||
new_set_refcount = set_refcount_funcs[refcount_order];
|
||||
|
||||
|
||||
do {
|
||||
int total_walks;
|
||||
|
||||
new_allocation = false;
|
||||
|
||||
/* At least we have to do this walk and the one which writes the
|
||||
* refblocks; also, at least we have to do this loop here at least
|
||||
* twice (normally), first to do the allocations, and second to
|
||||
* determine that everything is correctly allocated, this then makes
|
||||
* three walks in total */
|
||||
total_walks = MAX(walk_index + 2, 3);
|
||||
|
||||
/* First, allocate the structures so they are present in the refcount
|
||||
* structures */
|
||||
ret = walk_over_reftable(bs, &new_reftable, &new_reftable_index,
|
||||
&new_reftable_size, NULL, new_refblock_size,
|
||||
new_refcount_bits, &alloc_refblock,
|
||||
&new_allocation, NULL, status_cb, cb_opaque,
|
||||
walk_index++, total_walks, errp);
|
||||
if (ret < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
new_reftable_index = 0;
|
||||
|
||||
if (new_allocation) {
|
||||
if (new_reftable_offset) {
|
||||
qcow2_free_clusters(bs, new_reftable_offset,
|
||||
allocated_reftable_size * sizeof(uint64_t),
|
||||
QCOW2_DISCARD_NEVER);
|
||||
}
|
||||
|
||||
new_reftable_offset = qcow2_alloc_clusters(bs, new_reftable_size *
|
||||
sizeof(uint64_t));
|
||||
if (new_reftable_offset < 0) {
|
||||
error_setg_errno(errp, -new_reftable_offset,
|
||||
"Failed to allocate the new reftable");
|
||||
ret = new_reftable_offset;
|
||||
goto done;
|
||||
}
|
||||
allocated_reftable_size = new_reftable_size;
|
||||
}
|
||||
} while (new_allocation);
|
||||
|
||||
/* Second, write the new refblocks */
|
||||
ret = walk_over_reftable(bs, &new_reftable, &new_reftable_index,
|
||||
&new_reftable_size, new_refblock,
|
||||
new_refblock_size, new_refcount_bits,
|
||||
&flush_refblock, &new_allocation, new_set_refcount,
|
||||
status_cb, cb_opaque, walk_index, walk_index + 1,
|
||||
errp);
|
||||
if (ret < 0) {
|
||||
goto done;
|
||||
}
|
||||
assert(!new_allocation);
|
||||
|
||||
|
||||
/* Write the new reftable */
|
||||
ret = qcow2_pre_write_overlap_check(bs, 0, new_reftable_offset,
|
||||
new_reftable_size * sizeof(uint64_t));
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Overlap check failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0; i < new_reftable_size; i++) {
|
||||
cpu_to_be64s(&new_reftable[i]);
|
||||
}
|
||||
|
||||
ret = bdrv_pwrite(bs->file->bs, new_reftable_offset, new_reftable,
|
||||
new_reftable_size * sizeof(uint64_t));
|
||||
|
||||
for (i = 0; i < new_reftable_size; i++) {
|
||||
be64_to_cpus(&new_reftable[i]);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to write the new reftable");
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
/* Empty the refcount cache */
|
||||
ret = qcow2_cache_flush(bs, s->refcount_block_cache);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Failed to flush the refblock cache");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Update the image header to point to the new reftable; this only updates
|
||||
* the fields which are relevant to qcow2_update_header(); other fields
|
||||
* such as s->refcount_table or s->refcount_bits stay stale for now
|
||||
* (because we have to restore everything if qcow2_update_header() fails) */
|
||||
old_refcount_order = s->refcount_order;
|
||||
old_reftable_size = s->refcount_table_size;
|
||||
old_reftable_offset = s->refcount_table_offset;
|
||||
|
||||
s->refcount_order = refcount_order;
|
||||
s->refcount_table_size = new_reftable_size;
|
||||
s->refcount_table_offset = new_reftable_offset;
|
||||
|
||||
ret = qcow2_update_header(bs);
|
||||
if (ret < 0) {
|
||||
s->refcount_order = old_refcount_order;
|
||||
s->refcount_table_size = old_reftable_size;
|
||||
s->refcount_table_offset = old_reftable_offset;
|
||||
error_setg_errno(errp, -ret, "Failed to update the qcow2 header");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Now update the rest of the in-memory information */
|
||||
old_reftable = s->refcount_table;
|
||||
s->refcount_table = new_reftable;
|
||||
|
||||
s->refcount_bits = 1 << refcount_order;
|
||||
s->refcount_max = UINT64_C(1) << (s->refcount_bits - 1);
|
||||
s->refcount_max += s->refcount_max - 1;
|
||||
|
||||
s->refcount_block_bits = s->cluster_bits - (refcount_order - 3);
|
||||
s->refcount_block_size = 1 << s->refcount_block_bits;
|
||||
|
||||
s->get_refcount = new_get_refcount;
|
||||
s->set_refcount = new_set_refcount;
|
||||
|
||||
/* For cleaning up all old refblocks and the old reftable below the "done"
|
||||
* label */
|
||||
new_reftable = old_reftable;
|
||||
new_reftable_size = old_reftable_size;
|
||||
new_reftable_offset = old_reftable_offset;
|
||||
|
||||
done:
|
||||
if (new_reftable) {
|
||||
/* On success, new_reftable actually points to the old reftable (and
|
||||
* new_reftable_size is the old reftable's size); but that is just
|
||||
* fine */
|
||||
for (i = 0; i < new_reftable_size; i++) {
|
||||
uint64_t offset = new_reftable[i] & REFT_OFFSET_MASK;
|
||||
if (offset) {
|
||||
qcow2_free_clusters(bs, offset, s->cluster_size,
|
||||
QCOW2_DISCARD_OTHER);
|
||||
}
|
||||
}
|
||||
g_free(new_reftable);
|
||||
|
||||
if (new_reftable_offset > 0) {
|
||||
qcow2_free_clusters(bs, new_reftable_offset,
|
||||
new_reftable_size * sizeof(uint64_t),
|
||||
QCOW2_DISCARD_OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
qemu_vfree(new_refblock);
|
||||
return ret;
|
||||
}
|
||||
|
@@ -22,7 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/qcow2.h"
|
||||
|
347
block/qcow2.c
347
block/qcow2.c
@@ -21,7 +21,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
@@ -1141,7 +1140,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
/* Clear unknown autoclear feature bits */
|
||||
if (!bs->read_only && !(flags & BDRV_O_INACTIVE) && s->autoclear_features) {
|
||||
if (!bs->read_only && !(flags & BDRV_O_INCOMING) && s->autoclear_features) {
|
||||
s->autoclear_features = 0;
|
||||
ret = qcow2_update_header(bs);
|
||||
if (ret < 0) {
|
||||
@@ -1154,7 +1153,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
|
||||
/* Repair image if dirty */
|
||||
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
|
||||
if (!(flags & (BDRV_O_CHECK | BDRV_O_INCOMING)) && !bs->read_only &&
|
||||
(s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) {
|
||||
BdrvCheckResult result = {0};
|
||||
|
||||
@@ -1283,52 +1282,6 @@ static void qcow2_reopen_abort(BDRVReopenState *state)
|
||||
g_free(state->opaque);
|
||||
}
|
||||
|
||||
static void qcow2_join_options(QDict *options, QDict *old_options)
|
||||
{
|
||||
bool has_new_overlap_template =
|
||||
qdict_haskey(options, QCOW2_OPT_OVERLAP) ||
|
||||
qdict_haskey(options, QCOW2_OPT_OVERLAP_TEMPLATE);
|
||||
bool has_new_total_cache_size =
|
||||
qdict_haskey(options, QCOW2_OPT_CACHE_SIZE);
|
||||
bool has_all_cache_options;
|
||||
|
||||
/* New overlap template overrides all old overlap options */
|
||||
if (has_new_overlap_template) {
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP);
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP_TEMPLATE);
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP_MAIN_HEADER);
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP_ACTIVE_L1);
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP_ACTIVE_L2);
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP_REFCOUNT_TABLE);
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK);
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE);
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP_INACTIVE_L1);
|
||||
qdict_del(old_options, QCOW2_OPT_OVERLAP_INACTIVE_L2);
|
||||
}
|
||||
|
||||
/* New total cache size overrides all old options */
|
||||
if (qdict_haskey(options, QCOW2_OPT_CACHE_SIZE)) {
|
||||
qdict_del(old_options, QCOW2_OPT_L2_CACHE_SIZE);
|
||||
qdict_del(old_options, QCOW2_OPT_REFCOUNT_CACHE_SIZE);
|
||||
}
|
||||
|
||||
qdict_join(options, old_options, false);
|
||||
|
||||
/*
|
||||
* If after merging all cache size options are set, an old total size is
|
||||
* overwritten. Do keep all options, however, if all three are new. The
|
||||
* resulting error message is what we want to happen.
|
||||
*/
|
||||
has_all_cache_options =
|
||||
qdict_haskey(options, QCOW2_OPT_CACHE_SIZE) ||
|
||||
qdict_haskey(options, QCOW2_OPT_L2_CACHE_SIZE) ||
|
||||
qdict_haskey(options, QCOW2_OPT_REFCOUNT_CACHE_SIZE);
|
||||
|
||||
if (has_all_cache_options && !has_new_total_cache_size) {
|
||||
qdict_del(options, QCOW2_OPT_CACHE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors, int *pnum)
|
||||
{
|
||||
@@ -1686,32 +1639,6 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcow2_inactivate(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int ret, result = 0;
|
||||
|
||||
ret = qcow2_cache_flush(bs, s->l2_table_cache);
|
||||
if (ret) {
|
||||
result = ret;
|
||||
error_report("Failed to flush the L2 table cache: %s",
|
||||
strerror(-ret));
|
||||
}
|
||||
|
||||
ret = qcow2_cache_flush(bs, s->refcount_block_cache);
|
||||
if (ret) {
|
||||
result = ret;
|
||||
error_report("Failed to flush the refcount block cache: %s",
|
||||
strerror(-ret));
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
qcow2_mark_clean(bs);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void qcow2_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
@@ -1719,8 +1646,24 @@ static void qcow2_close(BlockDriverState *bs)
|
||||
/* else pre-write overlap checks in cache_destroy may crash */
|
||||
s->l1_table = NULL;
|
||||
|
||||
if (!(s->flags & BDRV_O_INACTIVE)) {
|
||||
qcow2_inactivate(bs);
|
||||
if (!(bs->open_flags & BDRV_O_INCOMING)) {
|
||||
int ret1, ret2;
|
||||
|
||||
ret1 = qcow2_cache_flush(bs, s->l2_table_cache);
|
||||
ret2 = qcow2_cache_flush(bs, s->refcount_block_cache);
|
||||
|
||||
if (ret1) {
|
||||
error_report("Failed to flush the L2 table cache: %s",
|
||||
strerror(-ret1));
|
||||
}
|
||||
if (ret2) {
|
||||
error_report("Failed to flush the refcount block cache: %s",
|
||||
strerror(-ret2));
|
||||
}
|
||||
|
||||
if (!ret1 && !ret2) {
|
||||
qcow2_mark_clean(bs);
|
||||
}
|
||||
}
|
||||
|
||||
cache_clean_timer_del(bs);
|
||||
@@ -1764,24 +1707,21 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||
bdrv_invalidate_cache(bs->file->bs, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
bs->drv = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(s, 0, sizeof(BDRVQcow2State));
|
||||
options = qdict_clone_shallow(bs->options);
|
||||
|
||||
flags &= ~BDRV_O_INACTIVE;
|
||||
ret = qcow2_open(bs, options, flags, &local_err);
|
||||
QDECREF(options);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
error_prepend(errp, "Could not reopen qcow2 layer: ");
|
||||
bs->drv = NULL;
|
||||
error_setg(errp, "Could not reopen qcow2 layer: %s",
|
||||
error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
return;
|
||||
} else if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not reopen qcow2 layer");
|
||||
bs->drv = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1909,33 +1849,31 @@ int qcow2_update_header(BlockDriverState *bs)
|
||||
}
|
||||
|
||||
/* Feature table */
|
||||
if (s->qcow_version >= 3) {
|
||||
Qcow2Feature features[] = {
|
||||
{
|
||||
.type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
|
||||
.bit = QCOW2_INCOMPAT_DIRTY_BITNR,
|
||||
.name = "dirty bit",
|
||||
},
|
||||
{
|
||||
.type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
|
||||
.bit = QCOW2_INCOMPAT_CORRUPT_BITNR,
|
||||
.name = "corrupt bit",
|
||||
},
|
||||
{
|
||||
.type = QCOW2_FEAT_TYPE_COMPATIBLE,
|
||||
.bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
|
||||
.name = "lazy refcounts",
|
||||
},
|
||||
};
|
||||
Qcow2Feature features[] = {
|
||||
{
|
||||
.type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
|
||||
.bit = QCOW2_INCOMPAT_DIRTY_BITNR,
|
||||
.name = "dirty bit",
|
||||
},
|
||||
{
|
||||
.type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
|
||||
.bit = QCOW2_INCOMPAT_CORRUPT_BITNR,
|
||||
.name = "corrupt bit",
|
||||
},
|
||||
{
|
||||
.type = QCOW2_FEAT_TYPE_COMPATIBLE,
|
||||
.bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
|
||||
.name = "lazy refcounts",
|
||||
},
|
||||
};
|
||||
|
||||
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE,
|
||||
features, sizeof(features), buflen);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
buf += ret;
|
||||
buflen -= ret;
|
||||
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE,
|
||||
features, sizeof(features), buflen);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
buf += ret;
|
||||
buflen -= ret;
|
||||
|
||||
/* Keep unknown header extensions */
|
||||
QLIST_FOREACH(uext, &s->unknown_header_ext, next) {
|
||||
@@ -2253,13 +2191,6 @@ static int qcow2_create2(const char *filename, int64_t total_size,
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Create a full header (including things like feature table) */
|
||||
ret = qcow2_update_header(bs);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not update qcow2 header");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Okay, now that we have a valid image, let's give it the right size */
|
||||
ret = bdrv_truncate(bs, total_size);
|
||||
if (ret < 0) {
|
||||
@@ -2338,7 +2269,7 @@ static int qcow2_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
DEFAULT_CLUSTER_SIZE);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
|
||||
PREALLOC_MODE_MAX, PREALLOC_MODE_OFF,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
@@ -2826,10 +2757,6 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
|
||||
.has_corrupt = true,
|
||||
.refcount_bits = s->refcount_bits,
|
||||
};
|
||||
} else {
|
||||
/* if this assertion fails, this probably means a new version was
|
||||
* added without having it covered here */
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return spec_info;
|
||||
@@ -2897,7 +2824,7 @@ static int qcow2_load_vmstate(BlockDriverState *bs, uint8_t *buf,
|
||||
* have to be removed.
|
||||
*/
|
||||
static int qcow2_downgrade(BlockDriverState *bs, int target_version,
|
||||
BlockDriverAmendStatusCB *status_cb, void *cb_opaque)
|
||||
BlockDriverAmendStatusCB *status_cb)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int current_version = s->qcow_version;
|
||||
@@ -2912,7 +2839,13 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
|
||||
}
|
||||
|
||||
if (s->refcount_order != 4) {
|
||||
error_report("compat=0.10 requires refcount_bits=16");
|
||||
/* we would have to convert the image to a refcount_order == 4 image
|
||||
* here; however, since qemu (at the time of writing this) does not
|
||||
* support anything different than 4 anyway, there is no point in doing
|
||||
* so right now; however, we should error out (if qemu supports this in
|
||||
* the future and this code has not been adapted) */
|
||||
error_report("qcow2_downgrade: Image refcount orders other than 4 are "
|
||||
"currently not supported.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
@@ -2940,7 +2873,7 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
|
||||
/* clearing autoclear features is trivial */
|
||||
s->autoclear_features = 0;
|
||||
|
||||
ret = qcow2_expand_zero_clusters(bs, status_cb, cb_opaque);
|
||||
ret = qcow2_expand_zero_clusters(bs, status_cb);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@@ -2954,79 +2887,8 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version,
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef enum Qcow2AmendOperation {
|
||||
/* This is the value Qcow2AmendHelperCBInfo::last_operation will be
|
||||
* statically initialized to so that the helper CB can discern the first
|
||||
* invocation from an operation change */
|
||||
QCOW2_NO_OPERATION = 0,
|
||||
|
||||
QCOW2_CHANGING_REFCOUNT_ORDER,
|
||||
QCOW2_DOWNGRADING,
|
||||
} Qcow2AmendOperation;
|
||||
|
||||
typedef struct Qcow2AmendHelperCBInfo {
|
||||
/* The code coordinating the amend operations should only modify
|
||||
* these four fields; the rest will be managed by the CB */
|
||||
BlockDriverAmendStatusCB *original_status_cb;
|
||||
void *original_cb_opaque;
|
||||
|
||||
Qcow2AmendOperation current_operation;
|
||||
|
||||
/* Total number of operations to perform (only set once) */
|
||||
int total_operations;
|
||||
|
||||
/* The following fields are managed by the CB */
|
||||
|
||||
/* Number of operations completed */
|
||||
int operations_completed;
|
||||
|
||||
/* Cumulative offset of all completed operations */
|
||||
int64_t offset_completed;
|
||||
|
||||
Qcow2AmendOperation last_operation;
|
||||
int64_t last_work_size;
|
||||
} Qcow2AmendHelperCBInfo;
|
||||
|
||||
static void qcow2_amend_helper_cb(BlockDriverState *bs,
|
||||
int64_t operation_offset,
|
||||
int64_t operation_work_size, void *opaque)
|
||||
{
|
||||
Qcow2AmendHelperCBInfo *info = opaque;
|
||||
int64_t current_work_size;
|
||||
int64_t projected_work_size;
|
||||
|
||||
if (info->current_operation != info->last_operation) {
|
||||
if (info->last_operation != QCOW2_NO_OPERATION) {
|
||||
info->offset_completed += info->last_work_size;
|
||||
info->operations_completed++;
|
||||
}
|
||||
|
||||
info->last_operation = info->current_operation;
|
||||
}
|
||||
|
||||
assert(info->total_operations > 0);
|
||||
assert(info->operations_completed < info->total_operations);
|
||||
|
||||
info->last_work_size = operation_work_size;
|
||||
|
||||
current_work_size = info->offset_completed + operation_work_size;
|
||||
|
||||
/* current_work_size is the total work size for (operations_completed + 1)
|
||||
* operations (which includes this one), so multiply it by the number of
|
||||
* operations not covered and divide it by the number of operations
|
||||
* covered to get a projection for the operations not covered */
|
||||
projected_work_size = current_work_size * (info->total_operations -
|
||||
info->operations_completed - 1)
|
||||
/ (info->operations_completed + 1);
|
||||
|
||||
info->original_status_cb(bs, info->offset_completed + operation_offset,
|
||||
current_work_size + projected_work_size,
|
||||
info->original_cb_opaque);
|
||||
}
|
||||
|
||||
static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque)
|
||||
BlockDriverAmendStatusCB *status_cb)
|
||||
{
|
||||
BDRVQcow2State *s = bs->opaque;
|
||||
int old_version = s->qcow_version, new_version = old_version;
|
||||
@@ -3036,10 +2898,8 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
const char *compat = NULL;
|
||||
uint64_t cluster_size = s->cluster_size;
|
||||
bool encrypt;
|
||||
int refcount_bits = s->refcount_bits;
|
||||
int ret;
|
||||
QemuOptDesc *desc = opts->list->desc;
|
||||
Qcow2AmendHelperCBInfo helper_cb_info;
|
||||
|
||||
while (desc && desc->name) {
|
||||
if (!qemu_opt_find(opts, desc->name)) {
|
||||
@@ -3057,11 +2917,11 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
} else if (!strcmp(compat, "1.1")) {
|
||||
new_version = 3;
|
||||
} else {
|
||||
error_report("Unknown compatibility level %s", compat);
|
||||
fprintf(stderr, "Unknown compatibility level %s.\n", compat);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (!strcmp(desc->name, BLOCK_OPT_PREALLOC)) {
|
||||
error_report("Cannot change preallocation mode");
|
||||
fprintf(stderr, "Cannot change preallocation mode.\n");
|
||||
return -ENOTSUP;
|
||||
} else if (!strcmp(desc->name, BLOCK_OPT_SIZE)) {
|
||||
new_size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0);
|
||||
@@ -3074,74 +2934,47 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
!!s->cipher);
|
||||
|
||||
if (encrypt != !!s->cipher) {
|
||||
error_report("Changing the encryption flag is not supported");
|
||||
fprintf(stderr, "Changing the encryption flag is not "
|
||||
"supported.\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
} else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) {
|
||||
cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE,
|
||||
cluster_size);
|
||||
if (cluster_size != s->cluster_size) {
|
||||
error_report("Changing the cluster size is not supported");
|
||||
fprintf(stderr, "Changing the cluster size is not "
|
||||
"supported.\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
} else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) {
|
||||
lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS,
|
||||
lazy_refcounts);
|
||||
} else if (!strcmp(desc->name, BLOCK_OPT_REFCOUNT_BITS)) {
|
||||
refcount_bits = qemu_opt_get_number(opts, BLOCK_OPT_REFCOUNT_BITS,
|
||||
refcount_bits);
|
||||
|
||||
if (refcount_bits <= 0 || refcount_bits > 64 ||
|
||||
!is_power_of_2(refcount_bits))
|
||||
{
|
||||
error_report("Refcount width must be a power of two and may "
|
||||
"not exceed 64 bits");
|
||||
return -EINVAL;
|
||||
}
|
||||
error_report("Cannot change refcount entry width");
|
||||
return -ENOTSUP;
|
||||
} else {
|
||||
/* if this point is reached, this probably means a new option was
|
||||
/* if this assertion fails, this probably means a new option was
|
||||
* added without having it covered here */
|
||||
abort();
|
||||
assert(false);
|
||||
}
|
||||
|
||||
desc++;
|
||||
}
|
||||
|
||||
helper_cb_info = (Qcow2AmendHelperCBInfo){
|
||||
.original_status_cb = status_cb,
|
||||
.original_cb_opaque = cb_opaque,
|
||||
.total_operations = (new_version < old_version)
|
||||
+ (s->refcount_bits != refcount_bits)
|
||||
};
|
||||
|
||||
/* Upgrade first (some features may require compat=1.1) */
|
||||
if (new_version > old_version) {
|
||||
s->qcow_version = new_version;
|
||||
ret = qcow2_update_header(bs);
|
||||
if (ret < 0) {
|
||||
s->qcow_version = old_version;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->refcount_bits != refcount_bits) {
|
||||
int refcount_order = ctz32(refcount_bits);
|
||||
Error *local_error = NULL;
|
||||
|
||||
if (new_version < 3 && refcount_bits != 16) {
|
||||
error_report("Different refcount widths than 16 bits require "
|
||||
"compatibility level 1.1 or above (use compat=1.1 or "
|
||||
"greater)");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
helper_cb_info.current_operation = QCOW2_CHANGING_REFCOUNT_ORDER;
|
||||
ret = qcow2_change_refcount_order(bs, refcount_order,
|
||||
&qcow2_amend_helper_cb,
|
||||
&helper_cb_info, &local_error);
|
||||
if (ret < 0) {
|
||||
error_report_err(local_error);
|
||||
return ret;
|
||||
if (new_version != old_version) {
|
||||
if (new_version > old_version) {
|
||||
/* Upgrade */
|
||||
s->qcow_version = new_version;
|
||||
ret = qcow2_update_header(bs);
|
||||
if (ret < 0) {
|
||||
s->qcow_version = old_version;
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = qcow2_downgrade(bs, new_version, status_cb);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3156,9 +2989,9 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
|
||||
if (s->use_lazy_refcounts != lazy_refcounts) {
|
||||
if (lazy_refcounts) {
|
||||
if (new_version < 3) {
|
||||
error_report("Lazy refcounts only supported with compatibility "
|
||||
"level 1.1 and above (use compat=1.1 or greater)");
|
||||
if (s->qcow_version < 3) {
|
||||
fprintf(stderr, "Lazy refcounts only supported with compatibility "
|
||||
"level 1.1 and above (use compat=1.1 or greater)\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
s->compatible_features |= QCOW2_COMPAT_LAZY_REFCOUNTS;
|
||||
@@ -3192,16 +3025,6 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||
}
|
||||
}
|
||||
|
||||
/* Downgrade last (so unsupported features can be removed before) */
|
||||
if (new_version < old_version) {
|
||||
helper_cb_info.current_operation = QCOW2_DOWNGRADING;
|
||||
ret = qcow2_downgrade(bs, new_version, &qcow2_amend_helper_cb,
|
||||
&helper_cb_info);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3322,7 +3145,6 @@ BlockDriver bdrv_qcow2 = {
|
||||
.bdrv_reopen_prepare = qcow2_reopen_prepare,
|
||||
.bdrv_reopen_commit = qcow2_reopen_commit,
|
||||
.bdrv_reopen_abort = qcow2_reopen_abort,
|
||||
.bdrv_join_options = qcow2_join_options,
|
||||
.bdrv_create = qcow2_create,
|
||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||
.bdrv_co_get_block_status = qcow2_co_get_block_status,
|
||||
@@ -3354,7 +3176,6 @@ BlockDriver bdrv_qcow2 = {
|
||||
|
||||
.bdrv_refresh_limits = qcow2_refresh_limits,
|
||||
.bdrv_invalidate_cache = qcow2_invalidate_cache,
|
||||
.bdrv_inactivate = qcow2_inactivate,
|
||||
|
||||
.create_opts = &qcow2_create_opts,
|
||||
.bdrv_check = qcow2_check,
|
||||
|
@@ -529,10 +529,6 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
|
||||
int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset,
|
||||
int64_t size);
|
||||
|
||||
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque, Error **errp);
|
||||
|
||||
/* qcow2-cluster.c functions */
|
||||
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
|
||||
bool exact_size);
|
||||
@@ -557,8 +553,7 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
|
||||
int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors);
|
||||
|
||||
int qcow2_expand_zero_clusters(BlockDriverState *bs,
|
||||
BlockDriverAmendStatusCB *status_cb,
|
||||
void *cb_opaque);
|
||||
BlockDriverAmendStatusCB *status_cb);
|
||||
|
||||
/* qcow2-snapshot.c functions */
|
||||
int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
|
||||
|
@@ -11,7 +11,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qed.h"
|
||||
|
||||
typedef struct {
|
||||
|
@@ -12,7 +12,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qed.h"
|
||||
|
||||
/**
|
||||
|
@@ -11,7 +11,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qed.h"
|
||||
|
||||
void *gencb_alloc(size_t len, BlockCompletionFunc *cb, void *opaque)
|
||||
|
@@ -50,7 +50,6 @@
|
||||
* table will be deleted in favor of the existing cache entry.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "trace.h"
|
||||
#include "qed.h"
|
||||
|
||||
|
@@ -12,7 +12,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "trace.h"
|
||||
#include "qemu/sockets.h" /* for EINPROGRESS on Windows */
|
||||
#include "qed.h"
|
||||
|
10
block/qed.c
10
block/qed.c
@@ -12,7 +12,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "trace.h"
|
||||
#include "qed.h"
|
||||
@@ -478,7 +477,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
* feature is no longer valid.
|
||||
*/
|
||||
if ((s->header.autoclear_features & ~QED_AUTOCLEAR_FEATURE_MASK) != 0 &&
|
||||
!bdrv_is_read_only(bs->file->bs) && !(flags & BDRV_O_INACTIVE)) {
|
||||
!bdrv_is_read_only(bs->file->bs) && !(flags & BDRV_O_INCOMING)) {
|
||||
s->header.autoclear_features &= QED_AUTOCLEAR_FEATURE_MASK;
|
||||
|
||||
ret = qed_write_header_sync(s);
|
||||
@@ -506,7 +505,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
* aid data recovery from an otherwise inconsistent image.
|
||||
*/
|
||||
if (!bdrv_is_read_only(bs->file->bs) &&
|
||||
!(flags & BDRV_O_INACTIVE)) {
|
||||
!(flags & BDRV_O_INCOMING)) {
|
||||
BdrvCheckResult result = {0};
|
||||
|
||||
ret = qed_check(s, &result, true);
|
||||
@@ -1612,8 +1611,9 @@ static void bdrv_qed_invalidate_cache(BlockDriverState *bs, Error **errp)
|
||||
memset(s, 0, sizeof(BDRVQEDState));
|
||||
ret = bdrv_qed_open(bs, NULL, bs->open_flags, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
error_prepend(errp, "Could not reopen qed layer: ");
|
||||
error_setg(errp, "Could not reopen qed layer: %s",
|
||||
error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
return;
|
||||
} else if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "Could not reopen qed layer");
|
||||
|
@@ -13,7 +13,6 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
@@ -647,8 +646,9 @@ static BlockAIOCB *read_quorum_children(QuorumAIOCB *acb)
|
||||
}
|
||||
|
||||
for (i = 0; i < s->num_children; i++) {
|
||||
bdrv_aio_readv(s->children[i]->bs, acb->sector_num, &acb->qcrs[i].qiov,
|
||||
acb->nb_sectors, quorum_aio_cb, &acb->qcrs[i]);
|
||||
acb->qcrs[i].aiocb = bdrv_aio_readv(s->children[i]->bs, acb->sector_num,
|
||||
&acb->qcrs[i].qiov, acb->nb_sectors,
|
||||
quorum_aio_cb, &acb->qcrs[i]);
|
||||
}
|
||||
|
||||
return &acb->common;
|
||||
@@ -663,9 +663,10 @@ static BlockAIOCB *read_fifo_child(QuorumAIOCB *acb)
|
||||
qemu_iovec_init(&acb->qcrs[acb->child_iter].qiov, acb->qiov->niov);
|
||||
qemu_iovec_clone(&acb->qcrs[acb->child_iter].qiov, acb->qiov,
|
||||
acb->qcrs[acb->child_iter].buf);
|
||||
bdrv_aio_readv(s->children[acb->child_iter]->bs, acb->sector_num,
|
||||
&acb->qcrs[acb->child_iter].qiov, acb->nb_sectors,
|
||||
quorum_aio_cb, &acb->qcrs[acb->child_iter]);
|
||||
acb->qcrs[acb->child_iter].aiocb =
|
||||
bdrv_aio_readv(s->children[acb->child_iter]->bs, acb->sector_num,
|
||||
&acb->qcrs[acb->child_iter].qiov, acb->nb_sectors,
|
||||
quorum_aio_cb, &acb->qcrs[acb->child_iter]);
|
||||
|
||||
return &acb->common;
|
||||
}
|
||||
@@ -848,7 +849,7 @@ static int parse_read_pattern(const char *opt)
|
||||
return QUORUM_READ_PATTERN_QUORUM;
|
||||
}
|
||||
|
||||
for (i = 0; i < QUORUM_READ_PATTERN__MAX; i++) {
|
||||
for (i = 0; i < QUORUM_READ_PATTERN_MAX; i++) {
|
||||
if (!strcmp(opt, QuorumReadPattern_lookup[i])) {
|
||||
return i;
|
||||
}
|
||||
@@ -998,7 +999,7 @@ static void quorum_attach_aio_context(BlockDriverState *bs,
|
||||
}
|
||||
}
|
||||
|
||||
static void quorum_refresh_filename(BlockDriverState *bs, QDict *options)
|
||||
static void quorum_refresh_filename(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQuorumState *s = bs->opaque;
|
||||
QDict *opts;
|
||||
|
@@ -21,7 +21,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/timer.h"
|
||||
@@ -52,6 +51,8 @@
|
||||
#include <sys/dkio.h>
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <linux/cdrom.h>
|
||||
@@ -499,17 +500,21 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
||||
goto fail;
|
||||
}
|
||||
if (!s->use_aio && (bdrv_flags & BDRV_O_NATIVE_AIO)) {
|
||||
error_setg(errp, "aio=native was specified, but it requires "
|
||||
"cache.direct=on, which was not specified.");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
error_printf("WARNING: aio=native was specified for '%s', but "
|
||||
"it requires cache.direct=on, which was not "
|
||||
"specified. Falling back to aio=threads.\n"
|
||||
" This will become an error condition in "
|
||||
"future QEMU versions.\n",
|
||||
bs->filename);
|
||||
}
|
||||
#else
|
||||
if (bdrv_flags & BDRV_O_NATIVE_AIO) {
|
||||
error_setg(errp, "aio=native was specified, but is not supported "
|
||||
"in this build.");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
error_printf("WARNING: aio=native was specified for '%s', but "
|
||||
"is not supported in this build. Falling back to "
|
||||
"aio=threads.\n"
|
||||
" This will become an error condition in "
|
||||
"future QEMU versions.\n",
|
||||
bs->filename);
|
||||
}
|
||||
#endif /* !defined(CONFIG_LINUX_AIO) */
|
||||
|
||||
@@ -1624,7 +1629,7 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
|
||||
nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false);
|
||||
buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
|
||||
prealloc = qapi_enum_parse(PreallocMode_lookup, buf,
|
||||
PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
|
||||
PREALLOC_MODE_MAX, PREALLOC_MODE_OFF,
|
||||
&local_err);
|
||||
g_free(buf);
|
||||
if (local_err) {
|
||||
|
@@ -21,7 +21,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "block/block_int.h"
|
||||
|
@@ -26,7 +26,6 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/option.h"
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
@@ -12,7 +12,6 @@
|
||||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/uri.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -1862,7 +1861,8 @@ static int sd_create(const char *filename, QemuOpts *opts,
|
||||
|
||||
fd = connect_to_sdog(s, &local_err);
|
||||
if (fd < 0) {
|
||||
error_report_err(local_err);
|
||||
error_report("%s", error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
@@ -2406,8 +2406,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
|
||||
ret = do_sd_create(s, &new_vid, 1, &local_err);
|
||||
if (ret < 0) {
|
||||
error_reportf_err(local_err,
|
||||
"failed to create inode for snapshot: ");
|
||||
error_report("failed to create inode for snapshot: %s",
|
||||
error_get_pretty(local_err));
|
||||
error_free(local_err);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@@ -22,7 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/snapshot.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
@@ -230,8 +229,6 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int ret;
|
||||
|
||||
if (!drv) {
|
||||
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
|
||||
return -ENOMEDIUM;
|
||||
@@ -242,21 +239,18 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
/* drain all pending i/o before deleting snapshot */
|
||||
bdrv_drained_begin(bs);
|
||||
bdrv_drain(bs);
|
||||
|
||||
if (drv->bdrv_snapshot_delete) {
|
||||
ret = drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
|
||||
} else if (bs->file) {
|
||||
ret = bdrv_snapshot_delete(bs->file->bs, snapshot_id, name, errp);
|
||||
} else {
|
||||
error_setg(errp, "Block format '%s' used by device '%s' "
|
||||
"does not support internal snapshot deletion",
|
||||
drv->format_name, bdrv_get_device_name(bs));
|
||||
ret = -ENOTSUP;
|
||||
return drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
|
||||
}
|
||||
|
||||
bdrv_drained_end(bs);
|
||||
return ret;
|
||||
if (bs->file) {
|
||||
return bdrv_snapshot_delete(bs->file->bs, snapshot_id, name, errp);
|
||||
}
|
||||
error_setg(errp, "Block format '%s' used by device '%s' "
|
||||
"does not support internal snapshot deletion",
|
||||
drv->format_name, bdrv_get_device_name(bs));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
||||
|
@@ -22,7 +22,9 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <libssh2.h>
|
||||
#include <libssh2_sftp.h>
|
||||
|
@@ -11,7 +11,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "trace.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/blockjob.h"
|
||||
|
@@ -22,7 +22,6 @@
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/throttle-groups.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/thread.h"
|
||||
|
@@ -49,7 +49,6 @@
|
||||
* so this seems to be reasonable.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
|
@@ -15,7 +15,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/vhdx.h"
|
||||
|
@@ -17,7 +17,6 @@
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -785,13 +784,12 @@ int vhdx_parse_log(BlockDriverState *bs, BDRVVHDXState *s, bool *flushed,
|
||||
if (logs.valid) {
|
||||
if (bs->read_only) {
|
||||
ret = -EPERM;
|
||||
error_setg(errp,
|
||||
"VHDX image file '%s' opened read-only, but "
|
||||
"contains a log that needs to be replayed",
|
||||
bs->filename);
|
||||
error_append_hint(errp, "To replay the log, run:\n"
|
||||
"qemu-img check -r all '%s'\n",
|
||||
bs->filename);
|
||||
error_setg_errno(errp, EPERM,
|
||||
"VHDX image file '%s' opened read-only, but "
|
||||
"contains a log that needs to be replayed. To "
|
||||
"replay the log, execute:\n qemu-img check -r "
|
||||
"all '%s'",
|
||||
bs->filename, bs->filename);
|
||||
goto exit;
|
||||
}
|
||||
/* now flush the log */
|
||||
|
@@ -15,7 +15,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
|
57
block/vmdk.c
57
block/vmdk.c
@@ -23,7 +23,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
@@ -571,6 +570,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||
VmdkExtent *extent;
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
int64_t l1_backup_offset = 0;
|
||||
bool compressed;
|
||||
|
||||
ret = bdrv_pread(file->bs, sizeof(magic), &header, sizeof(header));
|
||||
if (ret < 0) {
|
||||
@@ -645,6 +645,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||
header = footer.header;
|
||||
}
|
||||
|
||||
compressed =
|
||||
le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
|
||||
if (le32_to_cpu(header.version) > 3) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "VMDK version %" PRId32,
|
||||
@@ -652,7 +654,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||
error_setg(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
|
||||
bdrv_get_device_or_node_name(bs), "vmdk", buf);
|
||||
return -ENOTSUP;
|
||||
} else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR)) {
|
||||
} else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR) &&
|
||||
!compressed) {
|
||||
/* VMware KB 2064959 explains that version 3 added support for
|
||||
* persistent changed block tracking (CBT), and backup software can
|
||||
* read it as version=1 if it doesn't care about the changed area
|
||||
@@ -761,17 +764,6 @@ static int vmdk_open_sparse(BlockDriverState *bs, BdrvChild *file, int flags,
|
||||
}
|
||||
}
|
||||
|
||||
static const char *next_line(const char *s)
|
||||
{
|
||||
while (*s) {
|
||||
if (*s == '\n') {
|
||||
return s + 1;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
||||
const char *desc_file_path, QDict *options,
|
||||
Error **errp)
|
||||
@@ -781,7 +773,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
||||
char access[11];
|
||||
char type[11];
|
||||
char fname[512];
|
||||
const char *p, *np;
|
||||
const char *p = desc;
|
||||
int64_t sectors = 0;
|
||||
int64_t flat_offset;
|
||||
char *extent_path;
|
||||
@@ -791,7 +783,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
||||
char extent_opt_prefix[32];
|
||||
Error *local_err = NULL;
|
||||
|
||||
for (p = desc; *p; p = next_line(p)) {
|
||||
while (*p) {
|
||||
/* parse extent line in one of below formats:
|
||||
*
|
||||
* RW [size in sectors] FLAT "file-name.vmdk" OFFSET
|
||||
@@ -803,26 +795,29 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
||||
matches = sscanf(p, "%10s %" SCNd64 " %10s \"%511[^\n\r\"]\" %" SCNd64,
|
||||
access, §ors, type, fname, &flat_offset);
|
||||
if (matches < 4 || strcmp(access, "RW")) {
|
||||
continue;
|
||||
goto next_line;
|
||||
} else if (!strcmp(type, "FLAT")) {
|
||||
if (matches != 5 || flat_offset < 0) {
|
||||
goto invalid;
|
||||
error_setg(errp, "Invalid extent lines: \n%s", p);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (!strcmp(type, "VMFS")) {
|
||||
if (matches == 4) {
|
||||
flat_offset = 0;
|
||||
} else {
|
||||
goto invalid;
|
||||
error_setg(errp, "Invalid extent lines:\n%s", p);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (matches != 4) {
|
||||
goto invalid;
|
||||
error_setg(errp, "Invalid extent lines:\n%s", p);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sectors <= 0 ||
|
||||
(strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&
|
||||
strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) ||
|
||||
(strcmp(access, "RW"))) {
|
||||
continue;
|
||||
goto next_line;
|
||||
}
|
||||
|
||||
if (!path_is_absolute(fname) && !path_has_protocol(fname) &&
|
||||
@@ -879,17 +874,17 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
||||
return -ENOTSUP;
|
||||
}
|
||||
extent->type = g_strdup(type);
|
||||
next_line:
|
||||
/* move to next line */
|
||||
while (*p) {
|
||||
if (*p == '\n') {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
invalid:
|
||||
np = next_line(p);
|
||||
assert(np != p);
|
||||
if (np[-1] == '\n') {
|
||||
np--;
|
||||
}
|
||||
error_setg(errp, "Invalid extent line: %.*s", (int)(np - p), p);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
|
||||
@@ -1503,8 +1498,8 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
|
||||
|
||||
if (sector_num > bs->total_sectors) {
|
||||
error_report("Wrong offset: sector_num=0x%" PRIx64
|
||||
" total_sectors=0x%" PRIx64,
|
||||
sector_num, bs->total_sectors);
|
||||
" total_sectors=0x%" PRIx64 "\n",
|
||||
sector_num, bs->total_sectors);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@@ -22,7 +22,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/module.h"
|
||||
|
@@ -22,7 +22,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include "qemu-common.h"
|
||||
#include "block/block_int.h"
|
||||
|
@@ -21,7 +21,6 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "block/block_int.h"
|
||||
|
@@ -10,7 +10,6 @@
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/block_int.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "block/write-threshold.h"
|
||||
|
@@ -27,8 +27,9 @@ static void nbd_accept(void *opaque)
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
|
||||
int fd = accept(server_fd, (struct sockaddr *)&addr, &addr_len);
|
||||
if (fd >= 0) {
|
||||
nbd_client_new(NULL, fd, nbd_client_put);
|
||||
if (fd >= 0 && !nbd_client_new(NULL, fd, nbd_client_put)) {
|
||||
shutdown(fd, 2);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
287
blockdev.c
287
blockdev.c
@@ -348,8 +348,7 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
|
||||
}
|
||||
|
||||
if (!throttle_is_valid(cfg)) {
|
||||
error_setg(errp, "bps/iops/max values must be within [0, %lld]",
|
||||
THROTTLE_VALUE_MAX);
|
||||
error_setg(errp, "bps/iops/maxs values must be 0 or greater");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -388,6 +387,16 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
|
||||
}
|
||||
}
|
||||
|
||||
if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_WB, true)) {
|
||||
*bdrv_flags |= BDRV_O_CACHE_WB;
|
||||
}
|
||||
if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) {
|
||||
*bdrv_flags |= BDRV_O_NOCACHE;
|
||||
}
|
||||
if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
|
||||
*bdrv_flags |= BDRV_O_NO_FLUSH;
|
||||
}
|
||||
|
||||
if ((aio = qemu_opt_get(opts, "aio")) != NULL) {
|
||||
if (!strcmp(aio, "native")) {
|
||||
*bdrv_flags |= BDRV_O_NATIVE_AIO;
|
||||
@@ -445,7 +454,7 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags,
|
||||
*detect_zeroes =
|
||||
qapi_enum_parse(BlockdevDetectZeroesOptions_lookup,
|
||||
qemu_opt_get(opts, "detect-zeroes"),
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX,
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
|
||||
&local_error);
|
||||
if (local_error) {
|
||||
@@ -481,6 +490,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
||||
QDict *interval_dict = NULL;
|
||||
QList *interval_list = NULL;
|
||||
const char *id;
|
||||
bool has_driver_specific_opts;
|
||||
BlockdevDetectZeroesOptions detect_zeroes =
|
||||
BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF;
|
||||
const char *throttling_group = NULL;
|
||||
@@ -504,6 +514,8 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
||||
qdict_del(bs_opts, "id");
|
||||
}
|
||||
|
||||
has_driver_specific_opts = !!qdict_size(bs_opts);
|
||||
|
||||
/* extract parameters */
|
||||
snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
|
||||
|
||||
@@ -560,11 +572,13 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
||||
}
|
||||
|
||||
if (snapshot) {
|
||||
bdrv_flags |= BDRV_O_SNAPSHOT;
|
||||
/* always use cache=unsafe with snapshot */
|
||||
bdrv_flags &= ~BDRV_O_CACHE_MASK;
|
||||
bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
|
||||
}
|
||||
|
||||
/* init */
|
||||
if ((!file || !*file) && !qdict_size(bs_opts)) {
|
||||
if ((!file || !*file) && !has_driver_specific_opts) {
|
||||
BlockBackendRootState *blk_rs;
|
||||
|
||||
blk = blk_new(qemu_opts_id(opts), errp);
|
||||
@@ -592,20 +606,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
/* bdrv_open() defaults to the values in bdrv_flags (for compatibility
|
||||
* with other callers) rather than what we want as the real defaults.
|
||||
* Apply the defaults here instead. */
|
||||
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_WB, "on");
|
||||
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_DIRECT, "off");
|
||||
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
|
||||
|
||||
if (snapshot) {
|
||||
/* always use cache=unsafe with snapshot */
|
||||
qdict_put(bs_opts, BDRV_OPT_CACHE_WB, qstring_from_str("on"));
|
||||
qdict_put(bs_opts, BDRV_OPT_CACHE_DIRECT, qstring_from_str("off"));
|
||||
qdict_put(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, qstring_from_str("on"));
|
||||
}
|
||||
|
||||
blk = blk_new_open(qemu_opts_id(opts), file, NULL, bs_opts, bdrv_flags,
|
||||
errp);
|
||||
if (!blk) {
|
||||
@@ -1583,11 +1583,13 @@ static void internal_snapshot_abort(BlkActionState *common)
|
||||
}
|
||||
|
||||
if (bdrv_snapshot_delete(bs, sn->id_str, sn->name, &local_error) < 0) {
|
||||
error_reportf_err(local_error,
|
||||
"Failed to delete snapshot with id '%s' and "
|
||||
"name '%s' on device '%s' in abort: ",
|
||||
sn->id_str, sn->name,
|
||||
bdrv_get_device_name(bs));
|
||||
error_report("Failed to delete snapshot with id '%s' and name '%s' on "
|
||||
"device '%s' in abort: %s",
|
||||
sn->id_str,
|
||||
sn->name,
|
||||
bdrv_get_device_name(bs),
|
||||
error_get_pretty(local_error));
|
||||
error_free(local_error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2304,6 +2306,11 @@ void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blk_dev_has_tray(blk)) {
|
||||
/* Ignore this command on tray-less devices */
|
||||
return;
|
||||
}
|
||||
|
||||
if (blk_dev_is_tray_open(blk)) {
|
||||
return;
|
||||
}
|
||||
@@ -2334,6 +2341,11 @@ void qmp_blockdev_close_tray(const char *device, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blk_dev_has_tray(blk)) {
|
||||
/* Ignore this command on tray-less devices */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blk_dev_is_tray_open(blk)) {
|
||||
return;
|
||||
}
|
||||
@@ -2363,7 +2375,7 @@ void qmp_x_blockdev_remove_medium(const char *device, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (has_device && !blk_dev_is_tray_open(blk)) {
|
||||
if (has_device && blk_dev_has_tray(blk) && !blk_dev_is_tray_open(blk)) {
|
||||
error_setg(errp, "Tray of device '%s' is not open", device);
|
||||
return;
|
||||
}
|
||||
@@ -2382,12 +2394,19 @@ void qmp_x_blockdev_remove_medium(const char *device, Error **errp)
|
||||
|
||||
/* This follows the convention established by bdrv_make_anon() */
|
||||
if (bs->device_list.tqe_prev) {
|
||||
QTAILQ_REMOVE(&bdrv_states, bs, device_list);
|
||||
bs->device_list.tqe_prev = NULL;
|
||||
bdrv_device_remove(bs);
|
||||
}
|
||||
|
||||
blk_remove_bs(blk);
|
||||
|
||||
if (!blk_dev_has_tray(blk)) {
|
||||
/* For tray-less devices, blockdev-open-tray is a no-op (or may not be
|
||||
* called at all); therefore, the medium needs to be ejected here.
|
||||
* Do it after blk_remove_bs() so blk_is_inserted(blk) returns the @load
|
||||
* value passed here (i.e. false). */
|
||||
blk_dev_change_media_cb(blk, false);
|
||||
}
|
||||
|
||||
out:
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
@@ -2413,7 +2432,7 @@ static void qmp_blockdev_insert_anon_medium(const char *device,
|
||||
return;
|
||||
}
|
||||
|
||||
if (has_device && !blk_dev_is_tray_open(blk)) {
|
||||
if (has_device && blk_dev_has_tray(blk) && !blk_dev_is_tray_open(blk)) {
|
||||
error_setg(errp, "Tray of device '%s' is not open", device);
|
||||
return;
|
||||
}
|
||||
@@ -2426,6 +2445,15 @@ static void qmp_blockdev_insert_anon_medium(const char *device,
|
||||
blk_insert_bs(blk, bs);
|
||||
|
||||
QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
|
||||
|
||||
if (!blk_dev_has_tray(blk)) {
|
||||
/* For tray-less devices, blockdev-close-tray is a no-op (or may not be
|
||||
* called at all); therefore, the medium needs to be pushed into the
|
||||
* slot here.
|
||||
* Do it after blk_insert_bs() so blk_is_inserted(blk) returns the @load
|
||||
* value passed here (i.e. true). */
|
||||
blk_dev_change_media_cb(blk, true);
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_x_blockdev_insert_medium(const char *device, const char *node_name,
|
||||
@@ -3290,23 +3318,29 @@ void qmp_blockdev_backup(const char *device, const char *target,
|
||||
NULL, errp);
|
||||
}
|
||||
|
||||
/* Parameter check and block job starting for drive mirroring.
|
||||
* Caller should hold @device and @target's aio context (must be the same).
|
||||
**/
|
||||
static void blockdev_mirror_common(BlockDriverState *bs,
|
||||
BlockDriverState *target,
|
||||
bool has_replaces, const char *replaces,
|
||||
enum MirrorSyncMode sync,
|
||||
bool has_speed, int64_t speed,
|
||||
bool has_granularity, uint32_t granularity,
|
||||
bool has_buf_size, int64_t buf_size,
|
||||
bool has_on_source_error,
|
||||
BlockdevOnError on_source_error,
|
||||
bool has_on_target_error,
|
||||
BlockdevOnError on_target_error,
|
||||
bool has_unmap, bool unmap,
|
||||
Error **errp)
|
||||
void qmp_drive_mirror(const char *device, const char *target,
|
||||
bool has_format, const char *format,
|
||||
bool has_node_name, const char *node_name,
|
||||
bool has_replaces, const char *replaces,
|
||||
enum MirrorSyncMode sync,
|
||||
bool has_mode, enum NewImageMode mode,
|
||||
bool has_speed, int64_t speed,
|
||||
bool has_granularity, uint32_t granularity,
|
||||
bool has_buf_size, int64_t buf_size,
|
||||
bool has_on_source_error, BlockdevOnError on_source_error,
|
||||
bool has_on_target_error, BlockdevOnError on_target_error,
|
||||
bool has_unmap, bool unmap,
|
||||
Error **errp)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
BlockDriverState *source, *target_bs;
|
||||
AioContext *aio_context;
|
||||
Error *local_err = NULL;
|
||||
QDict *options;
|
||||
int flags;
|
||||
int64_t size;
|
||||
int ret;
|
||||
|
||||
if (!has_speed) {
|
||||
speed = 0;
|
||||
@@ -3317,6 +3351,9 @@ static void blockdev_mirror_common(BlockDriverState *bs,
|
||||
if (!has_on_target_error) {
|
||||
on_target_error = BLOCKDEV_ON_ERROR_REPORT;
|
||||
}
|
||||
if (!has_mode) {
|
||||
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||
}
|
||||
if (!has_granularity) {
|
||||
granularity = 0;
|
||||
}
|
||||
@@ -3338,55 +3375,6 @@ static void blockdev_mirror_common(BlockDriverState *bs,
|
||||
return;
|
||||
}
|
||||
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR_SOURCE, errp)) {
|
||||
return;
|
||||
}
|
||||
if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_MIRROR_TARGET, errp)) {
|
||||
return;
|
||||
}
|
||||
if (target->blk) {
|
||||
error_setg(errp, "Cannot mirror to an attached block device");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bs->backing && sync == MIRROR_SYNC_MODE_TOP) {
|
||||
sync = MIRROR_SYNC_MODE_FULL;
|
||||
}
|
||||
|
||||
/* pass the node name to replace to mirror start since it's loose coupling
|
||||
* and will allow to check whether the node still exist at mirror completion
|
||||
*/
|
||||
mirror_start(bs, target,
|
||||
has_replaces ? replaces : NULL,
|
||||
speed, granularity, buf_size, sync,
|
||||
on_source_error, on_target_error, unmap,
|
||||
block_job_cb, bs, errp);
|
||||
}
|
||||
|
||||
void qmp_drive_mirror(const char *device, const char *target,
|
||||
bool has_format, const char *format,
|
||||
bool has_node_name, const char *node_name,
|
||||
bool has_replaces, const char *replaces,
|
||||
enum MirrorSyncMode sync,
|
||||
bool has_mode, enum NewImageMode mode,
|
||||
bool has_speed, int64_t speed,
|
||||
bool has_granularity, uint32_t granularity,
|
||||
bool has_buf_size, int64_t buf_size,
|
||||
bool has_on_source_error, BlockdevOnError on_source_error,
|
||||
bool has_on_target_error, BlockdevOnError on_target_error,
|
||||
bool has_unmap, bool unmap,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *source, *target_bs;
|
||||
AioContext *aio_context;
|
||||
Error *local_err = NULL;
|
||||
QDict *options = NULL;
|
||||
int flags;
|
||||
int64_t size;
|
||||
int ret;
|
||||
|
||||
blk = blk_by_name(device);
|
||||
if (!blk) {
|
||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||
@@ -3402,14 +3390,15 @@ void qmp_drive_mirror(const char *device, const char *target,
|
||||
goto out;
|
||||
}
|
||||
bs = blk_bs(blk);
|
||||
if (!has_mode) {
|
||||
mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
|
||||
}
|
||||
|
||||
if (!has_format) {
|
||||
format = mode == NEW_IMAGE_MODE_EXISTING ? NULL : bs->drv->format_name;
|
||||
}
|
||||
|
||||
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_MIRROR, errp)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
flags = bs->open_flags | BDRV_O_RDWR;
|
||||
source = backing_bs(bs);
|
||||
if (!source && sync == MIRROR_SYNC_MODE_TOP) {
|
||||
@@ -3504,81 +3493,25 @@ void qmp_drive_mirror(const char *device, const char *target,
|
||||
|
||||
bdrv_set_aio_context(target_bs, aio_context);
|
||||
|
||||
blockdev_mirror_common(bs, target_bs,
|
||||
has_replaces, replaces, sync,
|
||||
has_speed, speed,
|
||||
has_granularity, granularity,
|
||||
has_buf_size, buf_size,
|
||||
has_on_source_error, on_source_error,
|
||||
has_on_target_error, on_target_error,
|
||||
has_unmap, unmap,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
/* pass the node name to replace to mirror start since it's loose coupling
|
||||
* and will allow to check whether the node still exist at mirror completion
|
||||
*/
|
||||
mirror_start(bs, target_bs,
|
||||
has_replaces ? replaces : NULL,
|
||||
speed, granularity, buf_size, sync,
|
||||
on_source_error, on_target_error,
|
||||
unmap,
|
||||
block_job_cb, bs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
bdrv_unref(target_bs);
|
||||
error_propagate(errp, local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
void qmp_blockdev_mirror(const char *device, const char *target,
|
||||
bool has_replaces, const char *replaces,
|
||||
MirrorSyncMode sync,
|
||||
bool has_speed, int64_t speed,
|
||||
bool has_granularity, uint32_t granularity,
|
||||
bool has_buf_size, int64_t buf_size,
|
||||
bool has_on_source_error,
|
||||
BlockdevOnError on_source_error,
|
||||
bool has_on_target_error,
|
||||
BlockdevOnError on_target_error,
|
||||
Error **errp)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *target_bs;
|
||||
AioContext *aio_context;
|
||||
Error *local_err = NULL;
|
||||
|
||||
blk = blk_by_name(device);
|
||||
if (!blk) {
|
||||
error_setg(errp, "Device '%s' not found", device);
|
||||
return;
|
||||
}
|
||||
bs = blk_bs(blk);
|
||||
|
||||
if (!bs) {
|
||||
error_setg(errp, "Device '%s' has no media", device);
|
||||
return;
|
||||
}
|
||||
|
||||
target_bs = bdrv_lookup_bs(target, target, errp);
|
||||
if (!target_bs) {
|
||||
return;
|
||||
}
|
||||
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
bdrv_ref(target_bs);
|
||||
bdrv_set_aio_context(target_bs, aio_context);
|
||||
|
||||
blockdev_mirror_common(bs, target_bs,
|
||||
has_replaces, replaces, sync,
|
||||
has_speed, speed,
|
||||
has_granularity, granularity,
|
||||
has_buf_size, buf_size,
|
||||
has_on_source_error, on_source_error,
|
||||
has_on_target_error, on_target_error,
|
||||
true, true,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
bdrv_unref(target_bs);
|
||||
}
|
||||
|
||||
aio_context_release(aio_context);
|
||||
}
|
||||
|
||||
/* Get the block job for a given device name and acquire its AioContext */
|
||||
static BlockJob *find_block_job(const char *device, AioContext **aio_context,
|
||||
Error **errp)
|
||||
@@ -3965,6 +3898,18 @@ QemuOptsList qemu_common_drive_opts = {
|
||||
.name = "discard",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "discard operation (ignore/off, unmap/on)",
|
||||
},{
|
||||
.name = BDRV_OPT_CACHE_WB,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "enables writeback mode for any caches",
|
||||
},{
|
||||
.name = BDRV_OPT_CACHE_DIRECT,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "enables use of O_DIRECT (bypass the host page cache)",
|
||||
},{
|
||||
.name = BDRV_OPT_CACHE_NO_FLUSH,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "ignore any flush requests for the device",
|
||||
},{
|
||||
.name = "aio",
|
||||
.type = QEMU_OPT_STRING,
|
||||
@@ -4072,6 +4017,18 @@ static QemuOptsList qemu_root_bds_opts = {
|
||||
.name = "discard",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "discard operation (ignore/off, unmap/on)",
|
||||
},{
|
||||
.name = "cache.writeback",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "enables writeback mode for any caches",
|
||||
},{
|
||||
.name = "cache.direct",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "enables use of O_DIRECT (bypass the host page cache)",
|
||||
},{
|
||||
.name = "cache.no-flush",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "ignore any flush requests for the device",
|
||||
},{
|
||||
.name = "aio",
|
||||
.type = QEMU_OPT_STRING,
|
||||
|
@@ -938,7 +938,7 @@ int main(int argc, char **argv)
|
||||
unsigned long tmp;
|
||||
if (fscanf(fp, "%lu", &tmp) == 1) {
|
||||
mmap_min_addr = tmp;
|
||||
qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", mmap_min_addr);
|
||||
qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -955,7 +955,7 @@ int main(int argc, char **argv)
|
||||
|
||||
free(target_environ);
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
|
||||
if (qemu_log_enabled()) {
|
||||
qemu_log("guest_base 0x%lx\n", guest_base);
|
||||
log_page_dump();
|
||||
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#include "qemu.h"
|
||||
#include "target_signal.h"
|
||||
|
||||
//#define DEBUG_SIGNAL
|
||||
|
||||
void signal_init(void)
|
||||
{
|
||||
}
|
||||
|
89
configure
vendored
89
configure
vendored
@@ -250,7 +250,6 @@ vnc_jpeg=""
|
||||
vnc_png=""
|
||||
xen=""
|
||||
xen_ctrl_version=""
|
||||
xen_pv_domain_build="no"
|
||||
xen_pci_passthrough=""
|
||||
linux_aio=""
|
||||
cap_ng=""
|
||||
@@ -928,10 +927,6 @@ for opt do
|
||||
;;
|
||||
--enable-xen-pci-passthrough) xen_pci_passthrough="yes"
|
||||
;;
|
||||
--disable-xen-pv-domain-build) xen_pv_domain_build="no"
|
||||
;;
|
||||
--enable-xen-pv-domain-build) xen_pv_domain_build="yes"
|
||||
;;
|
||||
--disable-brlapi) brlapi="no"
|
||||
;;
|
||||
--enable-brlapi) brlapi="yes"
|
||||
@@ -1943,7 +1938,6 @@ fi
|
||||
|
||||
if test "$xen" != "no" ; then
|
||||
xen_libs="-lxenstore -lxenctrl -lxenguest"
|
||||
xen_stable_libs="-lxenforeignmemory -lxengnttab -lxenevtchn"
|
||||
|
||||
# First we test whether Xen headers and libraries are available.
|
||||
# If no, we are done and there is no Xen support.
|
||||
@@ -1966,57 +1960,6 @@ EOF
|
||||
# Xen unstable
|
||||
elif
|
||||
cat > $TMPC <<EOF &&
|
||||
/*
|
||||
* If we have stable libs the we don't want the libxc compat
|
||||
* layers, regardless of what CFLAGS we may have been given.
|
||||
*/
|
||||
#undef XC_WANT_COMPAT_EVTCHN_API
|
||||
#undef XC_WANT_COMPAT_GNTTAB_API
|
||||
#undef XC_WANT_COMPAT_MAP_FOREIGN_API
|
||||
#include <xenctrl.h>
|
||||
#include <xenstore.h>
|
||||
#include <xenevtchn.h>
|
||||
#include <xengnttab.h>
|
||||
#include <xenforeignmemory.h>
|
||||
#include <stdint.h>
|
||||
#include <xen/hvm/hvm_info_table.h>
|
||||
#if !defined(HVM_MAX_VCPUS)
|
||||
# error HVM_MAX_VCPUS not defined
|
||||
#endif
|
||||
int main(void) {
|
||||
xc_interface *xc = NULL;
|
||||
xenforeignmemory_handle *xfmem;
|
||||
xenevtchn_handle *xe;
|
||||
xengnttab_handle *xg;
|
||||
xen_domain_handle_t handle;
|
||||
|
||||
xs_daemon_open();
|
||||
|
||||
xc = xc_interface_open(0, 0, 0);
|
||||
xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
|
||||
xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0);
|
||||
xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000);
|
||||
xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL);
|
||||
xc_domain_create(xc, 0, handle, 0, NULL, NULL);
|
||||
|
||||
xfmem = xenforeignmemory_open(0, 0);
|
||||
xenforeignmemory_map(xfmem, 0, 0, 0, 0, 0);
|
||||
|
||||
xe = xenevtchn_open(0, 0);
|
||||
xenevtchn_fd(xe);
|
||||
|
||||
xg = xengnttab_open(0, 0);
|
||||
xengnttab_map_grant_ref(xg, 0, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
compile_prog "" "$xen_libs $xen_stable_libs"
|
||||
then
|
||||
xen_ctrl_version=471
|
||||
xen=yes
|
||||
elif
|
||||
cat > $TMPC <<EOF &&
|
||||
#include <xenctrl.h>
|
||||
#include <stdint.h>
|
||||
int main(void) {
|
||||
@@ -2210,9 +2153,6 @@ EOF
|
||||
fi
|
||||
|
||||
if test "$xen" = yes; then
|
||||
if test $xen_ctrl_version -ge 471 ; then
|
||||
libs_softmmu="$xen_stable_libs $libs_softmmu"
|
||||
fi
|
||||
libs_softmmu="$xen_libs $libs_softmmu"
|
||||
fi
|
||||
fi
|
||||
@@ -2234,12 +2174,6 @@ if test "$xen_pci_passthrough" != "no"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$xen_pv_domain_build" = "yes" &&
|
||||
test "$xen" != "yes"; then
|
||||
error_exit "User requested Xen PV domain builder support" \
|
||||
"which requires Xen support."
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# libtool probe
|
||||
|
||||
@@ -2492,14 +2426,6 @@ else
|
||||
fi
|
||||
|
||||
|
||||
##########################################
|
||||
# getifaddrs (for tests/test-io-channel-socket )
|
||||
|
||||
have_ifaddrs_h=yes
|
||||
if ! check_include "ifaddrs.h" ; then
|
||||
have_ifaddrs_h=no
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# VTE probe
|
||||
|
||||
@@ -4859,7 +4785,6 @@ fi
|
||||
echo "xen support $xen"
|
||||
if test "$xen" = "yes" ; then
|
||||
echo "xen ctrl version $xen_ctrl_version"
|
||||
echo "pv dom build $xen_pv_domain_build"
|
||||
fi
|
||||
echo "brlapi support $brlapi"
|
||||
echo "bluez support $bluez"
|
||||
@@ -4884,7 +4809,7 @@ echo "libcap-ng support $cap_ng"
|
||||
echo "vhost-net support $vhost_net"
|
||||
echo "vhost-scsi support $vhost_scsi"
|
||||
echo "Trace backends $trace_backends"
|
||||
if have_backend "simple"; then
|
||||
if test "$trace_backend" = "simple"; then
|
||||
echo "Trace output file $trace_file-<pid>"
|
||||
fi
|
||||
if test "$spice" = "yes"; then
|
||||
@@ -5216,9 +5141,6 @@ fi
|
||||
if test "$tasn1" = "yes" ; then
|
||||
echo "CONFIG_TASN1=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$have_ifaddrs_h" = "yes" ; then
|
||||
echo "HAVE_IFADDRS_H=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$vte" = "yes" ; then
|
||||
echo "CONFIG_VTE=y" >> $config_host_mak
|
||||
echo "VTE_CFLAGS=$vte_cflags" >> $config_host_mak
|
||||
@@ -5231,9 +5153,6 @@ fi
|
||||
if test "$xen" = "yes" ; then
|
||||
echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak
|
||||
echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak
|
||||
if test "$xen_pv_domain_build" = "yes" ; then
|
||||
echo "CONFIG_XEN_PV_DOMAIN_BUILD=y" >> $config_host_mak
|
||||
fi
|
||||
fi
|
||||
if test "$linux_aio" = "yes" ; then
|
||||
echo "CONFIG_LINUX_AIO=y" >> $config_host_mak
|
||||
@@ -5702,20 +5621,20 @@ case "$target_name" in
|
||||
ppc64)
|
||||
TARGET_BASE_ARCH=ppc
|
||||
TARGET_ABI_DIR=ppc
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml"
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
|
||||
;;
|
||||
ppc64le)
|
||||
TARGET_ARCH=ppc64
|
||||
TARGET_BASE_ARCH=ppc
|
||||
TARGET_ABI_DIR=ppc
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml"
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
|
||||
;;
|
||||
ppc64abi32)
|
||||
TARGET_ARCH=ppc64
|
||||
TARGET_BASE_ARCH=ppc
|
||||
TARGET_ABI_DIR=ppc
|
||||
echo "TARGET_ABI32=y" >> $config_target_mak
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml"
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
|
||||
;;
|
||||
sh4|sh4eb)
|
||||
TARGET_ARCH=sh4
|
||||
|
@@ -65,7 +65,7 @@ ivshmem_server_parse_args(IvshmemServerArgs *args, int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
unsigned long long v;
|
||||
Error *err = NULL;
|
||||
Error *errp = NULL;
|
||||
|
||||
while ((c = getopt(argc, argv,
|
||||
"h" /* help */
|
||||
@@ -104,9 +104,11 @@ ivshmem_server_parse_args(IvshmemServerArgs *args, int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'l': /* shm_size */
|
||||
parse_option_size("shm_size", optarg, &args->shm_size, &err);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
parse_option_size("shm_size", optarg, &args->shm_size, &errp);
|
||||
if (errp) {
|
||||
fprintf(stderr, "cannot parse shm size: %s\n",
|
||||
error_get_pretty(errp));
|
||||
error_free(errp);
|
||||
ivshmem_server_usage(argv[0], 1);
|
||||
}
|
||||
break;
|
||||
|
@@ -17,7 +17,7 @@
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "exec/memory-internal.h"
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "trace.h"
|
||||
#include "disas/disas.h"
|
||||
|
46
cpus.c
46
cpus.c
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
/* Needed early for CONFIG_BSD etc. */
|
||||
#include "qemu/osdep.h"
|
||||
#include "config-host.h"
|
||||
|
||||
#include "monitor/monitor.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
@@ -1310,6 +1310,8 @@ static void qemu_tcg_init_vcpu(CPUState *cpu)
|
||||
static QemuCond *tcg_halt_cond;
|
||||
static QemuThread *tcg_cpu_thread;
|
||||
|
||||
tcg_cpu_address_space_init(cpu, cpu->as);
|
||||
|
||||
/* share a single thread for all cpus with TCG */
|
||||
if (!tcg_cpu_thread) {
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
@@ -1370,17 +1372,6 @@ void qemu_init_vcpu(CPUState *cpu)
|
||||
cpu->nr_cores = smp_cores;
|
||||
cpu->nr_threads = smp_threads;
|
||||
cpu->stopped = true;
|
||||
|
||||
if (!cpu->as) {
|
||||
/* If the target cpu hasn't set up any address spaces itself,
|
||||
* give it the default one.
|
||||
*/
|
||||
AddressSpace *as = address_space_init_shareable(cpu->memory,
|
||||
"cpu-memory");
|
||||
cpu->num_ases = 1;
|
||||
cpu_address_space_init(cpu, as, 0);
|
||||
}
|
||||
|
||||
if (kvm_enabled()) {
|
||||
qemu_kvm_start_vcpu(cpu);
|
||||
} else if (tcg_enabled()) {
|
||||
@@ -1567,29 +1558,22 @@ CpuInfoList *qmp_query_cpus(Error **errp)
|
||||
info->value->qom_path = object_get_canonical_path(OBJECT(cpu));
|
||||
info->value->thread_id = cpu->thread_id;
|
||||
#if defined(TARGET_I386)
|
||||
info->value->arch = CPU_INFO_ARCH_X86;
|
||||
info->value->u.x86 = g_new0(CpuInfoX86, 1);
|
||||
info->value->u.x86->pc = env->eip + env->segs[R_CS].base;
|
||||
info->value->has_pc = true;
|
||||
info->value->pc = env->eip + env->segs[R_CS].base;
|
||||
#elif defined(TARGET_PPC)
|
||||
info->value->arch = CPU_INFO_ARCH_PPC;
|
||||
info->value->u.ppc = g_new0(CpuInfoPPC, 1);
|
||||
info->value->u.ppc->nip = env->nip;
|
||||
info->value->has_nip = true;
|
||||
info->value->nip = env->nip;
|
||||
#elif defined(TARGET_SPARC)
|
||||
info->value->arch = CPU_INFO_ARCH_SPARC;
|
||||
info->value->u.sparc = g_new0(CpuInfoSPARC, 1);
|
||||
info->value->u.sparc->pc = env->pc;
|
||||
info->value->u.sparc->npc = env->npc;
|
||||
info->value->has_pc = true;
|
||||
info->value->pc = env->pc;
|
||||
info->value->has_npc = true;
|
||||
info->value->npc = env->npc;
|
||||
#elif defined(TARGET_MIPS)
|
||||
info->value->arch = CPU_INFO_ARCH_MIPS;
|
||||
info->value->u.mips = g_new0(CpuInfoMIPS, 1);
|
||||
info->value->u.mips->PC = env->active_tc.PC;
|
||||
info->value->has_PC = true;
|
||||
info->value->PC = env->active_tc.PC;
|
||||
#elif defined(TARGET_TRICORE)
|
||||
info->value->arch = CPU_INFO_ARCH_TRICORE;
|
||||
info->value->u.tricore = g_new0(CpuInfoTricore, 1);
|
||||
info->value->u.tricore->PC = env->PC;
|
||||
#else
|
||||
info->value->arch = CPU_INFO_ARCH_OTHER;
|
||||
info->value->u.other = g_new0(CpuInfoOther, 1);
|
||||
info->value->has_PC = true;
|
||||
info->value->PC = env->PC;
|
||||
#endif
|
||||
|
||||
/* XXX: waiting for the qapi to support GSList */
|
||||
|
11
cputlb.c
11
cputlb.c
@@ -17,7 +17,7 @@
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/memory.h"
|
||||
@@ -356,7 +356,6 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
|
||||
CPUTLBEntry *te;
|
||||
hwaddr iotlb, xlat, sz;
|
||||
unsigned vidx = env->vtlb_index++ % CPU_VTLB_SIZE;
|
||||
int asidx = cpu_asidx_from_attrs(cpu, attrs);
|
||||
|
||||
assert(size >= TARGET_PAGE_SIZE);
|
||||
if (size != TARGET_PAGE_SIZE) {
|
||||
@@ -364,7 +363,7 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
|
||||
}
|
||||
|
||||
sz = size;
|
||||
section = address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat, &sz);
|
||||
section = address_space_translate_for_iotlb(cpu, paddr, &xlat, &sz);
|
||||
assert(sz >= TARGET_PAGE_SIZE);
|
||||
|
||||
#if defined(DEBUG_TLB)
|
||||
@@ -449,7 +448,6 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
|
||||
void *p;
|
||||
MemoryRegion *mr;
|
||||
CPUState *cpu = ENV_GET_CPU(env1);
|
||||
CPUIOTLBEntry *iotlbentry;
|
||||
|
||||
page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
mmu_idx = cpu_mmu_index(env1, true);
|
||||
@@ -457,9 +455,8 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
|
||||
(addr & TARGET_PAGE_MASK))) {
|
||||
cpu_ldub_code(env1, addr);
|
||||
}
|
||||
iotlbentry = &env1->iotlb[mmu_idx][page_index];
|
||||
pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
|
||||
mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
|
||||
pd = env1->iotlb[mmu_idx][page_index].addr & ~TARGET_PAGE_MASK;
|
||||
mr = iotlb_to_region(cpu, pd);
|
||||
if (memory_region_is_unassigned(mr)) {
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
|
||||
|
@@ -7,7 +7,6 @@ crypto-obj-y += tlscreds.o
|
||||
crypto-obj-y += tlscredsanon.o
|
||||
crypto-obj-y += tlscredsx509.o
|
||||
crypto-obj-y += tlssession.o
|
||||
crypto-obj-y += secret.o
|
||||
|
||||
# Let the userspace emulators avoid linking gnutls/etc
|
||||
crypto-aes-obj-y = aes.o
|
||||
|
@@ -27,7 +27,6 @@
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "crypto/aes.h"
|
||||
|
||||
|
@@ -18,7 +18,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/aes.h"
|
||||
#include "crypto/desrfb.h"
|
||||
|
||||
|
@@ -18,7 +18,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <gcrypt.h>
|
||||
|
||||
|
||||
|
@@ -18,7 +18,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <nettle/nettle-types.h>
|
||||
#include <nettle/aes.h>
|
||||
#include <nettle/des.h>
|
||||
|
@@ -18,71 +18,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/cipher.h"
|
||||
|
||||
|
||||
static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
||||
static size_t alg_key_len[QCRYPTO_CIPHER_ALG_LAST] = {
|
||||
[QCRYPTO_CIPHER_ALG_AES_128] = 16,
|
||||
[QCRYPTO_CIPHER_ALG_AES_192] = 24,
|
||||
[QCRYPTO_CIPHER_ALG_AES_256] = 32,
|
||||
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
|
||||
};
|
||||
|
||||
static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
||||
[QCRYPTO_CIPHER_ALG_AES_128] = 16,
|
||||
[QCRYPTO_CIPHER_ALG_AES_192] = 16,
|
||||
[QCRYPTO_CIPHER_ALG_AES_256] = 16,
|
||||
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
|
||||
};
|
||||
|
||||
static bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = {
|
||||
[QCRYPTO_CIPHER_MODE_ECB] = false,
|
||||
[QCRYPTO_CIPHER_MODE_CBC] = true,
|
||||
};
|
||||
|
||||
|
||||
size_t qcrypto_cipher_get_block_len(QCryptoCipherAlgorithm alg)
|
||||
{
|
||||
if (alg >= G_N_ELEMENTS(alg_key_len)) {
|
||||
return 0;
|
||||
}
|
||||
return alg_block_len[alg];
|
||||
}
|
||||
|
||||
|
||||
size_t qcrypto_cipher_get_key_len(QCryptoCipherAlgorithm alg)
|
||||
{
|
||||
if (alg >= G_N_ELEMENTS(alg_key_len)) {
|
||||
return 0;
|
||||
}
|
||||
return alg_key_len[alg];
|
||||
}
|
||||
|
||||
|
||||
size_t qcrypto_cipher_get_iv_len(QCryptoCipherAlgorithm alg,
|
||||
QCryptoCipherMode mode)
|
||||
{
|
||||
if (alg >= G_N_ELEMENTS(alg_block_len)) {
|
||||
return 0;
|
||||
}
|
||||
if (mode >= G_N_ELEMENTS(mode_need_iv)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode_need_iv[mode]) {
|
||||
return alg_block_len[alg];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
|
||||
size_t nkey,
|
||||
Error **errp)
|
||||
{
|
||||
if ((unsigned)alg >= QCRYPTO_CIPHER_ALG__MAX) {
|
||||
if ((unsigned)alg >= QCRYPTO_CIPHER_ALG_LAST) {
|
||||
error_setg(errp, "Cipher algorithm %d out of range",
|
||||
alg);
|
||||
return false;
|
||||
@@ -90,7 +41,7 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
|
||||
|
||||
if (alg_key_len[alg] != nkey) {
|
||||
error_setg(errp, "Cipher key length %zu should be %zu",
|
||||
nkey, alg_key_len[alg]);
|
||||
alg_key_len[alg], nkey);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@@ -26,7 +26,6 @@
|
||||
* (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/desrfb.h"
|
||||
|
||||
static void scrunch(unsigned char *, unsigned long *);
|
||||
|
@@ -18,25 +18,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/hash.h"
|
||||
|
||||
#ifdef CONFIG_GNUTLS_HASH
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
|
||||
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG_LAST] = {
|
||||
[QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
|
||||
[QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
|
||||
[QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
|
||||
};
|
||||
|
||||
static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
|
||||
[QCRYPTO_HASH_ALG_MD5] = 16,
|
||||
[QCRYPTO_HASH_ALG_SHA1] = 20,
|
||||
[QCRYPTO_HASH_ALG_SHA256] = 32,
|
||||
};
|
||||
|
||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||
{
|
||||
if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map)) {
|
||||
@@ -45,15 +38,6 @@ gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
|
||||
{
|
||||
if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_size)) {
|
||||
return 0;
|
||||
}
|
||||
return qcrypto_hash_alg_size[alg];
|
||||
}
|
||||
|
||||
|
||||
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||
const struct iovec *iov,
|
||||
size_t niov,
|
||||
|
@@ -18,7 +18,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/init.h"
|
||||
#include "qemu/thread.h"
|
||||
|
||||
|
514
crypto/secret.c
514
crypto/secret.c
@@ -1,514 +0,0 @@
|
||||
/*
|
||||
* QEMU crypto secret support
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/secret.h"
|
||||
#include "crypto/cipher.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "qemu/base64.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_load_data(QCryptoSecret *secret,
|
||||
uint8_t **output,
|
||||
size_t *outputlen,
|
||||
Error **errp)
|
||||
{
|
||||
char *data = NULL;
|
||||
size_t length = 0;
|
||||
GError *gerr = NULL;
|
||||
|
||||
*output = NULL;
|
||||
*outputlen = 0;
|
||||
|
||||
if (secret->file) {
|
||||
if (secret->data) {
|
||||
error_setg(errp,
|
||||
"'file' and 'data' are mutually exclusive");
|
||||
return;
|
||||
}
|
||||
if (!g_file_get_contents(secret->file, &data, &length, &gerr)) {
|
||||
error_setg(errp,
|
||||
"Unable to read %s: %s",
|
||||
secret->file, gerr->message);
|
||||
g_error_free(gerr);
|
||||
return;
|
||||
}
|
||||
*output = (uint8_t *)data;
|
||||
*outputlen = length;
|
||||
} else if (secret->data) {
|
||||
*outputlen = strlen(secret->data);
|
||||
*output = (uint8_t *)g_strdup(secret->data);
|
||||
} else {
|
||||
error_setg(errp, "Either 'file' or 'data' must be provided");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void qcrypto_secret_decrypt(QCryptoSecret *secret,
|
||||
const uint8_t *input,
|
||||
size_t inputlen,
|
||||
uint8_t **output,
|
||||
size_t *outputlen,
|
||||
Error **errp)
|
||||
{
|
||||
uint8_t *key = NULL, *ciphertext = NULL, *iv = NULL;
|
||||
size_t keylen, ciphertextlen, ivlen;
|
||||
QCryptoCipher *aes = NULL;
|
||||
uint8_t *plaintext = NULL;
|
||||
|
||||
*output = NULL;
|
||||
*outputlen = 0;
|
||||
|
||||
if (qcrypto_secret_lookup(secret->keyid,
|
||||
&key, &keylen,
|
||||
errp) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (keylen != 32) {
|
||||
error_setg(errp, "Key should be 32 bytes in length");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!secret->iv) {
|
||||
error_setg(errp, "IV is required to decrypt secret");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
iv = qbase64_decode(secret->iv, -1, &ivlen, errp);
|
||||
if (!iv) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (ivlen != 16) {
|
||||
error_setg(errp, "IV should be 16 bytes in length not %zu",
|
||||
ivlen);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256,
|
||||
QCRYPTO_CIPHER_MODE_CBC,
|
||||
key, keylen,
|
||||
errp);
|
||||
if (!aes) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (qcrypto_cipher_setiv(aes, iv, ivlen, errp) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) {
|
||||
ciphertext = qbase64_decode((const gchar*)input,
|
||||
inputlen,
|
||||
&ciphertextlen,
|
||||
errp);
|
||||
if (!ciphertext) {
|
||||
goto cleanup;
|
||||
}
|
||||
plaintext = g_new0(uint8_t, ciphertextlen + 1);
|
||||
} else {
|
||||
ciphertextlen = inputlen;
|
||||
plaintext = g_new0(uint8_t, inputlen + 1);
|
||||
}
|
||||
if (qcrypto_cipher_decrypt(aes,
|
||||
ciphertext ? ciphertext : input,
|
||||
plaintext,
|
||||
ciphertextlen,
|
||||
errp) < 0) {
|
||||
plaintext = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (plaintext[ciphertextlen - 1] > 16 ||
|
||||
plaintext[ciphertextlen - 1] > ciphertextlen) {
|
||||
error_setg(errp, "Incorrect number of padding bytes (%d) "
|
||||
"found on decrypted data",
|
||||
(int)plaintext[ciphertextlen - 1]);
|
||||
g_free(plaintext);
|
||||
plaintext = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Even though plaintext may contain arbitrary NUL
|
||||
* ensure it is explicitly NUL terminated.
|
||||
*/
|
||||
ciphertextlen -= plaintext[ciphertextlen - 1];
|
||||
plaintext[ciphertextlen] = '\0';
|
||||
|
||||
*output = plaintext;
|
||||
*outputlen = ciphertextlen;
|
||||
|
||||
cleanup:
|
||||
g_free(ciphertext);
|
||||
g_free(iv);
|
||||
g_free(key);
|
||||
qcrypto_cipher_free(aes);
|
||||
}
|
||||
|
||||
|
||||
static void qcrypto_secret_decode(const uint8_t *input,
|
||||
size_t inputlen,
|
||||
uint8_t **output,
|
||||
size_t *outputlen,
|
||||
Error **errp)
|
||||
{
|
||||
*output = qbase64_decode((const gchar*)input,
|
||||
inputlen,
|
||||
outputlen,
|
||||
errp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_prop_set_loaded(Object *obj,
|
||||
bool value,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
|
||||
if (value) {
|
||||
Error *local_err = NULL;
|
||||
uint8_t *input = NULL;
|
||||
size_t inputlen = 0;
|
||||
uint8_t *output = NULL;
|
||||
size_t outputlen = 0;
|
||||
|
||||
qcrypto_secret_load_data(secret, &input, &inputlen, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (secret->keyid) {
|
||||
qcrypto_secret_decrypt(secret, input, inputlen,
|
||||
&output, &outputlen, &local_err);
|
||||
g_free(input);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
input = output;
|
||||
inputlen = outputlen;
|
||||
} else {
|
||||
if (secret->format != QCRYPTO_SECRET_FORMAT_RAW) {
|
||||
qcrypto_secret_decode(input, inputlen,
|
||||
&output, &outputlen, &local_err);
|
||||
g_free(input);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
input = output;
|
||||
inputlen = outputlen;
|
||||
}
|
||||
}
|
||||
|
||||
secret->rawdata = input;
|
||||
secret->rawlen = inputlen;
|
||||
} else {
|
||||
g_free(secret->rawdata);
|
||||
secret->rawlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
qcrypto_secret_prop_get_loaded(Object *obj,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
return secret->data != NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_prop_set_format(Object *obj,
|
||||
int value,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoSecret *creds = QCRYPTO_SECRET(obj);
|
||||
|
||||
creds->format = value;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qcrypto_secret_prop_get_format(Object *obj,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoSecret *creds = QCRYPTO_SECRET(obj);
|
||||
|
||||
return creds->format;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_prop_set_data(Object *obj,
|
||||
const char *value,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
|
||||
g_free(secret->data);
|
||||
secret->data = g_strdup(value);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qcrypto_secret_prop_get_data(Object *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
return g_strdup(secret->data);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_prop_set_file(Object *obj,
|
||||
const char *value,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
|
||||
g_free(secret->file);
|
||||
secret->file = g_strdup(value);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qcrypto_secret_prop_get_file(Object *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
return g_strdup(secret->file);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_prop_set_iv(Object *obj,
|
||||
const char *value,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
|
||||
g_free(secret->iv);
|
||||
secret->iv = g_strdup(value);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qcrypto_secret_prop_get_iv(Object *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
return g_strdup(secret->iv);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_prop_set_keyid(Object *obj,
|
||||
const char *value,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
|
||||
g_free(secret->keyid);
|
||||
secret->keyid = g_strdup(value);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qcrypto_secret_prop_get_keyid(Object *obj,
|
||||
Error **errp)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
return g_strdup(secret->keyid);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
object_property_set_bool(OBJECT(uc), true, "loaded", errp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_init(Object *obj)
|
||||
{
|
||||
object_property_add_bool(obj, "loaded",
|
||||
qcrypto_secret_prop_get_loaded,
|
||||
qcrypto_secret_prop_set_loaded,
|
||||
NULL);
|
||||
object_property_add_enum(obj, "format",
|
||||
"QCryptoSecretFormat",
|
||||
QCryptoSecretFormat_lookup,
|
||||
qcrypto_secret_prop_get_format,
|
||||
qcrypto_secret_prop_set_format,
|
||||
NULL);
|
||||
object_property_add_str(obj, "data",
|
||||
qcrypto_secret_prop_get_data,
|
||||
qcrypto_secret_prop_set_data,
|
||||
NULL);
|
||||
object_property_add_str(obj, "file",
|
||||
qcrypto_secret_prop_get_file,
|
||||
qcrypto_secret_prop_set_file,
|
||||
NULL);
|
||||
object_property_add_str(obj, "keyid",
|
||||
qcrypto_secret_prop_get_keyid,
|
||||
qcrypto_secret_prop_set_keyid,
|
||||
NULL);
|
||||
object_property_add_str(obj, "iv",
|
||||
qcrypto_secret_prop_get_iv,
|
||||
qcrypto_secret_prop_set_iv,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_finalize(Object *obj)
|
||||
{
|
||||
QCryptoSecret *secret = QCRYPTO_SECRET(obj);
|
||||
|
||||
g_free(secret->iv);
|
||||
g_free(secret->file);
|
||||
g_free(secret->keyid);
|
||||
g_free(secret->rawdata);
|
||||
g_free(secret->data);
|
||||
}
|
||||
|
||||
static void
|
||||
qcrypto_secret_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
|
||||
|
||||
ucc->complete = qcrypto_secret_complete;
|
||||
}
|
||||
|
||||
|
||||
int qcrypto_secret_lookup(const char *secretid,
|
||||
uint8_t **data,
|
||||
size_t *datalen,
|
||||
Error **errp)
|
||||
{
|
||||
Object *obj;
|
||||
QCryptoSecret *secret;
|
||||
|
||||
obj = object_resolve_path_component(
|
||||
object_get_objects_root(), secretid);
|
||||
if (!obj) {
|
||||
error_setg(errp, "No secret with id '%s'", secretid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
secret = (QCryptoSecret *)
|
||||
object_dynamic_cast(obj,
|
||||
TYPE_QCRYPTO_SECRET);
|
||||
if (!secret) {
|
||||
error_setg(errp, "Object with id '%s' is not a secret",
|
||||
secretid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!secret->rawdata) {
|
||||
error_setg(errp, "Secret with id '%s' has no data",
|
||||
secretid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*data = g_new0(uint8_t, secret->rawlen + 1);
|
||||
memcpy(*data, secret->rawdata, secret->rawlen);
|
||||
(*data)[secret->rawlen] = '\0';
|
||||
*datalen = secret->rawlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *qcrypto_secret_lookup_as_utf8(const char *secretid,
|
||||
Error **errp)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t datalen;
|
||||
|
||||
if (qcrypto_secret_lookup(secretid,
|
||||
&data,
|
||||
&datalen,
|
||||
errp) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!g_utf8_validate((const gchar*)data, datalen, NULL)) {
|
||||
error_setg(errp,
|
||||
"Data from secret %s is not valid UTF-8",
|
||||
secretid);
|
||||
g_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (char *)data;
|
||||
}
|
||||
|
||||
|
||||
char *qcrypto_secret_lookup_as_base64(const char *secretid,
|
||||
Error **errp)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t datalen;
|
||||
char *ret;
|
||||
|
||||
if (qcrypto_secret_lookup(secretid,
|
||||
&data,
|
||||
&datalen,
|
||||
errp) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = g_base64_encode(data, datalen);
|
||||
g_free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static const TypeInfo qcrypto_secret_info = {
|
||||
.parent = TYPE_OBJECT,
|
||||
.name = TYPE_QCRYPTO_SECRET,
|
||||
.instance_size = sizeof(QCryptoSecret),
|
||||
.instance_init = qcrypto_secret_init,
|
||||
.instance_finalize = qcrypto_secret_finalize,
|
||||
.class_size = sizeof(QCryptoSecretClass),
|
||||
.class_init = qcrypto_secret_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ TYPE_USER_CREATABLE },
|
||||
{ }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_secret_register_types(void)
|
||||
{
|
||||
type_register_static(&qcrypto_secret_info);
|
||||
}
|
||||
|
||||
|
||||
type_init(qcrypto_secret_register_types);
|
@@ -18,7 +18,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/tlscredspriv.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
@@ -18,7 +18,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/tlscredsanon.h"
|
||||
#include "crypto/tlscredspriv.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
|
@@ -18,10 +18,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/tlscredsx509.h"
|
||||
#include "crypto/tlscredspriv.h"
|
||||
#include "crypto/secret.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "trace.h"
|
||||
|
||||
@@ -609,30 +607,9 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
|
||||
}
|
||||
|
||||
if (cert != NULL && key != NULL) {
|
||||
#if GNUTLS_VERSION_NUMBER >= 0x030111
|
||||
char *password = NULL;
|
||||
if (creds->passwordid) {
|
||||
password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
|
||||
errp);
|
||||
if (!password) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
ret = gnutls_certificate_set_x509_key_file2(creds->data,
|
||||
cert, key,
|
||||
GNUTLS_X509_FMT_PEM,
|
||||
password,
|
||||
0);
|
||||
g_free(password);
|
||||
#else /* GNUTLS_VERSION_NUMBER < 0x030111 */
|
||||
if (creds->passwordid) {
|
||||
error_setg(errp, "PKCS8 decryption requires GNUTLS >= 3.1.11");
|
||||
goto cleanup;
|
||||
}
|
||||
ret = gnutls_certificate_set_x509_key_file(creds->data,
|
||||
cert, key,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
#endif /* GNUTLS_VERSION_NUMBER < 0x030111 */
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
|
||||
cert, key, gnutls_strerror(ret));
|
||||
@@ -760,27 +737,6 @@ qcrypto_tls_creds_x509_prop_set_sanity(Object *obj,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qcrypto_tls_creds_x509_prop_set_passwordid(Object *obj,
|
||||
const char *value,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
|
||||
|
||||
creds->passwordid = g_strdup(value);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
qcrypto_tls_creds_x509_prop_get_passwordid(Object *obj,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
{
|
||||
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
|
||||
|
||||
return g_strdup(creds->passwordid);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
qcrypto_tls_creds_x509_prop_get_sanity(Object *obj,
|
||||
Error **errp G_GNUC_UNUSED)
|
||||
@@ -813,10 +769,6 @@ qcrypto_tls_creds_x509_init(Object *obj)
|
||||
qcrypto_tls_creds_x509_prop_get_sanity,
|
||||
qcrypto_tls_creds_x509_prop_set_sanity,
|
||||
NULL);
|
||||
object_property_add_str(obj, "passwordid",
|
||||
qcrypto_tls_creds_x509_prop_get_passwordid,
|
||||
qcrypto_tls_creds_x509_prop_set_passwordid,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -825,7 +777,6 @@ qcrypto_tls_creds_x509_finalize(Object *obj)
|
||||
{
|
||||
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
|
||||
|
||||
g_free(creds->passwordid);
|
||||
qcrypto_tls_creds_x509_unload(creds);
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "crypto/tlssession.h"
|
||||
#include "crypto/tlscredsanon.h"
|
||||
#include "crypto/tlscredsx509.h"
|
||||
|
@@ -9,11 +9,6 @@ CONFIG_VGA_CIRRUS=y
|
||||
CONFIG_VMWARE_VGA=y
|
||||
CONFIG_VIRTIO_VGA=y
|
||||
CONFIG_VMMOUSE=y
|
||||
CONFIG_IPMI=y
|
||||
CONFIG_IPMI_LOCAL=y
|
||||
CONFIG_IPMI_EXTERN=y
|
||||
CONFIG_ISA_IPMI_KCS=y
|
||||
CONFIG_ISA_IPMI_BT=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_PARALLEL=y
|
||||
CONFIG_I8254=y
|
||||
@@ -51,10 +46,7 @@ CONFIG_APIC=y
|
||||
CONFIG_IOAPIC=y
|
||||
CONFIG_PVPANIC=y
|
||||
CONFIG_MEM_HOTPLUG=y
|
||||
CONFIG_NVDIMM=y
|
||||
CONFIG_ACPI_NVDIMM=y
|
||||
CONFIG_XIO3130=y
|
||||
CONFIG_IOH3420=y
|
||||
CONFIG_I82801B11=y
|
||||
CONFIG_SMBIOS=y
|
||||
CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
|
||||
|
@@ -9,11 +9,6 @@ CONFIG_VGA_CIRRUS=y
|
||||
CONFIG_VMWARE_VGA=y
|
||||
CONFIG_VIRTIO_VGA=y
|
||||
CONFIG_VMMOUSE=y
|
||||
CONFIG_IPMI=y
|
||||
CONFIG_IPMI_LOCAL=y
|
||||
CONFIG_IPMI_EXTERN=y
|
||||
CONFIG_ISA_IPMI_KCS=y
|
||||
CONFIG_ISA_IPMI_BT=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_PARALLEL=y
|
||||
CONFIG_I8254=y
|
||||
@@ -51,10 +46,7 @@ CONFIG_APIC=y
|
||||
CONFIG_IOAPIC=y
|
||||
CONFIG_PVPANIC=y
|
||||
CONFIG_MEM_HOTPLUG=y
|
||||
CONFIG_NVDIMM=y
|
||||
CONFIG_ACPI_NVDIMM=y
|
||||
CONFIG_XIO3130=y
|
||||
CONFIG_IOH3420=y
|
||||
CONFIG_I82801B11=y
|
||||
CONFIG_SMBIOS=y
|
||||
CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
|
||||
|
@@ -4,10 +4,7 @@ common-obj-$(CONFIG_ARM_DIS) += arm.o
|
||||
common-obj-$(CONFIG_ARM_A64_DIS) += arm-a64.o
|
||||
common-obj-$(CONFIG_ARM_A64_DIS) += libvixl/
|
||||
libvixldir = $(SRC_PATH)/disas/libvixl
|
||||
# The -Wno-sign-compare is needed only for gcc 4.6, which complains about
|
||||
# some signed-unsigned equality comparisons in libvixl which later gcc
|
||||
# versions do not.
|
||||
arm-a64.o-cflags := -I$(libvixldir) -Wno-sign-compare
|
||||
arm-a64.o-cflags := -I$(libvixldir)
|
||||
common-obj-$(CONFIG_CRIS_DIS) += cris.o
|
||||
common-obj-$(CONFIG_HPPA_DIS) += hppa.o
|
||||
common-obj-$(CONFIG_I386_DIS) += i386.o
|
||||
|
@@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this file; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <stdio.h>
|
||||
#include "disas/bfd.h"
|
||||
|
||||
/* MAX is redefined below, so remove any previous definition. */
|
||||
|
@@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "vixl/a64/disasm-a64.h"
|
||||
#include "a64/disasm-a64.h"
|
||||
|
||||
extern "C" {
|
||||
#include "disas/bfd.h"
|
||||
|
@@ -22,7 +22,6 @@
|
||||
/* Start of qemu specific additions. Mostly this is stub definitions
|
||||
for things we don't care about. */
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "disas/bfd.h"
|
||||
#define ATTRIBUTE_UNUSED __attribute__((unused))
|
||||
#define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
|
||||
|
@@ -18,7 +18,6 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "disas/bfd.h"
|
||||
//#include "sysdep.h"
|
||||
|
@@ -1,11 +1,8 @@
|
||||
libvixl_OBJS = vixl/utils.o \
|
||||
vixl/compiler-intrinsics.o \
|
||||
vixl/a64/instructions-a64.o \
|
||||
vixl/a64/decoder-a64.o \
|
||||
vixl/a64/disasm-a64.o
|
||||
libvixl_OBJS = utils.o \
|
||||
a64/instructions-a64.o \
|
||||
a64/decoder-a64.o \
|
||||
a64/disasm-a64.o
|
||||
|
||||
# The -Wno-sign-compare is needed only for gcc 4.6, which complains about
|
||||
# some signed-unsigned equality comparisons which later gcc versions do not.
|
||||
$(addprefix $(obj)/,$(libvixl_OBJS)): QEMU_CFLAGS := -I$(SRC_PATH)/disas/libvixl $(QEMU_CFLAGS) -Wno-sign-compare
|
||||
$(addprefix $(obj)/,$(libvixl_OBJS)): QEMU_CFLAGS := -I$(SRC_PATH)/disas/libvixl $(QEMU_CFLAGS)
|
||||
|
||||
common-obj-$(CONFIG_ARM_A64_DIS) += $(libvixl_OBJS)
|
||||
|
@@ -2,10 +2,11 @@
|
||||
The code in this directory is a subset of libvixl:
|
||||
https://github.com/armvixl/vixl
|
||||
(specifically, it is the set of files needed for disassembly only,
|
||||
taken from libvixl 1.12).
|
||||
taken from libvixl 1.7).
|
||||
Bugfixes should preferably be sent upstream initially.
|
||||
|
||||
The disassembler does not currently support the entire A64 instruction
|
||||
set. Notably:
|
||||
* No Advanced SIMD support.
|
||||
* Limited support for system instructions.
|
||||
* A few miscellaneous integer and floating point instructions are missing.
|
||||
|
2353
disas/libvixl/a64/assembler-a64.h
Normal file
2353
disas/libvixl/a64/assembler-a64.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user