diff --git a/hmp-commands.hx b/hmp-commands.hx index f5d9d91de8..eea8b32894 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1236,8 +1236,7 @@ ETEXI .args_type = "fdname:s", .params = "getfd name", .help = "receive a file descriptor via SCM rights and assign it a name", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_getfd, + .mhandler.cmd = hmp_getfd, }, STEXI @@ -1253,8 +1252,7 @@ ETEXI .args_type = "fdname:s", .params = "closefd name", .help = "close a file descriptor previously passed via SCM rights", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_closefd, + .mhandler.cmd = hmp_closefd, }, STEXI diff --git a/hmp.c b/hmp.c index 4c6d4ae942..6b72a64d99 100644 --- a/hmp.c +++ b/hmp.c @@ -1002,3 +1002,21 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict) qmp_netdev_del(id, &err); hmp_handle_error(mon, &err); } + +void hmp_getfd(Monitor *mon, const QDict *qdict) +{ + const char *fdname = qdict_get_str(qdict, "fdname"); + Error *errp = NULL; + + qmp_getfd(fdname, &errp); + hmp_handle_error(mon, &errp); +} + +void hmp_closefd(Monitor *mon, const QDict *qdict) +{ + const char *fdname = qdict_get_str(qdict, "fdname"); + Error *errp = NULL; + + qmp_closefd(fdname, &errp); + hmp_handle_error(mon, &errp); +} diff --git a/hmp.h b/hmp.h index 79d138d3ee..8d2b0d76da 100644 --- a/hmp.h +++ b/hmp.h @@ -64,5 +64,7 @@ void hmp_device_del(Monitor *mon, const QDict *qdict); void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict); void hmp_netdev_add(Monitor *mon, const QDict *qdict); void hmp_netdev_del(Monitor *mon, const QDict *qdict); +void hmp_getfd(Monitor *mon, const QDict *qdict); +void hmp_closefd(Monitor *mon, const QDict *qdict); #endif diff --git a/monitor.c b/monitor.c index 188c03d5b1..09aa3cdf52 100644 --- a/monitor.c +++ b/monitor.c @@ -2307,48 +2307,45 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict) } #endif -static int do_getfd(Monitor *mon, const QDict *qdict, QObject **ret_data) +void qmp_getfd(const char *fdname, Error **errp) { - const char *fdname = qdict_get_str(qdict, "fdname"); mon_fd_t *monfd; int fd; - fd = qemu_chr_fe_get_msgfd(mon->chr); + fd = qemu_chr_fe_get_msgfd(cur_mon->chr); if (fd == -1) { - qerror_report(QERR_FD_NOT_SUPPLIED); - return -1; + error_set(errp, QERR_FD_NOT_SUPPLIED); + return; } if (qemu_isdigit(fdname[0])) { - qerror_report(QERR_INVALID_PARAMETER_VALUE, "fdname", - "a name not starting with a digit"); - return -1; + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "fdname", + "a name not starting with a digit"); + return; } - QLIST_FOREACH(monfd, &mon->fds, next) { + QLIST_FOREACH(monfd, &cur_mon->fds, next) { if (strcmp(monfd->name, fdname) != 0) { continue; } close(monfd->fd); monfd->fd = fd; - return 0; + return; } monfd = g_malloc0(sizeof(mon_fd_t)); monfd->name = g_strdup(fdname); monfd->fd = fd; - QLIST_INSERT_HEAD(&mon->fds, monfd, next); - return 0; + QLIST_INSERT_HEAD(&cur_mon->fds, monfd, next); } -static int do_closefd(Monitor *mon, const QDict *qdict, QObject **ret_data) +void qmp_closefd(const char *fdname, Error **errp) { - const char *fdname = qdict_get_str(qdict, "fdname"); mon_fd_t *monfd; - QLIST_FOREACH(monfd, &mon->fds, next) { + QLIST_FOREACH(monfd, &cur_mon->fds, next) { if (strcmp(monfd->name, fdname) != 0) { continue; } @@ -2357,11 +2354,10 @@ static int do_closefd(Monitor *mon, const QDict *qdict, QObject **ret_data) close(monfd->fd); g_free(monfd->name); g_free(monfd); - return 0; + return; } - qerror_report(QERR_FD_NOT_FOUND, fdname); - return -1; + error_set(errp, QERR_FD_NOT_FOUND, fdname); } static void do_loadvm(Monitor *mon, const QDict *qdict) diff --git a/qapi-schema.json b/qapi-schema.json index 1ab5dbd5ff..a92adb1d5b 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1789,34 +1789,36 @@ # # Dump guest's memory to vmcore. It is a synchronous operation that can take # very long depending on the amount of guest memory. This command is only -# supported only on i386 and x86_64 +# supported on i386 and x86_64. +# +# @paging: if true, do paging to get guest's memory mapping. This allows +# using gdb to process the core file. However, setting @paging to false +# may be desirable because of two reasons: +# +# 1. The guest may be in a catastrophic state or can have corrupted +# memory, which cannot be trusted +# 2. The guest can be in real-mode even if paging is enabled. For example, +# the guest uses ACPI to sleep, and ACPI sleep state goes in real-mode # -# @paging: if true, do paging to get guest's memory mapping. The @paging's -# default value of @paging is false, If you want to use gdb to process the -# core, please set @paging to true. The reason why the @paging's value is -# false: -# 1. guest machine in a catastrophic state can have corrupted memory, -# which we cannot trust. -# 2. The guest machine can be in read-mode even if paging is enabled. -# For example: the guest machine uses ACPI to sleep, and ACPI sleep -# state goes in real-mode # @protocol: the filename or file descriptor of the vmcore. The supported -# protocol can be file or fd: +# protocols are: +# # 1. file: the protocol starts with "file:", and the following string is # the file's path. # 2. fd: the protocol starts with "fd:", and the following string is the # fd's name. +# # @begin: #optional if specified, the starting physical address. +# # @length: #optional if specified, the memory size, in bytes. If you don't -# want to dump all guest's memory, please specify the start @begin and -# @length +# want to dump all guest's memory, please specify the start @begin and @length # # Returns: nothing on success # If @begin contains an invalid address, InvalidParameter # If only one of @begin and @length is specified, MissingParameter # If @protocol stats with "fd:", and the fd cannot be found, FdNotFound # If @protocol starts with "file:", and the file cannot be -# opened, OpenFileFailed +# opened, OpenFileFailed # If @protocol does not start with "fd:" or "file:", InvalidParameter # If an I/O error occurs while writing the file, IOError # If the target does not support this command, Unsupported @@ -1868,3 +1870,38 @@ # Since: 0.14.0 ## { 'command': 'netdev_del', 'data': {'id': 'str'} } + +## +# @getfd: +# +# Receive a file descriptor via SCM rights and assign it a name +# +# @fdname: file descriptor name +# +# Returns: Nothing on success +# If file descriptor was not received, FdNotSupplied +# If @fdname is not valid, InvalidParameterType +# +# Since: 0.14.0 +# +# Notes: If @fdname already exists, the file descriptor assigned to +# it will be closed and replaced by the received file +# descriptor. +# The 'closefd' command can be used to explicitly close the +# file descriptor when it is no longer needed. +## +{ 'command': 'getfd', 'data': {'fdname': 'str'} } + +## +# @closefd: +# +# Close a file descriptor previously passed via SCM rights +# +# @fdname: file descriptor name +# +# Returns: Nothing on success +# If @fdname is not found, FdNotFound +# +# Since: 0.14.0 +## +{ 'command': 'closefd', 'data': {'fdname': 'str'} } diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index ffffbf79aa..705eca90aa 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -298,7 +298,7 @@ void input_type_enum(Visitor *v, int *obj, const char *strings[], } if (strings[value] == NULL) { - error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null"); + error_set(errp, QERR_INVALID_PARAMETER, enum_str); g_free(enum_str); return; } diff --git a/qmp-commands.hx b/qmp-commands.hx index 2e1a38e695..e3cf3c5a1a 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -873,8 +873,7 @@ EQMP .args_type = "fdname:s", .params = "getfd name", .help = "receive a file descriptor via SCM rights and assign it a name", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_getfd, + .mhandler.cmd_new = qmp_marshal_input_getfd, }, SQMP @@ -892,6 +891,14 @@ Example: -> { "execute": "getfd", "arguments": { "fdname": "fd1" } } <- { "return": {} } +Notes: + +(1) If the name specified by the "fdname" argument already exists, + the file descriptor assigned to it will be closed and replaced + by the received file descriptor. +(2) The 'closefd' command can be used to explicitly close the file + descriptor when it is no longer needed. + EQMP { @@ -899,8 +906,7 @@ EQMP .args_type = "fdname:s", .params = "closefd name", .help = "close a file descriptor previously passed via SCM rights", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_closefd, + .mhandler.cmd_new = qmp_marshal_input_closefd, }, SQMP