diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 69eede6c28..f3e7ced212 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -1321,6 +1321,7 @@ Example: }; void qapi_free_UserDefOne(UserDefOne *obj); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(UserDefOne, qapi_free_UserDefOne) struct UserDefOneList { UserDefOneList *next; @@ -1328,6 +1329,7 @@ Example: }; void qapi_free_UserDefOneList(UserDefOneList *obj); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(UserDefOneList, qapi_free_UserDefOneList) struct q_obj_my_command_arg { UserDefOneList *arg1; diff --git a/docs/interop/qmp-spec.txt b/docs/interop/qmp-spec.txt index adcf86754d..cdf5842555 100644 --- a/docs/interop/qmp-spec.txt +++ b/docs/interop/qmp-spec.txt @@ -110,6 +110,9 @@ or if provided. The "id" member can be any json-value. A json-number incremented for each successive command works fine. +The actual commands are documented in the QEMU QMP reference manual +docs/interop/qemu-qmp-ref.{7,html,info,pdf,txt}. + 2.3.1 Out-of-band execution --------------------------- @@ -207,13 +210,13 @@ The format of asynchronous events is: there is a failure to retrieve host time, both members of the timestamp will be set to -1. -For a listing of supported asynchronous events, please, refer to the -qmp-events.txt file. +The actual asynchronous events are documented in the QEMU QMP +reference manual docs/interop/qemu-qmp-ref.{7,html,info,pdf,txt}. Some events are rate-limited to at most one per second. If additional "similar" events arrive within one second, all but the last one are dropped, and the last one is delayed. "Similar" normally means same -event type. See qmp-events.txt for details. +event type. 2.6 Forcing the JSON parser into known-good state ------------------------------------------------- diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt index 9889521e3c..245cdf29c7 100644 --- a/docs/qdev-device-use.txt +++ b/docs/qdev-device-use.txt @@ -125,7 +125,14 @@ The -device argument differs in detail for each type of drive: * if=pflash, if=mtd, if=sd, if=xen are not yet available with -device -For USB storage devices, you can use something like: +For USB devices, the old way was actually different: + + -usbdevice disk:format=FMT:FILENAME + +"Was" because "disk:" is gone since v2.12.0. + +The old way provided much less control than -drive's OPTS... The new +way fixes that: -device usb-storage,drive=DRIVE-ID,removable=RMB @@ -178,6 +185,9 @@ The appropriate DEVNAME depends on the machine type. For type "pc": -device usb-braille,chardev=braille -chardev braille,id=braille +* -usbdevice serial::chardev is gone since v2.12.0. It became + -device usb-serial,chardev=dev. + LEGACY-CHARDEV translates to -chardev HOST-OPTS... as follows: * null becomes -chardev null @@ -231,6 +241,12 @@ The old way to define the guest part looks like this: -net nic,netdev=NET-ID,macaddr=MACADDR,model=MODEL,name=ID,addr=STR,vectors=V +Except for USB it looked like this: + + -usbdevice net:netdev=NET-ID,macaddr=MACADDR,name=ID + +"Looked" because "net:" is gone since v2.12.0. + The new way is -device: -device DEVNAME,netdev=NET-ID,mac=MACADDR,DEV-OPTS... @@ -328,6 +344,13 @@ The new way is -device DEVNAME,DEV-OPTS... Details depend on DRIVER: * u2f -device u2f-{emulated,passthru} * braille See "Character Devices" +Until v2.12.0, we additionally had + +* host:... See "Host Device Assignment" +* disk:... See "Block Devices" +* serial:... See "Character Devices" +* net:... See "Network Devices" + === Watchdog Devices === Host and guest part of watchdog devices have always been separate. @@ -343,7 +366,14 @@ and host USB devices. PCI devices can only be assigned with -device: -device vfio-pci,host=ADDR,id=ID -To assign a host USB device use: +The old way to assign a USB host device + + -usbdevice host:auto:BUS.ADDR:VID:PRID + +was removed in v2.12.0. Any of BUS, ADDR, VID, PRID could be the +wildcard *. + +The new way is -device usb-host,hostbus=BUS,hostaddr=ADDR,vendorid=VID,productid=PRID diff --git a/include/crypto/block.h b/include/crypto/block.h index d274819791..7a65e8e402 100644 --- a/include/crypto/block.h +++ b/include/crypto/block.h @@ -311,7 +311,5 @@ uint64_t qcrypto_block_get_sector_size(QCryptoBlock *block); void qcrypto_block_free(QCryptoBlock *block); G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlock, qcrypto_block_free) -G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlockCreateOptions, - qapi_free_QCryptoBlockCreateOptions) #endif /* QCRYPTO_BLOCK_H */ diff --git a/qapi/block-core.json b/qapi/block-core.json index db08c58d78..55b58ba892 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -4036,9 +4036,7 @@ ## # @blockdev-add: # -# Creates a new block device. If the @id option is given at the top level, a -# BlockBackend will be created; otherwise, @node-name is mandatory at the top -# level and no BlockBackend will be created. +# Creates a new block device. # # Since: 2.9 # diff --git a/qapi/char.json b/qapi/char.json index 8aeedf96b2..b4d66ec90b 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -562,6 +562,8 @@ # # @open: true if the guest has opened the virtio-serial port # +# Note: This event is rate-limited. +# # Since: 2.1 # # Example: diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py index 3ad33af4ee..3640f17cd6 100644 --- a/scripts/qapi/types.py +++ b/scripts/qapi/types.py @@ -213,6 +213,7 @@ def gen_type_cleanup_decl(name): ret = mcgen(''' void qapi_free_%(c_name)s(%(c_name)s *obj); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(%(c_name)s, qapi_free_%(c_name)s) ''', c_name=c_name(name)) return ret diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse index 5fa6b3bf64..7c7cff8edf 100755 --- a/scripts/qmp/qom-fuse +++ b/scripts/qmp/qom-fuse @@ -3,17 +3,19 @@ # QEMU Object Model test tools # # Copyright IBM, Corp. 2012 +# Copyright (C) 2020 Red Hat, Inc. # # Authors: # Anthony Liguori +# Markus Armbruster # # This work is licensed under the terms of the GNU GPL, version 2 or later. See # the COPYING file in the top-level directory. ## import fuse, stat -from fuse import Fuse -import os, posix +from fuse import FUSE, FuseOSError, Operations +import os, posix, sys from errno import * sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) @@ -21,9 +23,8 @@ from qemu.qmp import QEMUMonitorProtocol fuse.fuse_python_api = (0, 2) -class QOMFS(Fuse): - def __init__(self, qmp, *args, **kwds): - Fuse.__init__(self, *args, **kwds) +class QOMFS(Operations): + def __init__(self, qmp): self.qmp = qmp self.qmp.connect() self.ino_map = {} @@ -44,8 +45,10 @@ class QOMFS(Fuse): return False def is_property(self, path): + path, prop = path.rsplit('/', 1) + if path == '': + path = '/' try: - path, prop = path.rsplit('/', 1) for item in self.qmp.command('qom-list', path=path): if item['name'] == prop: return True @@ -54,8 +57,10 @@ class QOMFS(Fuse): return False def is_link(self, path): + path, prop = path.rsplit('/', 1) + if path == '': + path = '/' try: - path, prop = path.rsplit('/', 1) for item in self.qmp.command('qom-list', path=path): if item['name'] == prop: if item['type'].startswith('link<'): @@ -65,21 +70,23 @@ class QOMFS(Fuse): except: return False - def read(self, path, length, offset): + def read(self, path, length, offset, fh): if not self.is_property(path): return -ENOENT path, prop = path.rsplit('/', 1) + if path == '': + path = '/' try: - data = str(self.qmp.command('qom-get', path=path, property=prop)) + data = self.qmp.command('qom-get', path=path, property=prop) data += '\n' # make values shell friendly except: - return -EPERM + raise FuseOSError(EPERM) if offset > len(data): return '' - return str(data[offset:][:length]) + return bytes(data[offset:][:length], encoding='utf-8') def readlink(self, path): if not self.is_link(path): @@ -89,52 +96,52 @@ class QOMFS(Fuse): return prefix + str(self.qmp.command('qom-get', path=path, property=prop)) - def getattr(self, path): + def getattr(self, path, fh=None): if self.is_link(path): - value = posix.stat_result((0o755 | stat.S_IFLNK, - self.get_ino(path), - 0, - 2, - 1000, - 1000, - 4096, - 0, - 0, - 0)) + value = { 'st_mode': 0o755 | stat.S_IFLNK, + 'st_ino': self.get_ino(path), + 'st_dev': 0, + 'st_nlink': 2, + 'st_uid': 1000, + 'st_gid': 1000, + 'st_size': 4096, + 'st_atime': 0, + 'st_mtime': 0, + 'st_ctime': 0 } elif self.is_object(path): - value = posix.stat_result((0o755 | stat.S_IFDIR, - self.get_ino(path), - 0, - 2, - 1000, - 1000, - 4096, - 0, - 0, - 0)) + value = { 'st_mode': 0o755 | stat.S_IFDIR, + 'st_ino': self.get_ino(path), + 'st_dev': 0, + 'st_nlink': 2, + 'st_uid': 1000, + 'st_gid': 1000, + 'st_size': 4096, + 'st_atime': 0, + 'st_mtime': 0, + 'st_ctime': 0 } elif self.is_property(path): - value = posix.stat_result((0o644 | stat.S_IFREG, - self.get_ino(path), - 0, - 1, - 1000, - 1000, - 4096, - 0, - 0, - 0)) + value = { 'st_mode': 0o644 | stat.S_IFREG, + 'st_ino': self.get_ino(path), + 'st_dev': 0, + 'st_nlink': 1, + 'st_uid': 1000, + 'st_gid': 1000, + 'st_size': 4096, + 'st_atime': 0, + 'st_mtime': 0, + 'st_ctime': 0 } else: - value = -ENOENT + raise FuseOSError(ENOENT) return value - def readdir(self, path, offset): - yield fuse.Direntry('.') - yield fuse.Direntry('..') + def readdir(self, path, fh): + yield '.' + yield '..' for item in self.qmp.command('qom-list', path=path): - yield fuse.Direntry(str(item['name'])) + yield str(item['name']) if __name__ == '__main__': - import sys, os + import os - fs = QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET'])) - fs.main(sys.argv) + fuse = FUSE(QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET'])), + sys.argv[1], foreground=True) diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c index 6bacabf063..e41b91a2a6 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -417,7 +417,7 @@ static void test_visitor_in_struct(TestInputVisitorData *data, static void test_visitor_in_struct_nested(TestInputVisitorData *data, const void *unused) { - UserDefTwo *udp = NULL; + g_autoptr(UserDefTwo) udp = NULL; Visitor *v; v = visitor_input_test_init(data, "{ 'string0': 'string0', " @@ -433,8 +433,6 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data, g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string"); g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2"); g_assert(udp->dict1->has_dict3 == false); - - qapi_free_UserDefTwo(udp); } static void test_visitor_in_list(TestInputVisitorData *data, @@ -546,7 +544,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, const void *unused) { Visitor *v; - UserDefFlatUnion *tmp; + g_autoptr(UserDefFlatUnion) tmp = NULL; UserDefUnionBase *base; v = visitor_input_test_init(data, @@ -563,8 +561,6 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, base = qapi_UserDefFlatUnion_base(tmp); g_assert(&base->enum1 == &tmp->enum1); - - qapi_free_UserDefFlatUnion(tmp); } static void test_visitor_in_alternate(TestInputVisitorData *data, @@ -690,7 +686,7 @@ static void test_list_union_integer_helper(TestInputVisitorData *data, const void *unused, UserDefListUnionKind kind) { - UserDefListUnion *cvalue = NULL; + g_autoptr(UserDefListUnion) cvalue = NULL; Visitor *v; GString *gstr_list = g_string_new(""); GString *gstr_union = g_string_new(""); @@ -782,7 +778,6 @@ static void test_list_union_integer_helper(TestInputVisitorData *data, g_string_free(gstr_union, true); g_string_free(gstr_list, true); - qapi_free_UserDefListUnion(cvalue); } static void test_visitor_in_list_union_int(TestInputVisitorData *data, @@ -851,7 +846,7 @@ static void test_visitor_in_list_union_uint64(TestInputVisitorData *data, static void test_visitor_in_list_union_bool(TestInputVisitorData *data, const void *unused) { - UserDefListUnion *cvalue = NULL; + g_autoptr(UserDefListUnion) cvalue = NULL; boolList *elem = NULL; Visitor *v; GString *gstr_list = g_string_new(""); @@ -879,13 +874,12 @@ static void test_visitor_in_list_union_bool(TestInputVisitorData *data, g_string_free(gstr_union, true); g_string_free(gstr_list, true); - qapi_free_UserDefListUnion(cvalue); } static void test_visitor_in_list_union_string(TestInputVisitorData *data, const void *unused) { - UserDefListUnion *cvalue = NULL; + g_autoptr(UserDefListUnion) cvalue = NULL; strList *elem = NULL; Visitor *v; GString *gstr_list = g_string_new(""); @@ -914,7 +908,6 @@ static void test_visitor_in_list_union_string(TestInputVisitorData *data, g_string_free(gstr_union, true); g_string_free(gstr_list, true); - qapi_free_UserDefListUnion(cvalue); } #define DOUBLE_STR_MAX 16 @@ -922,7 +915,7 @@ static void test_visitor_in_list_union_string(TestInputVisitorData *data, static void test_visitor_in_list_union_number(TestInputVisitorData *data, const void *unused) { - UserDefListUnion *cvalue = NULL; + g_autoptr(UserDefListUnion) cvalue = NULL; numberList *elem = NULL; Visitor *v; GString *gstr_list = g_string_new(""); @@ -957,7 +950,6 @@ static void test_visitor_in_list_union_number(TestInputVisitorData *data, g_string_free(gstr_union, true); g_string_free(gstr_list, true); - qapi_free_UserDefListUnion(cvalue); } static void input_visitor_test_add(const char *testpath, @@ -1253,7 +1245,7 @@ static void test_visitor_in_fail_alternate(TestInputVisitorData *data, static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data, const QLitObject *qlit) { - SchemaInfoList *schema = NULL; + g_autoptr(SchemaInfoList) schema = NULL; QObject *obj = qobject_from_qlit(qlit); Visitor *v; @@ -1262,7 +1254,6 @@ static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data, visit_type_SchemaInfoList(v, NULL, &schema, &error_abort); g_assert(schema); - qapi_free_SchemaInfoList(schema); qobject_unref(obj); visit_free(v); }