]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore/bluestore_types: onode_t::punch_hole()
authorSage Weil <sage@redhat.com>
Mon, 9 May 2016 19:27:00 +0000 (15:27 -0400)
committerSage Weil <sage@redhat.com>
Wed, 1 Jun 2016 15:38:44 +0000 (11:38 -0400)
Signed-off-by: Sage Weil <sage@redhat.com>
src/os/bluestore/bluestore_types.cc
src/os/bluestore/bluestore_types.h
src/test/objectstore/test_bluestore_types.cc

index 039149f27f973f9153fa4a6e2afb2c4291b484bd..ae15f97dcc656f515985a9b5750ce2732358275c 100644 (file)
@@ -628,6 +628,73 @@ void bluestore_onode_t::generate_test_instances(list<bluestore_onode_t*>& o)
   // FIXME
 }
 
+void bluestore_onode_t::punch_hole(
+  uint64_t offset,
+  uint64_t length,
+  vector<bluestore_lextent_t> *deref)
+{
+  auto p = seek_lextent(offset);
+  uint64_t end = offset + length;
+  while (p != extent_map.end()) {
+    if (p->first >= end) {
+      break;
+    }
+    if (p->first < offset) {
+      if (p->first + p->second.length > end) {
+       // split and deref middle
+       uint64_t front = offset - p->first;
+       deref->emplace_back(
+         bluestore_lextent_t(
+           p->second.blob,
+           p->second.offset + front,
+           length,
+           p->second.flags));
+       extent_map[end] = bluestore_lextent_t(
+         p->second.blob,
+         p->second.offset + front + length,
+         p->second.length - front - length,
+         p->second.flags);
+       p->second.length = front;
+       break;
+      } else {
+       // deref tail
+       assert(p->first + p->second.length > offset); // else bug in find_lextent
+       uint64_t keep = offset - p->first;
+       deref->emplace_back(
+         bluestore_lextent_t(
+           p->second.blob,
+           p->second.offset + keep,
+           p->second.length - keep,
+           p->second.flags));
+       p->second.length = keep;
+       ++p;
+       continue;
+      }
+    }
+    if (p->first + p->second.length <= end) {
+      // deref whole lextent
+      deref->push_back(p->second);
+      extent_map.erase(p++);
+      continue;
+    }
+    // deref head
+    uint64_t keep = (p->first + p->second.length) - end;
+    deref->emplace_back(
+      bluestore_lextent_t(
+       p->second.blob,
+       p->second.offset,
+       p->second.length - keep,
+       p->second.flags));
+    extent_map[end] = bluestore_lextent_t(
+      p->second.blob,
+      p->second.offset + p->second.length - keep,
+      keep,
+      p->second.flags);
+    extent_map.erase(p++);
+    break;
+  }
+}
+
 // bluestore_wal_op_t
 
 void bluestore_wal_op_t::encode(bufferlist& bl) const
index fcc488cba8829799b9a639b8e49bf9f656e0c51a..7968d161b99738f3beb1f4007ee60f9ab636744f 100644 (file)
@@ -505,6 +505,10 @@ struct bluestore_onode_t {
     return &p->second;
   }
 
+  /// punch a logical hole.  add lextents to deref to target list.
+  void punch_hole(uint64_t offset, uint64_t length,
+                 vector<bluestore_lextent_t> *deref);
+
   bool put_overlay_ref(uint64_t key) {
     map<uint64_t,uint16_t>::iterator q = overlay_refs.find(key);
     if (q == overlay_refs.end())
index abed0b4d07335b78fb5dd485adc8e77588d56308..3ab37170274e01241e64d71dd5862de0d4096693 100644 (file)
@@ -155,3 +155,94 @@ TEST(bluestore_extent_ref_map_t, contains)
   ASSERT_FALSE(m.contains(40, 3000));
   ASSERT_FALSE(m.contains(4000, 30));
 }
+
+TEST(bluestore_onode_t, punch_hole)
+{
+  bluestore_onode_t on;
+  vector<bluestore_lextent_t> r;
+  on.extent_map[0] = bluestore_lextent_t(1, 0, 100, 0);
+  on.extent_map[100] = bluestore_lextent_t(2, 0, 100, 0);
+
+  on.punch_hole(0, 100, &r);
+  ASSERT_EQ(1u, on.extent_map.size());
+  ASSERT_EQ(1u, r.size());
+  ASSERT_EQ(1, r[0].blob);
+  ASSERT_EQ(0u, r[0].offset);
+  ASSERT_EQ(100u, r[0].length);
+  r.clear();
+
+  on.punch_hole(150, 10, &r);
+  ASSERT_EQ(2u, on.extent_map.size());
+  ASSERT_EQ(100u, on.extent_map.begin()->first);
+  ASSERT_EQ(0u, on.extent_map.begin()->second.offset);
+  ASSERT_EQ(50u, on.extent_map.begin()->second.length);
+  ASSERT_EQ(160u, on.extent_map.rbegin()->first);
+  ASSERT_EQ(60u, on.extent_map.rbegin()->second.offset);
+  ASSERT_EQ(40u, on.extent_map.rbegin()->second.length);
+  ASSERT_EQ(1u, r.size());
+  ASSERT_EQ(2, r[0].blob);
+  ASSERT_EQ(50u, r[0].offset);
+  ASSERT_EQ(10u, r[0].length);
+  r.clear();
+
+  on.punch_hole(140, 20, &r);
+  ASSERT_EQ(2u, on.extent_map.size());
+  ASSERT_EQ(100u, on.extent_map.begin()->first);
+  ASSERT_EQ(0u, on.extent_map.begin()->second.offset);
+  ASSERT_EQ(40u, on.extent_map.begin()->second.length);
+  ASSERT_EQ(160u, on.extent_map.rbegin()->first);
+  ASSERT_EQ(60u, on.extent_map.rbegin()->second.offset);
+  ASSERT_EQ(40u, on.extent_map.rbegin()->second.length);
+  ASSERT_EQ(1u, r.size());
+  ASSERT_EQ(2, r[0].blob);
+  ASSERT_EQ(40u, r[0].offset);
+  ASSERT_EQ(10u, r[0].length);
+  r.clear();
+
+  on.punch_hole(130, 40, &r);
+  ASSERT_EQ(2u, on.extent_map.size());
+  ASSERT_EQ(100u, on.extent_map.begin()->first);
+  ASSERT_EQ(0u, on.extent_map.begin()->second.offset);
+  ASSERT_EQ(30u, on.extent_map.begin()->second.length);
+  ASSERT_EQ(170u, on.extent_map.rbegin()->first);
+  ASSERT_EQ(70u, on.extent_map.rbegin()->second.offset);
+  ASSERT_EQ(30u, on.extent_map.rbegin()->second.length);
+  ASSERT_EQ(2u, r.size());
+  ASSERT_EQ(2, r[0].blob);
+  ASSERT_EQ(30u, r[0].offset);
+  ASSERT_EQ(10u, r[0].length);
+  ASSERT_EQ(2, r[1].blob);
+  ASSERT_EQ(60u, r[1].offset);
+  ASSERT_EQ(10u, r[1].length);
+  r.clear();
+
+  on.punch_hole(110, 10, &r);
+  ASSERT_EQ(3u, on.extent_map.size());
+  ASSERT_EQ(100u, on.extent_map.begin()->first);
+  ASSERT_EQ(0u, on.extent_map.begin()->second.offset);
+  ASSERT_EQ(10u, on.extent_map.begin()->second.length);
+  ASSERT_EQ(20u, on.extent_map[120].offset);
+  ASSERT_EQ(10u, on.extent_map[120].length);
+  ASSERT_EQ(170u, on.extent_map.rbegin()->first);
+  ASSERT_EQ(70u, on.extent_map.rbegin()->second.offset);
+  ASSERT_EQ(30u, on.extent_map.rbegin()->second.length);
+  ASSERT_EQ(1u, r.size());
+  ASSERT_EQ(2, r[0].blob);
+  ASSERT_EQ(10u, r[0].offset);
+  ASSERT_EQ(10u, r[0].length);
+  r.clear();
+
+  on.punch_hole(0, 1000, &r);
+  ASSERT_EQ(0u, on.extent_map.size());
+  ASSERT_EQ(3u, r.size());
+  ASSERT_EQ(2, r[0].blob);
+  ASSERT_EQ(0u, r[0].offset);
+  ASSERT_EQ(10u, r[0].length);
+  ASSERT_EQ(2, r[1].blob);
+  ASSERT_EQ(20u, r[1].offset);
+  ASSERT_EQ(10u, r[1].length);
+  ASSERT_EQ(2, r[2].blob);
+  ASSERT_EQ(70u, r[2].offset);
+  ASSERT_EQ(30u, r[2].length);
+  r.clear();
+}