0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-03 07:31:54 +00:00

Netindex: consistency checks and deletion of whole hash

This commit is contained in:
Maria Matejka 2024-05-30 22:59:08 +02:00 committed by Katerina Kubecova
parent 1371661156
commit 178ae9ba9e
4 changed files with 106 additions and 20 deletions

View File

@ -33,11 +33,32 @@ net_lock_revive_unlock(struct netindex_hash_private *hp, struct netindex *i)
return i; return i;
} }
void
netindex_hash_consistency_check(struct netindex_hash_private *nh)
{
for (uint t = 0; t < NET_MAX; t++)
{
if (!nh->net[t].hash.data)
continue;
uint count = 0;
HASH_WALK(nh->net[t].hash, next, i)
{
ASSERT_DIE(count < nh->net[t].hash.count);
ASSERT_DIE(nh->net[t].block[i->index] == i);
count++;
}
HASH_WALK_END;
ASSERT_DIE(count == nh->net[t].hash.count);
}
}
/* /*
* Index initialization * Index initialization
*/ */
netindex_hash * netindex_hash *
netindex_hash_new(pool *sp) netindex_hash_new(pool *sp, event_list *cleanup_target)
{ {
DOMAIN(attrs) dom = DOMAIN_NEW(attrs); DOMAIN(attrs) dom = DOMAIN_NEW(attrs);
LOCK_DOMAIN(attrs, dom); LOCK_DOMAIN(attrs, dom);
@ -48,7 +69,7 @@ netindex_hash_new(pool *sp)
nh->lock = dom; nh->lock = dom;
nh->pool = p; nh->pool = p;
nh->cleanup_list = &global_event_list; nh->cleanup_list = cleanup_target;
nh->cleanup_event = (event) { .hook = netindex_hash_cleanup, nh }; nh->cleanup_event = (event) { .hook = netindex_hash_cleanup, nh };
UNLOCK_DOMAIN(attrs, dom); UNLOCK_DOMAIN(attrs, dom);
@ -58,29 +79,71 @@ netindex_hash_new(pool *sp)
static void static void
netindex_hash_cleanup(void *_nh) netindex_hash_cleanup(void *_nh)
{ {
NH_LOCK((netindex_hash *) _nh, nh); struct netindex_hash_private *nh = _nh;
DOMAIN(attrs) dom = nh->lock;
LOCK_DOMAIN(attrs, dom);
EXPENSIVE_CHECK(netindex_hash_consistency_check(nh));
uint kept = 0;
for (uint t = 0; t < NET_MAX; t++) for (uint t = 0; t < NET_MAX; t++)
{ for (uint i = 0; i < nh->net[t].block_size; i++)
if (!nh->net[t].hash.data) {
continue; struct netindex *ni = nh->net[t].block[i];
if (!ni)
continue;
HASH_WALK_FILTER(nh->net[t].hash, next, i, ii) ASSERT_DIE(i == ni->index);
if (lfuc_finished(&i->uc))
if (lfuc_finished(&ni->uc))
{ {
HASH_DO_REMOVE(nh->net[t].hash, NETINDEX, ii); HASH_REMOVE2(nh->net[t].hash, NETINDEX, nh->pool, ni);
hmap_clear(&nh->net[t].id_map, i->index); hmap_clear(&nh->net[t].id_map, ni->index);
nh->net[t].block[i->index] = NULL; nh->net[t].block[i] = NULL;
if (nh->net[t].slab) if (nh->net[t].slab)
sl_free(i); sl_free(ni);
else else
mb_free(i); mb_free(ni);
} }
HASH_WALK_DELSAFE_END; else
} kept++;
} }
EXPENSIVE_CHECK(netindex_hash_consistency_check(nh));
if (kept || !nh->deleted_event)
{
UNLOCK_DOMAIN(attrs, dom);
return;
}
ev_postpone(&nh->cleanup_event);
event *e = nh->deleted_event;
event_list *t = nh->deleted_target;
/* Check cleanliness */
for (uint t = 0; t < NET_MAX; t++)
if (nh->net[t].hash.data)
{
HASH_WALK(nh->net[t].hash, next, i)
bug("Stray netindex in deleted hash");
HASH_WALK_END;
}
/* Pool free is enough to drop everything */
rp_free(nh->pool);
/* And only the lock remains */
UNLOCK_DOMAIN(attrs, dom);
DOMAIN_FREE(attrs, dom);
/* Notify the requestor */
ev_send(t, e);
}
static void static void
netindex_hash_init(struct netindex_hash_private *hp, u8 type) netindex_hash_init(struct netindex_hash_private *hp, u8 type)
@ -94,6 +157,19 @@ netindex_hash_init(struct netindex_hash_private *hp, u8 type)
hmap_init(&hp->net[type].id_map, hp->pool, 128); hmap_init(&hp->net[type].id_map, hp->pool, 128);
}; };
void
netindex_hash_delete(netindex_hash *h, event *e, event_list *t)
{
NH_LOCK(h, hp);
EXPENSIVE_CHECK(netindex_hash_consistency_check(nh));
hp->deleted_event = e;
hp->deleted_target = t;
ev_send(hp->cleanup_list, &hp->cleanup_event);
}
/* /*
* Private index manipulation * Private index manipulation
*/ */
@ -115,6 +191,8 @@ net_find_index_fragile(struct netindex_hash_private *hp, const net_addr *n)
if (!hp->net[n->type].block) if (!hp->net[n->type].block)
return NULL; return NULL;
EXPENSIVE_CHECK(netindex_hash_consistency_check(nh));
u32 h = net_hash(n); u32 h = net_hash(n);
return HASH_FIND(hp->net[n->type].hash, NETINDEX, h, n); return HASH_FIND(hp->net[n->type].hash, NETINDEX, h, n);
} }
@ -128,6 +206,8 @@ net_find_index_locked(struct netindex_hash_private *hp, const net_addr *n)
static struct netindex * static struct netindex *
net_new_index_locked(struct netindex_hash_private *hp, const net_addr *n) net_new_index_locked(struct netindex_hash_private *hp, const net_addr *n)
{ {
ASSERT_DIE(!hp->deleted_event);
if (!hp->net[n->type].block) if (!hp->net[n->type].block)
netindex_hash_init(hp, n->type); netindex_hash_init(hp, n->type);
@ -151,8 +231,11 @@ net_new_index_locked(struct netindex_hash_private *hp, const net_addr *n)
struct netindex **nb = mb_alloc(hp->pool, bs * 2 * sizeof *nb); struct netindex **nb = mb_alloc(hp->pool, bs * 2 * sizeof *nb);
memcpy(nb, hp->net[n->type].block, bs * sizeof *nb); memcpy(nb, hp->net[n->type].block, bs * sizeof *nb);
memset(&nb[bs], 0, bs * sizeof *nb); memset(&nb[bs], 0, bs * sizeof *nb);
hp->net[n->type].block_size *= 2;
mb_free(hp->net[n->type].block);
hp->net[n->type].block = nb; hp->net[n->type].block = nb;
hp->net[n->type].block_size *= 2;
} }
hp->net[n->type].block[i] = ni; hp->net[n->type].block[i] = ni;

View File

@ -27,8 +27,9 @@ struct netindex {
/* Index hash: data structure completely opaque, use handlers */ /* Index hash: data structure completely opaque, use handlers */
typedef union netindex_hash netindex_hash; typedef union netindex_hash netindex_hash;
/* Initialization */ /* Initialization and teardown */
netindex_hash *netindex_hash_new(pool *); netindex_hash *netindex_hash_new(pool *, event_list *);
void netindex_hash_delete(netindex_hash *, event *, event_list *);
/* Find/get/resolve index; pointer valid until end of task */ /* Find/get/resolve index; pointer valid until end of task */
struct netindex *net_find_index(netindex_hash *, const net_addr *); struct netindex *net_find_index(netindex_hash *, const net_addr *);

View File

@ -27,6 +27,8 @@ struct netindex_hash_private {
struct netindex **block; struct netindex **block;
struct hmap id_map; struct hmap id_map;
} net[NET_MAX]; } net[NET_MAX];
event *deleted_event;
event_list *deleted_target;
}; };
typedef union netindex_hash { typedef union netindex_hash {

View File

@ -2899,7 +2899,7 @@ rt_init(void)
ev_init_list(&rt_cork.queue, &main_birdloop, "Route cork release"); ev_init_list(&rt_cork.queue, &main_birdloop, "Route cork release");
rt_cork.run = (event) { .hook = rt_cork_release_hook }; rt_cork.run = (event) { .hook = rt_cork_release_hook };
idm_init(&rtable_idm, rt_table_pool, 256); idm_init(&rtable_idm, rt_table_pool, 256);
rt_global_netindex_hash = netindex_hash_new(rt_table_pool); rt_global_netindex_hash = netindex_hash_new(rt_table_pool, &global_event_list);
} }
static _Bool static _Bool