}
void PG::repair_object(
- const hobject_t& soid, ScrubMap::object *po,
- pg_shard_t bad_peer, pg_shard_t ok_peer)
+ const hobject_t& soid, list<pair<ScrubMap::object, pg_shard_t> > *ok_peers,
+ pg_shard_t bad_peer)
{
dout(10) << "repair_object " << soid << " bad_peer osd."
- << bad_peer << " ok_peer osd." << ok_peer << dendl;
+ << bad_peer << " ok_peers osd.{" << ok_peers << "}" << dendl;
+ ScrubMap::object &po = ok_peers->back().first;
eversion_t v;
bufferlist bv;
- bv.push_back(po->attrs[OI_ATTR]);
+ bv.push_back(po.attrs[OI_ATTR]);
object_info_t oi(bv);
if (bad_peer != primary) {
peer_missing[bad_peer].add(soid, oi.version, eversion_t());
pg_log.missing_add(soid, oi.version, eversion_t());
missing_loc.add_missing(soid, oi.version, eversion_t());
- missing_loc.add_location(soid, ok_peer);
+ list<pair<ScrubMap::object, pg_shard_t> >::iterator i;
+ for (i = ok_peers->begin();
+ i != ok_peers->end();
+ i++)
+ missing_loc.add_location(soid, i->second);
pg_log.set_last_requested(0);
+ dout(10) << __func__ << ": primary = " << primary << dendl;
}
}
stringstream ss;
// Map from object with errors to good peer
- map<hobject_t, pg_shard_t> authoritative;
+ map<hobject_t, list<pg_shard_t> > authoritative;
map<pg_shard_t, ScrubMap *> maps;
dout(2) << __func__ << " osd." << acting[0] << " has "
osd->clog->error(ss);
}
- for (map<hobject_t, pg_shard_t>::iterator i = authoritative.begin();
+ for (map<hobject_t, list<pg_shard_t> >::iterator i = authoritative.begin();
i != authoritative.end();
++i) {
+ list<pair<ScrubMap::object, pg_shard_t> > good_peers;
+ for (list<pg_shard_t>::const_iterator j = i->second.begin();
+ j != i->second.end();
+ j++) {
+ good_peers.push_back(make_pair(maps[*j]->objects[i->first], *j));
+ }
scrubber.authoritative.insert(
make_pair(
i->first,
- make_pair(maps[i->second]->objects[i->first], i->second)));
+ good_peers));
}
- for (map<hobject_t, pg_shard_t>::iterator i = authoritative.begin();
+ for (map<hobject_t, list<pg_shard_t> >::iterator i = authoritative.begin();
i != authoritative.end();
++i) {
authmap.objects.erase(i->first);
- authmap.objects.insert(*(maps[i->second]->objects.find(i->first)));
+ authmap.objects.insert(*(maps[i->second.back()]->objects.find(i->first)));
}
}
void PG::scrub_process_inconsistent()
{
- dout(10) << "process_inconsistent() checking authoritative" << dendl;
+ dout(10) << __func__ << ": checking authoritative" << dendl;
bool repair = state_test(PG_STATE_REPAIR);
bool deep_scrub = state_test(PG_STATE_DEEP_SCRUB);
const char *mode = (repair ? "repair": (deep_scrub ? "deep-scrub" : "scrub"));
osd->clog->error(ss);
if (repair) {
state_clear(PG_STATE_CLEAN);
- for (map<hobject_t, pair<ScrubMap::object, pg_shard_t> >::iterator i =
+ for (map<hobject_t, list<pair<ScrubMap::object, pg_shard_t> > >::iterator i =
scrubber.authoritative.begin();
i != scrubber.authoritative.end();
++i) {
++j) {
repair_object(
i->first,
- &(i->second.first),
- *j,
- i->second.second);
+ &(i->second),
+ *j);
++scrubber.fixed;
}
}
j != scrubber.inconsistent[i->first].end();
++j) {
repair_object(i->first,
- &(i->second.first),
- *j,
- i->second.second);
+ &(i->second),
+ *j);
++scrubber.fixed;
}
}
map<hobject_t, set<pg_shard_t> > missing;
map<hobject_t, set<pg_shard_t> > inconsistent;
- // Map from object with errors to good peer
- map<hobject_t, pair<ScrubMap::object, pg_shard_t> > authoritative;
+ // Map from object with errors to good peers
+ map<hobject_t, list<pair<ScrubMap::object, pg_shard_t> > > authoritative;
// Objects who need digest updates
map<hobject_t, pair<uint32_t,uint32_t> > missing_digest;
int active_pushes;
void repair_object(
- const hobject_t& soid, ScrubMap::object *po,
- pg_shard_t bad_peer,
- pg_shard_t ok_peer);
+ const hobject_t& soid, list<pair<ScrubMap::object, pg_shard_t> > *ok_peers,
+ pg_shard_t bad_peer);
void scrub(ThreadPool::TPHandle &handle);
void chunky_scrub(ThreadPool::TPHandle &handle);
return error;
}
-map<pg_shard_t, ScrubMap *>::const_iterator
+list<map<pg_shard_t, ScrubMap *>::const_iterator>
PGBackend::be_select_auth_object(
const hobject_t &obj,
const map<pg_shard_t,ScrubMap*> &maps,
bool okseed,
object_info_t *auth_oi)
{
- map<pg_shard_t, ScrubMap *>::const_iterator auth = maps.end();
+ list<map<pg_shard_t, ScrubMap *>::const_iterator> auth;
for (map<pg_shard_t, ScrubMap *>::const_iterator j = maps.begin();
j != maps.end();
++j) {
<< " for obj " << obj
<< dendl;
*auth_oi = oi;
- auth = j;
+ auth.push_back(j);
}
return auth;
}
bool okseed,
map<hobject_t, set<pg_shard_t> > &missing,
map<hobject_t, set<pg_shard_t> > &inconsistent,
- map<hobject_t, pg_shard_t> &authoritative,
+ map<hobject_t, list<pg_shard_t> > &authoritative,
map<hobject_t, pair<uint32_t,uint32_t> > &missing_digest,
int &shallow_errors, int &deep_errors,
const spg_t& pgid,
k != master_set.end();
++k) {
object_info_t auth_oi;
- map<pg_shard_t, ScrubMap *>::const_iterator auth =
+ list<map<pg_shard_t, ScrubMap *>::const_iterator> auth =
be_select_auth_object(*k, maps, okseed, &auth_oi);
- if (auth == maps.end()) {
+ if (auth.empty()) {
// Something is better than nothing
// TODO: something is NOT better than nothing, do something like
// unfound_lost if no valid copies can be found, or just mark unfound
map<pg_shard_t, ScrubMap *>::const_iterator fallback = maps.begin();
- auth = fallback;
+ auth.push_back(fallback);
dout(10) << __func__ << ": selecting osd " << fallback->first
<< " for obj " << *k
<< ", something is better than nothing, FIXME"
continue;
}
- assert(auth != maps.end());
- ScrubMap::object& auth_object = auth->second->objects[*k];
+ ScrubMap::object& auth_object = auth.back()->second->objects[*k];
set<pg_shard_t> cur_missing;
set<pg_shard_t> cur_inconsistent;
for (j = maps.begin(); j != maps.end(); ++j) {
- if (j == auth)
+ if (j == auth.back())
continue;
if (j->second->objects.count(*k)) {
// Compare
stringstream ss;
enum scrub_error_type error =
- be_compare_scrub_objects(auth->first,
+ be_compare_scrub_objects(auth.back()->first,
auth_object,
auth_oi,
okseed,
else
++deep_errors;
errorstream << __func__ << ": " << pgid << " shard " << j->first
- << ": soid " << *k << " " << ss.str() << std::endl;
+ << ": soid " << *k << " " << ss.str();
}
} else {
cur_missing.insert(j->first);
++shallow_errors;
errorstream << __func__ << ": " << pgid << " shard " << j->first
- << " missing " << *k << std::endl;
+ << " missing " << *k;
}
}
- assert(auth != maps.end());
if (!cur_missing.empty()) {
missing[*k] = cur_missing;
}
inconsistent[*k] = cur_inconsistent;
}
if (!cur_inconsistent.empty() || !cur_missing.empty()) {
- authoritative[*k] = auth->first;
+ list<map<pg_shard_t, ScrubMap *>::const_iterator>::const_iterator i;
+ for (i = auth.begin(); i != auth.end(); i++) {
+ authoritative[*k].push_back((*i)->first);
+ }
}
if (okseed &&
auth_object.digest_present && auth_object.omap_digest_present &&
bool okseed,
const ScrubMap::object &candidate,
ostream &errorstream);
- map<pg_shard_t, ScrubMap *>::const_iterator be_select_auth_object(
+ list<map<pg_shard_t, ScrubMap *>::const_iterator> be_select_auth_object(
const hobject_t &obj,
const map<pg_shard_t,ScrubMap*> &maps,
bool okseed,
bool okseed, ///< true if scrub digests have same seed our oi digests
map<hobject_t, set<pg_shard_t> > &missing,
map<hobject_t, set<pg_shard_t> > &inconsistent,
- map<hobject_t, pg_shard_t> &authoritative,
+ map<hobject_t, list<pg_shard_t> > &authoritative,
map<hobject_t, pair<uint32_t,uint32_t> > &missing_digest,
int &shallow_errors, int &deep_errors,
const spg_t& pgid,