]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: Fix fast EC truncate to whole stripe 66542/head
authorAlex Ainscow <aainscow@uk.ibm.com>
Sat, 6 Dec 2025 10:14:08 +0000 (10:14 +0000)
committerAlex Ainscow <aainscow@uk.ibm.com>
Sat, 6 Dec 2025 10:15:11 +0000 (10:15 +0000)
WritePlanObj has a key-not-found exception on truncates to exact
stripe lengths.

I have recreated in a unit test as well as on a real system.

It is a concern that ceph_test_rados and ceph_test_rados_io_sequence
never hit this pattern naturally.

Signed-off-by: Alex Ainscow <aainscow@uk.ibm.com>
src/osd/ECTransaction.cc
src/test/osd/test_ec_transaction.cc

index b0c49f62b445f59663864ea9f5465109a59c8572..330c4a7e48ddb87e07d0b8c3422a7e3c45b5a56c 100644 (file)
@@ -270,14 +270,14 @@ ECTransaction::WritePlanObj::WritePlanObj(
      * for the partial stripe and update the parity. For the purposes of
      * parity, the truncated shards are all zero.
      */
-    extent_set truncate_write;
+    if (!truncate_read.empty()) {
+      extent_set truncate_write;
 
-    if (next_align != 0) {
-      truncate_write = truncate_read.at(shard_id_t(0));
-      truncate_write.align(EC_ALIGN_SIZE);
-    }
+      if (next_align != 0) {
+        truncate_write = truncate_read.at(shard_id_t(0));
+        truncate_write.align(EC_ALIGN_SIZE);
+      }
 
-    if (!truncate_read.empty()) {
       if (to_read) {
         to_read->insert(truncate_read);
       } else {
index 252f4973812dafd8410ace5eda92d47cfcc85da7..37ec6a467cc2ddb9baf9aeaba5312db544b600c4 100644 (file)
@@ -465,4 +465,43 @@ TEST(ectransaction, delete_and_write_misaligned) {
   ref_write[shard_id_t(1)].insert(0, 2*EC_ALIGN_SIZE);
   ref_write[shard_id_t(2)].insert(0, 2*EC_ALIGN_SIZE);
   ASSERT_EQ(ref_write, plan.will_write);
+}
+
+TEST(ectransaction, truncate_to_stripe) {
+  hobject_t h;
+  PGTransaction::ObjectOperation op;
+  uint64_t new_size = 2 * EC_ALIGN_SIZE;
+
+  // We have a 4k write quite a way after the current limit of a 4k object
+  op.truncate.emplace(new_size, new_size);
+
+  pg_pool_t pool;
+  pool.set_flag(pg_pool_t::FLAG_EC_OPTIMIZATIONS);
+  ECUtil::stripe_info_t sinfo(2, 1, 2 * EC_ALIGN_SIZE, &pool, std::vector<shard_id_t>(0));
+  object_info_t oi;
+  oi.size = new_size;
+  shard_id_set shards;
+  shards.insert_range(shard_id_t(0), 3);
+
+  ECTransaction::WritePlanObj plan(
+    h,
+    op,
+    sinfo,
+    shards,
+    shards,
+    false,
+    16*EC_ALIGN_SIZE,
+    std::nullopt,
+    std::nullopt,
+    0);
+
+  generic_derr << "plan " << plan << dendl;
+
+  /* We are going to delete the object before writing it.  Best not write anything
+   * from the old object... */
+  ASSERT_FALSE(plan.to_read);
+
+  // Truncating to a whole shard - no writes needed.
+  ECUtil::shard_extent_set_t ref_write(sinfo.get_k_plus_m());
+  ASSERT_EQ(ref_write, plan.will_write);
 }
\ No newline at end of file