assert(osd_lock.is_locked());
PG* pg = _make_pg(createmap, pgid);
-
{
RWLock::WLocker l(pg_map_lock);
+ pg->lock(no_lockdep_check);
pg_map[pgid] = pg;
+ pg->get("PGMap"); // because it's in pg_map
+ wake_pg_waiters(pg, pgid);
}
-
- pg->lock(no_lockdep_check);
- pg->get("PGMap"); // because it's in pg_map
return pg;
}
{
RWLock::WLocker l(pg_map_lock);
pg_map[pg->info.pgid] = pg;
+ wake_pg_waiters(pg, pg->info.pgid);
}
dout(10) << "Adding newly split pg " << *pg << dendl;
vector<int> up, acting;
}
peering_wait_for_split.erase(to_wake);
}
- wake_pg_waiters(pg->info.pgid);
if (!service.get_osdmap()->have_pg_pool(pg->info.pgid.pool()))
_remove_pg(pg);
}
dout(10) << *pg << " is new" << dendl;
- // kick any waiters
- wake_pg_waiters(pg->info.pgid);
-
pg->queue_peering_event(evt);
pg->unlock();
return;
dout(10) << *pg << " is new (resurrected)" << dendl;
- // kick any waiters
- wake_pg_waiters(pg->info.pgid);
-
pg->queue_peering_event(evt);
pg->unlock();
return;
dout(10) << *parent << " is new" << dendl;
- // kick any waiters
- wake_pg_waiters(parent->info.pgid);
-
assert(service.splitting(pgid));
peering_wait_for_split[pgid].push_back(evt);
}
// scan pgs with waiters
+ RWLock::WLocker l(pg_map_lock);
map<spg_t, list<OpRequestRef> >::iterator p = waiting_for_pg.begin();
while (p != waiting_for_pg.end()) {
spg_t pgid = p->first;
*rctx.transaction);
pg->info.last_epoch_started = pg->info.history.last_epoch_started;
creating_pgs.erase(pgid);
- wake_pg_waiters(pg->info.pgid);
pg->handle_create(&rctx);
pg->write_if_dirty(*rctx.transaction);
pg->publish_stats_to_osd();
protected:
// -- placement groups --
- RWLock pg_map_lock;
+ RWLock pg_map_lock; // this lock orders *above* individual PG _locks
ceph::unordered_map<spg_t, PG*> pg_map; // protected by pg_map lock
- map<spg_t, list<OpRequestRef> > waiting_for_pg;
+ map<spg_t, list<OpRequestRef> > waiting_for_pg; // protected by pg_map lock
map<spg_t, list<PG::CephPeeringEvtRef> > peering_wait_for_split;
PGRecoveryStats pg_recovery_stats;
int lastactingprimary
); ///< @return false if there was a map gap between from and now
- void wake_pg_waiters(spg_t pgid) {
- if (waiting_for_pg.count(pgid)) {
- take_waiters_front(waiting_for_pg[pgid]);
- waiting_for_pg.erase(pgid);
+ void wake_pg_waiters(PG* pg, spg_t pgid) {
+ // Need write lock on pg_map
+ map<spg_t, list<OpRequestRef> >::iterator i = waiting_for_pg.find(pgid);
+ if (i != waiting_for_pg.end()) {
+ for (list<OpRequestRef>::iterator j = i->second.begin();
+ j != i->second.end();
+ ++j) {
+ enqueue_op(pg, *j);
+ }
+ waiting_for_pg.erase(i);
}
}