]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/os/seastore/onode: add the "need_cow" field to indicate whether
authorXuehan Xu <xuxuehan@qianxin.com>
Tue, 12 Aug 2025 06:51:15 +0000 (14:51 +0800)
committerXuehan Xu <xuxuehan@qianxin.com>
Sun, 28 Sep 2025 06:48:59 +0000 (14:48 +0800)
the onode's object data space needs to do clone before modification

At present, it's only when the onode's object data space is sharing its
own direct lba mappings with other onodes that the "need_cow" field
would be true.

Signed-off-by: Xuehan Xu <xuxuehan@qianxin.com>
src/crimson/os/seastore/onode.h
src/crimson/os/seastore/onode_manager/staged-fltree/fltree_onode_manager.cc
src/crimson/os/seastore/onode_manager/staged-fltree/fltree_onode_manager.h
src/test/crimson/seastore/test_object_data_handler.cc

index 71326c89167a4ebdb44b3c15283c8501f2f2f097..470578c044b915817058fddfff6bdc48aef5add9 100644 (file)
@@ -40,6 +40,14 @@ struct onode_layout_t {
 
   char oi[MAX_OI_LENGTH] = {0};
   char ss[MAX_SS_LENGTH] = {0};
+  /**
+    * needs_cow
+    *
+    * If true, all lba mappings for onode must be cloned
+    * to a new range prior to mutation. See ObjectDataHandler::copy_on_write,
+    * do_clone, do_clonerange
+    */
+  bool need_cow = false;
 
   onode_layout_t() : omap_root(omap_type_t::OMAP), log_root(omap_type_t::LOG),
     xattr_root(omap_type_t::XATTR) {}
@@ -94,6 +102,8 @@ public:
   virtual void update_snapset(Transaction&, ceph::bufferlist&) = 0;
   virtual void clear_object_info(Transaction&) = 0;
   virtual void clear_snapset(Transaction&) = 0;
+  virtual void set_need_cow(Transaction&) = 0;
+  virtual void unset_need_cow(Transaction&) = 0;
 
   laddr_t get_metadata_hint(uint64_t block_size) const {
     assert(default_metadata_offset);
index e675bf346f15b6b075d12a992c4e051593124dc5..1f0ffcb0c6d56e0858ae058f6b900ed789af0cbb 100644 (file)
@@ -20,6 +20,18 @@ void FLTreeOnode::Recorder::apply_value_delta(
     ceph::decode(op, bliter);
     auto &mlayout = *reinterpret_cast<onode_layout_t*>(value.get_write());
     switch (op) {
+    case delta_op_t::UNSET_NEED_COW:
+      DEBUG("setting need_cow");
+      bliter.copy(
+       sizeof(mlayout.need_cow),
+       (char *)&mlayout.need_cow);
+      break;
+    case delta_op_t::SET_NEED_COW:
+      DEBUG("setting need_cow");
+      bliter.copy(
+       sizeof(mlayout.need_cow),
+       (char *)&mlayout.need_cow);
+      break;
     case delta_op_t::UPDATE_ONODE_SIZE:
       DEBUG("update onode size");
       bliter.copy(sizeof(mlayout.size), (char *)&mlayout.size);
@@ -80,6 +92,18 @@ void FLTreeOnode::Recorder::encode_update(
   auto &encoded = get_encoded(payload_mut);
   ceph::encode(op, encoded);
   switch(op) {
+  case delta_op_t::UNSET_NEED_COW:
+    DEBUG("setting need_cow");
+    encoded.append(
+      (const char *)&layout.need_cow,
+      sizeof(layout.need_cow));
+    break;
+  case delta_op_t::SET_NEED_COW:
+    DEBUG("setting need_cow");
+    encoded.append(
+      (const char *)&layout.need_cow,
+      sizeof(layout.need_cow));
+    break;
   case delta_op_t::UPDATE_ONODE_SIZE:
     DEBUG("update onode size");
     encoded.append(
index 06a0809d932c89e1fed4a84ab204ebcad31cd6af..8a1e3710648d18c438e61d9be2b57bb9b8d10398 100644 (file)
@@ -56,7 +56,9 @@ struct FLTreeOnode final : Onode, Value {
       UPDATE_SNAPSET,
       CLEAR_OBJECT_INFO,
       CLEAR_SNAPSET,
-      CREATE_DEFAULT
+      CREATE_DEFAULT,
+      SET_NEED_COW,
+      UNSET_NEED_COW
     };
     Recorder(bufferlist &bl) : ValueDeltaRecorder(bl) {}
 
@@ -105,6 +107,34 @@ struct FLTreeOnode final : Onode, Value {
     });
   }
 
+  void set_need_cow(Transaction &t) final {
+    with_mutable_layout(
+      t,
+      [](NodeExtentMutable &payload_mut, Recorder *recorder) {
+       auto &mlayout = *reinterpret_cast<onode_layout_t*>(
+          payload_mut.get_write());
+       mlayout.need_cow = true;
+       if (recorder) {
+         recorder->encode_update(
+           payload_mut, Recorder::delta_op_t::SET_NEED_COW);
+       }
+    });
+  }
+
+  void unset_need_cow(Transaction &t) final {
+    with_mutable_layout(
+      t,
+      [](NodeExtentMutable &payload_mut, Recorder *recorder) {
+       auto &mlayout = *reinterpret_cast<onode_layout_t*>(
+          payload_mut.get_write());
+       mlayout.need_cow = false;
+       if (recorder) {
+         recorder->encode_update(
+           payload_mut, Recorder::delta_op_t::UNSET_NEED_COW);
+       }
+    });
+  }
+
   void update_onode_size(Transaction &t, uint32_t size) final {
     with_mutable_layout(
       t,
index fd6d2a001182d995dcdd4126e451d0bb3faace15..d1f1568e19c1e18fe60787bf8752fb22e86151ac 100644 (file)
@@ -39,6 +39,18 @@ public:
   laddr_t get_hint() const final {return L_ADDR_MIN; }
   ~TestOnode() final = default;
 
+  void set_need_cow(Transaction &t) final {
+    with_mutable_layout(t, [](onode_layout_t &mlayout) {
+      mlayout.need_cow = true;
+    });
+  }
+
+  void unset_need_cow(Transaction &t) final {
+    with_mutable_layout(t, [](onode_layout_t &mlayout) {
+      mlayout.need_cow = false;
+    });
+  }
+
   void update_onode_size(Transaction &t, uint32_t size) final {
     with_mutable_layout(t, [size](onode_layout_t &mlayout) {
       mlayout.size = size;