From a2ad0ce2fb439bd41815d895640f7dd63a9ec0b9 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 9 May 2016 15:27:00 -0400 Subject: [PATCH] os/bluestore/bluestore_types: onode_t::punch_hole() Signed-off-by: Sage Weil --- src/os/bluestore/bluestore_types.cc | 67 ++++++++++++++ src/os/bluestore/bluestore_types.h | 4 + src/test/objectstore/test_bluestore_types.cc | 91 ++++++++++++++++++++ 3 files changed, 162 insertions(+) diff --git a/src/os/bluestore/bluestore_types.cc b/src/os/bluestore/bluestore_types.cc index 039149f27f973..ae15f97dcc656 100644 --- a/src/os/bluestore/bluestore_types.cc +++ b/src/os/bluestore/bluestore_types.cc @@ -628,6 +628,73 @@ void bluestore_onode_t::generate_test_instances(list& o) // FIXME } +void bluestore_onode_t::punch_hole( + uint64_t offset, + uint64_t length, + vector *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 diff --git a/src/os/bluestore/bluestore_types.h b/src/os/bluestore/bluestore_types.h index fcc488cba8829..7968d161b9973 100644 --- a/src/os/bluestore/bluestore_types.h +++ b/src/os/bluestore/bluestore_types.h @@ -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 *deref); + bool put_overlay_ref(uint64_t key) { map::iterator q = overlay_refs.find(key); if (q == overlay_refs.end()) diff --git a/src/test/objectstore/test_bluestore_types.cc b/src/test/objectstore/test_bluestore_types.cc index abed0b4d07335..3ab37170274e0 100644 --- a/src/test/objectstore/test_bluestore_types.cc +++ b/src/test/objectstore/test_bluestore_types.cc @@ -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 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(); +} -- 2.39.5