0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

Table: Freeing routes deferred to save rcu synchronization

This commit is contained in:
Maria Matejka 2024-06-04 21:38:05 +02:00 committed by Katerina Kubecova
parent 4e60865a4d
commit 24010536f3
2 changed files with 34 additions and 3 deletions

View File

@ -408,6 +408,7 @@ struct rtable_private {
struct f_trie *flowspec_trie; /* Trie for evaluation of flowspec notifications */
struct roa_digestor *roa_digest; /* Digest of changed ROAs export */
// struct mpls_domain *mpls_domain; /* Label allocator for MPLS */
u32 rte_free_deferred; /* Counter of deferred rte_free calls */
};
/* The final union private-public rtable structure */

View File

@ -530,8 +530,16 @@ rte_store(const rte *r, struct netindex *i, struct rtable_private *tab)
return s;
}
static void rte_free_deferred(struct deferred_call *dc);
struct rte_free_deferred_item {
struct deferred_call dc;
struct rte_storage *e;
rtable *tab;
};
/**
* rte_free - delete a &rte
* rte_free_defer - delete a &rte (happens later)
* @e: &struct rte_storage to be deleted
* @tab: the table which the rte belongs to
*
@ -541,8 +549,27 @@ rte_store(const rte *r, struct netindex *i, struct rtable_private *tab)
static void
rte_free(struct rte_storage *e, struct rtable_private *tab)
{
/* Wait for very slow table readers */
synchronize_rcu();
struct rte_free_deferred_item rfdi = {
.dc.hook = rte_free_deferred,
.e = e,
.tab = RT_PUB(tab),
};
if (!tab->rte_free_deferred++)
rt_lock_table(tab);
defer_call(&rfdi.dc, sizeof rfdi);
}
static void
rte_free_deferred(struct deferred_call *dc)
{
SKIP_BACK_DECLARE(struct rte_free_deferred_item, rfdi, dc, dc);
struct rte_storage *e = rfdi->e;
RT_LOCK(rfdi->tab, tab);
/* No need for synchronize_rcu, implied by the deferred_call */
rt_rte_trace_in(D_ROUTES, e->rte.sender->req, &e->rte, "freeing");
@ -553,6 +580,9 @@ rte_free(struct rte_storage *e, struct rtable_private *tab)
ea_free(e->rte.attrs);
sl_free(e);
if (!--tab->rte_free_deferred)
rt_unlock_table(tab);
}
static int /* Actually better or at least as good as */