diff --git a/block/commit.c b/block/commit.c index acec4ac5a8..5c09f4444e 100644 --- a/block/commit.c +++ b/block/commit.c @@ -194,7 +194,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base, if ((on_error == BLOCKDEV_ON_ERROR_STOP || on_error == BLOCKDEV_ON_ERROR_ENOSPC) && !bdrv_iostatus_is_enabled(bs)) { - error_set(errp, QERR_INVALID_PARAMETER_COMBINATION); + error_setg(errp, "Invalid parameter combination"); return; } diff --git a/blockdev.c b/blockdev.c index 952eb60e3d..7810e9fb68 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1523,14 +1523,16 @@ static void eject_device(BlockDriverState *bs, int force, Error **errp) return; } if (!bdrv_dev_has_removable_media(bs)) { - error_set(errp, QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs)); + error_setg(errp, "Device '%s' is not removable", + bdrv_get_device_name(bs)); return; } if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) { bdrv_dev_eject_request(bs, force); if (!force) { - error_set(errp, QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); + error_setg(errp, "Device '%s' is locked", + bdrv_get_device_name(bs)); return; } } @@ -2222,7 +2224,8 @@ void qmp_block_job_cancel(const char *device, return; } if (job->paused && !force) { - error_set(errp, QERR_BLOCK_JOB_PAUSED, device); + error_setg(errp, "The block job for device '%s' is currently paused", + device); return; } diff --git a/blockjob.c b/blockjob.c index b3ce14cebd..cd4784f053 100644 --- a/blockjob.c +++ b/blockjob.c @@ -88,7 +88,7 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) Error *local_err = NULL; if (!job->driver->set_speed) { - error_set(errp, QERR_NOT_SUPPORTED); + error_set(errp, QERR_UNSUPPORTED); return; } job->driver->set_speed(job, speed, &local_err); diff --git a/hmp-commands.hx b/hmp-commands.hx index f3fc514427..8971f1b153 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -176,7 +176,7 @@ ETEXI { .name = "drive_del", - .args_type = "id:s", + .args_type = "id:B", .params = "device", .help = "remove host block device", .user_print = monitor_user_noop, @@ -658,6 +658,7 @@ ETEXI .help = "add device, like -device on the command line", .user_print = monitor_user_noop, .mhandler.cmd_new = do_device_add, + .command_completion = device_add_completion, }, STEXI @@ -673,6 +674,7 @@ ETEXI .params = "device", .help = "remove device", .mhandler.cmd = hmp_device_del, + .command_completion = device_del_completion, }, STEXI @@ -998,26 +1000,34 @@ ETEXI { .name = "dump-guest-memory", - .args_type = "paging:-p,filename:F,begin:i?,length:i?", - .params = "[-p] filename [begin] [length]", - .help = "dump guest memory to file" - "\n\t\t\t begin(optional): the starting physical address" - "\n\t\t\t length(optional): the memory size, in bytes", + .args_type = "paging:-p,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:i?,length:i?", + .params = "[-p] [-z|-l|-s] filename [begin length]", + .help = "dump guest memory into file 'filename'.\n\t\t\t" + "-p: do paging to get guest's memory mapping.\n\t\t\t" + "-z: dump in kdump-compressed format, with zlib compression.\n\t\t\t" + "-l: dump in kdump-compressed format, with lzo compression.\n\t\t\t" + "-s: dump in kdump-compressed format, with snappy compression.\n\t\t\t" + "begin: the starting physical address.\n\t\t\t" + "length: the memory size, in bytes.", .mhandler.cmd = hmp_dump_guest_memory, }, STEXI -@item dump-guest-memory [-p] @var{protocol} @var{begin} @var{length} +@item dump-guest-memory [-p] @var{filename} @var{begin} @var{length} +@item dump-guest-memory [-z|-l|-s] @var{filename} @findex dump-guest-memory Dump guest memory to @var{protocol}. The file can be processed with crash or -gdb. - filename: dump file name - paging: do paging to get guest's memory mapping +gdb. Without -z|-l|-s, the dump format is ELF. + -p: do paging to get guest's memory mapping. + -z: dump in kdump-compressed format, with zlib compression. + -l: dump in kdump-compressed format, with lzo compression. + -s: dump in kdump-compressed format, with snappy compression. + filename: dump file name. begin: the starting physical address. It's optional, and should be - specified with length together. + specified together with length. length: the memory size, in bytes. It's optional, and should be specified - with begin together. + together with begin. ETEXI { @@ -1254,6 +1264,7 @@ ETEXI .params = "[qom-type=]type,id=str[,prop=value][,...]", .help = "create QOM object", .mhandler.cmd = hmp_object_add, + .command_completion = object_add_completion, }, STEXI @@ -1268,6 +1279,7 @@ ETEXI .params = "id", .help = "destroy QOM object", .mhandler.cmd = hmp_object_del, + .command_completion = object_del_completion, }, STEXI diff --git a/hmp.c b/hmp.c index 2f279c4ff2..ca869bafa8 100644 --- a/hmp.c +++ b/hmp.c @@ -1308,16 +1308,35 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict) { Error *errp = NULL; int paging = qdict_get_try_bool(qdict, "paging", 0); + int zlib = qdict_get_try_bool(qdict, "zlib", 0); + int lzo = qdict_get_try_bool(qdict, "lzo", 0); + int snappy = qdict_get_try_bool(qdict, "snappy", 0); const char *file = qdict_get_str(qdict, "filename"); bool has_begin = qdict_haskey(qdict, "begin"); bool has_length = qdict_haskey(qdict, "length"); - /* kdump-compressed format is not supported for HMP */ - bool has_format = false; int64_t begin = 0; int64_t length = 0; enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF; char *prot; + if (zlib + lzo + snappy > 1) { + error_setg(&errp, "only one of '-z|-l|-s' can be set"); + hmp_handle_error(mon, &errp); + return; + } + + if (zlib) { + dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB; + } + + if (lzo) { + dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO; + } + + if (snappy) { + dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY; + } + if (has_begin) { begin = qdict_get_int(qdict, "begin"); } @@ -1328,7 +1347,7 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict) prot = g_strconcat("file:", file, NULL); qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length, - has_format, dump_format, &errp); + true, dump_format, &errp); hmp_handle_error(mon, &errp); g_free(prot); } diff --git a/hmp.h b/hmp.h index ed58f0ea41..20ef454b4a 100644 --- a/hmp.h +++ b/hmp.h @@ -15,6 +15,7 @@ #define HMP_H #include "qemu-common.h" +#include "qemu/readline.h" #include "qapi-types.h" #include "qapi/qmp/qdict.h" @@ -92,5 +93,9 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict); void hmp_cpu_add(Monitor *mon, const QDict *qdict); void hmp_object_add(Monitor *mon, const QDict *qdict); void hmp_object_del(Monitor *mon, const QDict *qdict); +void object_add_completion(ReadLineState *rs, int nb_args, const char *str); +void object_del_completion(ReadLineState *rs, int nb_args, const char *str); +void device_add_completion(ReadLineState *rs, int nb_args, const char *str); +void device_del_completion(ReadLineState *rs, int nb_args, const char *str); #endif diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 83e4e93983..9aa6725f09 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -987,8 +987,9 @@ static void v9fs_attach(void *opaque) */ if (!s->migration_blocker) { s->root_fid = fid; - error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION, - s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag); + error_setg(&s->migration_blocker, + "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'", + s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag); migrate_add_blocker(s->migration_blocker); } out: diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index c67acf58b5..585a8e902e 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -587,8 +587,9 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque, /* We rely on power-of-2 blocksizes for bitmasks */ if ((value & (value - 1)) != 0) { - error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2, - dev->id?:"", name, (int64_t)value); + error_setg(errp, + "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2", + dev->id ?: "", name, (int64_t)value); return; } @@ -853,7 +854,7 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, { switch (ret) { case -EEXIST: - error_set(errp, QERR_PROPERTY_VALUE_IN_USE, + error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use", object_get_typename(OBJECT(dev)), prop->name, value); break; default: @@ -862,7 +863,7 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, object_get_typename(OBJECT(dev)), prop->name, value); break; case -ENOENT: - error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND, + error_setg(errp, "Property '%s.%s' can't find value '%s'", object_get_typename(OBJECT(dev)), prop->name, value); break; case 0: diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 8d144baa1e..768e5288bc 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -684,8 +684,8 @@ static int pci_ivshmem_init(PCIDevice *dev) } if (s->role_val == IVSHMEM_PEER) { - error_set(&s->migration_blocker, QERR_DEVICE_FEATURE_BLOCKS_MIGRATION, - "peer mode", "ivshmem"); + error_setg(&s->migration_blocker, + "Migration is disabled when using feature 'peer mode' in device 'ivshmem'"); migrate_add_blocker(s->migration_blocker); } diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index a49ea11eb4..42d867155b 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -79,7 +79,6 @@ int monitor_handle_fd_param(Monitor *mon, const char *fdname); void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0); void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3); -void monitor_print_filename(Monitor *mon, const char *filename); void monitor_flush(Monitor *mon); int monitor_set_cpu(int cpu_index); int monitor_get_cpu_index(void); diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h index da75abf6d6..902d1a7a18 100644 --- a/include/qapi/qmp/qerror.h +++ b/include/qapi/qmp/qerror.h @@ -12,7 +12,6 @@ #ifndef QERROR_H #define QERROR_H -#include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" #include "qemu/error-report.h" #include "qapi/error.h" @@ -35,51 +34,30 @@ void qerror_report_err(Error *err); * Please keep the definitions in alphabetical order. * Use scripts/check-qerror.sh to check. */ -#define QERR_ADD_CLIENT_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Could not add client" - -#define QERR_AMBIGUOUS_PATH \ - ERROR_CLASS_GENERIC_ERROR, "Path '%s' does not uniquely identify an object" - -#define QERR_BAD_BUS_FOR_DEVICE \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' can't go on a %s bus" - #define QERR_BASE_NOT_FOUND \ ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found" #define QERR_BLOCK_JOB_NOT_ACTIVE \ ERROR_CLASS_DEVICE_NOT_ACTIVE, "No active block job on device '%s'" -#define QERR_BLOCK_JOB_PAUSED \ - ERROR_CLASS_GENERIC_ERROR, "The block job for device '%s' is currently paused" - #define QERR_BLOCK_JOB_NOT_READY \ ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed" #define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \ ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'" -#define QERR_BUFFER_OVERRUN \ - ERROR_CLASS_GENERIC_ERROR, "An internal buffer overran" - #define QERR_BUS_NO_HOTPLUG \ ERROR_CLASS_GENERIC_ERROR, "Bus '%s' does not support hotplugging" #define QERR_BUS_NOT_FOUND \ ERROR_CLASS_GENERIC_ERROR, "Bus '%s' not found" -#define QERR_COMMAND_DISABLED \ - ERROR_CLASS_GENERIC_ERROR, "The command %s has been disabled for this instance" - #define QERR_COMMAND_NOT_FOUND \ ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found" #define QERR_DEVICE_ENCRYPTED \ ERROR_CLASS_DEVICE_ENCRYPTED, "'%s' (%s) is encrypted" -#define QERR_DEVICE_FEATURE_BLOCKS_MIGRATION \ - ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when using feature '%s' in device '%s'" - #define QERR_DEVICE_HAS_NO_MEDIUM \ ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no medium" @@ -92,15 +70,6 @@ void qerror_report_err(Error *err); #define QERR_DEVICE_IS_READ_ONLY \ ERROR_CLASS_GENERIC_ERROR, "Device '%s' is read only" -#define QERR_DEVICE_LOCKED \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' is locked" - -#define QERR_DEVICE_MULTIPLE_BUSSES \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' has multiple child busses" - -#define QERR_DEVICE_NO_BUS \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no child bus" - #define QERR_DEVICE_NO_HOTPLUG \ ERROR_CLASS_GENERIC_ERROR, "Device '%s' does not support hotplugging" @@ -113,12 +82,6 @@ void qerror_report_err(Error *err); #define QERR_DEVICE_NOT_FOUND \ ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found" -#define QERR_DEVICE_NOT_REMOVABLE \ - ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not removable" - -#define QERR_DUPLICATE_ID \ - ERROR_CLASS_GENERIC_ERROR, "Duplicate ID '%s' for %s" - #define QERR_FD_NOT_FOUND \ ERROR_CLASS_GENERIC_ERROR, "File descriptor named '%s' not found" @@ -131,15 +94,9 @@ void qerror_report_err(Error *err); #define QERR_INVALID_BLOCK_FORMAT \ ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'" -#define QERR_INVALID_OPTION_GROUP \ - ERROR_CLASS_GENERIC_ERROR, "There is no option group '%s'" - #define QERR_INVALID_PARAMETER \ ERROR_CLASS_GENERIC_ERROR, "Invalid parameter '%s'" -#define QERR_INVALID_PARAMETER_COMBINATION \ - ERROR_CLASS_GENERIC_ERROR, "Invalid parameter combination" - #define QERR_INVALID_PARAMETER_TYPE \ ERROR_CLASS_GENERIC_ERROR, "Invalid parameter type for '%s', expected: %s" @@ -152,9 +109,6 @@ void qerror_report_err(Error *err); #define QERR_IO_ERROR \ ERROR_CLASS_GENERIC_ERROR, "An IO error has occurred" -#define QERR_JSON_PARSE_ERROR \ - ERROR_CLASS_GENERIC_ERROR, "JSON parse error, %s" - #define QERR_JSON_PARSING \ ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax" @@ -164,45 +118,21 @@ void qerror_report_err(Error *err); #define QERR_MIGRATION_ACTIVE \ ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress" -#define QERR_MIGRATION_NOT_SUPPORTED \ - ERROR_CLASS_GENERIC_ERROR, "State blocked by non-migratable device '%s'" - #define QERR_MISSING_PARAMETER \ ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' is missing" -#define QERR_NO_BUS_FOR_DEVICE \ - ERROR_CLASS_GENERIC_ERROR, "No '%s' bus found for device '%s'" - -#define QERR_NOT_SUPPORTED \ - ERROR_CLASS_GENERIC_ERROR, "Not supported" - #define QERR_PERMISSION_DENIED \ ERROR_CLASS_GENERIC_ERROR, "Insufficient permission to perform this operation" -#define QERR_PROPERTY_NOT_FOUND \ - ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' not found" - #define QERR_PROPERTY_VALUE_BAD \ ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' doesn't take value '%s'" -#define QERR_PROPERTY_VALUE_IN_USE \ - ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't take value '%s', it's in use" - -#define QERR_PROPERTY_VALUE_NOT_FOUND \ - ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' can't find value '%s'" - -#define QERR_PROPERTY_VALUE_NOT_POWER_OF_2 \ - ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2" - #define QERR_PROPERTY_VALUE_OUT_OF_RANGE \ ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")" #define QERR_QGA_COMMAND_FAILED \ ERROR_CLASS_GENERIC_ERROR, "Guest agent command failed, error was '%s'" -#define QERR_QGA_LOGGING_FAILED \ - ERROR_CLASS_GENERIC_ERROR, "Guest agent failed to log non-optional log statement" - #define QERR_QMP_BAD_INPUT_OBJECT \ ERROR_CLASS_GENERIC_ERROR, "Expected '%s' in QMP input" @@ -212,15 +142,9 @@ void qerror_report_err(Error *err); #define QERR_QMP_EXTRA_MEMBER \ ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' is unexpected" -#define QERR_RESET_REQUIRED \ - ERROR_CLASS_GENERIC_ERROR, "Resetting the Virtual Machine is required" - #define QERR_SET_PASSWD_FAILED \ ERROR_CLASS_GENERIC_ERROR, "Could not set password" -#define QERR_TOO_MANY_FILES \ - ERROR_CLASS_GENERIC_ERROR, "Too many open files" - #define QERR_UNDEFINED_ERROR \ ERROR_CLASS_GENERIC_ERROR, "An undefined error has occurred" @@ -230,9 +154,6 @@ void qerror_report_err(Error *err); #define QERR_UNSUPPORTED \ ERROR_CLASS_GENERIC_ERROR, "this feature or command is not currently supported" -#define QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION \ - ERROR_CLASS_GENERIC_ERROR, "Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'" - #define QERR_SOCKET_CONNECT_FAILED \ ERROR_CLASS_GENERIC_ERROR, "Failed to connect to socket" diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h index 3b098a9173..000eae3957 100644 --- a/include/qemu/error-report.h +++ b/include/qemu/error-report.h @@ -37,7 +37,6 @@ void loc_set_file(const char *fname, int lno); void error_vprintf(const char *fmt, va_list ap) GCC_FMT_ATTR(1, 0); void error_printf(const char *fmt, ...) GCC_FMT_ATTR(1, 2); void error_printf_unless_qmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2); -void error_print_loc(void); void error_set_progname(const char *argv0); void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2); const char *error_get_progname(void); diff --git a/monitor.c b/monitor.c index 342e83baea..1266ba06fb 100644 --- a/monitor.c +++ b/monitor.c @@ -137,6 +137,7 @@ typedef struct mon_cmd_t { * used, and mhandler of 1st level plays the role of help function. */ struct mon_cmd_t *sub_table; + void (*command_completion)(ReadLineState *rs, int nb_args, const char *str); } mon_cmd_t; /* file descriptors passed via SCM_RIGHTS */ @@ -352,33 +353,6 @@ void monitor_printf(Monitor *mon, const char *fmt, ...) va_end(ap); } -void monitor_print_filename(Monitor *mon, const char *filename) -{ - int i; - - for (i = 0; filename[i]; i++) { - switch (filename[i]) { - case ' ': - case '"': - case '\\': - monitor_printf(mon, "\\%c", filename[i]); - break; - case '\t': - monitor_printf(mon, "\\t"); - break; - case '\r': - monitor_printf(mon, "\\r"); - break; - case '\n': - monitor_printf(mon, "\\n"); - break; - default: - monitor_printf(mon, "%c", filename[i]); - break; - } - } -} - static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream, const char *fmt, ...) { @@ -2254,6 +2228,7 @@ void qmp_getfd(const char *fdname, Error **errp) } if (qemu_isdigit(fdname[0])) { + close(fd); error_set(errp, QERR_INVALID_PARAMETER_VALUE, "fdname", "a name not starting with a digit"); return; @@ -4277,11 +4252,15 @@ static const char *next_arg_type(const char *typestr) return (p != NULL ? ++p : typestr); } -static void device_add_completion(ReadLineState *rs, const char *str) +void device_add_completion(ReadLineState *rs, int nb_args, const char *str) { GSList *list, *elt; size_t len; + if (nb_args != 2) { + return; + } + len = strlen(str); readline_set_completion_index(rs, len); list = elt = object_class_get_list(TYPE_DEVICE, false); @@ -4290,7 +4269,9 @@ static void device_add_completion(ReadLineState *rs, const char *str) DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data, TYPE_DEVICE); name = object_class_get_name(OBJECT_CLASS(dc)); - if (!strncmp(name, str, len)) { + + if (!dc->cannot_instantiate_with_device_add_yet + && !strncmp(name, str, len)) { readline_add_completion(rs, name); } elt = elt->next; @@ -4298,11 +4279,15 @@ static void device_add_completion(ReadLineState *rs, const char *str) g_slist_free(list); } -static void object_add_completion(ReadLineState *rs, const char *str) +void object_add_completion(ReadLineState *rs, int nb_args, const char *str) { GSList *list, *elt; size_t len; + if (nb_args != 2) { + return; + } + len = strlen(str); readline_set_completion_index(rs, len); list = elt = object_class_get_list(TYPE_USER_CREATABLE, false); @@ -4318,8 +4303,8 @@ static void object_add_completion(ReadLineState *rs, const char *str) g_slist_free(list); } -static void device_del_completion(ReadLineState *rs, BusState *bus, - const char *str, size_t len) +static void device_del_bus_completion(ReadLineState *rs, BusState *bus, + const char *str, size_t len) { BusChild *kid; @@ -4332,16 +4317,32 @@ static void device_del_completion(ReadLineState *rs, BusState *bus, } QLIST_FOREACH(dev_child, &dev->child_bus, sibling) { - device_del_completion(rs, dev_child, str, len); + device_del_bus_completion(rs, dev_child, str, len); } } } -static void object_del_completion(ReadLineState *rs, const char *str) +void device_del_completion(ReadLineState *rs, int nb_args, const char *str) +{ + size_t len; + + if (nb_args != 2) { + return; + } + + len = strlen(str); + readline_set_completion_index(rs, len); + device_del_bus_completion(rs, sysbus_get_default(), str, len); +} + +void object_del_completion(ReadLineState *rs, int nb_args, const char *str) { ObjectPropertyInfoList *list, *start; size_t len; + if (nb_args != 2) { + return; + } len = strlen(str); readline_set_completion_index(rs, len); @@ -4395,6 +4396,9 @@ static void monitor_find_completion_by_table(Monitor *mon, return monitor_find_completion_by_table(mon, cmd->sub_table, &args[1], nb_args - 1); } + if (cmd->command_completion) { + return cmd->command_completion(mon->rs, nb_args, args[nb_args - 1]); + } ptype = next_arg_type(cmd->args_type); for(i = 0; i < nb_args - 2; i++) { @@ -4421,13 +4425,6 @@ static void monitor_find_completion_by_table(Monitor *mon, readline_set_completion_index(mon->rs, strlen(str)); bdrv_iterate(block_completion_it, &mbs); break; - case 'O': - if (!strcmp(cmd->name, "device_add") && nb_args == 2) { - device_add_completion(mon->rs, str); - } else if (!strcmp(cmd->name, "object_add") && nb_args == 2) { - object_add_completion(mon->rs, str); - } - break; case 's': case 'S': if (!strcmp(cmd->name, "sendkey")) { @@ -4441,12 +4438,6 @@ static void monitor_find_completion_by_table(Monitor *mon, } else if (!strcmp(cmd->name, "help|?")) { monitor_find_completion_by_table(mon, cmd_table, &args[1], nb_args - 1); - } else if (!strcmp(cmd->name, "device_del") && nb_args == 2) { - size_t len = strlen(str); - readline_set_completion_index(mon->rs, len); - device_del_completion(mon->rs, sysbus_get_default(), str, len); - } else if (!strcmp(cmd->name, "object_del") && nb_args == 2) { - object_del_completion(mon->rs, str); } break; default: diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 921de33bce..9c614494f1 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -80,7 +80,8 @@ static QObject *do_qmp_dispatch(QObject *request, Error **errp) return NULL; } if (!cmd->enabled) { - error_set(errp, QERR_COMMAND_DISABLED, command); + error_setg(errp, "The command %s has been disabled for this instance", + command); return NULL; } diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index bf42c04ea6..a2bed1ef10 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -71,7 +71,7 @@ static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp) GHashTable *h; if (qiv->nb_stack >= QIV_STACK_SIZE) { - error_set(errp, QERR_BUFFER_OVERRUN); + error_setg(errp, "An internal buffer overran"); return; } diff --git a/qdev-monitor.c b/qdev-monitor.c index 9268c8759f..6189780fd7 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -422,12 +422,14 @@ static BusState *qbus_find(const char *path) * one child bus accept it nevertheless */ switch (dev->num_child_bus) { case 0: - qerror_report(QERR_DEVICE_NO_BUS, elem); + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "Device '%s' has no child bus", elem); return NULL; case 1: return QLIST_FIRST(&dev->child_bus); default: - qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem); + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "Device '%s' has multiple child busses", elem); if (!monitor_cur_is_qmp()) { qbus_list_bus(dev); } @@ -505,14 +507,16 @@ DeviceState *qdev_device_add(QemuOpts *opts) return NULL; } if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) { - qerror_report(QERR_BAD_BUS_FOR_DEVICE, + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "Device '%s' can't go on a %s bus", driver, object_get_typename(OBJECT(bus))); return NULL; } } else if (dc->bus_type != NULL) { bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type); if (!bus) { - qerror_report(QERR_NO_BUS_FOR_DEVICE, + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "No '%s' bus found for device '%s'", dc->bus_type, driver); return NULL; } diff --git a/qmp.c b/qmp.c index 87a28f797d..74107be41b 100644 --- a/qmp.c +++ b/qmp.c @@ -166,7 +166,7 @@ void qmp_cont(Error **errp) Error *local_err = NULL; if (runstate_needs_reset()) { - error_set(errp, QERR_RESET_REQUIRED); + error_setg(errp, "Resetting the Virtual Machine is required"); return; } else if (runstate_check(RUN_STATE_SUSPENDED)) { return; @@ -540,14 +540,27 @@ void object_add(const char *type, const char *id, const QDict *qdict, Visitor *v, Error **errp) { Object *obj; + ObjectClass *klass; const QDictEntry *e; Error *local_err = NULL; - if (!object_class_by_name(type)) { + klass = object_class_by_name(type); + if (!klass) { error_setg(errp, "invalid class name"); return; } + if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { + error_setg(errp, "object type '%s' isn't supported by object-add", + type); + return; + } + + if (object_class_is_abstract(klass)) { + error_setg(errp, "object type '%s' is abstract", type); + return; + } + obj = object_new(type); if (qdict) { for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { @@ -558,12 +571,6 @@ void object_add(const char *type, const char *id, const QDict *qdict, } } - if (!object_dynamic_cast(obj, TYPE_USER_CREATABLE)) { - error_setg(&local_err, "object type '%s' isn't supported by object-add", - type); - goto out; - } - user_creatable_complete(obj, &local_err); if (local_err) { goto out; diff --git a/qobject/json-parser.c b/qobject/json-parser.c index e7947b340c..e46c26448e 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -110,7 +110,7 @@ static void GCC_FMT_ATTR(3, 4) parse_error(JSONParserContext *ctxt, error_free(ctxt->err); ctxt->err = NULL; } - error_set(&ctxt->err, QERR_JSON_PARSE_ERROR, message); + error_setg(&ctxt->err, "JSON parse error, %s", message); } /** diff --git a/qom/object.c b/qom/object.c index 9a730e74c1..e42b254303 100644 --- a/qom/object.c +++ b/qom/object.c @@ -768,7 +768,7 @@ ObjectProperty *object_property_find(Object *obj, const char *name, } } - error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); + error_setg(errp, "Property '.%s' not found", name); return NULL; } @@ -1075,7 +1075,8 @@ static Object *object_resolve_link(Object *obj, const char *name, target = object_resolve_path_type(path, target_type, &ambiguous); if (ambiguous) { - error_set(errp, QERR_AMBIGUOUS_PATH, path); + error_set(errp, ERROR_CLASS_GENERIC_ERROR, + "Path '%s' does not uniquely identify an object", path); } else if (!target) { target = object_resolve_path(path, &ambiguous); if (target || ambiguous) { diff --git a/savevm.c b/savevm.c index 22123be4f9..da8aa2428d 100644 --- a/savevm.c +++ b/savevm.c @@ -453,7 +453,8 @@ bool qemu_savevm_state_blocked(Error **errp) QTAILQ_FOREACH(se, &savevm_handlers, entry) { if (se->no_migrate) { - error_set(errp, QERR_MIGRATION_NOT_SUPPORTED, se->idstr); + error_setg(errp, "State blocked by non-migratable device '%s'", + se->idstr); return true; } } diff --git a/slirp/misc.c b/slirp/misc.c index 6c1636f7b6..b8eb74cab0 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -136,7 +136,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty) if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || listen(s, 1) < 0) { - lprint("Error: inet socket: %s\n", strerror(errno)); + error_report("Error: inet socket: %s", strerror(errno)); closesocket(s); return 0; @@ -146,7 +146,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty) pid = fork(); switch(pid) { case -1: - lprint("Error: fork failed: %s\n", strerror(errno)); + error_report("Error: fork failed: %s", strerror(errno)); close(s); return 0; @@ -242,15 +242,6 @@ strdup(str) } #endif -void lprint(const char *format, ...) -{ - va_list args; - - va_start(args, format); - monitor_vprintf(default_mon, format, args); - va_end(args); -} - void slirp_connection_info(Slirp *slirp, Monitor *mon) { const char * const tcpstates[] = { diff --git a/slirp/slirp.c b/slirp/slirp.c index bad8dad02e..3fb48a4921 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -139,7 +139,7 @@ int get_dns_addr(struct in_addr *pdns_addr) return -1; #ifdef DEBUG - lprint("IP address of your DNS(s): "); + fprintf(stderr, "IP address of your DNS(s): "); #endif while (fgets(buff, 512, f) != NULL) { if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) { @@ -153,17 +153,17 @@ int get_dns_addr(struct in_addr *pdns_addr) } #ifdef DEBUG else - lprint(", "); + fprintf(stderr, ", "); #endif if (++found > 3) { #ifdef DEBUG - lprint("(more)"); + fprintf(stderr, "(more)"); #endif break; } #ifdef DEBUG else - lprint("%s", inet_ntoa(tmp_addr)); + fprintf(stderr, "%s", inet_ntoa(tmp_addr)); #endif } } diff --git a/slirp/slirp.h b/slirp/slirp.h index e4a1bd4abb..6589d7eef0 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -287,8 +287,6 @@ void if_start(struct ttys *); long gethostid(void); #endif -void lprint(const char *, ...) GCC_FMT_ATTR(1, 2); - #ifndef _WIN32 #include #endif diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs index 5ed1d38d70..d99e2b9259 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -14,7 +14,6 @@ stub-obj-y += iothread-lock.o stub-obj-y += migr-blocker.o stub-obj-y += mon-is-qmp.o stub-obj-y += mon-printf.o -stub-obj-y += mon-print-filename.o stub-obj-y += mon-protocol-event.o stub-obj-y += mon-set-error.o stub-obj-y += pci-drive-hot-add.o diff --git a/stubs/arch-query-cpu-def.c b/stubs/arch-query-cpu-def.c index fa6789598a..22e0b43de9 100644 --- a/stubs/arch-query-cpu-def.c +++ b/stubs/arch-query-cpu-def.c @@ -4,6 +4,6 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) { - error_set(errp, QERR_NOT_SUPPORTED); + error_set(errp, QERR_UNSUPPORTED); return NULL; } diff --git a/stubs/mon-print-filename.c b/stubs/mon-print-filename.c deleted file mode 100644 index 9c939641ff..0000000000 --- a/stubs/mon-print-filename.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "qemu-common.h" -#include "monitor/monitor.h" - -void monitor_print_filename(Monitor *mon, const char *filename) -{ -} diff --git a/ui/vnc.c b/ui/vnc.c index 5925774509..2d7def9aa2 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -996,7 +996,7 @@ static void audio_add(VncState *vs) struct audio_capture_ops ops; if (vs->audio_cap) { - monitor_printf(default_mon, "audio already running\n"); + error_report("audio already running"); return; } @@ -1006,7 +1006,7 @@ static void audio_add(VncState *vs) vs->audio_cap = AUD_add_capture(&vs->as, &ops, vs); if (!vs->audio_cap) { - monitor_printf(default_mon, "Failed to add audio capture\n"); + error_report("Failed to add audio capture"); } } diff --git a/util/error.c b/util/error.c index f11f1d57a0..2bb42e1c4b 100644 --- a/util/error.c +++ b/util/error.c @@ -12,10 +12,7 @@ #include "qemu-common.h" #include "qapi/error.h" -#include "qapi/qmp/qjson.h" -#include "qapi/qmp/qdict.h" -#include "qapi-types.h" -#include "qapi/qmp/qerror.h" +#include "qemu/error-report.h" struct Error { diff --git a/util/qemu-config.c b/util/qemu-config.c index f6101012c0..bcf0b86f91 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -20,7 +20,7 @@ static QemuOptsList *find_list(QemuOptsList **lists, const char *group, break; } if (lists[i] == NULL) { - error_set(errp, QERR_INVALID_OPTION_GROUP, group); + error_setg(errp, "There is no option group '%s'", group); } return lists[i]; } diff --git a/util/qemu-error.c b/util/qemu-error.c index fec02c6075..7b167fd06b 100644 --- a/util/qemu-error.c +++ b/util/qemu-error.c @@ -20,7 +20,7 @@ */ void error_vprintf(const char *fmt, va_list ap) { - if (cur_mon) { + if (cur_mon && !monitor_cur_is_qmp()) { monitor_vprintf(cur_mon, fmt, ap); } else { vfprintf(stderr, fmt, ap); @@ -165,7 +165,7 @@ const char *error_get_progname(void) /* * Print current location to current monitor if we have one, else to stderr. */ -void error_print_loc(void) +static void error_print_loc(void) { const char *sep = ""; int i; diff --git a/util/qemu-option.c b/util/qemu-option.c index 9d898af443..8bbc3ad4a3 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -819,7 +819,7 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, opts = qemu_opts_find(list, id); if (opts != NULL) { if (fail_if_exists && !list->merge_lists) { - error_set(errp, QERR_DUPLICATE_ID, id, list->name); + error_setg(errp, "Duplicate ID '%s' for %s", id, list->name); return NULL; } else { return opts;