From: Mark Andrews Date: Thu, 5 Dec 2019 23:08:52 +0000 (+1100) Subject: Add is_leaf and send_to_prune_tree. X-Git-Tag: v9.14.10~7^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=067b9f8d31ba113fbb0b658c9c3f0b20107fe47e;p=thirdparty%2Fbind9.git Add is_leaf and send_to_prune_tree. Add is_leaf and send_to_prune_tree to make the logic easier to understand in cleanup_dead_nodes and decrement_reference. (cherry picked from commit c6efc0e50fd806f48c243baed69b70a7e6473347) --- diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index cabd63e9f35..c289589fdc2 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -1840,6 +1840,31 @@ new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) { } } +/*% + * The tree lock must be held for the result to be valid. + */ +static inline bool +is_leaf(dns_rbtnode_t *node) { + return (node->parent != NULL && node->parent->down == node && + node->left == NULL && node->right == NULL); +} + +static inline void +send_to_prune_tree(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) { + isc_event_t *ev; + dns_db_t *db; + + ev = isc_event_allocate(rbtdb->common.mctx, NULL, + DNS_EVENT_RBTPRUNE, + prune_tree, node, + sizeof(isc_event_t)); + new_reference(rbtdb, node); + db = NULL; + attach((dns_db_t *)rbtdb, &db); + ev->ev_sender = db; + isc_task_send(rbtdb->task, &ev); +} + /*% * Clean up dead nodes. These are nodes which have no references, and * have no data. They are dead but we could not or chose not to delete @@ -1868,22 +1893,8 @@ cleanup_dead_nodes(dns_rbtdb_t *rbtdb, int bucketnum) { INSIST(isc_refcount_current(&node->references) == 0 && node->data == NULL); - if (node->parent != NULL && - node->parent->down == node && node->left == NULL && - node->right == NULL && rbtdb->task != NULL) - { - isc_event_t *ev; - dns_db_t *db; - - ev = isc_event_allocate(rbtdb->common.mctx, NULL, - DNS_EVENT_RBTPRUNE, - prune_tree, node, - sizeof(isc_event_t)); - new_reference(rbtdb, node); - db = NULL; - attach((dns_db_t *)rbtdb, &db); - ev->ev_sender = db; - isc_task_send(rbtdb->task, &ev); + if (is_leaf(node) && rbtdb->task != NULL) { + send_to_prune_tree(rbtdb, node); } else if (node->down == NULL && node->data == NULL) { /* * Not a interior node and not needing to be @@ -2083,44 +2094,9 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, * it's their responsibility to purge stale leaves (e.g. by * periodic walk-through). */ - if (!pruning && node->parent != NULL && - node->parent->down == node && node->left == NULL && - node->right == NULL && rbtdb->task != NULL) { - isc_event_t *ev; - dns_db_t *db; - - ev = isc_event_allocate(rbtdb->common.mctx, NULL, - DNS_EVENT_RBTPRUNE, - prune_tree, node, - sizeof(isc_event_t)); - if (ev != NULL) { - new_reference(rbtdb, node); - db = NULL; - attach((dns_db_t *)rbtdb, &db); - ev->ev_sender = db; - isc_task_send(rbtdb->task, &ev); - no_reference = false; - } else { - /* - * XXX: this is a weird situation. We could - * ignore this error case, but then the stale - * node will unlikely be purged except via a - * rare condition such as manual cleanup. So - * we queue it in the deadnodes list, hoping - * the memory shortage is temporary and the node - * will be deleted later. - */ - isc_log_write(dns_lctx, - DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_CACHE, - ISC_LOG_INFO, - "decrement_reference: failed to " - "allocate pruning event"); - INSIST(node->data == NULL); - INSIST(!ISC_LINK_LINKED(node, deadlink)); - ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node, - deadlink); - } + if (!pruning && is_leaf(node) && rbtdb->task != NULL) { + send_to_prune_tree(rbtdb, node); + no_reference = false; } else { delete_node(rbtdb, node); }