summaryrefslogtreecommitdiff
path: root/src/osd/ReplicatedPG.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/ReplicatedPG.cc')
-rw-r--r--src/osd/ReplicatedPG.cc85
1 files changed, 81 insertions, 4 deletions
diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc
index 6446717e2a5..92df99778c6 100644
--- a/src/osd/ReplicatedPG.cc
+++ b/src/osd/ReplicatedPG.cc
@@ -5738,7 +5738,8 @@ void ReplicatedPG::on_change()
scrub_clear_state();
} else if (is_scrubbing()) {
state_clear(PG_STATE_SCRUBBING);
- state_clear(PG_STATE_REPAIR);
+ must_scrub = false;
+ must_repair = false;
}
context_registry_on_change();
@@ -6461,7 +6462,7 @@ int ReplicatedPG::_scrub(ScrubMap& scrubmap, int& errors, int& fixed)
dout(10) << "_scrub" << dendl;
coll_t c(info.pgid);
- bool repair = state_test(PG_STATE_REPAIR);
+ bool repair = must_repair;
const char *mode = repair ? "repair":"scrub";
// traverse in reverse order.
@@ -6563,10 +6564,15 @@ int ReplicatedPG::_scrub(ScrubMap& scrubmap, int& errors, int& fixed)
}
} else if (soid.snap) {
// it's a clone
- assert(head != hobject_t());
-
stat.num_object_clones++;
+ if (head == hobject_t()) {
+ osd->clog.error() << mode << " " << info.pgid << " " << soid
+ << " found clone without head";
+ ++errors;
+ continue;
+ }
+
if (soid.snap != *curclone) {
osd->clog.error() << mode << " " << info.pgid << " " << soid
<< " expected clone " << *curclone;
@@ -6628,6 +6634,77 @@ int ReplicatedPG::_scrub(ScrubMap& scrubmap, int& errors, int& fixed)
return errors;
}
+static set<snapid_t> get_expected_snap_colls(
+ const map<string, bufferptr> &attrs,
+ object_info_t *oi = 0)
+{
+ object_info_t _oi;
+ if (!oi)
+ oi = &_oi;
+
+ set<snapid_t> to_check;
+ map<string, bufferptr>::const_iterator oiiter = attrs.find(OI_ATTR);
+ if (oiiter == attrs.end())
+ return to_check;
+
+ bufferlist oiattr;
+ oiattr.push_back(oiiter->second);
+ *oi = object_info_t(oiattr);
+ if (oi->snaps.size() > 0)
+ to_check.insert(*(oi->snaps.begin()));
+ if (oi->snaps.size() > 1)
+ to_check.insert(*(oi->snaps.rbegin()));
+ return to_check;
+}
+
+bool ReplicatedPG::_report_snap_collection_errors(
+ const hobject_t &hoid,
+ int osd,
+ const map<string, bufferptr> &attrs,
+ const set<snapid_t> &snapcolls,
+ uint32_t nlinks,
+ ostream &out)
+{
+ bool errors = false;
+ set<snapid_t> to_check = get_expected_snap_colls(attrs);
+ if (to_check != snapcolls) {
+ out << info.pgid << " osd." << osd << " inconsistent snapcolls on "
+ << hoid << " found " << snapcolls << " expected " << to_check
+ << std::endl;
+ errors = true;
+ }
+ if (nlinks != snapcolls.size() + 1) {
+ out << info.pgid << " osd." << osd << " unaccounted for links on object "
+ << hoid << " snapcolls " << snapcolls << " nlinks " << nlinks
+ << std::endl;
+ errors = true;
+ }
+ return errors;
+}
+
+void ReplicatedPG::check_snap_collections(
+ ino_t hino,
+ const hobject_t &hoid,
+ const map<string, bufferptr> &attrs,
+ set<snapid_t> *snapcolls)
+{
+ object_info_t oi;
+ set<snapid_t> to_check = get_expected_snap_colls(attrs, &oi);
+
+ for (set<snapid_t>::iterator i = to_check.begin(); i != to_check.end(); ++i) {
+ struct stat st;
+ int r = osd->store->stat(coll_t(info.pgid, *i), hoid, &st);
+ if (r == -ENOENT) {
+ } else if (r == 0) {
+ if (hino == st.st_ino) {
+ snapcolls->insert(*i);
+ }
+ } else {
+ assert(0);
+ }
+ }
+}
+
/*---SnapTrimmer Logging---*/
#undef dout_prefix
#define dout_prefix *_dout << pg->gen_prefix()