// 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
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();
+}