::decode(id, p);
Blob *b = new Blob(id, c);
::decode(b->blob, p);
+ b->get();
blob_map.insert(*b);
}
}
<< r.blob_xoffset << "~" << r.length << std::dec;
}
};
+
+bool less(const BlueStore::BlobRef& a, const BlueStore::BlobRef& b)
+{
+ return *a < *b;
+}
typedef list<region_t> regions2read_t;
-typedef map<Blob*, regions2read_t> blobs2read_t;
+typedef map<BlueStore::BlobRef, regions2read_t> blobs2read_t;
int BlueStore::_do_read(
Collection *c,
pos += hole;
left -= hole;
}
- Blob *bptr = c->get_blob(o, lp->second.blob);
+ BlobRef bptr = c->get_blob(o, lp->second.blob);
if (bptr == nullptr) {
dout(20) << __func__ << " missed blob " << lp->second.blob << dendl;
assert(bptr != nullptr);
//enumerate and read/decompress desired blobs
blobs2read_t::iterator b2r_it = blobs2read.begin();
while (b2r_it != blobs2read.end()) {
- Blob* bptr = b2r_it->first;
+ BlobRef bptr = b2r_it->first;
dout(20) << __func__ << " blob " << *bptr << std::hex
<< " need 0x" << b2r_it->second << std::dec << dendl;
if (bptr->blob.has_flag(bluestore_blob_t::FLAG_COMPRESSED)) {
// delayed csum calculation?
for (auto& d : txc->deferred_csum) {
- Blob *b = d.onode->get_blob(d.blob);
+ BlobRef b = d.onode->get_blob(d.blob);
dout(20) << __func__ << " deferred csum calc blob " << d.blob
<< " b_off 0x" << std::hex << d.b_off << std::dec
<< " on " << d.onode->oid << dendl;
blp.copy(length, bl);
// look for an existing mutable blob we can use
- Blob *b = 0;
+ BlobRef b = 0;
map<uint64_t,bluestore_lextent_t>::iterator ep = o->onode.seek_lextent(offset);
if (ep != o->onode.extent_map.begin()) {
--ep;
<< " compress " << (int)wctx->compress
<< std::dec << dendl;
while (length > 0) {
- Blob *b = o->blob_map.new_blob(c->cache);
+ BlobRef b = o->blob_map.new_blob(c->cache);
auto l = MIN(max_blob_len, length);
bufferlist t;
blp.copy(l, t);
uint64_t hint = 0;
for (auto& wi : wctx->writes) {
- Blob *b = wi.b;
+ BlobRef b = wi.b;
uint64_t b_off = wi.b_off;
bufferlist *l = &wi.bl;
uint64_t final_length = wi.blob_length;
WriteContext *wctx)
{
dout(10) << __func__ << " lex_old " << wctx->lex_old << dendl;
- set<pair<bool, Blob*> > blobs2remove;
+ set<pair<bool, BlobRef> > blobs2remove;
for (auto &lo : wctx->lex_old) {
bluestore_lextent_t& l = lo.second;
- Blob *b = c->get_blob(o, l.blob);
+ BlobRef b = c->get_blob(o, l.blob);
vector<bluestore_pextent_t> r;
bool compressed = b->blob.is_compressed();
if (o->onode.deref_lextent(lo.first, l, &b->blob, min_alloc_size, &r)) {
}
}
for (auto br : blobs2remove) {
- Blob* b = br.second;
- dout(20) << __func__ << " rm blob " << *b << dendl;
- txc->statfs_delta.compressed() -= b->blob.get_compressed_payload_length();
+ dout(20) << __func__ << " rm blob " << *br.second << dendl;
+ txc->statfs_delta.compressed() -= br.second->blob.get_compressed_payload_length();
if (br.first) {
- o->blob_map.erase(b);
+ o->blob_map.erase(br.second);
} else {
- o->bnode->blob_map.erase(b);
+ o->bnode->blob_map.erase(br.second);
}
}
map<int64_t,int64_t> moved_blobs;
for (auto& p : oldo->onode.extent_map) {
if (!p.second.is_shared()) {
- Blob *b;
+ BlobRef b;
if (moved_blobs.count(p.second.blob) == 0) {
b = oldo->blob_map.get(p.second.blob);
oldo->blob_map.erase(b);
void _set_compression();
class TransContext;
- class Blob;
typedef map<uint64_t, bufferlist> ready_regions_t;
/// in-memory blob metadata and associated cached buffers (if any)
struct Blob : public boost::intrusive::set_base_hook<> {
+ std::atomic_int nref; ///< reference count
int64_t id = 0; ///< id
bluestore_blob_t blob; ///< blob metadata
BufferSpace bc; ///< buffer cache
- Blob(int64_t i, Cache *c) : id(i), bc(c) {}
+ Blob(int64_t i, Cache *c) : nref(0), id(i), bc(c) {}
~Blob() {
assert(bc.empty());
}
+ friend void intrusive_ptr_add_ref(Blob *b) { b->get(); }
+ friend void intrusive_ptr_release(Blob *b) { b->put(); }
+
// comparators for intrusive_set
friend bool operator<(const Blob &a, const Blob &b) {
return a.id < b.id;
/// discard buffers for unallocated regions
void discard_unallocated();
+
+ void get() {
+ ++nref;
+ }
+ void put() {
+ if (--nref == 0)
+ delete this;
+ }
};
+ typedef boost::intrusive_ptr<Blob> BlobRef;
/// a map of blobs, indexed by int64_t
struct BlobMap {
return blob_map.empty();
}
- Blob *get(int64_t id) {
+ BlobRef get(int64_t id) {
Blob dummy(id, nullptr);
auto p = blob_map.find(dummy);
if (p != blob_map.end()) {
return nullptr;
}
- Blob *new_blob(Cache *c) {
+ BlobRef new_blob(Cache *c) {
int64_t id = get_new_id();
Blob *b = new Blob(id, c);
+ b->get();
blob_map.insert(*b);
return b;
}
- void claim(Blob *b) {
+ void claim(BlobRef b) {
assert(b->id == 0);
b->id = get_new_id();
+ b->get();
blob_map.insert(*b);
}
- void erase(Blob *b) {
+ void erase(BlobRef b) {
blob_map.erase(*b);
b->id = 0;
+ b->put();
}
int64_t get_new_id() {
Blob *b = &*blob_map.begin();
b->bc._clear();
erase(b);
- delete b;
}
}
exists(false) {
}
- Blob *get_blob(int64_t id) {
+ BlobRef get_blob(int64_t id) {
if (id < 0) {
assert(bnode);
return bnode->blob_map.get(-id);
OnodeRef get_onode(const ghobject_t& oid, bool create);
BnodeRef get_bnode(uint32_t hash);
- Blob *get_blob(OnodeRef& o, int64_t blob) {
+ BlobRef get_blob(OnodeRef& o, int64_t blob) {
if (blob < 0) {
if (!o->bnode) {
o->bnode = get_bnode(o->oid.hobj.get_hash());
vector<std::pair<uint64_t, bluestore_lextent_t> > lex_old; ///< must deref blobs
struct write_item {
- Blob *b;
+ BlobRef b;
uint64_t blob_length;
uint64_t b_off;
bufferlist bl;
bool mark_unused;
- write_item(Blob *b, uint64_t blob_len, uint64_t o, bufferlist& bl, bool _mark_unused)
+ write_item(BlobRef b, uint64_t blob_len, uint64_t o, bufferlist& bl, bool _mark_unused)
: b(b), blob_length(blob_len), b_off(o), bl(bl), mark_unused(_mark_unused) {}
};
vector<write_item> writes; ///< blobs we're writing
- void write(Blob *b, uint64_t blob_len, uint64_t o, bufferlist& bl, bool _mark_unused) {
+ void write(BlobRef b, uint64_t blob_len, uint64_t o, bufferlist& bl, bool _mark_unused) {
writes.emplace_back(write_item(b, blob_len, o, bl, _mark_unused));
}
};