-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Cache and Eviction
-
None
-
Storage Engines - Transactions
-
105.611
-
SE Transactions - 2026-08-28
-
5
Problem
__wti_evict_walk resumes the tree it last worked on so a partially walked tree gets finished (src/evict/evict_walk.c:404). Only later iterations of a pass advance the dhandle cursor.
btree->evict_ref persists across visits, so the walk does progress through the tree — but on reaching the end it wraps rather than handing off. ref == NULL increments restarts and continues from the top (:1381), filling the remainder of the quota. The tree is never finished, the pass still ends on its first iteration, and the next pass resumes the same tree.
restarts is reset on every entry (:1322), so each visit gets a fresh wrap allowance. A tree can therefore be traversed an unbounded number of times while no other tree is considered. With the wrap bounded, reaching the end would exit with the quota unfilled, and the outer loop would advance the cursor via __evict_walk_choose_dhandle.
Filling the quota also defeats the mechanisms that would rotate away: evict_walk_period is zeroed (:1484) and the walk target resets (:872). The backoff keys on pages queued rather than pages evicted, so a tree whose nominations are all refused by __evict_review looks maximally productive.
Definition of done
- After one round of the dhandle list, no tree has been traversed more than twice.
- A partially walked tree is still finished, not abandoned mid-way.
- Test: Stress runs of the disagg switch stepdown-async tasks no longer reproduce such cache-stuck failure, the cache may still stuck when ingest table dominates the cache but we should see increment of eviction_dhandle_complete_walk.
Notes on approach
Wrapping itself is wanted — a tree smaller than the quota needs it. What is missing is that the allowance is per-visit rather than cumulative. Options: carry the wrap count on the btree and reset it only when the cursor advances past that tree, or clear evict->walk_tree on reaching the end of a tree so the next pass advances.