@cryptotaxi247 / netdata-1 / commits / 2733e6fc6

Add revalidation for clean pages under lock to ensure queue integrity (#21793)

* Prevent potential race conditions by revalidating page status after acquiring the clean lock. * Handle inconsistent states by logging and updating flags appropriately.

Stelios Fragkakis committed Feb 21, 2026 at 17:55 UTC 2733e6fc60cf9c76a840e70c554dff5a6b6e01e2
1 file changed +13 -3
src/database/engine/cache.c
+13 -3
@@ -765,10 +765,20 @@ static ALWAYS_INLINE void page_has_been_accessed(PGC *cache, PGC_PAGE *page) {
765
766 if (flags & PGC_PAGE_CLEAN) {
767 if(pgc_queue_trylock(cache, &cache->clean, PGC_QUEUE_LOCK_PRIO_EVICTORS)) {
768 - DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(cache->clean.base, page, link.prev, link.next);
769 - DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(cache->clean.base, page, link.prev, link.next);
768 + // The status check above is lockless. Re-validate under the clean lock to avoid
769 + // touching clean-list pointers after the page moved to another queue.
770 + if(is_page_clean(page)) {
771 + DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(cache->clean.base, page, link.prev, link.next);
772 + DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(cache->clean.base, page, link.prev, link.next);
773 + page_flag_clear(page, PGC_PAGE_HAS_BEEN_ACCESSED);
774 + }
775 + else {
776 + // Expected concurrent transition: page may move clean -> dirty/hot
777 + // between lockless flag read and acquiring the clean queue lock.
778 + page_flag_set(page, PGC_PAGE_HAS_BEEN_ACCESSED);
779 + }
780 +
781 pgc_queue_unlock(cache, &cache->clean);
771 - page_flag_clear(page, PGC_PAGE_HAS_BEEN_ACCESSED);
782 }
783 else
784 page_flag_set(page, PGC_PAGE_HAS_BEEN_ACCESSED);