]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: refactor bluestore_blob_t to encapsulate extents/*length fields.
authorIgor Fedotov <ifedotov@mirantis.com>
Thu, 26 Jan 2017 12:15:56 +0000 (15:15 +0300)
committerIgor Fedotov <ifedotov@mirantis.com>
Mon, 27 Mar 2017 12:34:42 +0000 (12:34 +0000)
Signed-off-by: Igor Fedotov <ifedotov@mirantis.com>
src/os/bluestore/BlueStore.cc
src/os/bluestore/bluestore_types.cc
src/os/bluestore/bluestore_types.h
src/test/objectstore/test_bluestore_types.cc

index fdf936fe861409d8085ac540dad509d6f8c06968..b0a237bfbf261ab48c9d5fd1e000fcb15eff0524 100644 (file)
@@ -1658,7 +1658,7 @@ void BlueStore::Blob::discard_unallocated(Collection *coll)
   if (blob.is_compressed()) {
     bool discard = false;
     bool all_invalid = true;
-    for (auto e : blob.extents) {
+    for (auto e : blob.get_extents()) {
       if (!e.is_valid()) {
         discard = true;
       } else {
@@ -1672,7 +1672,7 @@ void BlueStore::Blob::discard_unallocated(Collection *coll)
     }
   } else {
     size_t pos = 0;
-    for (auto e : blob.extents) {
+    for (auto e : blob.get_extents()) {
       if (!e.is_valid()) {
        ldout(coll->store->cct, 20) << __func__ << " 0x" << std::hex << pos
                                    << "~" << e.length
@@ -1718,32 +1718,6 @@ void BlueStore::Blob::get_ref(
     length);
 }
 
-// cut it out of extents
-struct vecbuilder {
-  PExtentVector v;
-  uint64_t invalid = 0;
-
-  void add_invalid(uint64_t length) {
-    invalid += length;
-  }
-  void flush() {
-    if (invalid) {
-      v.emplace_back(bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET,
-       invalid));
-      invalid = 0;
-    }
-  }
-  void add(uint64_t offset, uint64_t length) {
-    if (offset == bluestore_pextent_t::INVALID_OFFSET) {
-      add_invalid(length);
-    }
-    else {
-      flush();
-      v.emplace_back(bluestore_pextent_t(offset, length));
-    }
-  }
-};
-
 bool BlueStore::Blob::put_ref(
   Collection *coll,
   uint32_t offset,
@@ -1767,82 +1741,7 @@ bool BlueStore::Blob::put_ref(
   }
 
   bluestore_blob_t& b = dirty_blob();
-
-  // common case: all of it?
-  if (empty) {
-    uint64_t pos = 0;
-    for (auto& e : b.extents) {
-      if (e.is_valid()) {
-       r->push_back(e);
-      }
-      pos += e.length;
-    }
-    assert(b.is_compressed() || b.get_logical_length() == pos);
-    b.extents.resize(1);
-    b.extents[0].offset = bluestore_pextent_t::INVALID_OFFSET;
-    b.extents[0].length = pos;
-    return true;
-  }
-  // remove from pextents according to logical release list
-  vecbuilder vb;
-  auto loffs_it = logical.begin();
-  auto lend = logical.end();
-  uint32_t pext_loffs_start = 0; //starting loffset of the current pextent
-  uint32_t pext_loffs = 0; //current loffset
-  auto pext_it = b.extents.begin();
-  auto pext_end = b.extents.end();
-  while (pext_it != pext_end) {
-    if (loffs_it == lend || pext_loffs_start + pext_it->length <= loffs_it->offset) {
-      int delta0 = pext_loffs - pext_loffs_start;
-      assert(delta0 >= 0);
-      if ((uint32_t)delta0 < pext_it->length) {
-        vb.add(pext_it->offset + delta0, pext_it->length - delta0);
-      }
-      pext_loffs_start += pext_it->length;
-      pext_loffs = pext_loffs_start;
-      ++pext_it;
-    } else {
-      //assert(pext_loffs == pext_loffs_start);
-      int delta0 = pext_loffs - pext_loffs_start;
-      assert(delta0 >= 0);
-
-      int delta = loffs_it->offset - pext_loffs;
-      assert(delta >= 0);
-      if (delta > 0 ) {
-        vb.add(pext_it->offset + delta0, delta);
-        pext_loffs += delta;
-      }
-  
-      PExtentVector::iterator last_r = r->end();
-      if (r->begin() != last_r) {
-        --last_r;
-      }
-      uint32_t to_release = loffs_it->length;
-      do {
-        uint32_t to_release_part =
-          MIN(pext_it->length - delta0 - delta, to_release);
-        auto o = pext_it->offset + delta0 + delta;
-        if (last_r != r->end() && last_r->offset + last_r->length == o) {
-          last_r->length += to_release_part;
-        } else {
-         last_r = r->emplace(r->end(), o, to_release_part);
-        }
-        to_release -= to_release_part;
-        pext_loffs += to_release_part;
-        if (pext_loffs == pext_loffs_start + pext_it->length) {
-          pext_loffs_start += pext_it->length;
-          pext_loffs = pext_loffs_start;
-          pext_it++;
-          delta0 = delta = 0;
-        }            
-      } while (to_release > 0 && pext_it != pext_end);
-      vb.add_invalid(loffs_it->length - to_release);
-      ++loffs_it;
-    }
-  }
-  vb.flush();
-  b.extents.swap(vb.v);
-  return false;
+  return b.release_extents(empty, logical, r);
 }
 
 void BlueStore::Blob::split(Collection *coll, uint32_t blob_offset, Blob *r)
@@ -1855,60 +1754,11 @@ void BlueStore::Blob::split(Collection *coll, uint32_t blob_offset, Blob *r)
   bluestore_blob_t &lb = dirty_blob();
   bluestore_blob_t &rb = r->dirty_blob();
 
-  unsigned i = 0;
-  size_t left = blob_offset;
-
   used_in_blob.split(
     blob_offset,
     &(r->used_in_blob));
 
-  uint32_t llen_lb = 0;
-  uint32_t llen_rb = 0;
-  for (auto p = lb.extents.begin(); p != lb.extents.end(); ++p, ++i) {
-    if (p->length <= left) {
-      left -= p->length;
-      llen_lb += p->length;
-      continue;
-    }
-    if (left) {
-      if (p->is_valid()) {
-       rb.extents.emplace_back(bluestore_pextent_t(p->offset + left,
-                                                   p->length - left));
-      } else {
-       rb.extents.emplace_back(bluestore_pextent_t(
-                                 bluestore_pextent_t::INVALID_OFFSET,
-                                 p->length - left));
-      }
-      llen_rb += p->length - left;
-      llen_lb += left;
-      p->length = left;
-      ++i;
-      ++p;
-    }
-    while (p != lb.extents.end()) {
-      llen_rb += p->length;
-      rb.extents.push_back(*p++);
-    }
-    lb.extents.resize(i);
-    lb.logical_length = llen_lb;
-    rb.logical_length = llen_rb;
-    break;
-  }
-  rb.flags = lb.flags;
-
-  if (lb.has_csum()) {
-    rb.csum_type = lb.csum_type;
-    rb.csum_chunk_order = lb.csum_chunk_order;
-    size_t csum_order = lb.get_csum_chunk_size();
-    assert(blob_offset % csum_order == 0);
-    size_t pos = (blob_offset / csum_order) * lb.get_csum_value_size();
-    // deep copy csum data
-    bufferptr old;
-    old.swap(lb.csum_data);
-    rb.csum_data = bufferptr(old.c_str() + pos, old.length() - pos);
-    lb.csum_data = bufferptr(old.c_str(), pos);
-  }
-
+  lb.split(blob_offset, rb);
   shared_blob->bc.split(shared_blob->get_cache(), blob_offset, r->shared_blob->bc);
 
   dout(10) << __func__ << " 0x" << std::hex << blob_offset << std::dec
@@ -3010,7 +2860,7 @@ void BlueStore::Collection::make_blob_shared(uint64_t sbid, BlobRef b)
   b->shared_blob->loaded = true;
   b->shared_blob->persistent = new bluestore_shared_blob_t(sbid);
   shared_blob_set.add(this, b->shared_blob.get());
-  for (auto p : blob.extents) {
+  for (auto p : blob.get_extents()) {
     if (p.is_valid()) {
       b->shared_blob->get_ref(
        p.offset,
@@ -5257,7 +5107,7 @@ int BlueStore::fsck(bool deep)
          ++errors;
        }
        if (blob.is_compressed()) {
-         expected_statfs.compressed += blob.compressed_length;
+         expected_statfs.compressed += blob.get_compressed_payload_length();
          expected_statfs.compressed_original += 
            i.first->get_referenced_bytes();
        }
@@ -5277,13 +5127,13 @@ int BlueStore::fsck(bool deep)
          sbi.sb = i.first->shared_blob;
          sbi.oids.push_back(oid);
          sbi.compressed = blob.is_compressed();
-         for (auto e : blob.extents) {
+         for (auto e : blob.get_extents()) {
            if (e.is_valid()) {
              sbi.ref_map.get(e.offset, e.length);
            }
          }
        } else {
-         errors += _fsck_check_extents(oid, blob.extents,
+         errors += _fsck_check_extents(oid, blob.get_extents(),
                                        blob.is_compressed(),
                                        used_blocks,
                                        expected_statfs);
@@ -9009,7 +8859,6 @@ int BlueStore::_do_alloc_write(
     }
     if (!compressed) {
       dblob.set_flag(bluestore_blob_t::FLAG_MUTABLE);
-      dblob.logical_length = final_length;
       if (l->length() != wi.blob_length) {
        // hrm, maybe we could do better here, but let's not bother.
        dout(20) << __func__ << " forcing csum_order to block_size_order "
@@ -9031,9 +8880,9 @@ int BlueStore::_do_alloc_write(
     for (auto& p : extents) {
       bluestore_pextent_t e = bluestore_pextent_t(p);
       txc->allocated.insert(e.offset, e.length);
-      dblob.extents.push_back(e);
       hint = p.end();
     }
+    dblob.allocated(extents);
 
     dout(20) << __func__ << " blob " << *b
             << " csum_type " << Checksummer::get_csum_type_string(csum)
@@ -9940,7 +9789,7 @@ int BlueStore::_do_clone_range(
       id_to_blob[n] = cb;
       e.blob->dup(*cb);
       // bump the extent refs on the copied blob's extents
-      for (auto p : blob.extents) {
+      for (auto p : blob.get_extents()) {
        if (p.is_valid()) {
          e.blob->shared_blob->get_ref(p.offset, p.length);
        }
index 610df4e4d89238704d01cf084ebe4fc4c1c46cc6..cda938c5cfe2e5704b8ba9a2beccfccf6d695f26 100644 (file)
@@ -626,30 +626,26 @@ void bluestore_blob_t::generate_test_instances(list<bluestore_blob_t*>& ls)
   ls.push_back(new bluestore_blob_t);
   ls.push_back(new bluestore_blob_t(0));
   ls.push_back(new bluestore_blob_t);
-  ls.back()->extents.push_back(bluestore_pextent_t(111, 222));
-  ls.back()->logical_length += 222;
+  ls.back()->allocated_test(bluestore_pextent_t(111, 222));
   ls.push_back(new bluestore_blob_t);
   ls.back()->init_csum(Checksummer::CSUM_XXHASH32, 16, 65536);
   ls.back()->csum_data = buffer::claim_malloc(4, strdup("abcd"));
-  ls.back()->extents.emplace_back(bluestore_pextent_t(0x40100000, 0x10000));
-  ls.back()->logical_length += 0x10000;
-  ls.back()->extents.emplace_back(
-    bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET, 0x1000));
-  ls.back()->logical_length += 0x1000;
-  ls.back()->extents.emplace_back(bluestore_pextent_t(0x40120000, 0x10000));
   ls.back()->add_unused(0, 3);
   ls.back()->add_unused(8, 8);
-  ls.back()->logical_length += 0x10000;
+  ls.back()->allocated_test(bluestore_pextent_t(0x40100000, 0x10000));
+  ls.back()->allocated_test(
+    bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET, 0x1000));
+  ls.back()->allocated_test(bluestore_pextent_t(0x40120000, 0x10000));
 }
 
 ostream& operator<<(ostream& out, const bluestore_blob_t& o)
 {
-  out << "blob(" << o.extents;
+  out << "blob(" << o.get_extents();
   if (o.is_compressed()) {
     out << " clen 0x" << std::hex
-       << o.logical_length
+       << o.get_logical_length()
        << " -> 0x"
-       << o.compressed_length
+       << o.get_compressed_payload_length()
        << std::dec;
   }
   if (o.flags) {
@@ -733,6 +729,194 @@ int bluestore_blob_t::verify_csum(uint64_t b_off, const bufferlist& bl,
     return 0;
 }
 
+void bluestore_blob_t::allocated(const AllocExtentVector& allocs)
+{
+  assert(extents.size() == 0);
+  
+  // if blob is compressed then logical length to be already configured
+  // otherwise - to be unset.
+  assert( (is_compressed() && logical_length != 0) ||
+          (!is_compressed() && logical_length == 0));
+  extents.reserve(allocs.size());
+  for (auto& a : allocs) {
+    extents.emplace_back(a.offset, a.length);
+    if (!is_compressed()) {
+      logical_length += a.length;
+    }
+  }
+}
+
+// cut it out of extents
+struct vecbuilder {
+  PExtentVector v;
+  uint64_t invalid = 0;
+
+  void add_invalid(uint64_t length) {
+    invalid += length;
+  }
+  void flush() {
+    if (invalid) {
+      v.emplace_back(bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET,
+       invalid));
+      invalid = 0;
+    }
+  }
+  void add(uint64_t offset, uint64_t length) {
+    if (offset == bluestore_pextent_t::INVALID_OFFSET) {
+      add_invalid(length);
+    }
+    else {
+      flush();
+      v.emplace_back(bluestore_pextent_t(offset, length));
+    }
+  }
+};
+
+void bluestore_blob_t::allocated_test(const bluestore_pextent_t& alloc)
+{
+  extents.emplace_back(alloc);
+  if (!is_compressed()) {
+    logical_length += alloc.length;
+  }
+}
+
+bool bluestore_blob_t::release_extents(bool all,
+                                      const PExtentVector& logical,
+                                      PExtentVector* r)
+{
+  // common case: all of it?
+  if (all) {
+    uint64_t pos = 0;
+    for (auto& e : extents) {
+      if (e.is_valid()) {
+       r->push_back(e);
+      }
+      pos += e.length;
+    }
+    assert(is_compressed() || get_logical_length() == pos);
+    extents.resize(1);
+    extents[0].offset = bluestore_pextent_t::INVALID_OFFSET;
+    extents[0].length = pos;
+    return true;
+  }
+  // remove from pextents according to logical release list
+  vecbuilder vb;
+  auto loffs_it = logical.begin();
+  auto lend = logical.end();
+  uint32_t pext_loffs_start = 0; //starting loffset of the current pextent
+  uint32_t pext_loffs = 0; //current loffset
+  auto pext_it = extents.begin();
+  auto pext_end = extents.end();
+  while (pext_it != pext_end) {
+    if (loffs_it == lend ||
+        pext_loffs_start + pext_it->length <= loffs_it->offset) {
+      int delta0 = pext_loffs - pext_loffs_start;
+      assert(delta0 >= 0);
+      if ((uint32_t)delta0 < pext_it->length) {
+       vb.add(pext_it->offset + delta0, pext_it->length - delta0);
+      }
+      pext_loffs_start += pext_it->length;
+      pext_loffs = pext_loffs_start;
+      ++pext_it;
+    }
+    else {
+      //assert(pext_loffs == pext_loffs_start);
+      int delta0 = pext_loffs - pext_loffs_start;
+      assert(delta0 >= 0);
+
+      int delta = loffs_it->offset - pext_loffs;
+      assert(delta >= 0);
+      if (delta > 0) {
+       vb.add(pext_it->offset + delta0, delta);
+       pext_loffs += delta;
+      }
+
+      PExtentVector::iterator last_r = r->end();
+      if (r->begin() != last_r) {
+       --last_r;
+      }
+      uint32_t to_release = loffs_it->length;
+      do {
+       uint32_t to_release_part =
+         MIN(pext_it->length - delta0 - delta, to_release);
+       auto o = pext_it->offset + delta0 + delta;
+       if (last_r != r->end() && last_r->offset + last_r->length == o) {
+         last_r->length += to_release_part;
+       }
+       else {
+         last_r = r->emplace(r->end(), o, to_release_part);
+       }
+       to_release -= to_release_part;
+       pext_loffs += to_release_part;
+       if (pext_loffs == pext_loffs_start + pext_it->length) {
+         pext_loffs_start += pext_it->length;
+         pext_loffs = pext_loffs_start;
+         pext_it++;
+         delta0 = delta = 0;
+       }
+      } while (to_release > 0 && pext_it != pext_end);
+      vb.add_invalid(loffs_it->length - to_release);
+      ++loffs_it;
+    }
+  }
+  vb.flush();
+  extents.swap(vb.v);
+  return false;
+}
+
+void bluestore_blob_t::split(uint32_t blob_offset, bluestore_blob_t& rb)
+{
+  size_t left = blob_offset;
+  uint32_t llen_lb = 0;
+  uint32_t llen_rb = 0;
+  unsigned i = 0;
+  for (auto p = extents.begin(); p != extents.end(); ++p, ++i) {
+    if (p->length <= left) {
+      left -= p->length;
+      llen_lb += p->length;
+      continue;
+    }
+    if (left) {
+      if (p->is_valid()) {
+       rb.extents.emplace_back(bluestore_pextent_t(p->offset + left,
+         p->length - left));
+      }
+      else {
+       rb.extents.emplace_back(bluestore_pextent_t(
+         bluestore_pextent_t::INVALID_OFFSET,
+         p->length - left));
+      }
+      llen_rb += p->length - left;
+      llen_lb += left;
+      p->length = left;
+      ++i;
+      ++p;
+    }
+    while (p != extents.end()) {
+      llen_rb += p->length;
+      rb.extents.push_back(*p++);
+    }
+    extents.resize(i);
+    logical_length = llen_lb;
+    rb.logical_length = llen_rb;
+    break;
+  }
+  rb.flags = flags;
+
+  if (has_csum()) {
+    rb.csum_type = csum_type;
+    rb.csum_chunk_order = csum_chunk_order;
+    size_t csum_order = get_csum_chunk_size();
+    assert(blob_offset % csum_order == 0);
+    size_t pos = (blob_offset / csum_order) * get_csum_value_size();
+    // deep copy csum data
+    bufferptr old;
+    old.swap(csum_data);
+    rb.csum_data = bufferptr(old.c_str() + pos, old.length() - pos);
+    csum_data = bufferptr(old.c_str(), pos);
+  }
+}
+
 // bluestore_shared_blob_t
 
 void bluestore_shared_blob_t::dump(Formatter *f) const
index 48c53c349658f6c453a55d2e446e82ddb33ea993..900a7ead918bf04d58bcb4a9a2caeaf255589e92 100644 (file)
@@ -438,6 +438,12 @@ ostream& operator<<(ostream& out, const bluestore_blob_use_tracker_t& rm);
 
 /// blob: a piece of data on disk
 struct bluestore_blob_t {
+private:
+  PExtentVector extents;              ///< raw data position on device
+  uint32_t logical_length = 0;        ///< < original length of data stored in the blob
+  uint32_t compressed_length = 0;     ///< compressed length if any
+
+public:
   enum {
     FLAG_MUTABLE = 1,         ///< blob can be overwritten or split
     FLAG_COMPRESSED = 2,      ///< blob is compressed
@@ -447,9 +453,6 @@ struct bluestore_blob_t {
   };
   static string get_flags_string(unsigned flags);
 
-  PExtentVector extents;              ///< raw data position on device
-  uint32_t logical_length = 0;        ///< < original length of data stored in the blob
-  uint32_t compressed_length = 0;     ///< compressed length if any
   uint32_t flags = 0;                 ///< FLAG_*
 
   uint16_t unused = 0;     ///< portion that has never been written to (bitmap)
@@ -461,6 +464,10 @@ struct bluestore_blob_t {
 
   bluestore_blob_t(uint32_t f = 0) : flags(f) {}
 
+  const PExtentVector& get_extents() const {
+    return extents;
+  }
+
   DENC_HELPERS;
   void bound_encode(size_t& p, uint64_t struct_v) const {
     assert(struct_v == 1 || struct_v == 2);
@@ -800,6 +807,21 @@ struct bluestore_blob_t {
     }
     return res;
   }
+
+  void split(uint32_t blob_offset, bluestore_blob_t& rb);
+  void allocated(const AllocExtentVector& allocs);
+  void allocated_test(const bluestore_pextent_t& alloc); // intended for UT only
+
+  /// updates blob's pextents container and return unused pextents eligible
+  /// for release.
+  /// all - indicates that the whole blob to be released.
+  /// logical - specifies set of logical extents within blob's
+  /// to be released
+  /// Returns true if blob has no more valid pextents
+  bool release_extents(
+    bool all,
+    const PExtentVector& logical,
+    PExtentVector* r);
 };
 WRITE_CLASS_DENC_FEATURED(bluestore_blob_t)
 
index 5a6533e736d55f30ddf4abe0c8b5e7017f99c156..9ccf0d28047a6f443cc10bb5b62a8118babcaab7 100644 (file)
@@ -29,7 +29,7 @@ TEST(bluestore, sizeof) {
   P(BlueStore::Buffer);
   P(bluestore_onode_t);
   P(bluestore_blob_t);
-  P(bluestore_blob_t::extents);
+  P(PExtentVector);
   P(bluestore_shared_blob_t);
   P(bluestore_extent_ref_map_t);
   P(bluestore_extent_ref_map_t::record_t);
@@ -328,11 +328,10 @@ TEST(Blob, put_ref)
     BlueStore::Blob b;
     b.shared_blob = new BlueStore::SharedBlob(nullptr);
     b.shared_blob->get();  // hack to avoid dtor from running
-    b.dirty_blob().extents.push_back(bluestore_pextent_t(0x40715000, 0x2000));
-    b.dirty_blob().extents.push_back(
+    b.dirty_blob().allocated_test(bluestore_pextent_t(0x40715000, 0x2000));
+    b.dirty_blob().allocated_test(
       bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET, 0x8000));
-    b.dirty_blob().extents.push_back(bluestore_pextent_t(0x4071f000, 0x5000));
-    b.dirty_blob().logical_length = b.get_blob().get_ondisk_length();
+    b.dirty_blob().allocated_test(bluestore_pextent_t(0x4071f000, 0x5000));
     b.get_ref(&coll, 0, 0x1200);
     b.get_ref(&coll, 0xae00, 0x4200);
     ASSERT_EQ(0x5400u, b.get_referenced_bytes());
@@ -363,8 +362,7 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(0, mas*2));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(0, mas * 2));
     B.get_ref(coll.get(), 0, mas*2);
     ASSERT_EQ(mas * 2, B.get_referenced_bytes());
     ASSERT_TRUE(b.is_allocated(0, mas*2));
@@ -377,8 +375,8 @@ TEST(Blob, put_ref)
     ASSERT_FALSE(b.is_allocated(0, mas*2));
     ASSERT_FALSE(b.is_allocated(0, mas));
     ASSERT_FALSE(b.is_allocated(mas, 0));
-    ASSERT_FALSE(b.extents[0].is_valid());
-    ASSERT_EQ(mas*2, b.extents[0].length);
+    ASSERT_FALSE(b.get_extents()[0].is_valid());
+    ASSERT_EQ(mas*2, b.get_extents()[0].length);
   }
   {
     BlueStore::Blob B;
@@ -386,8 +384,7 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(123, mas*2));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(123, mas * 2));
     B.get_ref(coll.get(), 0, mas*2);
     ASSERT_EQ(mas * 2, B.get_referenced_bytes());
     B.put_ref(coll.get(), 0, mas, &r);
@@ -403,8 +400,8 @@ TEST(Blob, put_ref)
     ASSERT_EQ(123u, r[0].offset);
     ASSERT_EQ(mas*2, r[0].length);
     ASSERT_FALSE(b.is_allocated(0, mas*2));
-    ASSERT_FALSE(b.extents[0].is_valid());
-    ASSERT_EQ(mas*2, b.extents[0].length);
+    ASSERT_FALSE(b.get_extents()[0].is_valid());
+    ASSERT_EQ(mas*2, b.get_extents()[0].length);
   }
   {
     BlueStore::Blob B;
@@ -412,11 +409,10 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(1, mas));
-    b.extents.push_back(bluestore_pextent_t(2, mas));
-    b.extents.push_back(bluestore_pextent_t(3, mas));
-    b.extents.push_back(bluestore_pextent_t(4, mas));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(1, mas));
+    b.allocated_test(bluestore_pextent_t(2, mas));
+    b.allocated_test(bluestore_pextent_t(3, mas));
+    b.allocated_test(bluestore_pextent_t(4, mas));
     B.get_ref(coll.get(), 0, mas*4);
     ASSERT_EQ(mas * 4, B.get_referenced_bytes());
     B.put_ref(coll.get(), mas, mas, &r);
@@ -441,10 +437,10 @@ TEST(Blob, put_ref)
     ASSERT_EQ(mas, r[1].length);
     ASSERT_TRUE(b.is_allocated(0, mas*2));
     ASSERT_FALSE(b.is_allocated(mas*2, mas*2));
-    ASSERT_TRUE(b.extents[0].is_valid());
-    ASSERT_TRUE(b.extents[1].is_valid());
-    ASSERT_FALSE(b.extents[2].is_valid());
-    ASSERT_EQ(3u, b.extents.size());
+    ASSERT_TRUE(b.get_extents()[0].is_valid());
+    ASSERT_TRUE(b.get_extents()[1].is_valid());
+    ASSERT_FALSE(b.get_extents()[2].is_valid());
+    ASSERT_EQ(3u, b.get_extents().size());
   }
   {
     BlueStore::Blob B;
@@ -452,13 +448,12 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(1, mas));
-    b.extents.push_back(bluestore_pextent_t(2, mas));
-    b.extents.push_back(bluestore_pextent_t(3, mas));
-    b.extents.push_back(bluestore_pextent_t(4, mas));
-    b.extents.push_back(bluestore_pextent_t(5, mas));
-    b.extents.push_back(bluestore_pextent_t(6, mas));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(1, mas));
+    b.allocated_test(bluestore_pextent_t(2, mas));
+    b.allocated_test(bluestore_pextent_t(3, mas));
+    b.allocated_test(bluestore_pextent_t(4, mas));
+    b.allocated_test(bluestore_pextent_t(5, mas));
+    b.allocated_test(bluestore_pextent_t(6, mas));
     B.get_ref(coll.get(), 0, mas*6);
     ASSERT_EQ(mas * 6, B.get_referenced_bytes());
     B.put_ref(coll.get(), mas, mas, &r);
@@ -482,12 +477,12 @@ TEST(Blob, put_ref)
     ASSERT_TRUE(b.is_allocated(0, mas*2));
     ASSERT_FALSE(b.is_allocated(mas*2, mas*2));
     ASSERT_TRUE(b.is_allocated(mas*4, mas*2));
-    ASSERT_EQ(5u, b.extents.size());
-    ASSERT_TRUE(b.extents[0].is_valid());
-    ASSERT_TRUE(b.extents[1].is_valid());
-    ASSERT_FALSE(b.extents[2].is_valid());
-    ASSERT_TRUE(b.extents[3].is_valid());
-    ASSERT_TRUE(b.extents[4].is_valid());
+    ASSERT_EQ(5u, b.get_extents().size());
+    ASSERT_TRUE(b.get_extents()[0].is_valid());
+    ASSERT_TRUE(b.get_extents()[1].is_valid());
+    ASSERT_FALSE(b.get_extents()[2].is_valid());
+    ASSERT_TRUE(b.get_extents()[3].is_valid());
+    ASSERT_TRUE(b.get_extents()[4].is_valid());
   }
   {
     BlueStore::Blob B;
@@ -495,8 +490,7 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(1, mas * 6));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(1, mas * 6));
     B.get_ref(coll.get(), 0, mas*6);
     ASSERT_EQ(mas * 6, B.get_referenced_bytes());
     B.put_ref(coll.get(), mas, mas, &r);
@@ -518,10 +512,10 @@ TEST(Blob, put_ref)
     ASSERT_TRUE(b.is_allocated(0, mas*2));
     ASSERT_FALSE(b.is_allocated(mas*2, mas*2));
     ASSERT_TRUE(b.is_allocated(mas*4, mas*2));
-    ASSERT_EQ(3u, b.extents.size());
-    ASSERT_TRUE(b.extents[0].is_valid());
-    ASSERT_FALSE(b.extents[1].is_valid());
-    ASSERT_TRUE(b.extents[2].is_valid());
+    ASSERT_EQ(3u, b.get_extents().size());
+    ASSERT_TRUE(b.get_extents()[0].is_valid());
+    ASSERT_FALSE(b.get_extents()[1].is_valid());
+    ASSERT_TRUE(b.get_extents()[2].is_valid());
   }
   {
     BlueStore::Blob B;
@@ -529,10 +523,9 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(1, mas * 4));
-    b.extents.push_back(bluestore_pextent_t(2, mas * 4));
-    b.extents.push_back(bluestore_pextent_t(3, mas * 4));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(1, mas * 4));
+    b.allocated_test(bluestore_pextent_t(2, mas * 4));
+    b.allocated_test(bluestore_pextent_t(3, mas * 4));
     B.get_ref(coll.get(), 0, mas*12);
     ASSERT_EQ(mas * 12, B.get_referenced_bytes());
     B.put_ref(coll.get(), mas, mas, &r);
@@ -558,10 +551,10 @@ TEST(Blob, put_ref)
     ASSERT_TRUE(b.is_allocated(0, mas*2));
     ASSERT_FALSE(b.is_allocated(mas*2, mas*8));
     ASSERT_TRUE(b.is_allocated(mas*10, mas*2));
-    ASSERT_EQ(3u, b.extents.size());
-    ASSERT_TRUE(b.extents[0].is_valid());
-    ASSERT_FALSE(b.extents[1].is_valid());
-    ASSERT_TRUE(b.extents[2].is_valid());
+    ASSERT_EQ(3u, b.get_extents().size());
+    ASSERT_TRUE(b.get_extents()[0].is_valid());
+    ASSERT_FALSE(b.get_extents()[1].is_valid());
+    ASSERT_TRUE(b.get_extents()[2].is_valid());
   }
   {
     BlueStore::Blob B;
@@ -569,10 +562,9 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(1, mas * 4));
-    b.extents.push_back(bluestore_pextent_t(2, mas * 4));
-    b.extents.push_back(bluestore_pextent_t(3, mas * 4));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(1, mas * 4));
+    b.allocated_test(bluestore_pextent_t(2, mas * 4));
+    b.allocated_test(bluestore_pextent_t(3, mas * 4));
     B.get_ref(coll.get(), 0, mas*12);
     ASSERT_EQ(mas * 12, B.get_referenced_bytes());
     B.put_ref(coll.get(), mas, mas, &r);
@@ -598,27 +590,27 @@ TEST(Blob, put_ref)
     ASSERT_TRUE(b.is_allocated(0, mas*2));
     ASSERT_FALSE(b.is_allocated(mas*2, mas*8));
     ASSERT_TRUE(b.is_allocated(mas*10, mas*2));
-    ASSERT_EQ(3u, b.extents.size());
-    ASSERT_TRUE(b.extents[0].is_valid());
-    ASSERT_FALSE(b.extents[1].is_valid());
-    ASSERT_TRUE(b.extents[2].is_valid());
+    ASSERT_EQ(3u, b.get_extents().size());
+    ASSERT_TRUE(b.get_extents()[0].is_valid());
+    ASSERT_FALSE(b.get_extents()[1].is_valid());
+    ASSERT_TRUE(b.get_extents()[2].is_valid());
     B.put_ref(coll.get(), 0, mas, &r);
     ASSERT_EQ(mas * 2, B.get_referenced_bytes());
     cout << "r " << r << " " << b << std::endl;
     ASSERT_EQ(1u, r.size());
     ASSERT_EQ(0x1u, r[0].offset);
     ASSERT_EQ(mas*2, r[0].length);
-    ASSERT_EQ(2u, b.extents.size());
-    ASSERT_FALSE(b.extents[0].is_valid());
-    ASSERT_TRUE(b.extents[1].is_valid());
+    ASSERT_EQ(2u, b.get_extents().size());
+    ASSERT_FALSE(b.get_extents()[0].is_valid());
+    ASSERT_TRUE(b.get_extents()[1].is_valid());
     B.put_ref(coll.get(), mas*10, mas*2, &r);
     ASSERT_EQ(mas * 0, B.get_referenced_bytes());
     cout << "r " << r << " " << b << std::endl;
     ASSERT_EQ(1u, r.size());
     ASSERT_EQ(0x2003u, r[0].offset);
     ASSERT_EQ(mas*2, r[0].length);
-    ASSERT_EQ(1u, b.extents.size());
-    ASSERT_FALSE(b.extents[0].is_valid());
+    ASSERT_EQ(1u, b.get_extents().size());
+    ASSERT_FALSE(b.get_extents()[0].is_valid());
   }
   {
     BlueStore::Blob B;
@@ -626,10 +618,9 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(1, mas * 4));
-    b.extents.push_back(bluestore_pextent_t(2, mas * 4));
-    b.extents.push_back(bluestore_pextent_t(3, mas * 4));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(1, mas * 4));
+    b.allocated_test(bluestore_pextent_t(2, mas * 4));
+    b.allocated_test(bluestore_pextent_t(3, mas * 4));
     B.get_ref(coll.get(), 0, mas*12);
     ASSERT_EQ(mas * 12, B.get_referenced_bytes());
     B.put_ref(coll.get(), mas, mas, &r);
@@ -655,27 +646,27 @@ TEST(Blob, put_ref)
     ASSERT_TRUE(b.is_allocated(0, mas*2));
     ASSERT_FALSE(b.is_allocated(mas*2, mas*8));
     ASSERT_TRUE(b.is_allocated(mas*10, mas*2));
-    ASSERT_EQ(3u, b.extents.size());
-    ASSERT_TRUE(b.extents[0].is_valid());
-    ASSERT_FALSE(b.extents[1].is_valid());
-    ASSERT_TRUE(b.extents[2].is_valid());
+    ASSERT_EQ(3u, b.get_extents().size());
+    ASSERT_TRUE(b.get_extents()[0].is_valid());
+    ASSERT_FALSE(b.get_extents()[1].is_valid());
+    ASSERT_TRUE(b.get_extents()[2].is_valid());
     B.put_ref(coll.get(), mas*10, mas*2, &r);
     ASSERT_EQ(mas * 1, B.get_referenced_bytes());
     cout << "r " << r << " " << b << std::endl;
     ASSERT_EQ(1u, r.size());
     ASSERT_EQ(0x2003u, r[0].offset);
     ASSERT_EQ(mas*2, r[0].length);
-    ASSERT_EQ(2u, b.extents.size());
-    ASSERT_TRUE(b.extents[0].is_valid());
-    ASSERT_FALSE(b.extents[1].is_valid());
+    ASSERT_EQ(2u, b.get_extents().size());
+    ASSERT_TRUE(b.get_extents()[0].is_valid());
+    ASSERT_FALSE(b.get_extents()[1].is_valid());
     B.put_ref(coll.get(), 0, mas, &r);
     ASSERT_EQ(mas * 0, B.get_referenced_bytes());
     cout << "r " << r << " " << b << std::endl;
     ASSERT_EQ(1u, r.size());
     ASSERT_EQ(0x1u, r[0].offset);
     ASSERT_EQ(mas*2, r[0].length);
-    ASSERT_EQ(1u, b.extents.size());
-    ASSERT_FALSE(b.extents[0].is_valid());
+    ASSERT_EQ(1u, b.get_extents().size());
+    ASSERT_FALSE(b.get_extents()[0].is_valid());
   }
   {
     BlueStore::Blob B;
@@ -683,8 +674,7 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(1, mas * 8));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(1, mas * 8));
     B.get_ref(coll.get(), 0, mas*8);
     ASSERT_EQ(mas * 8, B.get_referenced_bytes());
     B.put_ref(coll.get(), 0, mas, &r);
@@ -709,17 +699,17 @@ TEST(Blob, put_ref)
     ASSERT_EQ(mas*6, r[0].length);
     ASSERT_TRUE(b.is_allocated(0, mas*2));
     ASSERT_FALSE(b.is_allocated(mas*2, mas*6));
-    ASSERT_EQ(2u, b.extents.size());
-    ASSERT_TRUE(b.extents[0].is_valid());
-    ASSERT_FALSE(b.extents[1].is_valid());
+    ASSERT_EQ(2u, b.get_extents().size());
+    ASSERT_TRUE(b.get_extents()[0].is_valid());
+    ASSERT_FALSE(b.get_extents()[1].is_valid());
     B.put_ref(coll.get(), mas, mas, &r);
     ASSERT_EQ(mas * 0, B.get_referenced_bytes());
     cout << "r " << r << " " << b << std::endl;
     ASSERT_EQ(1u, r.size());
     ASSERT_EQ(0x1u, r[0].offset);
     ASSERT_EQ(mas*2, r[0].length);
-    ASSERT_EQ(1u, b.extents.size());
-    ASSERT_FALSE(b.extents[0].is_valid());
+    ASSERT_EQ(1u, b.get_extents().size());
+    ASSERT_FALSE(b.get_extents()[0].is_valid());
   }
   // verify csum chunk size if factored in properly
   {
@@ -728,8 +718,7 @@ TEST(Blob, put_ref)
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
     PExtentVector r;
-    b.extents.push_back(bluestore_pextent_t(0, mas*4));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(0, mas*4));
     b.init_csum(Checksummer::CSUM_CRC32C, 14, mas * 4);
     B.get_ref(coll.get(), 0, mas*4);
     ASSERT_EQ(mas * 4, B.get_referenced_bytes());
@@ -739,20 +728,20 @@ TEST(Blob, put_ref)
     cout << "r " << r << " " << b << std::endl;
     ASSERT_EQ(0u, r.size());
     ASSERT_TRUE(b.is_allocated(0, mas*4));
-    ASSERT_TRUE(b.extents[0].is_valid());
-    ASSERT_EQ(mas*4, b.extents[0].length);
+    ASSERT_TRUE(b.get_extents()[0].is_valid());
+    ASSERT_EQ(mas*4, b.get_extents()[0].length);
   }
   {
     BlueStore::Blob B;
     B.shared_blob = new BlueStore::SharedBlob(nullptr);
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
-    b.extents.push_back(bluestore_pextent_t(0x40101000, 0x4000));
-    b.extents.push_back(bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET,
+    b.allocated_test(bluestore_pextent_t(0x40101000, 0x4000));
+    b.allocated_test(bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET,
                                            0x13000));
-    b.extents.push_back(bluestore_pextent_t(0x40118000, 0x7000));
-    b.logical_length = b.get_ondisk_length();
-    B.get_ref(coll.get(0, 0x0, 0x3800);
+
+    b.allocated_test(bluestore_pextent_t(0x40118000, 0x7000));
+    B.get_ref(coll.get(), 0x0, 0x3800);
     B.get_ref(coll.get(), 0x17c00, 0x6400);
     ASSERT_EQ(0x3800u + 0x6400u, B.get_referenced_bytes());
     b.set_flag(bluestore_blob_t::FLAG_SHARED);
@@ -770,10 +759,9 @@ TEST(Blob, put_ref)
     B.shared_blob = new BlueStore::SharedBlob(nullptr);
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
-    b.extents.push_back(bluestore_pextent_t(1, 0x5000));
-    b.extents.push_back(bluestore_pextent_t(2, 0x5000));
-    b.logical_length = b.get_ondisk_length();
-    B.get_ref(coll.get(0, 0x0, 0xa000);
+    b.allocated_test(bluestore_pextent_t(1, 0x5000));
+    b.allocated_test(bluestore_pextent_t(2, 0x5000));
+    B.get_ref(coll.get(), 0x0, 0xa000);
     ASSERT_EQ(0xa000u, B.get_referenced_bytes());
     cout << "before: " << B << std::endl;
     PExtentVector r;
@@ -790,9 +778,8 @@ TEST(Blob, put_ref)
     B.shared_blob = new BlueStore::SharedBlob(nullptr);
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
-    b.extents.push_back(bluestore_pextent_t(1, 0x7000));
-    b.extents.push_back(bluestore_pextent_t(2, 0x7000));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(1, 0x7000));
+    b.allocated_test(bluestore_pextent_t(2, 0x7000));
     B.get_ref(coll.get(), 0x0, 0xe000);
     ASSERT_EQ(0xe000u, B.get_referenced_bytes());
     cout << "before: " << B << std::endl;
@@ -818,9 +805,8 @@ TEST(Blob, put_ref)
     B.shared_blob = new BlueStore::SharedBlob(nullptr);
     B.shared_blob->get();  // hack to avoid dtor from running
     bluestore_blob_t& b = B.dirty_blob();
-    b.extents.push_back(bluestore_pextent_t(1, 0x5000));
-    b.extents.push_back(bluestore_pextent_t(2, 0x7000));
-    b.logical_length = b.get_ondisk_length();
+    b.allocated_test(bluestore_pextent_t(1, 0x5000));
+    b.allocated_test(bluestore_pextent_t(2, 0x7000));
     B.get_ref(coll.get(), 0x0, 0xc000);
     ASSERT_EQ(0xc000u, B.get_referenced_bytes());
     cout << "before: " << B << std::endl;
@@ -834,8 +820,8 @@ TEST(Blob, put_ref)
     ASSERT_EQ(0x1000u, r[0].length);
     ASSERT_EQ(2u, r[1].offset);
     ASSERT_EQ(0x7000u, r[1].length);
-    ASSERT_EQ(1u, b.extents[0].offset);
-    ASSERT_EQ(0x4000u, b.extents[0].length);
+    ASSERT_EQ(1u, b.get_extents()[0].offset);
+    ASSERT_EQ(0x4000u, b.get_extents()[0].length);
   }
 }
 
@@ -856,8 +842,8 @@ TEST(bluestore_blob_t, can_split_at)
 {
   bluestore_blob_t a;
   a.flags = bluestore_blob_t::FLAG_MUTABLE;
-  a.extents.emplace_back(bluestore_pextent_t(0x10000, 0x2000));
-  a.extents.emplace_back(bluestore_pextent_t(0x20000, 0x2000));
+  a.allocated_test(bluestore_pextent_t(0x10000, 0x2000));
+  a.allocated_test(bluestore_pextent_t(0x20000, 0x2000));
   ASSERT_TRUE(a.can_split_at(0x1000));
   ASSERT_TRUE(a.can_split_at(0x1800));
   a.init_csum(Checksummer::CSUM_CRC32C, 12, 0x4000);
@@ -871,34 +857,31 @@ TEST(bluestore_blob_t, prune_tail)
 {
   bluestore_blob_t a;
   a.flags = bluestore_blob_t::FLAG_MUTABLE;
-  a.extents.emplace_back(bluestore_pextent_t(0x10000, 0x2000));
-  a.extents.emplace_back(bluestore_pextent_t(0x20000, 0x2000));
+  a.allocated_test(bluestore_pextent_t(0x10000, 0x2000));
+  a.allocated_test(bluestore_pextent_t(0x20000, 0x2000));
   ASSERT_FALSE(a.can_prune_tail());
-  a.extents.emplace_back(
+  a.allocated_test(
     bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET, 0x2000));
-  a.logical_length = 0x2000 * 3;
   ASSERT_TRUE(a.can_prune_tail());
   a.prune_tail();
   ASSERT_FALSE(a.can_prune_tail());
-  ASSERT_EQ(2u, a.extents.size());
+  ASSERT_EQ(2u, a.get_extents().size());
   ASSERT_EQ(0x4000u, a.get_logical_length());
 
-  a.extents.emplace_back(
+  a.allocated_test(
     bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET, 0x2000));
-  a.logical_length += 0x2000;
   a.init_csum(Checksummer::CSUM_CRC32C_8, 12, 0x6000);
   ASSERT_EQ(6u, a.csum_data.length());
   ASSERT_TRUE(a.can_prune_tail());
   a.prune_tail();
   ASSERT_FALSE(a.can_prune_tail());
-  ASSERT_EQ(2u, a.extents.size());
+  ASSERT_EQ(2u, a.get_extents().size());
   ASSERT_EQ(0x4000u, a.get_logical_length());
   ASSERT_EQ(4u, a.csum_data.length());
 
   bluestore_blob_t b;
-  b.extents.emplace_back(
+  b.allocated_test(
     bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET, 0x2000));
-  a.logical_length += 0x2000;
   ASSERT_FALSE(a.can_prune_tail());
 }
 
@@ -914,22 +897,21 @@ TEST(Blob, split)
     L.shared_blob->get();  // hack to avoid dtor from running
     R.shared_blob = new BlueStore::SharedBlob(coll.get());
     R.shared_blob->get();  // hack to avoid dtor from running
-    L.dirty_blob().extents.emplace_back(bluestore_pextent_t(0x2000, 0x2000));
-    L.dirty_blob().logical_length = L.get_blob().get_ondisk_length();
+    L.dirty_blob().allocated_test(bluestore_pextent_t(0x2000, 0x2000));
     L.dirty_blob().init_csum(Checksummer::CSUM_CRC32C, 12, 0x2000);
     L.get_ref(coll.get(), 0, 0x2000);
     L.split(coll.get(), 0x1000, &R);
     ASSERT_EQ(0x1000u, L.get_blob().get_logical_length());
     ASSERT_EQ(4u, L.get_blob().csum_data.length());
-    ASSERT_EQ(1u, L.get_blob().extents.size());
-    ASSERT_EQ(0x2000u, L.get_blob().extents.front().offset);
-    ASSERT_EQ(0x1000u, L.get_blob().extents.front().length);
+    ASSERT_EQ(1u, L.get_blob().get_extents().size());
+    ASSERT_EQ(0x2000u, L.get_blob().get_extents().front().offset);
+    ASSERT_EQ(0x1000u, L.get_blob().get_extents().front().length);
     ASSERT_EQ(0x1000u, L.get_referenced_bytes());
     ASSERT_EQ(0x1000u, R.get_blob().get_logical_length());
     ASSERT_EQ(4u, R.get_blob().csum_data.length());
-    ASSERT_EQ(1u, R.get_blob().extents.size());
-    ASSERT_EQ(0x3000u, R.get_blob().extents.front().offset);
-    ASSERT_EQ(0x1000u, R.get_blob().extents.front().length);
+    ASSERT_EQ(1u, R.get_blob().get_extents().size());
+    ASSERT_EQ(0x3000u, R.get_blob().get_extents().front().offset);
+    ASSERT_EQ(0x1000u, R.get_blob().get_extents().front().length);
     ASSERT_EQ(0x1000u, R.get_referenced_bytes());
   }
   {
@@ -938,24 +920,23 @@ TEST(Blob, split)
     L.shared_blob->get();  // hack to avoid dtor from running
     R.shared_blob = new BlueStore::SharedBlob(coll.get());
     R.shared_blob->get();  // hack to avoid dtor from running
-    L.dirty_blob().extents.emplace_back(bluestore_pextent_t(0x2000, 0x1000));
-    L.dirty_blob().extents.emplace_back(bluestore_pextent_t(0x12000, 0x1000));
-    L.dirty_blob().logical_length = L.get_blob().get_ondisk_length();
+    L.dirty_blob().allocated_test(bluestore_pextent_t(0x2000, 0x1000));
+    L.dirty_blob().allocated_test(bluestore_pextent_t(0x12000, 0x1000));
     L.dirty_blob().init_csum(Checksummer::CSUM_CRC32C, 12, 0x2000);
     L.get_ref(coll.get(), 0, 0x1000);
     L.get_ref(coll.get(), 0x1000, 0x1000);
     L.split(coll.get(), 0x1000, &R);
     ASSERT_EQ(0x1000u, L.get_blob().get_logical_length());
     ASSERT_EQ(4u, L.get_blob().csum_data.length());
-    ASSERT_EQ(1u, L.get_blob().extents.size());
-    ASSERT_EQ(0x2000u, L.get_blob().extents.front().offset);
-    ASSERT_EQ(0x1000u, L.get_blob().extents.front().length);
+    ASSERT_EQ(1u, L.get_blob().get_extents().size());
+    ASSERT_EQ(0x2000u, L.get_blob().get_extents().front().offset);
+    ASSERT_EQ(0x1000u, L.get_blob().get_extents().front().length);
     ASSERT_EQ(0x1000u, L.get_referenced_bytes());
     ASSERT_EQ(0x1000u, R.get_blob().get_logical_length());
     ASSERT_EQ(4u, R.get_blob().csum_data.length());
-    ASSERT_EQ(1u, R.get_blob().extents.size());
-    ASSERT_EQ(0x12000u, R.get_blob().extents.front().offset);
-    ASSERT_EQ(0x1000u, R.get_blob().extents.front().length);
+    ASSERT_EQ(1u, R.get_blob().get_extents().size());
+    ASSERT_EQ(0x12000u, R.get_blob().get_extents().front().offset);
+    ASSERT_EQ(0x1000u, R.get_blob().get_extents().front().length);
     ASSERT_EQ(0x1000u, R.get_referenced_bytes());
   }
 }
@@ -969,10 +950,10 @@ TEST(Blob, legacy_decode)
   bufferlist bl, bl2;
   {
     BlueStore::Blob B;
+
     B.shared_blob = new BlueStore::SharedBlob(coll.get());
-    B.dirty_blob().extents.emplace_back(bluestore_pextent_t(0x1, 0x2000));
+    B.dirty_blob().allocated_test(bluestore_pextent_t(0x1, 0x2000));
     B.dirty_blob().init_csum(Checksummer::CSUM_CRC32C, 12, 0x2000);
-    B.dirty_blob().logical_length = B.get_blob().get_ondisk_length();
     B.get_ref(coll.get(), 0, 0xff0);
     B.get_ref(coll.get(), 0x1fff, 1);
 
@@ -1278,16 +1259,11 @@ TEST(GarbageCollector, BasicTest)
     b2->shared_blob = new BlueStore::SharedBlob(coll.get());
     b3->shared_blob = new BlueStore::SharedBlob(coll.get());
     b4->shared_blob = new BlueStore::SharedBlob(coll.get());
-    b1->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED);
-    b1->dirty_blob().logical_length = 0x2000;
-    b1->dirty_blob().compressed_length = 0x1000;
-    b1->dirty_blob().extents.emplace_back(0, 0x1000);
-    b2->dirty_blob().extents.emplace_back(1, 0x1000);
-    b2->dirty_blob().logical_length = b2->get_blob().get_ondisk_length();
-    b3->dirty_blob().extents.emplace_back(2, 0x1000);
-    b3->dirty_blob().logical_length = b3->get_blob().get_ondisk_length();
-    b4->dirty_blob().extents.emplace_back(3, 0x1000);
-    b4->dirty_blob().logical_length = b4->get_blob().get_ondisk_length();
+    b1->dirty_blob().set_compressed(0x2000, 0x1000);
+    b1->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x1000));
+    b2->dirty_blob().allocated_test(bluestore_pextent_t(1, 0x1000));
+    b3->dirty_blob().allocated_test(bluestore_pextent_t(2, 0x1000));
+    b4->dirty_blob().allocated_test(bluestore_pextent_t(3, 0x1000));
     em.extent_map.insert(*new BlueStore::Extent(100, 100, 10, b1));
     b1->get_ref(coll.get(), 100, 10);
     em.extent_map.insert(*new BlueStore::Extent(200, 200, 10, b2));
@@ -1345,16 +1321,11 @@ TEST(GarbageCollector, BasicTest)
     b2->shared_blob = new BlueStore::SharedBlob(coll.get());
     b3->shared_blob = new BlueStore::SharedBlob(coll.get());
     b4->shared_blob = new BlueStore::SharedBlob(coll.get());
-    b1->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED);
-    b1->dirty_blob().extents.emplace_back(0, 0x20000);
-    b1->dirty_blob().compressed_length = 0x20000;
-    b1->dirty_blob().logical_length = 0x40000;
-    b2->dirty_blob().extents.emplace_back(1, 0x10000);
-    b2->dirty_blob().logical_length = b2->get_blob().get_ondisk_length();
-    b3->dirty_blob().extents.emplace_back(2, 0x20000);
-    b3->dirty_blob().logical_length = b3->get_blob().get_ondisk_length();
-    b4->dirty_blob().extents.emplace_back(3, 0x10000);
-    b4->dirty_blob().logical_length = b4->get_blob().get_ondisk_length();
+    b1->dirty_blob().set_compressed(0x40000, 0x20000);
+    b1->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x20000));
+    b2->dirty_blob().allocated_test(bluestore_pextent_t(1, 0x10000));
+    b3->dirty_blob().allocated_test(bluestore_pextent_t(2, 0x20000));
+    b4->dirty_blob().allocated_test(bluestore_pextent_t(3, 0x10000));
 
     em.extent_map.insert(*new BlueStore::Extent(0, 0, 0x8000, b1));
     b1->get_ref(coll.get(), 0, 0x8000);
@@ -1411,14 +1382,10 @@ TEST(GarbageCollector, BasicTest)
     BlueStore::BlobRef b2(new BlueStore::Blob);
     b1->shared_blob = new BlueStore::SharedBlob(coll.get());
     b2->shared_blob = new BlueStore::SharedBlob(coll.get());
-    b1->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED);
-    b1->dirty_blob().extents.emplace_back(0, 0x2000);
-    b1->dirty_blob().logical_length = 0x4000;
-    b1->dirty_blob().compressed_length = 0x2000;
-    b2->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED);
-    b2->dirty_blob().extents.emplace_back(0, 0x2000);
-    b2->dirty_blob().logical_length = 0x4000;
-    b2->dirty_blob().compressed_length = 0x2000;
+    b1->dirty_blob().set_compressed(0x4000, 0x2000);
+    b1->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x2000));
+    b2->dirty_blob().set_compressed(0x4000, 0x2000);
+    b2->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x2000));
 
     em.extent_map.insert(*new BlueStore::Extent(0, 0, 0x3000, b1));
     b1->get_ref(coll.get(), 0, 0x3000);
@@ -1476,20 +1443,13 @@ TEST(GarbageCollector, BasicTest)
     b2->shared_blob = new BlueStore::SharedBlob(coll.get());
     b3->shared_blob = new BlueStore::SharedBlob(coll.get());
     b4->shared_blob = new BlueStore::SharedBlob(coll.get());
-    b0->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED);
-    b0->dirty_blob().extents.emplace_back(0, 0x10000);
-    b0->dirty_blob().logical_length = 0x20000;
-    b0->dirty_blob().compressed_length = 0x10000;
-    b1->dirty_blob().set_flag(bluestore_blob_t::FLAG_COMPRESSED);
-    b1->dirty_blob().extents.emplace_back(0, 0x10000);
-    b1->dirty_blob().logical_length = 0x20000;
-    b1->dirty_blob().compressed_length = 0x10000;
-    b2->dirty_blob().extents.emplace_back(1, 0x10000);
-    b2->dirty_blob().logical_length = b2->get_blob().get_ondisk_length();
-    b3->dirty_blob().extents.emplace_back(2, 0x20000);
-    b3->dirty_blob().logical_length = b3->get_blob().get_ondisk_length();
-    b4->dirty_blob().extents.emplace_back(3, 0x1000);
-    b4->dirty_blob().logical_length = b4->get_blob().get_ondisk_length();
+    b0->dirty_blob().set_compressed(0x2000, 0x1000);
+    b0->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x10000));
+    b1->dirty_blob().set_compressed(0x20000, 0x10000);
+    b1->dirty_blob().allocated_test(bluestore_pextent_t(0, 0x10000));
+    b2->dirty_blob().allocated_test(bluestore_pextent_t(1, 0x10000));
+    b3->dirty_blob().allocated_test(bluestore_pextent_t(2, 0x20000));
+    b4->dirty_blob().allocated_test(bluestore_pextent_t(3, 0x1000));
 
     em.extent_map.insert(*new BlueStore::Extent(0, 0, 0x8000, b0));
     b0->get_ref(coll.get(), 0, 0x8000);