From 61b6d72226072d8eae791909b066471ce42d746c Mon Sep 17 00:00:00 2001 From: Oguzhan Ozmen Date: Tue, 19 May 2026 22:12:35 +0000 Subject: [PATCH] rgw/datalog: DataLogBackends::trim_entries: fix crash when target_gen > head_gen When a cluster has no sync zones (single-zone), DataLogTrimCR passes max_marker() as the trim marker, which encodes target_gen = UINT64_MAX from gencursor(). In DataLogBackends::trim_entries, after trimming the head (last) generation, the break condition if (be->gen_id == target_gen) is false (e.g. 0 != UINT64_MAX), so the loop attempts its increment expression: be = upper_bound(be->gen_id)->second upper_bound(head_gen) returns end(), and dereferencing end()->second causes crash. Fix: also break when be->gen_id >= head_gen. Once we've trimmed the head generation there are no further backends in the map, so the upper_bound dereference in the loop increment will be skipped. This is a general bug that affects any cluster using max_marker() as a trim target (i.e. every single-zone deployment). Signed-off-by: Oguzhan Ozmen --- src/rgw/driver/rados/rgw_datalog.cc | 2 +- src/test/rgw/test_datalog.cc | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/rgw/driver/rados/rgw_datalog.cc b/src/rgw/driver/rados/rgw_datalog.cc index 74a0675caf1..52a98720519 100644 --- a/src/rgw/driver/rados/rgw_datalog.cc +++ b/src/rgw/driver/rados/rgw_datalog.cc @@ -1193,7 +1193,7 @@ asio::awaitable DataLogBackends::trim_entries( l.unlock(); auto c = be->gen_id == target_gen ? cursor : be->max_marker(); co_await be->trim(dpp, shard_id, c); - if (be->gen_id == target_gen) + if (be->gen_id == target_gen || be->gen_id >= head_gen) break; l.lock(); }; diff --git a/src/test/rgw/test_datalog.cc b/src/test/rgw/test_datalog.cc index 6dbb985f2df..1fb48e2ebe7 100644 --- a/src/test/rgw/test_datalog.cc +++ b/src/test/rgw/test_datalog.cc @@ -443,8 +443,6 @@ CORO_TEST_F(DataLogBulky, BulkyCycleRecovery, DataLogBulky) { } // trim_entries with max_marker() must not crash on a single-generation cluster. -// Without the fix, the loop increment would call upper_bound(head_gen)->second, -// dereferencing end() and causing a SIGSEGV. CORO_TEST_F(DataLogBulky, TrimWithMaxMarker, DataLogBulky) { for (const auto& bg : bulky) { co_await add_entry(dpp(), bg); -- 2.47.3