]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
test/neocls/log trimming: reproduce log trimming can go into an infinite loop
authorOguzhan Ozmen <oozmen@bloomberg.net>
Tue, 12 May 2026 19:31:04 +0000 (19:31 +0000)
committerOguzhan Ozmen <oozmen@bloomberg.net>
Tue, 12 May 2026 20:17:52 +0000 (20:17 +0000)
Add two tests that calls trim() loop function directly (the
use_awaitable_t overloads) rather than the single-op wrapper used by
existing tests. Two test cases for the marker-based overload:

- trim_loop_all_entries_by_marker: writes 10 entries, trims all, verifies
  the loop terminates and entries are gone.
- trim_loop_empty_log_by_marker: trims an empty log object, verifying
  the loop terminates on immediate ENODATA.

Without the fix in the following commits, both tests hang indefinitely.

- start a vstart cluster
- run the test: [build] $ ./bin/ceph_test_neocls_log
- the test introduced in this commit stalls forever:
    ...
    RUN      ] neocls_log.trim_loop_all_entries_by_marker <-- stalls forever

Reproduces: https://tracker.ceph.com/issues/76563
Signed-off-by: Oguzhan Ozmen <oozmen@bloomberg.net>
src/test/cls_log/test_neocls_log.cc

index f5f4ae3fdfa0a545f10ee8e47b3619925cd4f5ce..78a2e0cfca90536a1fd1562843bcf799fc87087d 100644 (file)
@@ -473,6 +473,48 @@ CORO_TEST_F(neocls_log, trim_by_marker, NeoRadosTest)
   }
 }
 
+// Test the neorados::trim() loop function (use_awaitable overloads) to verify
+// it terminates. Before any fix in neorados/cls/log.h, the use_awaitable_t
+// overloads had the try-catch for ENODATA inside the for(;;) loop, causing
+// the loop to never exit in certain cluster configs and this CPU hogging.
+CORO_TEST_F(neocls_log, trim_loop_all_entries_by_marker, NeoRadosTest)
+{
+  co_await create_obj(oid);
+  auto start_time = real_clock::now();
+
+  // write 10 cls_log entries into the object
+  co_await generate_log(rados(), oid, pool(), 10, start_time, true,
+                       asio::use_awaitable);
+
+  // call trim() loop function. Without a fix, this never returns
+  // because of where the try-catch sits relative to the for(;;)
+  co_await neorados::cls::log::trim(
+    rados(), oid, pool(),
+    std::string_view{neorados::cls::log::begin_marker},
+    std::string_view{neorados::cls::log::end_marker},
+    asio::use_awaitable);
+
+  // Verify all entries are gone
+  std::vector<l::entry> entries{neorados::cls::log::max_list_entries};
+  std::span<l::entry> result;
+  co_await list(rados(), oid, pool(), entries, &result, asio::use_awaitable);
+  EXPECT_EQ(0u, result.size());
+}
+
+CORO_TEST_F(neocls_log, trim_loop_empty_log_by_marker, NeoRadosTest)
+{
+  co_await create_obj(oid);
+
+  // Trim an empty log object. With the bug, cls_log_trim returns ENODATA,
+  // which is caught and swallowed inside the for(;;), looping forever.
+  co_await neorados::cls::log::trim(
+    rados(), oid, pool(),
+    std::string_view{neorados::cls::log::begin_marker},
+    std::string_view{neorados::cls::log::end_marker},
+    asio::use_awaitable);
+}
+
+
 #if 0 // Disable until we get rid of GCC11
 TEST(neocls_log_bare, lambdata)
 {