The RGW POSIX driver's BucketCache had two memory leak issues:
1. BucketCache destructor did not clean up cached entries
2. list_bucket() had missing lru.unref() calls on early return paths
Issue 1: Missing destructor cleanup
------------------------------------
BucketCache did not have a destructor to clean up BucketCacheEntry
objects at destruction, causing LeakSanitizer to report ~22-31MB of
leaks in unittest_rgw_posix_driver and unittest_posix_bucket_cache.
The cache is properly bounded at runtime (max 100 entries with LRU
eviction), but entries remaining at test shutdown were not freed.
Issue 2: Missing unref calls in list_bucket()
----------------------------------------------
The list_bucket() function had three early return paths that failed
to call lru.unref() before returning:
1. Line 475: When marker not found (MDB_NOTFOUND)
2. Line 483: When bucket is empty (MDB_NOTFOUND)
3. Line 491: When iteration stops early (!again)
This left entries with refcount=2 instead of the expected refcount=1
(sentinel state), preventing proper cleanup in the destructor.
Root cause analysis
-------------------
Through debugging, we discovered:
- Entries created with FLAG_INITIAL start with refcount=2
- list_bucket() should call lru.unref() to decrement to refcount=1
- Missing unref calls left entries with refcount=2
- Destructor's single unref only decremented to refcount=1, not 0
- Entries with refcount=1 were moved to LRU instead of deleted
The fix
-------
1. Add BucketCache destructor that:
- Stops inotify thread first (prevents heap-use-after-free)
- Drains AVL cache and calls lru.unref() on each entry
2. Add lru.unref() calls to all three early return paths in list_bucket()
This ensures all entries reach refcount=0 and are properly deleted,
eliminating all memory leaks while maintaining cache performance.