]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
test: ceph_test_rados_io_sequence support appends
authorBill Scales <bill_scales@uk.ibm.com>
Wed, 27 Nov 2024 10:33:28 +0000 (10:33 +0000)
committerAlex Ainscow <aainscow@uk.ibm.com>
Wed, 5 Mar 2025 08:59:16 +0000 (08:59 +0000)
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 <bill_scales@uk.ibm.com>
src/common/io_exerciser/IoOp.cc
src/common/io_exerciser/IoOp.h
src/common/io_exerciser/ObjectModel.cc
src/common/io_exerciser/OpType.h
src/common/io_exerciser/RadosIo.cc
src/test/osd/ceph_test_rados_io_sequence.cc
src/test/osd/ceph_test_rados_io_sequence.h

index 493d1f435b48aacc54db167a2ee498f9cbfa77e5..53e79c327f3738194835066ce124fbab71c0580f 100644 (file)
@@ -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 <OpType opType, int numIOs>
 std::string ceph::io_exerciser::ReadWriteOp<opType, numIOs>::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<opType, numIOs>::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> TripleWriteOp::generate(
                                          offset3, length3);
 }
 
+SingleAppendOp::SingleAppendOp(uint64_t length)
+    : ReadWriteOp<OpType::Append, 1>({0}, {length}) {}
+
+std::unique_ptr<SingleAppendOp> SingleAppendOp::generate(uint64_t length) {
+  return std::make_unique<SingleAppendOp>(length);
+}
+
 SingleFailedWriteOp::SingleFailedWriteOp(uint64_t offset, uint64_t length)
     : ReadWriteOp<OpType::FailedWrite, 1>({offset}, {length}) {}
 
@@ -313,4 +328,4 @@ std::unique_ptr<ceph::io_exerciser::ClearWriteErrorInjectOp>
 ceph::io_exerciser ::ClearWriteErrorInjectOp::generate(
     int shard, const std::optional<uint64_t>& type) {
   return std::make_unique<ClearWriteErrorInjectOp>(shard, type);
-}
\ No newline at end of file
+}
index 1887eafcc1f412936102397ce9601b61aba67284..e72d74b90fdec2179d911a0cdfbb0a126093601a 100644 (file)
@@ -125,6 +125,12 @@ class TripleWriteOp : public ReadWriteOp<OpType::Write3, 3> {
       uint64_t offset3, uint64_t length3);
 };
 
+class SingleAppendOp : public ReadWriteOp<OpType::Append, 1> {
+ public:
+  SingleAppendOp(uint64_t length);
+  static std::unique_ptr<SingleAppendOp> generate(uint64_t length);
+};
+
 class SingleFailedWriteOp : public ReadWriteOp<OpType::FailedWrite, 1> {
  public:
   SingleFailedWriteOp(uint64_t offset, uint64_t length);
index 454d7254cf2a875bf5526f8d354bb418ffefa2e6..edb7f9367f9b847615b0e53380366934dadaf429 100644 (file)
@@ -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<TripleWriteOp&>(op);
       verify_write_and_record_and_generate_seed(writeOp);
     } break;
+
+    case OpType::Append: {
+      ceph_assert(created);
+      SingleAppendOp& appendOp = static_cast<SingleAppendOp&>(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<SingleWriteOp&>(op);
@@ -156,6 +166,7 @@ void ObjectModel::applyIoOp(IoOp& op) {
     case OpType::FailedWrite2: {
       DoubleWriteOp& writeOp = static_cast<DoubleWriteOp&>(op);
       verify_failed_write_and_record(writeOp);
+
     } break;
     case OpType::FailedWrite3: {
       TripleWriteOp& writeOp = static_cast<TripleWriteOp&>(op);
index 7cddb805e458c31d02d1804f974fea3558d7e457..f8e9091071432e148b0ba43eb26cd1006526b1ea 100644 (file)
@@ -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<ceph::io_exerciser::OpType> {
         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<ceph::io_exerciser::OpType> {
         return fmt::format_to(ctx.out(), "Unknown OpType");
     }
   }
-};
\ No newline at end of file
+};
index 6e2b57b43e7f5f787a35b83ab3afd5477dc3a374..e055f891acde99d8dd249e5d891c34bfb3209fd6 100644 (file)
@@ -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<SingleAppendOp&>(op);
+      applyWriteOp(appendOp);
+      break;
+    }
+
     case OpType::FailedWrite: {
       start_io();
       SingleFailedWriteOp& writeOp = static_cast<SingleFailedWriteOp&>(op);
index 96808ea37e56cbd1eb6728be6bdc1b9bd0234cf3..5e7e184b6a36d46fff03746659b6430c29adbd7e 100644 (file)
@@ -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();
index 9af5f706b2fdf92d584d746449feb6b8d423060d..98ebb58985ec0fd51aad818fc792b1a71bcbaaf2 100644 (file)
@@ -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<std::string> get_optional_token();
   uint64_t get_numeric_token();
   std::optional<uint64_t> get_optional_numeric_token();