From: Bill Scales Date: Wed, 27 Nov 2024 10:33:28 +0000 (+0000) Subject: test: ceph_test_rados_io_sequence support appends X-Git-Tag: v20.3.0~439^2~5 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=03316ff4ace9af4f2eb77e0957fc6077476e95f6;p=ceph.git test: ceph_test_rados_io_sequence support appends 1. Add append I/O to extend size of object 2. Allow write I/Os to extend size of object 3. Make interactive mode handle EOF gracefully Signed-off-by: Bill Scales --- diff --git a/src/common/io_exerciser/IoOp.cc b/src/common/io_exerciser/IoOp.cc index 493d1f435b48a..53e79c327f373 100644 --- a/src/common/io_exerciser/IoOp.cc +++ b/src/common/io_exerciser/IoOp.cc @@ -19,6 +19,7 @@ using TripleWriteOp = ceph::io_exerciser::TripleWriteOp; using SingleFailedWriteOp = ceph::io_exerciser::SingleFailedWriteOp; using DoubleFailedWriteOp = ceph::io_exerciser::DoubleFailedWriteOp; using TripleFailedWriteOp = ceph::io_exerciser::TripleFailedWriteOp; +using SingleAppendOp = ceph::io_exerciser::SingleAppendOp; namespace { std::string value_to_string(uint64_t v) { @@ -100,16 +101,21 @@ template std::string ceph::io_exerciser::ReadWriteOp::to_string( uint64_t block_size) const { std::string offset_length_desc; + std::string length_desc; if (numIOs > 0) { offset_length_desc += fmt::format( "offset1={}", value_to_string(this->offset[0] * block_size)); - offset_length_desc += fmt::format( - ",length1={}", value_to_string(this->length[0] * block_size)); + length_desc += fmt::format("length1={}", + value_to_string(this->length[0] * block_size)); + offset_length_desc += "," + length_desc; for (int i = 1; i < numIOs; i++) { + std::string length; offset_length_desc += fmt::format( ",offset{}={}", i + 1, value_to_string(this->offset[i] * block_size)); - offset_length_desc += fmt::format( - ",length{}={}", i + 1, value_to_string(this->length[i] * block_size)); + length += fmt::format(",length{}={}", i + 1, + value_to_string(this->length[i] * block_size)); + length_desc += length; + offset_length_desc += length; } } switch (opType) { @@ -125,6 +131,8 @@ std::string ceph::io_exerciser::ReadWriteOp::to_string( [[fallthrough]]; case OpType::Write3: return fmt::format("Write{} ({})", numIOs, offset_length_desc); + case OpType::Append: + return fmt::format("Append{} ({})", numIOs, length_desc); case OpType::FailedWrite: [[fallthrough]]; case OpType::FailedWrite2: @@ -200,6 +208,13 @@ std::unique_ptr TripleWriteOp::generate( offset3, length3); } +SingleAppendOp::SingleAppendOp(uint64_t length) + : ReadWriteOp({0}, {length}) {} + +std::unique_ptr SingleAppendOp::generate(uint64_t length) { + return std::make_unique(length); +} + SingleFailedWriteOp::SingleFailedWriteOp(uint64_t offset, uint64_t length) : ReadWriteOp({offset}, {length}) {} @@ -313,4 +328,4 @@ std::unique_ptr ceph::io_exerciser ::ClearWriteErrorInjectOp::generate( int shard, const std::optional& type) { return std::make_unique(shard, type); -} \ No newline at end of file +} diff --git a/src/common/io_exerciser/IoOp.h b/src/common/io_exerciser/IoOp.h index 1887eafcc1f41..e72d74b90fdec 100644 --- a/src/common/io_exerciser/IoOp.h +++ b/src/common/io_exerciser/IoOp.h @@ -125,6 +125,12 @@ class TripleWriteOp : public ReadWriteOp { uint64_t offset3, uint64_t length3); }; +class SingleAppendOp : public ReadWriteOp { + public: + SingleAppendOp(uint64_t length); + static std::unique_ptr generate(uint64_t length); +}; + 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 454d7254cf2a8..edb7f9367f9b8 100644 --- a/src/common/io_exerciser/ObjectModel.cc +++ b/src/common/io_exerciser/ObjectModel.cc @@ -71,7 +71,9 @@ void ObjectModel::applyIoOp(IoOp& op) { ceph_assert(!reads.intersects(writeOp.offset[i], writeOp.length[i])); ceph_assert(!writes.intersects(writeOp.offset[i], writeOp.length[i])); writes.union_insert(writeOp.offset[i], writeOp.length[i]); - ceph_assert(writeOp.offset[i] + writeOp.length[i] <= contents.size()); + if (writeOp.offset[i] + writeOp.length[i] > contents.size()) { + contents.resize(writeOp.offset[i] + writeOp.length[i]); + } std::generate(std::execution::seq, std::next(contents.begin(), writeOp.offset[i]), std::next(contents.begin(), @@ -148,6 +150,14 @@ void ObjectModel::applyIoOp(IoOp& op) { TripleWriteOp& writeOp = static_cast(op); verify_write_and_record_and_generate_seed(writeOp); } break; + + case OpType::Append: { + ceph_assert(created); + SingleAppendOp& appendOp = static_cast(op); + appendOp.offset[0] = contents.size(); + verify_write_and_record_and_generate_seed(appendOp); + } break; + case OpType::FailedWrite: { ceph_assert(created); SingleWriteOp& writeOp = static_cast(op); @@ -156,6 +166,7 @@ void ObjectModel::applyIoOp(IoOp& op) { case OpType::FailedWrite2: { DoubleWriteOp& writeOp = static_cast(op); verify_failed_write_and_record(writeOp); + } break; case OpType::FailedWrite3: { TripleWriteOp& writeOp = static_cast(op); diff --git a/src/common/io_exerciser/OpType.h b/src/common/io_exerciser/OpType.h index 7cddb805e458c..f8e9091071432 100644 --- a/src/common/io_exerciser/OpType.h +++ b/src/common/io_exerciser/OpType.h @@ -23,6 +23,7 @@ enum class OpType { Write, // Write Write2, // Two writes in a single op Write3, // Three writes in a single op + Append, // Append FailedWrite, // A write which should fail FailedWrite2, // Two writes in one op which should fail FailedWrite3, // Three writes in one op which should fail @@ -69,6 +70,8 @@ struct fmt::formatter { return fmt::format_to(ctx.out(), "Write2"); case ceph::io_exerciser::OpType::Write3: 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::FailedWrite: return fmt::format_to(ctx.out(), "FailedWrite"); case ceph::io_exerciser::OpType::FailedWrite2: @@ -88,4 +91,4 @@ struct fmt::formatter { return fmt::format_to(ctx.out(), "Unknown OpType"); } } -}; \ No newline at end of file +}; diff --git a/src/common/io_exerciser/RadosIo.cc b/src/common/io_exerciser/RadosIo.cc index 6e2b57b43e7f5..e055f891acde9 100644 --- a/src/common/io_exerciser/RadosIo.cc +++ b/src/common/io_exerciser/RadosIo.cc @@ -171,6 +171,8 @@ void RadosIo::applyIoOp(IoOp& op) { [[fallthrough]]; case OpType::Write3: [[fallthrough]]; + case OpType::Append: + [[fallthrough]]; case OpType::FailedWrite: [[fallthrough]]; case OpType::FailedWrite2: @@ -298,6 +300,13 @@ void RadosIo::applyReadWriteOp(IoOp& op) { break; } + case OpType::Append: { + start_io(); + SingleAppendOp& appendOp = static_cast(op); + applyWriteOp(appendOp); + break; + } + case OpType::FailedWrite: { start_io(); SingleFailedWriteOp& writeOp = static_cast(op); diff --git a/src/test/osd/ceph_test_rados_io_sequence.cc b/src/test/osd/ceph_test_rados_io_sequence.cc index 96808ea37e56c..5e7e184b6a36d 100644 --- a/src/test/osd/ceph_test_rados_io_sequence.cc +++ b/src/test/osd/ceph_test_rados_io_sequence.cc @@ -48,6 +48,7 @@ using TripleReadOp = ceph::io_exerciser::TripleReadOp; 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 SingleFailedWriteOp = ceph::io_exerciser::SingleFailedWriteOp; using DoubleFailedWriteOp = ceph::io_exerciser::DoubleFailedWriteOp; using TripleFailedWriteOp = ceph::io_exerciser::TripleFailedWriteOp; @@ -667,9 +668,12 @@ void ceph::io_sequence::tester::TestRunner::clear_tokens() { tokens = split.end(); } -std::string ceph::io_sequence::tester::TestRunner::get_token() { +std::string ceph::io_sequence::tester::TestRunner::get_token(bool allow_eof) { while (line.empty() || tokens == split.end()) { if (!std::getline(std::cin, line)) { + if (allow_eof) { + return "done"; + } throw std::runtime_error("End of input"); } split = ceph::split(line); @@ -759,7 +763,7 @@ bool ceph::io_sequence::tester::TestRunner::run_interactive_test() { } while (!done) { - const std::string op = get_token(); + const std::string op = get_token(true); if (op == "done" || op == "q" || op == "quit") { ioop = ceph::io_exerciser::DoneOp::generate(); } else if (op == "create") { @@ -804,6 +808,9 @@ bool ceph::io_sequence::tester::TestRunner::run_interactive_test() { uint64_t length3 = get_numeric_token(); ioop = TripleWriteOp::generate(offset1, length1, offset2, length2, offset3, length3); + } else if (op == "append") { + uint64_t length = get_numeric_token(); + ioop = SingleAppendOp::generate(length); } else if (op == "failedwrite") { uint64_t offset = get_numeric_token(); uint64_t length = get_numeric_token(); diff --git a/src/test/osd/ceph_test_rados_io_sequence.h b/src/test/osd/ceph_test_rados_io_sequence.h index 9af5f706b2fdf..98ebb58985ec0 100644 --- a/src/test/osd/ceph_test_rados_io_sequence.h +++ b/src/test/osd/ceph_test_rados_io_sequence.h @@ -322,7 +322,7 @@ class TestRunner { ceph::spliterator tokens; void clear_tokens(); - std::string get_token(); + std::string get_token(bool allow_eof = false); std::optional get_optional_token(); uint64_t get_numeric_token(); std::optional get_optional_numeric_token();