]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/datalog: DataLogBackends::trim_entries: fix crash when target_gen > head_gen 68874/head
authorOguzhan Ozmen <oozmen@bloomberg.net>
Tue, 19 May 2026 22:12:35 +0000 (22:12 +0000)
committerOguzhan Ozmen <oozmen@bloomberg.net>
Wed, 20 May 2026 13:56:31 +0000 (13:56 +0000)
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 <oozmen@bloomberg.net>
src/rgw/driver/rados/rgw_datalog.cc
src/test/rgw/test_datalog.cc

index 74a0675caf145ad048e5962d86abb778cc2d50f5..52a98720519a13dded27514746e07c813cc8bcd9 100644 (file)
@@ -1193,7 +1193,7 @@ asio::awaitable<void> 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();
   };
index 6dbb985f2df6892520ba847f3907efbf7b6d3813..1fb48e2ebe74ecca993c49cb4608f775aa8e79eb 100644 (file)
@@ -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);