struct MOSDPGCreate : public Message {
- const static int HEAD_VERSION = 2;
+ const static int HEAD_VERSION = 3;
+ // At head_version 2 the unspecified compat_version was set to 2
+ const static int COMPAT_VERSION = 2;
version_t epoch;
map<pg_t,pg_create_t> mkpg;
+ map<pg_t,utime_t> ctimes;
MOSDPGCreate()
- : Message(MSG_OSD_PG_CREATE, HEAD_VERSION) {}
+ : Message(MSG_OSD_PG_CREATE, HEAD_VERSION, COMPAT_VERSION) {}
MOSDPGCreate(epoch_t e)
- : Message(MSG_OSD_PG_CREATE, HEAD_VERSION),
+ : Message(MSG_OSD_PG_CREATE, HEAD_VERSION, COMPAT_VERSION),
epoch(e) { }
private:
~MOSDPGCreate() {}
void encode_payload(uint64_t features) {
::encode(epoch, payload);
::encode(mkpg, payload);
+ ::encode(ctimes, payload);
}
void decode_payload() {
bufferlist::iterator p = payload.begin();
mkpg[pgid] = pg_create_t(created, parent, split_bits);
}
}
+ if (header.version >= 3) {
+ ::decode(ctimes, p);
+ } else {
+ // To make other code simpler create map with time of 0,0 for each pg
+ for (map<pg_t,pg_create_t>::const_iterator i = mkpg.begin();
+ i != mkpg.end(); ++i) {
+ ctimes[i->first] = utime_t();
+ }
+ }
}
void print(ostream& out) const {
out << "osd_pg_create(";
+ map<pg_t,utime_t>::const_iterator ci = ctimes.begin();
for (map<pg_t,pg_create_t>::const_iterator i = mkpg.begin();
i != mkpg.end();
- ++i) {
- out << "pg" << i->first << "," << i->second.created << "; ";
+ ++i, ++ci) {
+ assert(ci != ctimes.end() && ci->first == i->first);
+ out << "pg" << i->first << "," << i->second.created << "@" << ci->second << "; ";
}
out << ")";
}
{
pg_t parent;
int split_bits = 0;
+ bool parent_found = false;
if (!new_pool) {
parent = pgid;
while (1) {
if (pg_map.pg_stat.count(parent) &&
pg_map.pg_stat[parent].state != PG_STATE_CREATING) {
dout(10) << " parent is " << parent << dendl;
+ parent_found = true;
break;
}
}
stats.parent = parent;
stats.parent_split_bits = split_bits;
- utime_t now = ceph_clock_now(g_ceph_context);
- stats.last_scrub_stamp = now;
- stats.last_deep_scrub_stamp = now;
- stats.last_clean_scrub_stamp = now;
+ if (parent_found) {
+ stats.last_scrub_stamp = pg_map.pg_stat[parent].last_scrub_stamp;
+ stats.last_deep_scrub_stamp = pg_map.pg_stat[parent].last_deep_scrub_stamp;
+ stats.last_clean_scrub_stamp = pg_map.pg_stat[parent].last_clean_scrub_stamp;
+ } else {
+ utime_t now = ceph_clock_now(g_ceph_context);
+ stats.last_scrub_stamp = now;
+ stats.last_deep_scrub_stamp = now;
+ stats.last_clean_scrub_stamp = now;
+ }
+
if (split_bits == 0) {
dout(10) << "register_new_pgs will create " << pgid << dendl;
m->mkpg[*q] = pg_create_t(pg_map.pg_stat[*q].created,
pg_map.pg_stat[*q].parent,
pg_map.pg_stat[*q].parent_split_bits);
+ // Need the create time from the monitor using his clock to set last_scrub_stamp
+ // upon pg creation.
+ m->ctimes[*q] = pg_map.pg_stat[*q].last_scrub_stamp;
}
if (con) {
int num_created = 0;
+ map<pg_t,utime_t>::iterator ci = m->ctimes.begin();
for (map<pg_t,pg_create_t>::iterator p = m->mkpg.begin();
p != m->mkpg.end();
- ++p) {
+ ++p, ++ci) {
+ assert(ci != m->ctimes.end() && ci->first == p->first);
epoch_t created = p->second.created;
pg_t parent = p->second.parent;
if (p->second.split_bits) // Skip split pgs
continue;
}
- dout(20) << "mkpg " << on << " e" << created << dendl;
+ dout(20) << "mkpg " << on << " e" << created << "@" << ci->second << dendl;
// is it still ours?
vector<int> up, acting;
history.last_epoch_clean = created;
// Newly created PGs don't need to scrub immediately, so mark them
// as scrubbed at creation time.
- utime_t now = ceph_clock_now(NULL);
- history.last_scrub_stamp = now;
- history.last_deep_scrub_stamp = now;
+ if (ci->second == utime_t()) {
+ // Older OSD doesn't send ctime, so just do what we did before
+ // The repair_test.py can fail in a mixed cluster
+ utime_t now = ceph_clock_now(NULL);
+ history.last_scrub_stamp = now;
+ history.last_deep_scrub_stamp = now;
+ } else {
+ history.last_scrub_stamp = ci->second;
+ history.last_deep_scrub_stamp = ci->second;
+ }
bool valid_history = project_pg_history(
pgid, history, created, up, up_primary, acting, acting_primary);
/* the pg creation message must have come from a mon and therefore