From ae012cce34e75005f1eb82fdea378aee9e11047a Mon Sep 17 00:00:00 2001 From: Bill Scales Date: Tue, 10 Dec 2024 10:51:16 +0000 Subject: [PATCH] test: ceph_test_rados_io_sequence - add truncate Add support for truncate I/O in interactive mode Signed-off-by: Bill Scales --- src/common/io_exerciser/IoOp.cc | 12 ++++++++++++ src/common/io_exerciser/IoOp.h | 8 ++++++++ src/common/io_exerciser/ObjectModel.cc | 7 +++++++ src/common/io_exerciser/OpType.h | 3 +++ src/common/io_exerciser/RadosIo.cc | 15 +++++++++++++++ src/test/osd/ceph_test_rados_io_sequence.cc | 3 +++ 6 files changed, 48 insertions(+) diff --git a/src/common/io_exerciser/IoOp.cc b/src/common/io_exerciser/IoOp.cc index 53e79c327f373..1046d6aaa914a 100644 --- a/src/common/io_exerciser/IoOp.cc +++ b/src/common/io_exerciser/IoOp.cc @@ -20,6 +20,7 @@ using SingleFailedWriteOp = ceph::io_exerciser::SingleFailedWriteOp; using DoubleFailedWriteOp = ceph::io_exerciser::DoubleFailedWriteOp; using TripleFailedWriteOp = ceph::io_exerciser::TripleFailedWriteOp; using SingleAppendOp = ceph::io_exerciser::SingleAppendOp; +using TruncateOp = ceph::io_exerciser::TruncateOp; namespace { std::string value_to_string(uint64_t v) { @@ -215,6 +216,17 @@ std::unique_ptr SingleAppendOp::generate(uint64_t length) { return std::make_unique(length); } +TruncateOp::TruncateOp(uint64_t size) + : TestOp(), size(size) {} + +std::unique_ptr TruncateOp::generate(uint64_t size) { + return std::make_unique(size); +} + +std::string TruncateOp::to_string(uint64_t block_size) const { + return "Truncate (size=" + value_to_string(size * block_size) + ")"; +} + SingleFailedWriteOp::SingleFailedWriteOp(uint64_t offset, uint64_t length) : ReadWriteOp({offset}, {length}) {} diff --git a/src/common/io_exerciser/IoOp.h b/src/common/io_exerciser/IoOp.h index e72d74b90fdec..0cfc6c0230926 100644 --- a/src/common/io_exerciser/IoOp.h +++ b/src/common/io_exerciser/IoOp.h @@ -131,6 +131,14 @@ class SingleAppendOp : public ReadWriteOp { static std::unique_ptr generate(uint64_t length); }; +class TruncateOp : public TestOp { + public: + TruncateOp(uint64_t size); + static std::unique_ptr generate(uint64_t size); + std::string to_string(uint64_t block_size) const override; + uint64_t size; +}; + class SingleFailedWriteOp : public ReadWriteOp { public: SingleFailedWriteOp(uint64_t offset, uint64_t length); diff --git a/src/common/io_exerciser/ObjectModel.cc b/src/common/io_exerciser/ObjectModel.cc index 95708e33cae8d..de77c0757b6f3 100644 --- a/src/common/io_exerciser/ObjectModel.cc +++ b/src/common/io_exerciser/ObjectModel.cc @@ -118,6 +118,13 @@ void ObjectModel::applyIoOp(IoOp& op) { generate_random); break; + case OpType::Truncate: + ceph_assert(created); + ceph_assert(reads.empty()); + ceph_assert(writes.empty()); + contents.resize(static_cast(op).size); + break; + case OpType::Remove: ceph_assert(created); ceph_assert(reads.empty()); diff --git a/src/common/io_exerciser/OpType.h b/src/common/io_exerciser/OpType.h index f8e9091071432..6a7e4604407e5 100644 --- a/src/common/io_exerciser/OpType.h +++ b/src/common/io_exerciser/OpType.h @@ -24,6 +24,7 @@ enum class OpType { Write2, // Two writes in a single op Write3, // Three writes in a single op Append, // Append + Truncate, // Truncate FailedWrite, // A write which should fail FailedWrite2, // Two writes in one op which should fail FailedWrite3, // Three writes in one op which should fail @@ -72,6 +73,8 @@ struct fmt::formatter { return fmt::format_to(ctx.out(), "Write3"); case ceph::io_exerciser::OpType::Append: return fmt::format_to(ctx.out(), "Append"); + case ceph::io_exerciser::OpType::Truncate: + return fmt::format_to(ctx.out(), "Truncate"); case ceph::io_exerciser::OpType::FailedWrite: return fmt::format_to(ctx.out(), "FailedWrite"); case ceph::io_exerciser::OpType::FailedWrite2: diff --git a/src/common/io_exerciser/RadosIo.cc b/src/common/io_exerciser/RadosIo.cc index e055f891acde9..cf0cc1163d448 100644 --- a/src/common/io_exerciser/RadosIo.cc +++ b/src/common/io_exerciser/RadosIo.cc @@ -146,6 +146,21 @@ void RadosIo::applyIoOp(IoOp& op) { break; } + case OpType::Truncate: { + start_io(); + uint64_t opSize = static_cast(op).size; + auto op_info = std::make_shared>(); + librados::ObjectWriteOperation wop; + wop.truncate(opSize * block_size); + auto truncate_cb = [this](boost::system::error_code ec, version_t ver) { + ceph_assert(ec == boost::system::errc::success); + finish_io(); + }; + librados::async_operate(asio.get_executor(), io, oid, std::move(wop), 0, + nullptr, truncate_cb); + break; + } + case OpType::Remove: { start_io(); auto op_info = std::make_shared>(); diff --git a/src/test/osd/ceph_test_rados_io_sequence.cc b/src/test/osd/ceph_test_rados_io_sequence.cc index 5e7e184b6a36d..0646ac0162cb1 100644 --- a/src/test/osd/ceph_test_rados_io_sequence.cc +++ b/src/test/osd/ceph_test_rados_io_sequence.cc @@ -49,6 +49,7 @@ using SingleWriteOp = ceph::io_exerciser::SingleWriteOp; using DoubleWriteOp = ceph::io_exerciser::DoubleWriteOp; using TripleWriteOp = ceph::io_exerciser::TripleWriteOp; using SingleAppendOp = ceph::io_exerciser::SingleAppendOp; +using TruncateOp = ceph::io_exerciser::TruncateOp; using SingleFailedWriteOp = ceph::io_exerciser::SingleFailedWriteOp; using DoubleFailedWriteOp = ceph::io_exerciser::DoubleFailedWriteOp; using TripleFailedWriteOp = ceph::io_exerciser::TripleFailedWriteOp; @@ -811,6 +812,8 @@ bool ceph::io_sequence::tester::TestRunner::run_interactive_test() { } else if (op == "append") { uint64_t length = get_numeric_token(); ioop = SingleAppendOp::generate(length); + } else if (op == "truncate") { + ioop = TruncateOp::generate(get_numeric_token()); } else if (op == "failedwrite") { uint64_t offset = get_numeric_token(); uint64_t length = get_numeric_token(); -- 2.39.5