0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +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 f_trie *flowspec_trie; /* Trie for evaluation of flowspec notifications */
struct roa_digestor *roa_digest; /* Digest of changed ROAs export */ struct roa_digestor *roa_digest; /* Digest of changed ROAs export */
// struct mpls_domain *mpls_domain; /* Label allocator for MPLS */ // 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 */ /* 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; 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 * @e: &struct rte_storage to be deleted
* @tab: the table which the rte belongs to * @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 static void
rte_free(struct rte_storage *e, struct rtable_private *tab) rte_free(struct rte_storage *e, struct rtable_private *tab)
{ {
/* Wait for very slow table readers */ struct rte_free_deferred_item rfdi = {
synchronize_rcu(); .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"); 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); ea_free(e->rte.attrs);
sl_free(e); sl_free(e);
if (!--tab->rte_free_deferred)
rt_unlock_table(tab);
} }
static int /* Actually better or at least as good as */ static int /* Actually better or at least as good as */