diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2012-11-25 16:18:05 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2012-11-25 16:18:05 +0000 |
commit | 4519057d8d103717a65852648127ea04a98db5bd (patch) | |
tree | 8b6eccd79206898d4e6f9475c9fdeee62db358d0 /usr.sbin | |
parent | 13e8178d456f835587600d58a8361bf9c3de5d3a (diff) |
Properly remove virtual device ports if we remove the associated channels.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ldomctl/config.c | 91 |
1 files changed, 63 insertions, 28 deletions
diff --git a/usr.sbin/ldomctl/config.c b/usr.sbin/ldomctl/config.c index b9620498261..6f5fba56717 100644 --- a/usr.sbin/ldomctl/config.c +++ b/usr.sbin/ldomctl/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.4 2012/11/25 14:01:58 kettenis Exp $ */ +/* $OpenBSD: config.c,v 1.5 2012/11/25 16:18:04 kettenis Exp $ */ /* * Copyright (c) 2012 Mark Kettenis @@ -1679,6 +1679,66 @@ guest_lookup(const char *name) } void +guest_delete_virtual_device_port(struct guest *guest, struct md_node *port) +{ + struct md *md = guest->md; + struct md_node *node; + struct md_prop *prop; + + TAILQ_FOREACH(node, &md->node_list, link) { + if (strcmp(node->name->str, "virtual-device-port") != 0) + continue; + TAILQ_FOREACH(prop, &node->prop_list, link) { + if (prop->tag == MD_PROP_ARC && + prop->d.arc.node == port) { + md_delete_node(md, node); + return; + } + } + } +} + +void +guest_delete_endpoint(struct guest *guest, struct ldc_endpoint *endpoint) +{ + struct md *md = guest->md; + struct md_node *node, *node2; + struct md_prop *prop; + uint64_t id, resource_id; + + node = md_find_node(md, "channel-endpoints"); + TAILQ_FOREACH(prop, &node->prop_list, link) { + if (prop->tag == MD_PROP_ARC && + strcmp(prop->name->str, "fwd") == 0) { + node2 = prop->d.arc.node; + if (!md_get_prop_val(hvmd, node2, "id", &id)) + continue; + if (id == endpoint->channel) { + guest_delete_virtual_device_port(guest, node2); + md_delete_node(md, node2); + break; + } + } + } + + TAILQ_REMOVE(&guest->endpoint_list, endpoint, link); + ldc_endpoints[endpoint->resource_id] = NULL; + + /* Delete peer as well. */ + for (resource_id = 0; resource_id < max_guest_ldcs; resource_id++) { + struct ldc_endpoint *peer = ldc_endpoints[resource_id]; + + if (peer && peer->target_type == LDC_GUEST && + peer->target_channel == endpoint->channel && + peer->channel == endpoint->target_channel && + peer->target_guest == guest->gid) + guest_delete_endpoint(peer->guest, peer); + } + + free(endpoint); +} + +void guest_delete(struct guest *guest) { struct cpu *cpu, *cpu2; @@ -1703,31 +1763,8 @@ guest_delete(struct guest *guest) free(mblock); } - TAILQ_FOREACH_SAFE(endpoint, &guest->endpoint_list, link, endpoint2) { - uint64_t resource_id; - - TAILQ_REMOVE(&guest->endpoint_list, endpoint, link); - ldc_endpoints[endpoint->resource_id] = NULL; - - /* Delete peer as well. */ - for (resource_id = 0; - resource_id < max_guest_ldcs; resource_id++) { - struct ldc_endpoint *peer = ldc_endpoints[resource_id]; - - if (peer && peer->target_type == LDC_GUEST && - peer->target_channel == endpoint->channel && - peer->channel == endpoint->target_channel && - peer->target_guest == guest->gid) { - TAILQ_REMOVE(&peer->guest->endpoint_list, - peer, link); - ldc_endpoints[peer->resource_id] = NULL; - free(peer); - break; - } - } - - free(endpoint); - } + TAILQ_FOREACH_SAFE(endpoint, &guest->endpoint_list, link, endpoint2) + guest_delete_endpoint(guest, endpoint); hvmd_free_frag(guest->mdpa); @@ -1967,13 +2004,11 @@ struct guest * primary_init(void) { struct guest *guest; - struct md_node *vcc; guest = guest_lookup("primary"); assert(guest); guest_set_domaining_enabled(guest); - vcc = guest_add_vcc(guest); return guest; } |