if (b.is_spanning()) {
out << " spanning " << b.id;
}
- out << " " << b.get_blob() << " " << b.ref_map
+ out << " " << b.get_blob() << " " << b.get_ref_map()
<< (b.is_dirty() ? " (dirty)" : " (clean)")
<< " " << *b.shared_blob
<< ")";
return false;
}
+void BlueStore::Blob::pass_ref(Blob* other, uint64_t src_offset, uint64_t length, uint64_t dest_offset)
+{
+ ref_map.put(src_offset, length, nullptr);
+ other->ref_map.get(dest_offset, length);
+}
+
void BlueStore::Blob::split(size_t blob_offset, Blob *r)
{
dout(10) << __func__ << " 0x" << std::hex << blob_offset << std::dec
denc_varint(0, bound); // logical_offset
denc_varint(0, bound); // len
denc_varint(0, bound); // blob_offset
- p->blob->bound_encode(bound);
+ p->blob->bound_encode(bound, false);
}
{
}
pos = p->logical_offset + p->length;
if (include_blob) {
- p->blob->encode(app);
+ p->blob->encode(app, false);
}
}
}
assert(le->blob);
} else {
Blob *b = new Blob();
- b->decode(p);
+ b->decode(p, false);
blobs[n] = b;
onode->c->open_shared_blob(b);
le->assign_blob(b);
denc_varint((uint32_t)0, key_size);
p += spanning_blob_map.size() * key_size;
for (const auto& i : spanning_blob_map) {
- i.second->bound_encode(p);
- i.second->ref_map.bound_encode(p);
+ i.second->bound_encode(p, true);
}
}
denc_varint(spanning_blob_map.size(), p);
for (auto& i : spanning_blob_map) {
denc_varint(i.second->id, p);
- i.second->encode(p);
- i.second->ref_map.encode(p);
+ i.second->encode(p, true);
}
}
BlobRef b(new Blob());
denc_varint(b->id, p);
spanning_blob_map[b->id] = b;
- b->decode(p);
- b->ref_map.decode(p);
+ b->decode(p, true);
c->open_shared_blob(b);
}
}
if (ep->blob != lb) {
continue;
}
- vector<bluestore_pextent_t> released;
if (ep->logical_offset < pos) {
// split extent
size_t left = pos - ep->logical_offset;
Extent *ne = new Extent(pos, 0, ep->length - left, ep->blob_depth, rb);
extent_map.insert(*ne);
- lb->ref_map.put(ep->blob_offset + left, ep->length - left, &released);
+ lb->pass_ref(rb.get(), ep->blob_offset + left, ne->length, ne->blob_offset);
ep->length = left;
- rb->get_ref(ne->blob_offset, ne->length);
dout(30) << __func__ << " split " << *ep << dendl;
dout(30) << __func__ << " to " << *ne << dendl;
} else {
// switch blob
assert(ep->blob_offset >= blob_offset);
- lb->ref_map.put(ep->blob_offset, ep->length, &released);
+ lb->pass_ref(rb.get(), ep->blob_offset, ep->length, ep->blob_offset - blob_offset);
ep->blob = rb;
ep->blob_offset -= blob_offset;
- rb->get_ref(ep->blob_offset, ep->length);
dout(30) << __func__ << " adjusted " << *ep << dendl;
}
}
}
for (auto &i : ref_map) {
++num_blobs;
- if (i.first->ref_map != i.second) {
+ if (i.first->get_ref_map() != i.second) {
derr << __func__ << " " << oid << " blob " << *i.first
<< " doesn't match expected ref_map " << i.second << dendl;
++errors;
const bluestore_blob_t& blob = i.first->get_blob();
if (blob.is_compressed()) {
expected_statfs.compressed += blob.compressed_length;
- for (auto& r : i.first->ref_map.ref_map) {
+ for (auto& r : i.first->get_ref_map().ref_map) {
expected_statfs.compressed_original +=
r.second.refs * r.second.length;
}
}
}
delete &lo;
- if (b->id >= 0 && b->ref_map.empty()) {
+ if (b->id >= 0 && b->get_ref_map().empty()) {
dout(20) << __func__ << " spanning_blob_map removing empty " << *b
<< dendl;
auto it = o->extent_map.spanning_blob_map.find(b->id);
int16_t last_encoded_id = -1; ///< (ephemeral) used during encoding only
SharedBlobRef shared_blob; ///< shared blob state (if any)
- /// refs from this shard. ephemeral if id<0, persisted if spanning.
- bluestore_extent_ref_map_t ref_map;
-
private:
mutable bluestore_blob_t blob; ///< decoded blob metadata
mutable bool dirty = true; ///< true if blob is newer than blob_bl
mutable bufferlist blob_bl; ///< cached encoded blob
+ /// refs from this shard. ephemeral if id<0, persisted if spanning.
+ bluestore_extent_ref_map_t ref_map;
public:
Blob() {}
friend ostream& operator<<(ostream& out, const Blob &b);
+ const bluestore_extent_ref_map_t& get_ref_map() const {
+ return ref_map;
+ }
bool is_spanning() const {
return id >= 0;
}
/// put logical references, and get back any released extents
bool put_ref(uint64_t offset, uint64_t length, uint64_t min_alloc_size,
vector<bluestore_pextent_t> *r);
+ /// pass references for specific range to other blob
+ void pass_ref(Blob* other, uint64_t src_offset, uint64_t length, uint64_t dest_offset);
/// split the blob
void split(size_t blob_offset, Blob *o);
assert(blob_bl.length());
}
}
- void bound_encode(size_t& p) const {
+ void bound_encode(size_t& p, bool include_ref_map) const {
_encode();
p += blob_bl.length();
+ if (include_ref_map) {
+ ref_map.bound_encode(p);
+ }
}
- void encode(bufferlist::contiguous_appender& p) const {
+ void encode(bufferlist::contiguous_appender& p, bool include_ref_map) const {
_encode();
p.append(blob_bl);
+ if (include_ref_map) {
+ ref_map.encode(p);
+ }
}
- void decode(bufferptr::iterator& p) {
+ void decode(bufferptr::iterator& p, bool include_ref_map) {
const char *start = p.get_pos();
denc(blob, p);
const char *end = p.get_pos();
blob_bl.clear();
blob_bl.append(start, end - start);
dirty = false;
+ if (include_ref_map) {
+ ref_map.decode(p);
+ }
}
#else
- void bound_encode(size_t& p) const {
+ void bound_encode(size_t& p, bool include_ref_map) const {
denc(blob, p);
+ if (include_ref_map) {
+ ref_map.bound_encode(p);
+ }
}
- void encode(bufferlist::contiguous_appender& p) const {
+ void encode(bufferlist::contiguous_appender& p, bool include_ref_map) const {
denc(blob, p);
+ if (include_ref_map) {
+ ref_map.encode(p);
+ }
}
- void decode(bufferptr::iterator& p) {
+ void decode(bufferptr::iterator& p, bool include_ref_map) {
denc(blob, p);
+ if (include_ref_map) {
+ ref_map.decode(p);
+ }
}
#endif
};
b.dirty_blob().extents.push_back(
bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET, 0x8000));
b.dirty_blob().extents.push_back(bluestore_pextent_t(0x4071f000, 0x5000));
- b.ref_map.get(0, 0x1200);
- b.ref_map.get(0xae00, 0x4200);
+ b.get_ref(0, 0x1200);
+ b.get_ref(0xae00, 0x4200);
cout << b << std::endl;
vector<bluestore_pextent_t> r;
B.shared_blob = new BlueStore::SharedBlob(-1, string(), nullptr);
B.shared_blob->get(); // hack to avoid dtor from running
bluestore_blob_t& b = B.dirty_blob();
- B.ref_map.get(0x0, 0x3800);
- B.ref_map.get(0x17c00, 0x6400);
+ B.get_ref(0x0, 0x3800);
+ B.get_ref(0x17c00, 0x6400);
b.extents.push_back(bluestore_pextent_t(0x40101000, 0x4000));
b.extents.push_back(bluestore_pextent_t(bluestore_pextent_t::INVALID_OFFSET,
0x13000));