summaryrefslogtreecommitdiffstats
path: root/src/test/librbd/journal
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-23 16:45:17 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-23 16:45:44 +0000
commit17d6a993fc17d533460c5f40f3908c708e057c18 (patch)
tree1a3bd93e0ecd74fa02f93a528fe2f87e5314c4b5 /src/test/librbd/journal
parentReleasing progress-linux version 18.2.2-0progress7.99u1. (diff)
downloadceph-17d6a993fc17d533460c5f40f3908c708e057c18.tar.xz
ceph-17d6a993fc17d533460c5f40f3908c708e057c18.zip
Merging upstream version 18.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/librbd/journal')
-rw-r--r--src/test/librbd/journal/test_Entries.cc63
-rw-r--r--src/test/librbd/journal/test_Stress.cc121
2 files changed, 184 insertions, 0 deletions
diff --git a/src/test/librbd/journal/test_Entries.cc b/src/test/librbd/journal/test_Entries.cc
index c392fb9f8..bb4b06c03 100644
--- a/src/test/librbd/journal/test_Entries.cc
+++ b/src/test/librbd/journal/test_Entries.cc
@@ -196,6 +196,69 @@ TEST_F(TestJournalEntries, AioDiscard) {
ASSERT_EQ(234U, aio_discard_event.length);
}
+TEST_F(TestJournalEntries, AioDiscardWithPrune) {
+ REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+ // The discard path can create multiple image extents (ImageRequest.cc) in the
+ // case where the discard request needs to be pruned and multiple objects are
+ // involved in the request. This test ensures that journal event entries are
+ // queued up for each image extent.
+
+ // Create an image that is multiple objects so that we can force multiple
+ // image extents on the discard path.
+ CephContext* cct = reinterpret_cast<CephContext*>(_rados.cct());
+ auto object_size = 1ull << cct->_conf.get_val<uint64_t>("rbd_default_order");
+ auto image_size = 4 * object_size;
+
+ auto image_name = get_temp_image_name();
+ ASSERT_EQ(0, create_image_pp(m_rbd, m_ioctx, image_name, image_size));
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(image_name, &ictx));
+
+ ::journal::Journaler *journaler = create_journaler(ictx);
+ ASSERT_TRUE(journaler != NULL);
+
+ C_SaferCond cond_ctx;
+ auto c = librbd::io::AioCompletion::create(&cond_ctx);
+ c->get();
+ // We offset the discard by -4096 bytes and set discard granularity to 8192;
+ // this should cause two image extents to be formed in
+ // AbstractImageWriteRequest<I>::send_request().
+ api::Io<>::aio_discard(*ictx, c, object_size - 4096, 2 * object_size, 8192,
+ true);
+ ASSERT_EQ(0, c->wait_for_complete());
+ c->put();
+
+ for (uint64_t chunk = 0; chunk < 2; chunk++) {
+ auto offset = object_size;
+ auto size = object_size;
+ if (chunk == 1) {
+ offset = object_size * 2;
+ size = object_size - 8192;
+ }
+
+ ::journal::ReplayEntry replay_entry;
+ if (!journaler->try_pop_front(&replay_entry)) {
+ ASSERT_TRUE(wait_for_entries_available(ictx));
+ ASSERT_TRUE(journaler->try_pop_front(&replay_entry));
+ }
+
+ librbd::journal::EventEntry event_entry;
+ ASSERT_TRUE(get_event_entry(replay_entry, &event_entry));
+
+ ASSERT_EQ(librbd::journal::EVENT_TYPE_AIO_DISCARD,
+ event_entry.get_event_type());
+
+ librbd::journal::AioDiscardEvent aio_discard_event =
+ boost::get<librbd::journal::AioDiscardEvent>(event_entry.event);
+ ASSERT_EQ(offset, aio_discard_event.offset);
+ ASSERT_EQ(size, aio_discard_event.length);
+
+ journaler->committed(replay_entry);
+ }
+}
+
TEST_F(TestJournalEntries, AioFlush) {
REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
diff --git a/src/test/librbd/journal/test_Stress.cc b/src/test/librbd/journal/test_Stress.cc
new file mode 100644
index 000000000..d3df9147a
--- /dev/null
+++ b/src/test/librbd/journal/test_Stress.cc
@@ -0,0 +1,121 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/librados/test_cxx.h"
+#include "test/librbd/test_fixture.h"
+#include "test/librbd/test_support.h"
+#include "cls/rbd/cls_rbd_types.h"
+#include "cls/journal/cls_journal_types.h"
+#include "cls/journal/cls_journal_client.h"
+#include "journal/Journaler.h"
+#include "librbd/ExclusiveLock.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ImageState.h"
+#include "librbd/ImageWatcher.h"
+#include "librbd/internal.h"
+#include "librbd/Journal.h"
+#include "librbd/Operations.h"
+#include "librbd/api/Io.h"
+#include "librbd/api/Snapshot.h"
+#include "librbd/io/AioCompletion.h"
+#include "librbd/io/ImageDispatchSpec.h"
+#include "librbd/io/ImageRequest.h"
+#include "librbd/io/ReadResult.h"
+#include "librbd/journal/Types.h"
+#include <boost/scope_exit.hpp>
+
+void register_test_journal_stress() {
+}
+
+namespace librbd {
+namespace journal {
+
+class TestJournalStress : public TestFixture {
+};
+
+TEST_F(TestJournalStress, DiscardWithPruneWriteOverlap) {
+ REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+ // Overlap discards and writes while discard pruning is occurring. This tests
+ // the conditions under which https://tracker.ceph.com/issues/63422 occurred.
+
+ // Create an image that is multiple objects so that we can force multiple
+ // image extents on the discard path.
+ int order = 22;
+ auto object_size = uint64_t{1} << order;
+ auto image_size = 4 * object_size;
+
+ // Write-around cache required for overlapping I/O delays.
+ std::map<std::string, std::string> config;
+ config["rbd_cache"] = "true";
+ config["rbd_cache_policy"] = "writearound";
+ config["rbd_cache_max_dirty"] = std::to_string(image_size);
+ config["rbd_cache_writethrough_until_flush"] = "false";
+ // XXX: Work around https://tracker.ceph.com/issues/63681, which this test
+ // exposes when run under Valgrind.
+ config["librados_thread_count"] = "15";
+
+ librados::Rados rados;
+ ASSERT_EQ("", connect_cluster_pp(rados, config));
+
+ librados::IoCtx ioctx;
+ ASSERT_EQ(0, rados.ioctx_create(_pool_name.c_str(), ioctx));
+
+ uint64_t features;
+ ASSERT_TRUE(::get_features(&features));
+ auto image_name = get_temp_image_name();
+ ASSERT_EQ(0, create_image_full_pp(m_rbd, ioctx, image_name, image_size,
+ features, false, &order));
+
+ auto ictx = new librbd::ImageCtx(image_name, "", nullptr, ioctx, false);
+ ASSERT_EQ(0, ictx->state->open(0));
+ BOOST_SCOPE_EXIT(ictx) {
+ ictx->state->close();
+ } BOOST_SCOPE_EXIT_END;
+
+ std::thread write_thread(
+ [ictx, object_size]() {
+ std::string payload(object_size, '1');
+
+ for (auto i = 0; i < 200; i++) {
+ // Alternate overlaps with the two objects that the discard below
+ // touches.
+ for (auto offset = object_size;
+ offset < object_size * 3;
+ offset += object_size) {
+ bufferlist payload_bl;
+ payload_bl.append(payload);
+ auto aio_comp = new librbd::io::AioCompletion();
+ api::Io<>::aio_write(*ictx, aio_comp, offset, payload.size(),
+ std::move(payload_bl), 0, true);
+ ASSERT_EQ(0, aio_comp->wait_for_complete());
+ aio_comp->release();
+ }
+ }
+ }
+ );
+
+ auto discard_exit = false;
+ std::thread discard_thread(
+ [ictx, object_size, &discard_exit]() {
+ while (!discard_exit) {
+ // We offset the discard by -4096 bytes and set discard granularity to
+ // 8192; this should cause two image extents to be formed in
+ // AbstractImageWriteRequest<I>::send_request() on objects 1 and 2,
+ // overlapping with the writes above.
+ auto aio_comp = new librbd::io::AioCompletion();
+ api::Io<>::aio_discard(*ictx, aio_comp, object_size - 4096,
+ 2 * object_size, 8192, true);
+ ASSERT_EQ(0, aio_comp->wait_for_complete());
+ aio_comp->release();
+ }
+ }
+ );
+
+ write_thread.join();
+ discard_exit = true;
+ discard_thread.join();
+}
+
+} // namespace journal
+} // namespace librbd