Commit c39860e6 authored by Marc-André Lureau's avatar Marc-André Lureau Committed by Paolo Bonzini

char: replace qemu_chr_claim/release with qemu_chr_fe_init/deinit

Now that all front end use qemu_chr_fe_init(), we can move chardev
claiming in init(), and add a function deinit() to release the chardev
and cleanup handlers.

The qemu_chr_fe_claim_no_fail() for property are gone, since the
property will raise an error instead. In other cases, where there is
already an error path, an error is raised instead. Finally, other cases
are handled by &error_abort in qemu_chr_fe_init().
Signed-off-by: 's avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20161022095318.17775-19-marcandre.lureau@redhat.com>
Signed-off-by: 's avatarPaolo Bonzini <pbonzini@redhat.com>
parent 5d300164
......@@ -100,10 +100,6 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
"Device '%s' not found", s->chr_name);
return;
}
if (qemu_chr_fe_claim(chr) != 0) {
error_setg(errp, QERR_DEVICE_IN_USE, s->chr_name);
return;
}
if (!qemu_chr_fe_init(&s->chr, chr, errp)) {
return;
}
......@@ -149,11 +145,7 @@ static void rng_egd_finalize(Object *obj)
{
RngEgd *s = RNG_EGD(obj);
if (s->chr.chr) {
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr.chr);
}
qemu_chr_fe_deinit(&s->chr);
g_free(s->chr_name);
}
......
......@@ -1494,6 +1494,7 @@ void gdb_exit(CPUArchState *env, int code)
put_packet(s, buf);
#ifndef CONFIG_USER_ONLY
qemu_chr_fe_deinit(&s->chr);
qemu_chr_delete(chr);
#endif
}
......@@ -1752,8 +1753,6 @@ int gdbserver_start(const char *device)
chr = qemu_chr_new_noreplay("gdb", device);
if (!chr)
return -1;
qemu_chr_fe_claim_no_fail(chr);
}
s = gdbserver_state;
......
......@@ -1976,7 +1976,6 @@ static void pxa2xx_fir_realize(DeviceState *dev, Error **errp)
PXA2xxFIrState *s = PXA2XX_FIR(dev);
if (s->chr.chr) {
qemu_chr_fe_claim_no_fail(s->chr.chr);
qemu_chr_fe_set_handlers(&s->chr, pxa2xx_fir_is_empty,
pxa2xx_fir_rx, pxa2xx_fir_event, s, NULL);
}
......
......@@ -285,7 +285,6 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
s->irq = irq;
if (chr) {
qemu_chr_fe_init(&s->chr, chr, &error_abort);
qemu_chr_fe_claim_no_fail(chr);
qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive,
mcf_uart_receive, mcf_uart_event, s, NULL);
}
......
......@@ -905,7 +905,7 @@ void serial_realize_core(SerialState *s, Error **errp)
void serial_exit_core(SerialState *s)
{
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL, NULL);
qemu_chr_fe_deinit(&s->chr);
qemu_unregister_reset(serial_reset, s);
}
......
......@@ -397,7 +397,6 @@ void sh_serial_init(MemoryRegion *sysmem,
memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
if (chr) {
qemu_chr_fe_claim_no_fail(chr);
qemu_chr_fe_init(&s->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1,
sh_serial_receive1,
......
......@@ -245,15 +245,8 @@ static int con_initialise(struct XenDevice *xendev)
xen_be_bind_evtchn(&con->xendev);
if (con->chr.chr) {
if (qemu_chr_fe_claim(con->chr.chr) == 0) {
qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive,
xencons_receive, NULL, con, NULL);
} else {
xen_be_printf(xendev, 0,
"xen_console_init error chardev %s already used\n",
con->chr.chr->label);
con->chr.chr = NULL;
}
qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive,
xencons_receive, NULL, con, NULL);
}
xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
......@@ -268,10 +261,7 @@ static void con_disconnect(struct XenDevice *xendev)
{
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
if (con->chr.chr) {
qemu_chr_fe_set_handlers(&con->chr, NULL, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(con->chr.chr);
}
qemu_chr_fe_deinit(&con->chr);
xen_be_unbind_evtchn(&con->xendev);
if (con->sring) {
......
......@@ -206,13 +206,12 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
object_get_typename(obj), prop->name, str);
return;
}
if (qemu_chr_fe_claim(s) != 0) {
error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
object_get_typename(obj), prop->name, str);
if (!qemu_chr_fe_init(be, s, errp)) {
error_prepend(errp, "Property '%s.%s' can't take value '%s': ",
object_get_typename(obj), prop->name, str);
return;
}
qemu_chr_fe_init(be, s, errp);
}
static void release_chr(Object *obj, const char *name, void *opaque)
......@@ -221,10 +220,7 @@ static void release_chr(Object *obj, const char *name, void *opaque)
Property *prop = opaque;
CharBackend *be = qdev_get_prop_ptr(dev, prop);
if (be->chr) {
qemu_chr_fe_set_handlers(be, NULL, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(be->chr);
}
qemu_chr_fe_deinit(be);
}
PropertyInfo qdev_prop_chr = {
......
......@@ -266,6 +266,7 @@ static void ccid_card_vscard_drop_connection(PassthruState *card)
{
CharDriverState *chr = qemu_chr_fe_get_driver(&card->cs);
qemu_chr_fe_deinit(&card->cs);
qemu_chr_delete(chr);
card->vscard_in_pos = card->vscard_in_hdr = 0;
}
......
......@@ -1430,9 +1430,9 @@ static void usbredir_handle_destroy(USBDevice *udev)
USBRedirDevice *dev = USB_REDIRECT(udev);
CharDriverState *chr = qemu_chr_fe_get_driver(&dev->cs);
qemu_chr_fe_deinit(&dev->cs);
qemu_chr_delete(chr);
dev->cs.chr = NULL;
/* Note must be done after qemu_chr_close, as that causes a close event */
qemu_bh_delete(dev->chardev_close_bh);
qemu_bh_delete(dev->device_reject_bh);
......
......@@ -361,35 +361,6 @@ int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num);
*/
int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num);
/**
* @qemu_chr_fe_claim:
*
* Claim a backend before using it, should be called before calling
* qemu_chr_fe_set_handlers().
*
* Returns: -1 if the backend is already in use by another frontend, 0 on
* success.
*/
int qemu_chr_fe_claim(CharDriverState *s);
/**
* @qemu_chr_fe_claim_no_fail:
*
* Like qemu_chr_fe_claim, but will exit qemu with an error when the
* backend is already in use.
*/
void qemu_chr_fe_claim_no_fail(CharDriverState *s);
/**
* @qemu_chr_fe_release:
*
* Release a backend for use by another frontend.
*
* Returns: -1 if the backend is already in use by another frontend, 0 on
* success.
*/
void qemu_chr_fe_release(CharDriverState *s);
/**
* @qemu_chr_be_can_write:
*
......@@ -437,7 +408,8 @@ void qemu_chr_be_event(CharDriverState *s, int event);
* @qemu_chr_fe_init:
*
* Initializes a front end for the given CharBackend and
* CharDriver.
* CharDriver. Call qemu_chr_fe_deinit() to remove the association and
* release the driver.
*
* Returns: false on error.
*/
......@@ -450,6 +422,13 @@ bool qemu_chr_fe_init(CharBackend *b, CharDriverState *s, Error **errp);
*/
CharDriverState *qemu_chr_fe_get_driver(CharBackend *be);
/**
* @qemu_chr_fe_deinit:
*
* Dissociate the CharBackend from the CharDriver.
*/
void qemu_chr_fe_deinit(CharBackend *b);
/**
* @qemu_chr_fe_set_handlers:
* @b: a CharBackend
......
......@@ -582,9 +582,7 @@ static void monitor_data_init(Monitor *mon)
static void monitor_data_destroy(Monitor *mon)
{
if (mon->chr.chr) {
qemu_chr_fe_set_handlers(&mon->chr, NULL, NULL, NULL, NULL, NULL);
}
qemu_chr_fe_deinit(&mon->chr);
if (monitor_is_qmp(mon)) {
json_message_parser_destroy(&mon->qmp.parser);
}
......
......@@ -590,12 +590,6 @@ static int find_and_check_chardev(CharDriverState **chr,
return 1;
}
if (qemu_chr_fe_claim(*chr) < 0) {
error_setg(errp, "chardev \"%s\" cannot be claimed",
chr_name);
return 1;
}
return 0;
}
......@@ -707,17 +701,9 @@ static void colo_compare_finalize(Object *obj)
{
CompareState *s = COLO_COMPARE(obj);
if (s->chr_pri_in.chr) {
qemu_chr_fe_set_handlers(&s->chr_pri_in, NULL, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr_pri_in.chr);
}
if (s->chr_sec_in.chr) {
qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr_sec_in.chr);
}
if (s->chr_out.chr) {
qemu_chr_fe_release(s->chr_out.chr);
}
qemu_chr_fe_deinit(&s->chr_pri_in);
qemu_chr_fe_deinit(&s->chr_sec_in);
qemu_chr_fe_deinit(&s->chr_out);
g_queue_free(&s->conn_list);
......
......@@ -175,22 +175,15 @@ static void filter_mirror_cleanup(NetFilterState *nf)
{
MirrorState *s = FILTER_MIRROR(nf);
if (s->chr_out.chr) {
qemu_chr_fe_release(s->chr_out.chr);
}
qemu_chr_fe_deinit(&s->chr_out);
}
static void filter_redirector_cleanup(NetFilterState *nf)
{
MirrorState *s = FILTER_REDIRECTOR(nf);
if (s->chr_in.chr) {
qemu_chr_fe_set_handlers(&s->chr_in, NULL, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr_in.chr);
}
if (s->chr_out.chr) {
qemu_chr_fe_release(s->chr_out.chr);
}
qemu_chr_fe_deinit(&s->chr_in);
qemu_chr_fe_deinit(&s->chr_out);
}
static void filter_mirror_setup(NetFilterState *nf, Error **errp)
......@@ -211,11 +204,6 @@ static void filter_mirror_setup(NetFilterState *nf, Error **errp)
return;
}
if (qemu_chr_fe_claim(chr) != 0) {
error_setg(errp, QERR_DEVICE_IN_USE, s->outdev);
return;
}
qemu_chr_fe_init(&s->chr_out, chr, errp);
}
......@@ -254,7 +242,6 @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
return;
}
qemu_chr_fe_claim_no_fail(chr);
if (!qemu_chr_fe_init(&s->chr_in, chr, errp)) {
return;
}
......@@ -271,7 +258,6 @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
"OUT Device '%s' not found", s->outdev);
return;
}
qemu_chr_fe_claim_no_fail(chr);
if (!qemu_chr_fe_init(&s->chr_out, chr, errp)) {
return;
}
......
......@@ -774,7 +774,6 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
fwd->port = port;
fwd->slirp = s->slirp;
qemu_chr_fe_claim_no_fail(fwd->hd.chr);
qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
NULL, fwd, NULL);
}
......
......@@ -150,10 +150,8 @@ static void vhost_user_cleanup(NetClientState *nc)
g_free(s->vhost_net);
s->vhost_net = NULL;
}
if (nc->queue_index == 0 && s->chr.chr) {
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr.chr);
s->chr.chr = NULL;
if (nc->queue_index == 0) {
qemu_chr_fe_deinit(&s->chr);
}
qemu_purge_queued_packets(nc);
......@@ -297,8 +295,6 @@ static CharDriverState *net_vhost_claim_chardev(
return NULL;
}
qemu_chr_fe_claim_no_fail(chr);
return chr;
}
......
......@@ -776,6 +776,7 @@ static void mux_chr_close(struct CharDriverState *chr)
{
MuxDriver *d = chr->opaque;
qemu_chr_fe_deinit(&d->chr);
g_free(d);
}
......@@ -884,6 +885,17 @@ bool qemu_chr_fe_init(CharBackend *b, CharDriverState *s, Error **errp)
return true;
}
void qemu_chr_fe_deinit(CharBackend *b)
{
assert(b);
if (b->chr) {
qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL);
b->chr->avail_connections++;
b->chr = NULL;
}
}
void qemu_chr_fe_set_handlers(CharBackend *b,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
......@@ -4114,7 +4126,6 @@ CharDriverState *qemu_chr_new_noreplay(const char *label, const char *filename)
error_report_err(err);
}
if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
qemu_chr_fe_claim_no_fail(chr);
monitor_init(chr, MONITOR_USE_READLINE);
}
qemu_opts_del(opts);
......@@ -4190,29 +4201,6 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
return tag;
}
int qemu_chr_fe_claim(CharDriverState *s)
{
if (s->avail_connections < 1) {
return -1;
}
s->avail_connections--;
return 0;
}
void qemu_chr_fe_claim_no_fail(CharDriverState *s)
{
if (qemu_chr_fe_claim(s) != 0) {
fprintf(stderr, "%s: error chardev \"%s\" already used\n",
__func__, s->label);
exit(1);
}
}
void qemu_chr_fe_release(CharDriverState *s)
{
s->avail_connections++;
}
void qemu_chr_fe_disconnect(CharBackend *be)
{
CharDriverState *chr = be->chr;
......
......@@ -490,6 +490,7 @@ static gboolean _test_server_free(TestServer *server)
int i;
CharDriverState *chr = qemu_chr_fe_get_driver(&server->chr);
qemu_chr_fe_deinit(&server->chr);
qemu_chr_delete(chr);
for (i = 0; i < server->fds_num; i++) {
......
......@@ -2417,7 +2417,6 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
exit(1);
}
qemu_chr_fe_claim_no_fail(chr);
monitor_init(chr, flags);
return 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment