if (sb.sbid) {
out << " sbid 0x" << std::hex << sb.sbid << std::dec;
}
- if (sb.loaded) {
- out << " loaded " << sb.shared_blob;
+ if (sb.persistent) {
+ out << " loaded " << *sb.persistent;
}
return out << ")";
}
BlueStore::SharedBlob::SharedBlob(uint64_t i, Collection *_coll)
- : sbid(i), coll(_coll)
+ : sbid(i), coll(_coll), persistent(nullptr)
{
assert(sbid > 0);
if (get_cache()) {
bc._clear(get_cache());
get_cache()->rm_blob();
}
+ delete persistent; //nullptr is OK to delete too
}
void BlueStore::SharedBlob::put()
}
}
+void BlueStore::SharedBlob::get_ref(uint64_t offset, uint32_t length)
+{
+ assert(persistent);
+ persistent->ref_map.get(offset, length);
+}
+
+void BlueStore::SharedBlob::put_ref(uint64_t offset, uint32_t length,
+ PExtentVector *r)
+{
+ assert(persistent);
+ persistent->ref_map.put(offset, length, r);
+}
+
// Blob
#undef dout_prefix
void BlueStore::Collection::load_shared_blob(SharedBlobRef sb)
{
- assert(!sb->loaded);
- bufferlist v;
- string key;
- get_shared_blob_key(sb->sbid, &key);
- int r = store->db->get(PREFIX_SHARED_BLOB, key, &v);
- if (r < 0) {
- lderr(store->cct) << __func__ << " sbid 0x" << std::hex << sb->sbid
- << std::dec << " not found at key "
- << pretty_binary_string(key) << dendl;
- assert(0 == "uh oh, missing shared_blob");
- }
+ if (!sb->is_loaded()) {
+
+ bufferlist v;
+ string key;
+ get_shared_blob_key(sb->sbid, &key);
+ int r = store->db->get(PREFIX_SHARED_BLOB, key, &v);
+ if (r < 0) {
+ lderr(store->cct) << __func__ << " sbid 0x" << std::hex << sb->sbid
+ << std::dec << " not found at key "
+ << pretty_binary_string(key) << dendl;
+ assert(0 == "uh oh, missing shared_blob");
+ }
- bufferlist::iterator p = v.begin();
- ::decode(sb->shared_blob, p);
- ldout(store->cct, 10) << __func__ << " sbid 0x" << std::hex << sb->sbid
- << std::dec << " loaded shared_blob " << *sb << dendl;
- sb->loaded = true;
+ sb->persistent = new bluestore_shared_blob_t();
+ bufferlist::iterator p = v.begin();
+ ::decode(*(sb->persistent), p);
+ ldout(store->cct, 10) << __func__ << " sbid 0x" << std::hex << sb->sbid
+ << std::dec << " loaded shared_blob " << *sb << dendl;
+ }
}
void BlueStore::Collection::make_blob_shared(uint64_t sbid, BlobRef b)
{
+ assert(b->shared_blob->is_loaded());
+
ldout(store->cct, 10) << __func__ << " " << *b << dendl;
bluestore_blob_t& blob = b->dirty_blob();
blob.clear_flag(bluestore_blob_t::FLAG_MUTABLE);
// update shared blob
- b->shared_blob->loaded = true; // we are new and therefore up to date
b->shared_blob->sbid = sbid;
+ b->shared_blob->persistent = new bluestore_shared_blob_t();
shared_blob_set.add(this, b->shared_blob.get());
for (auto p : blob.extents) {
if (p.is_valid()) {
- b->shared_blob->shared_blob.ref_map.get(p.offset, p.length);
+ b->shared_blob->get_ref(
+ p.offset,
+ p.length);
}
}
ldout(store->cct, 20) << __func__ << " now " << *b << dendl;
for (auto sb : txc->shared_blobs) {
string key;
get_shared_blob_key(sb->sbid, &key);
- if (sb->shared_blob.empty()) {
+ if (sb->persistent->empty()) {
dout(20) << " shared_blob 0x" << std::hex << sb->sbid << std::dec
<< " is empty" << dendl;
t->rmkey(PREFIX_SHARED_BLOB, key);
} else {
bufferlist bl;
- ::encode(sb->shared_blob, bl);
+ ::encode(*(sb->persistent), bl);
dout(20) << " shared_blob 0x" << std::hex << sb->sbid << std::dec
<< " is " << bl.length() << dendl;
t->set(PREFIX_SHARED_BLOB, key, bl);
dout(20) << __func__ << " blob release " << r << dendl;
if (blob.is_shared()) {
PExtentVector final;
- if (!b->shared_blob->loaded) {
- c->load_shared_blob(b->shared_blob);
- }
+ c->load_shared_blob(b->shared_blob);
for (auto e : r) {
- PExtentVector cur;
- b->shared_blob->shared_blob.ref_map.put(e.offset, e.length, &cur);
- final.insert(final.end(), cur.begin(), cur.end());
+ b->shared_blob->put_ref(e.offset, e.length, &final);
}
dout(20) << __func__ << " shared_blob release " << final
<< " from " << *b->shared_blob << dendl;
if (!blob.is_shared()) {
c->make_blob_shared(_assign_blobid(txc), e.blob);
dirtied_oldo = true; // fixme: overkill
- } else if (!e.blob->shared_blob->loaded) {
+ } else {
c->load_shared_blob(e.blob->shared_blob);
}
cb = new Blob();
// bump the extent refs on the copied blob's extents
for (auto p : blob.extents) {
if (p.is_valid()) {
- e.blob->shared_blob->shared_blob.ref_map.get(p.offset, p.length);
+ e.blob->shared_blob->get_ref(p.offset, p.length);
}
}
txc->write_shared_blob(e.blob->shared_blob);
std::atomic_int nref = {0}; ///< reference count
- // these are defined/set if the shared_blob is 'loaded'
- bool loaded = false; ///< whether shared_blob is loaded
- bluestore_shared_blob_t shared_blob; ///< the actual shared state
-
// these are defined/set if the blob is marked 'shared'
uint64_t sbid = 0; ///< shared blob id
Collection *coll = nullptr;
+ bluestore_shared_blob_t *persistent; ///< persistent part of the shared blob if any
BufferSpace bc; ///< buffer cache
- SharedBlob(Collection *_coll) : coll(_coll) {
+ SharedBlob(Collection *_coll) : coll(_coll), persistent(nullptr) {
if (get_cache()) {
get_cache()->add_blob();
}
}
void put();
+ /// get logical references
+ void get_ref(uint64_t offset, uint32_t length);
+
+ /// put logical references, and get back any released extents
+ void put_ref(uint64_t offset, uint32_t length,
+ PExtentVector *r);
+
friend bool operator==(const SharedBlob &l, const SharedBlob &r) {
return l.sbid == r.sbid;
}
inline SharedBlobSet* get_parent() {
return coll ? &(coll->shared_blob_set) : nullptr;
}
+ inline bool is_loaded() const {
+ return persistent != nullptr;
+ }
+
};
typedef boost::intrusive_ptr<SharedBlob> SharedBlobRef;