PG *pg = i->second;
epoch_t start, end;
- if (!pg->_calc_past_interval_range(&start, &end, superblock.oldest_map))
+ if (!pg->_calc_past_interval_range(&start, &end, superblock.oldest_map)) {
+ if (pg->info.history.same_interval_since == 0)
+ pg->info.history.same_interval_since = end;
continue;
+ }
dout(10) << pg->info.pgid << " needs " << start << "-" << end << dendl;
pistate& p = pis[pg];
}
}
+ // Now that past_intervals have been recomputed let's fix the same_interval_since
+ // if it was cleared by import.
+ for (map<PG*,pistate>::iterator i = pis.begin(); i != pis.end(); ++i) {
+ PG *pg = i->first;
+ pistate& p = i->second;
+
+ // Verify same_interval_since is correct
+ if (pg->info.history.same_interval_since) {
+ assert(pg->info.history.same_interval_since == p.same_interval_since);
+ } else {
+ assert(p.same_interval_since);
+ dout(10) << __func__ << " fix same_interval_since " << p.same_interval_since << " pg " << *pg << dendl;
+ dout(10) << __func__ << " past_intervals " << pg->past_intervals << dendl;
+ // Fix it
+ pg->info.history.same_interval_since = p.same_interval_since;
+ }
+ }
+
// write info only at the end. this is necessary because we check
// whether the past_intervals go far enough back or forward in time,
// but we don't check for holes. we could avoid it by discarding
bool PG::_calc_past_interval_range(epoch_t *start, epoch_t *end, epoch_t oldest_map)
{
- *end = info.history.same_interval_since;
+ if (info.history.same_interval_since) {
+ *end = info.history.same_interval_since;
+ } else {
+ // PG must be imported, so let's calculate the whole range.
+ *end = osd->get_superblock().newest_map;
+ }
// Do we already have the intervals we want?
map<epoch_t,pg_interval_t>::const_iterator pif = past_intervals.begin();
epoch_t cur_epoch, end_epoch;
if (!_calc_past_interval_range(&cur_epoch, &end_epoch,
osd->get_superblock().oldest_map)) {
+ if (info.history.same_interval_since == 0)
+ info.history.same_interval_since = end_epoch;
return;
}
}
}
+ // Verify same_interval_since is correct
+ if (info.history.same_interval_since) {
+ assert(info.history.same_interval_since == same_interval_since);
+ } else {
+ assert(same_interval_since);
+ dout(10) << __func__ << " fix same_interval_since " << same_interval_since << " pg " << *this << dendl;
+ dout(10) << __func__ << " past_intervals " << past_intervals << dendl;
+ // Fix it
+ info.history.same_interval_since = same_interval_since;
+ }
+
// record our work.
dirty_info = true;
dirty_big_info = true;
info.history.same_interval_since = osdmap->get_epoch();
} else {
std::stringstream debug;
+ assert(info.history.same_interval_since != 0);
boost::scoped_ptr<IsPGRecoverablePredicate> recoverable(
get_is_recoverable_predicate());
bool new_interval = pg_interval_t::check_new_interval(
}
if (ms.map_epoch > sb.current_epoch) {
- cerr << "ERROR: Export map_epoch " << ms.map_epoch << " > osd epoch " << sb.current_epoch << std::endl;
+ cerr << "ERROR: Export PG's map_epoch " << ms.map_epoch << " > OSD's epoch " << sb.current_epoch << std::endl;
+ cerr << "The OSD you are using is older than the exported PG" << std::endl;
+ cerr << "Either use another OSD or join selected OSD to cluster to update it first" << std::endl;
return -EINVAL;
}
}
}
+ if (debug) {
+ cerr << "Import pgid " << ms.info.pgid << std::endl;
+ cerr << "Clearing past_intervals " << ms.past_intervals << std::endl;
+ cerr << "Zero same_interval_since " << ms.info.history.same_interval_since << std::endl;
+ }
+
+ // Let osd recompute past_intervals and same_interval_since
ms.past_intervals.clear();
- ms.info.history.same_interval_since = ms.map_epoch = sb.current_epoch;
+ ms.info.history.same_interval_since = 0;
+
+ if (debug)
+ cerr << "Changing pg epoch " << ms.map_epoch << " to " << sb.current_epoch << std::endl;
+
+ ms.map_epoch = sb.current_epoch;
return 0;
}