Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64c62723 authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller
Browse files

fib_trie: Various clean-ups for handling slen



While doing further work on the fib_trie I noted a few items.

First I was using calls that were far more complicated than they needed to
be for determining when to push/pull the suffix length.  I have updated the
code to reflect the simplier logic.

The second issue is that I realised we weren't necessarily handling the
case of a leaf_info struct surviving a flush.  I have updated the logic so
that now we will call pull_suffix in the event of having a leaf info value
left in the leaf after flushing it.

Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 02525368
Loading
Loading
Loading
Loading
+29 −20
Original line number Diff line number Diff line
@@ -917,28 +917,21 @@ static void leaf_push_suffix(struct tnode *l)

static void remove_leaf_info(struct tnode *l, struct leaf_info *old)
{
	struct hlist_node *prev;

	/* record the location of the pointer to this object */
	prev = rtnl_dereference(hlist_pprev_rcu(&old->hlist));
	/* record the location of the previous list_info entry */
	struct hlist_node **pprev = old->hlist.pprev;
	struct leaf_info *li = hlist_entry(pprev, typeof(*li), hlist.next);

	/* remove the leaf info from the list */
	hlist_del_rcu(&old->hlist);

	/* if we emptied the list this leaf will be freed and we can sort
	 * out parent suffix lengths as a part of trie_rebalance
	 */
	if (hlist_empty(&l->list))
	/* only access li if it is pointing at the last valid hlist_node */
	if (hlist_empty(&l->list) || (*pprev))
		return;

	/* if we removed the tail then we need to update slen */
	if (!rcu_access_pointer(hlist_next_rcu(prev))) {
		struct leaf_info *li = hlist_entry(prev, typeof(*li), hlist);

	/* update the trie with the latest suffix length */
	l->slen = KEYLENGTH - li->plen;
	leaf_pull_suffix(l);
}
}

static void insert_leaf_info(struct tnode *l, struct leaf_info *new)
{
@@ -961,7 +954,7 @@ static void insert_leaf_info(struct tnode *l, struct leaf_info *new)
	}

	/* if we added to the tail node then we need to update slen */
	if (!rcu_access_pointer(hlist_next_rcu(&new->hlist))) {
	if (l->slen < (KEYLENGTH - new->plen)) {
		l->slen = KEYLENGTH - new->plen;
		leaf_push_suffix(l);
	}
@@ -1613,6 +1606,7 @@ static int trie_flush_leaf(struct tnode *l)
	struct hlist_head *lih = &l->list;
	struct hlist_node *tmp;
	struct leaf_info *li = NULL;
	unsigned char plen = KEYLENGTH;

	hlist_for_each_entry_safe(li, tmp, lih, hlist) {
		found += trie_flush_list(&li->falh);
@@ -1620,8 +1614,14 @@ static int trie_flush_leaf(struct tnode *l)
		if (list_empty(&li->falh)) {
			hlist_del_rcu(&li->hlist);
			free_leaf_info(li);
			continue;
		}

		plen = li->plen;
	}

	l->slen = KEYLENGTH - plen;

	return found;
}

@@ -1700,13 +1700,22 @@ int fib_table_flush(struct fib_table *tb)
	for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
		found += trie_flush_leaf(l);

		if (ll && hlist_empty(&ll->list))
		if (ll) {
			if (hlist_empty(&ll->list))
				trie_leaf_remove(t, ll);
			else
				leaf_pull_suffix(ll);
		}

		ll = l;
	}

	if (ll && hlist_empty(&ll->list))
	if (ll) {
		if (hlist_empty(&ll->list))
			trie_leaf_remove(t, ll);
		else
			leaf_pull_suffix(ll);
	}

	pr_debug("trie_flush found=%d\n", found);
	return found;