Skip to content

Do time-driven purge of expired cache entries#6

Merged
jserv merged 1 commit into
mainfrom
ttl-expiry
Jul 3, 2026
Merged

Do time-driven purge of expired cache entries#6
jserv merged 1 commit into
mainfrom
ttl-expiry

Conversation

@jserv

@jserv jserv commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

An idle mount only reclaimed expired TTL-cache entries when a later read happened to sweep them (the opportunistic sweep in dnsfs_cache_lookup) or under memory pressure.

The timer callback runs in softirq context and does the I6 minimum: it sets an atomic purge_pending flag and wakes the resolver kthread, with no cache walk, allocation, or sleeping. The kthread reaps every entry whose TTL has
elapsed and that is not mid-refresh, under query_lock in process context, then re-arms while entries remain. Arming happens from the cache-store paths, guarded on the kthread's existence and made idempotent via timer_pending.

The sweep skips refreshing entries, and DNSFS_PURGE_INTERVAL_SEC (5s) sits above the gap between an entry's expiry and a demand read, so an entry read soon after expiry is still served stale; entries idle past the interval are reclaimed. A bounded stale window, documented at the constant.

Teardown is ordered: dnsfs_free_config calls timer_shutdown_sync after kthread_stop (the only side that re-arms), so no sweep can fire or re-arm before the cache it walks is drained. timer_setup runs in dnsfs_cache_init.

The softirq/process split uses an atomic flag rather than taking the process-context query_queue_lock in the timer, avoiding a lock-context inversion.


Summary by cubic

Add a time-driven purge for expired cache entries so idle mounts don’t retain dead records. This bounds staleness and reduces memory use without relying on reads or memory pressure.

  • New Features
    • Added a cache timer that sets a purge_pending flag in softirq and wakes the resolver thread; the kthread purges expired, non-refreshing entries under lock, then re-arms while the cache is non-empty (arming happens on store paths; idempotent via timer_pending).
    • Bounded stale window with DNSFS_PURGE_INTERVAL_SEC=5: reads shortly after expiry are still served stale; idle entries past the interval are reclaimed.
    • Ordered teardown: timer_shutdown_sync runs after kthread_stop, ensuring no purge fires while the cache is being drained.
    • New thorough test test_purge_timer validates that an expired entry is purged without a read and that the next read incurs resolver latency (real miss).

Written for commit e4835d8. Summary will update on new commits.

Review in cubic

An idle mount only reclaimed expired TTL-cache entries when a later read
happened to sweep them (the opportunistic sweep in dnsfs_cache_lookup)
or under memory pressure.

The timer callback runs in softirq context and does the I6 minimum: it
sets an atomic purge_pending flag and wakes the resolver kthread, with
no cache walk, allocation, or sleeping. The kthread reaps every entry
whose TTL has
elapsed and that is not mid-refresh, under query_lock in process context,
then re-arms while entries remain. Arming happens from the cache-store
paths, guarded on the kthread's existence and made idempotent via
timer_pending.

The sweep skips refreshing entries, and DNSFS_PURGE_INTERVAL_SEC (5s)
sits above the gap between an entry's expiry and a demand read, so an
entry read soon after expiry is still served stale; entries idle past
the interval are reclaimed. A bounded stale window, documented at the
constant.

Teardown is ordered: dnsfs_free_config calls timer_shutdown_sync after
kthread_stop (the only side that re-arms), so no sweep can fire or
re-arm before the cache it walks is drained. timer_setup runs in
dnsfs_cache_init.

The softirq/process split uses an atomic flag rather than taking the
process-context query_queue_lock in the timer, avoiding a lock-context
inversion.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

@jserv jserv merged commit 5180e31 into main Jul 3, 2026
5 checks passed
@jserv jserv deleted the ttl-expiry branch July 3, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant