// decremented. And another 'putting' thread on the instance will release it.
//
void BlueStore::Onode::get() {
- if (++nref == 2) {
+ if (++nref >= 2 && !pinned) {
OnodeCacheShard* ocs = c->get_onode_cache();
std::lock_guard l(ocs->lock);
bool was_pinned = pinned;
if (n == 2) {
OnodeCacheShard* ocs = c->get_onode_cache();
std::lock_guard l(ocs->lock);
- bool was_pinned = pinned;
+ bool need_unpin = pinned;
pinned = pinned && nref > 2; // intentionally use > not >= as we have
- // +1 due to pinned state
- bool r = was_pinned && !pinned;
- // additional decrement for newly unpinned instance
- if (r) {
- n = --nref;
- }
- if (cached && r) {
+ // +1 due to pinned state
+ need_unpin = need_unpin && !pinned;
+ if (cached && need_unpin) {
if (exists) {
ocs->_unpin(this);
} else {
c->onode_map._remove(oid);
}
}
+ // additional decrement for newly unpinned instance
+ // should be the last action since Onode can be released
+ // at any point after this decrement
+ if (need_unpin) {
+ n = --nref;
+ }
}
if (n == 0) {
delete this;
p = onode_map.onode_map.erase(p);
dest->onode_map.onode_map[o->oid] = o;
- if (get_onode_cache() != dest->get_onode_cache()) {
+ if (o->cached) {
get_onode_cache()->move_pinned(dest->get_onode_cache(), o.get());
}
o->c = dest;
bool cached; ///< Onode is logically in the cache
/// (it can be pinned and hence physically out
/// of it at the moment though)
- bool pinned; ///< Onode is pinned
+ std::atomic_bool pinned; ///< Onode is pinned
/// (or should be pinned when cached)
ExtentMap extent_map;