From 37101c7c8abbacaf07c30d5094bc6880cf4f7ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Fri, 1 Mar 2024 18:12:37 +0100 Subject: [PATCH] Do not re-add a node to the same prunenodes list If a node cleaned up by prune_tree() happens to belong to the same node bucket as its parent, the latter is directly appended to the prunenodes list currently processed by prune_tree(). However, the relevant code branch does not account for the fact that the parent might already be on the list it is trying to append it to. Fix by only calling ISC_LIST_APPEND() for parent nodes not yet added to their relevant prunenodes list. (cherry picked from commit 4b6fc97af6f936616a12e733b14ffc450af6df87) --- lib/dns/rbtdb.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index f18a358128..bb154824ab 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -2312,14 +2312,18 @@ prune_tree(isc_task_t *task, isc_event_t *event) { if (parent->locknum == locknum) { /* - * Add the parent to the matching prunenodes list - * manually, because send_to_prune_tree() would create - * new event in the case the current node was the last - * node on the prunenodes list. + * The parent belongs to the same node bucket as the + * node we just processed, so there is no need to + * switch node locks. Directly add the parent to the + * prunenodes list we are currently processing (unless + * the parent is already on that list). */ - new_reference(rbtdb, parent, isc_rwlocktype_write); - ISC_LIST_APPEND(rbtdb->prunenodes[parent->locknum], - parent, prunelink); + if (!ISC_LINK_LINKED(node, prunelink)) { + new_reference(rbtdb, parent, + isc_rwlocktype_write); + ISC_LIST_APPEND(rbtdb->prunenodes[locknum], + parent, prunelink); + } NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); } else {