void OSD::load_pgs()
{
  assert(osd_lock.is_locked());
  dout(0) << "load_pgs" << dendl;
  {
    RWLock::RLocker l(pg_map_lock);
    assert(pg_map.empty());
  }

  vector<coll_t> ls;
  int r = store->list_collections(ls);
  if (r < 0) {
    derr << "failed to list pgs: " << cpp_strerror(-r) << dendl;
  }

  bool has_upgraded = false;

  for (vector<coll_t>::iterator it = ls.begin();
       it != ls.end();
       ++it) {
    spg_t pgid;
    if (it->is_temp(&pgid) ||
       (it->is_pg(&pgid) && PG::_has_removal_flag(store, pgid))) {
      dout(10) << "load_pgs " << *it << " clearing temp" << dendl;
      recursive_remove_collection(cct, store, pgid, *it);
      continue;
    }

    if (!it->is_pg(&pgid)) {
      dout(10) << "load_pgs ignoring unrecognized " << *it << dendl;
      continue;
    }

    if (pgid.preferred() >= 0) {
      dout(10) << __func__ << ": skipping localized PG " << pgid << dendl;
      // FIXME: delete it too, eventually
      continue;
    }

    dout(10) << "pgid " << pgid << " coll " << coll_t(pgid) << dendl;
    bufferlist bl;
    epoch_t map_epoch = 0;
    int r = PG::peek_map_epoch(store, pgid, &map_epoch, &bl);
    if (r < 0) {
      derr << __func__ << " unable to peek at " << pgid << " metadata, skipping"
	   << dendl;
      continue;
    }

    PG *pg = NULL;
    if (map_epoch > 0) {
      OSDMapRef pgosdmap = service.try_get_map(map_epoch);
      if (!pgosdmap) {
	if (!osdmap->have_pg_pool(pgid.pool())) {
	  derr << __func__ << ": could not find map for epoch " << map_epoch
	       << " on pg " << pgid << ", but the pool is not present in the "
	       << "current map, so this is probably a result of bug 10617.  "
	       << "Skipping the pg for now, you can use ceph-objectstore-tool "
	       << "to clean it up later." << dendl;
	  continue;
	} else {
	  derr << __func__ << ": have pgid " << pgid << " at epoch "
	       << map_epoch << ", but missing map.  Crashing."
	       << dendl;
	  assert(0 == "Missing map in load_pgs");
	}
      }
      pg = _open_lock_pg(pgosdmap, pgid);
    } else {
      pg = _open_lock_pg(osdmap, pgid);
    }
    // there can be no waiters here, so we don't call wake_pg_waiters

    pg->ch = store->open_collection(pg->coll);

    // read pg state, log
    pg->read_state(store, bl);

    if (pg->must_upgrade()) {
      if (!pg->can_upgrade()) {
	derr << "PG needs upgrade, but on-disk data is too old; upgrade to"
	     << " an older version first." << dendl;
	assert(0 == "PG too old to upgrade");
      }
      if (!has_upgraded) {
	derr << "PGs are upgrading" << dendl;
	has_upgraded = true;
      }
      dout(10) << "PG " << pg->info.pgid
	       << " must upgrade..." << dendl;
      pg->upgrade(store);
    }

    if (pg->dne())  {
      dout(10) << "load_pgs " << *it << " deleting dne" << dendl;
      pg->ch = nullptr;
      service.pg_remove_epoch(pg->pg_id);
      pg->unlock();
      {
	// Delete pg
	RWLock::WLocker l(pg_map_lock);
	auto p = pg_map.find(pg->get_pgid());
	assert(p != pg_map.end() && p->second == pg);
	dout(20) << __func__ << " removed pg " << pg << " from pg_map" << dendl;
	pg_map.erase(p);
	pg->put("PGMap");
      }
      recursive_remove_collection(cct, store, pgid, *it);
      continue;
    }

    service.init_splits_between(pg->info.pgid, pg->get_osdmap(), osdmap);

    // generate state for PG's current mapping
    int primary, up_primary;
    vector<int> acting, up;
    pg->get_osdmap()->pg_to_up_acting_osds(
      pgid.pgid, &up, &up_primary, &acting, &primary);
    pg->init_primary_up_acting(
      up,
      acting,
      up_primary,
      primary);
    int role = OSDMap::calc_pg_role(whoami, pg->acting);
    if (pg->pool.info.is_replicated() || role == pg->pg_whoami.shard)
      pg->set_role(role);
    else
      pg->set_role(-1);

    pg->reg_next_scrub();

    PG::RecoveryCtx rctx(0, 0, 0, 0, 0, 0);
    pg->handle_loaded(&rctx);

    dout(10) << "load_pgs loaded " << *pg << " " << pg->pg_log.get_log() << dendl;
    if (pg->pg_log.is_dirty()) {
      ObjectStore::Transaction t;
      pg->write_if_dirty(t);
      store->apply_transaction(pg->osr.get(), std::move(t));
    }
    pg->unlock();
  }
  {
    RWLock::RLocker l(pg_map_lock);
    dout(0) << "load_pgs opened " << pg_map.size() << " pgs" << dendl;
  }

  // clean up old infos object?
  if (has_upgraded && store->exists(coll_t::meta(), OSD::make_infos_oid())) {
    dout(1) << __func__ << " removing legacy infos object" << dendl;
    ObjectStore::Transaction t;
    t.remove(coll_t::meta(), OSD::make_infos_oid());
    int r = store->apply_transaction(service.meta_osr.get(), std::move(t));
    if (r != 0) {
      derr << __func__ << ": apply_transaction returned "
	   << cpp_strerror(r) << dendl;
      ceph_abort();
    }
  }

  build_past_intervals_parallel();
}