]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: Fix fast EC truncate to whole stripe 66543/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:33:51 +0000 (10:33 +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>
(cherry picked from commit 6075be4821e4a03b56c871a3b35fbd3375ee16e6)

src/osd/ECTransaction.cc
src/test/osd/test_ec_transaction.cc

index 0ec86ee8bc6ececcecebf2f06ddcd686b891990a..eacce3c2d1a33c45a2aa63c93cd81a850c1f3e0a 100644 (file)
@@ -269,14 +269,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 44984a4444c7f807dc09ea781d9ee8629e6af65a..d4fedcb017029c683a7f9c826034278ecfe77605 100644 (file)
@@ -464,4 +464,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