vector<snapid_t>::reverse_iterator curclone; // Defined only if snapset initialized
unsigned missing = 0;
inconsistent_snapset_wrapper soid_error, head_error;
+ unsigned soid_error_count = 0;
for (map<hobject_t,ScrubMap::object>::reverse_iterator
p = scrubmap.objects.rbegin(); p != scrubmap.objects.rend(); ++p) {
++scrubber.shallow_errors;
soid_error.set_headless();
scrubber.store->add_snap_error(pool.id, soid_error);
+ ++soid_error_count;
if (head && soid.get_head() == head->get_head())
head_error.set_clone(soid.snap);
continue;
}
// Save previous head error information
- if (head && head_error.errors)
+ if (head && (head_error.errors || soid_error_count))
scrubber.store->add_snap_error(pool.id, head_error);
// Set this as a new head object
head = soid;
missing = 0;
head_error = soid_error;
+ soid_error_count = 0;
dout(20) << __func__ << " " << mode << " new head " << head << dendl;
try {
snapset = SnapSet(); // Initialize optional<> before decoding into it
decode(snapset.get(), blp);
+ head_error.ss_bl.push_back(p->second.attrs[SS_ATTR]);
} catch (buffer::error& e) {
snapset = boost::none;
osd->clog->error() << mode << " " << info.pgid << " " << soid
// what's next?
++curclone;
- if (soid_error.errors)
+ if (soid_error.errors) {
scrubber.store->add_snap_error(pool.id, soid_error);
+ ++soid_error_count;
+ }
}
scrub_cstat.add(stat);
log_missing(missing, head, osd->clog, info.pgid, __func__,
mode, pool.info.allow_incomplete_clones());
}
- if (head && head_error.errors)
+ if (head && (head_error.errors || soid_error_count))
scrubber.store->add_snap_error(pool.id, head_error);
for (auto p = missing_digest.begin(); p != missing_digest.end(); ++p) {
{
dump_object_id(inc.object, f);
+ if (inc.ss_bl.length()) {
+ SnapSet ss;
+ bufferlist bl = inc.ss_bl;
+ bufferlist::iterator bliter = bl.begin();
+ decode(ss, bliter); // Can't be corrupted
+ f.open_object_section("snapset");
+ ss.dump(&f);
+ f.close_section();
+ }
f.open_array_section("errors");
if (inc.snapset_missing())
f.dump_string("error", "snapset_missing");