]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commit
rgw/posix: fix memory leaks in BucketCache
authorKefu Chai <k.chai@proxmox.com>
Fri, 9 Jan 2026 02:02:37 +0000 (10:02 +0800)
committerKefu Chai <k.chai@proxmox.com>
Mon, 12 Jan 2026 12:52:25 +0000 (20:52 +0800)
commit41208b7df116e83576fd6bdda4b8da142e6ad388
tree3d7d208ac21149fab9f09efe1e01500a8add73dd
parentef8b405428bb6c4b5dfd688d5b563c1dbd99f353
rgw/posix: fix memory leaks in BucketCache

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.

Signed-off-by: Kefu Chai <k.chai@proxmox.com>
src/rgw/driver/posix/bucket_cache.h