<< "required " << ceph_release_name(mv);
pending_inc.new_require_min_compat_client = mv;
}
+
+ // upgrade to mimic?
+ if (osdmap.require_osd_release < CEPH_RELEASE_MIMIC &&
+ tmp.require_osd_release >= CEPH_RELEASE_MIMIC) {
+ dout(10) << __func__ << " first mimic epoch" << dendl;
+ // record this epoch as the deletion for all legacy removed_snaps
+ for (auto& p : tmp.get_pools()) {
+ // update every pool
+ if (pending_inc.new_pools.count(p.first) == 0) {
+ pending_inc.new_pools[p.first] = p.second;
+ }
+ auto& pi = pending_inc.new_pools[p.first];
+ if (pi.snap_seq == 0) {
+ // no snaps on this pool
+ continue;
+ }
+ if ((pi.flags & (pg_pool_t::FLAG_SELFMANAGED_SNAPS |
+ pg_pool_t::FLAG_POOL_SNAPS)) == 0) {
+ if (!pi.removed_snaps.empty()) {
+ pi.flags |= pg_pool_t::FLAG_SELFMANAGED_SNAPS;
+ } else {
+ pi.flags |= pg_pool_t::FLAG_POOL_SNAPS;
+ }
+ }
+
+ // Make all previously removed snaps appear to be removed in this
+ // epoch. this populates removed_snaps_queue. The OSD will subtract
+ // off its purged_snaps, as before, and this set will shrink over the
+ // following epochs as the purged snaps are reported back through the
+ // mgr.
+ OSDMap::snap_interval_set_t removed;
+ if (!p.second.removed_snaps.empty()) {
+ // different flavor of interval_set :(
+ for (auto q = p.second.removed_snaps.begin();
+ q != p.second.removed_snaps.end();
+ ++q) {
+ removed.insert(q.get_start(), q.get_len());
+ }
+ } else {
+ for (snapid_t s = 1; s <= pi.get_snap_seq(); s = s + 1) {
+ if (pi.snaps.count(s) == 0) {
+ removed.insert(s);
+ }
+ }
+ }
+ pending_inc.new_removed_snaps[p.first].union_of(removed);
+
+ dout(10) << __func__ << " converting pool " << p.first
+ << " with " << p.second.removed_snaps.size()
+ << " legacy removed_snaps" << dendl;
+ string k = make_snap_epoch_key(p.first, pending_inc.epoch);
+ bufferlist v;
+ ::encode(p.second.removed_snaps, v);
+ t->put(OSD_SNAP_PREFIX, k, v);
+ for (auto q = p.second.removed_snaps.begin();
+ q != p.second.removed_snaps.end();
+ ++q) {
+ bufferlist v;
+ string k = make_snap_key_value(p.first, q.get_start(),
+ q.get_len(), pending_inc.epoch, &v);
+ t->put(OSD_SNAP_PREFIX, k, v);
+ }
+ }
+ }
}
// tell me about it
peer_features(CEPH_FEATURES_SUPPORTED_DEFAULT),
acting_features(CEPH_FEATURES_SUPPORTED_DEFAULT),
upacting_features(CEPH_FEATURES_SUPPORTED_DEFAULT),
- last_epoch(0)
+ last_epoch(0),
+ last_require_osd_release(curmap->require_osd_release)
{
#ifdef PG_DEBUG_REFS
osd->add_pgid(p, this);
on_pool_change();
update_store_with_options();
}
+ last_require_osd_release = osdmap->require_osd_release;
}
void PG::handle_activate_map(RecoveryCtx *rctx)
decltype(pg->snap_trimq) added, overlap;
added.insert(j.first, j.second);
overlap.intersection_of(pg->snap_trimq, added);
- lderr(pg->cct) << __func__ << " removed_snaps already contains "
- << overlap << dendl;
- bad = true;
+ if (pg->last_require_osd_release < CEPH_RELEASE_MIMIC) {
+ lderr(pg->cct) << __func__ << " removed_snaps already contains "
+ << overlap << ", but this is the first mimic+ osdmap,"
+ << " so it's expected" << dendl;
+ } else {
+ lderr(pg->cct) << __func__ << " removed_snaps already contains "
+ << overlap << dendl;
+ bad = true;
+ }
pg->snap_trimq.union_of(added);
} else {
pg->snap_trimq.insert(j.first, j.second);
}
}
+ if (pg->last_require_osd_release < CEPH_RELEASE_MIMIC) {
+ // at upgrade, we report *all* previously removed snaps as removed in
+ // the first mimic epoch. remove the ones we previously divined were
+ // removed (and subsequently purged) from the trimq.
+ lderr(pg->cct) << __func__ << " first mimic map, filtering purged_snaps"
+ << " from new removed_snaps" << dendl;
+ pg->snap_trimq.subtract(pg->info.purged_snaps);
+ }
ldout(pg->cct,10) << __func__ << " new removed_snaps " << i->second
<< ", snap_trimq now " << pg->snap_trimq << dendl;
assert(!bad || !pg->cct->_conf->osd_debug_verify_cached_snaps);