]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ReplicatedPG/PG: check snap collections during _scan_list
authorSamuel Just <sam.just@inktank.com>
Thu, 10 Jan 2013 23:35:10 +0000 (15:35 -0800)
committerSage Weil <sage@inktank.com>
Wed, 23 Jan 2013 14:21:55 +0000 (06:21 -0800)
During _scan_list check the snapcollections corresponding to the
object_info attr on the object.  Report inconsistencies during
scrub_finalize.

Signed-off-by: Samuel Just <sam.just@inktank.com>
(cherry picked from commit 57352351bb86e0ae9f64f9ba0d460c532d882de6)

src/osd/PG.cc
src/osd/PG.h
src/osd/ReplicatedPG.cc
src/osd/ReplicatedPG.h

index 1ce1899bb282a4231f42570fdcf4e8a4d5e0cef5..429720e77a281f18949ac1ffd35a6e97cefb8909 100644 (file)
@@ -3150,6 +3150,7 @@ void PG::_scan_list(ScrubMap &map, vector<hobject_t> &ls, bool deep)
     if (r == 0) {
       ScrubMap::object &o = map.objects[poid];
       o.size = st.st_size;
+      o.nlinks = st.st_nlink;
       assert(!o.negative);
       osd->store->getattrs(coll, poid, o.attrs);
 
@@ -3169,6 +3170,10 @@ void PG::_scan_list(ScrubMap &map, vector<hobject_t> &ls, bool deep)
         o.digest_present = true;
       }
 
+      if (poid.snap != CEPH_SNAPDIR && poid.snap != CEPH_NOSNAP) {
+       // Check snap collections
+       check_snap_collections(poid, o.attrs, &o.snapcolls);
+      }
       dout(25) << "_scan_list  " << poid << dendl;
     } else {
       dout(25) << "_scan_list  " << poid << " got " << r << ", skipping" << dendl;
@@ -4119,6 +4124,7 @@ void PG::_compare_scrubmaps(const map<int,ScrubMap*> &maps,
                            map<hobject_t, set<int> > &missing,
                            map<hobject_t, set<int> > &inconsistent,
                            map<hobject_t, int> &authoritative,
+                           map<hobject_t, set<int> > &invalid_snapcolls,
                            ostream &errorstream)
 {
   map<hobject_t,ScrubMap::object>::const_iterator i;
@@ -4142,6 +4148,18 @@ void PG::_compare_scrubmaps(const map<int,ScrubMap*> &maps,
     set<int> cur_inconsistent;
     for (j = maps.begin(); j != maps.end(); j++) {
       if (j->second->objects.count(*k)) {
+       // Check snapcolls
+       if (k->snap < CEPH_MAXSNAP) {
+         if (_report_snap_collection_errors(
+               *k,
+               j->first,
+               j->second->objects[*k].attrs,
+               j->second->objects[*k].snapcolls,
+               j->second->objects[*k].nlinks,
+               errorstream)) {
+           invalid_snapcolls[*k].insert(j->first);
+         }
+       }
        // Compare
        stringstream ss;
        if (!_compare_scrub_objects(auth->second->objects[*k],
@@ -4198,11 +4216,13 @@ void PG::scrub_compare_maps() {
       scrubber.missing,
       scrubber.inconsistent,
       authoritative,
+      scrubber.inconsistent_snapcolls,
       ss);
     dout(2) << ss.str() << dendl;
 
-    if (authoritative.size())
+    if (authoritative.size() || scrubber.inconsistent_snapcolls.size()) {
       osd->clog.error(ss);
+    }
 
     for (map<hobject_t, int>::iterator i = authoritative.begin();
         i != authoritative.end();
@@ -4223,8 +4243,22 @@ void PG::scrub_process_inconsistent() {
   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"));
-  if (scrubber.authoritative.size()) {
+
+  if (scrubber.authoritative.size() || scrubber.inconsistent.size()) {
     stringstream ss;
+    for (map<hobject_t, set<int> >::iterator obj =
+          scrubber.inconsistent_snapcolls.begin();
+        obj != scrubber.inconsistent_snapcolls.end();
+        ++obj) {
+      for (set<int>::iterator j = obj->second.begin();
+          j != obj->second.end();
+          ++j) {
+       ++scrubber.errors;
+       ss << info.pgid << " " << mode << " " << " object " << obj->first
+          << " has inconsistent snapcolls on " << *j << std::endl;
+      }
+    }
+
     ss << info.pgid << " " << mode << " " << scrubber.missing.size() << " missing, "
        << scrubber.inconsistent.size() << " inconsistent objects\n";
     dout(2) << ss.str() << dendl;
index b2c99b9e3f62d927e60bd22fd4100ec6b41aafd5..4e2c434fc9da97effc0a8b2fafd31c8f45023a87 100644 (file)
@@ -844,6 +844,7 @@ public:
     // Maps from objects with erros to missing/inconsistent peers
     map<hobject_t, set<int> > missing;
     map<hobject_t, set<int> > inconsistent;
+    map<hobject_t, set<int> > inconsistent_snapcolls;
 
     // Map from object with errors to good peer
     map<hobject_t, pair<ScrubMap::object, int> > authoritative;
@@ -966,6 +967,7 @@ public:
                          map<hobject_t, set<int> > &missing,
                          map<hobject_t, set<int> > &inconsistent,
                          map<hobject_t, int> &authoritative,
+                         map<hobject_t, set<int> > &inconsistent_snapcolls,
                          ostream &errorstream);
   void scrub();
   void classic_scrub();
@@ -989,6 +991,17 @@ public:
   virtual void _scrub_finish() { }
   virtual coll_t get_temp_coll() = 0;
   virtual bool have_temp_coll() = 0;
+  virtual bool _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) { return false; };
+  virtual void check_snap_collections(
+    const hobject_t &hoid,
+    const map<string, bufferptr> &attrs,
+    set<snapid_t> *snapcolls) {};
   void clear_scrub_reserved();
   void scrub_reserve_replicas();
   void scrub_unreserve_replicas();
index 9e0c88635de445caf560c9e847c4f3eb7721257c..a487a713e01c50cbc48e90793bd5efc50a0dd1b8 100644 (file)
@@ -7201,6 +7201,68 @@ void ReplicatedPG::_scrub_finish()
   }
 }
 
+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;
+  }
+  return errors;
+}
+
+void ReplicatedPG::check_snap_collections(
+  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) {
+      snapcolls->insert(*i);
+    } else {
+      assert(0);
+    }
+  }
+}
+
 /*---SnapTrimmer Logging---*/
 #undef dout_prefix
 #define dout_prefix *_dout << pg->gen_prefix() 
index fbc1b65571cd301e3735f6989414ef28d0c9715b..f201ffdc9789999422ea1b94e0c174953a4e3a1f 100644 (file)
@@ -929,6 +929,17 @@ protected:
   virtual void _scrub_clear_state();
   virtual void _scrub_finish();
   object_stat_collection_t scrub_cstat;
+  virtual bool _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);
+  virtual void check_snap_collections(
+    const hobject_t &hoid,
+    const map<string, bufferptr> &attrs,
+    set<snapid_t> *snapcolls);
 
   virtual void _split_into(pg_t child_pgid, PG *child, unsigned split_bits);
   void apply_and_flush_repops(bool requeue);