]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: Move the rest of scrubbing routines to the backend
authorDavid Zafman <david.zafman@inktank.com>
Wed, 29 Jan 2014 03:18:32 +0000 (19:18 -0800)
committerDavid Zafman <david.zafman@inktank.com>
Fri, 31 Jan 2014 19:00:22 +0000 (11:00 -0800)
Move enum scrub_error_type to osd_types.h
Move PG::_compare_scrub_objects to ReplicatedBackend::be_compare_scrub_objects
Move PG::_select_auth_object to ReplicatedBackend::be_select_auth_object
Move PG::_compare_scrubmaps to ReplicatedBackend::be_compare_scrubmaps

Signed-off-by: David Zafman <david.zafman@inktank.com>
src/osd/PG.cc
src/osd/PG.h
src/osd/PGBackend.h
src/osd/ReplicatedBackend.cc
src/osd/ReplicatedBackend.h
src/osd/osd_types.h

index 7ca1d1616a2441dcff960cbc5cbb9c6489bac254..4c1d909f00ebd34ec0335f68eb1da0b210627521 100644 (file)
@@ -3750,212 +3750,7 @@ bool PG::scrub_gather_replica_maps()
   }
 }
 
-enum PG::error_type PG::_compare_scrub_objects(ScrubMap::object &auth,
-                               ScrubMap::object &candidate,
-                               ostream &errorstream)
-{
-  enum PG::error_type error = CLEAN;
-  if (candidate.read_error) {
-    // This can occur on stat() of a shallow scrub, but in that case size will
-    // be invalid, and this will be over-ridden below.
-    error = DEEP_ERROR;
-    errorstream << "candidate had a read error";
-  }
-  if (auth.digest_present && candidate.digest_present) {
-    if (auth.digest != candidate.digest) {
-      if (error != CLEAN)
-        errorstream << ", ";
-      error = DEEP_ERROR;
-
-      errorstream << "digest " << candidate.digest
-                  << " != known digest " << auth.digest;
-    }
-  }
-  if (auth.omap_digest_present && candidate.omap_digest_present) {
-    if (auth.omap_digest != candidate.omap_digest) {
-      if (error != CLEAN)
-        errorstream << ", ";
-      error = DEEP_ERROR;
-
-      errorstream << "omap_digest " << candidate.omap_digest
-                  << " != known omap_digest " << auth.omap_digest;
-    }
-  }
-  // Shallow error takes precendence because this will be seen by
-  // both types of scrubs.
-  if (auth.size != candidate.size) {
-    if (error != CLEAN)
-      errorstream << ", ";
-    error = SHALLOW_ERROR;
-    errorstream << "size " << candidate.size 
-               << " != known size " << auth.size;
-  }
-  for (map<string,bufferptr>::const_iterator i = auth.attrs.begin();
-       i != auth.attrs.end();
-       ++i) {
-    if (!candidate.attrs.count(i->first)) {
-      if (error != CLEAN)
-        errorstream << ", ";
-      error = SHALLOW_ERROR;
-      errorstream << "missing attr " << i->first;
-    } else if (candidate.attrs.find(i->first)->second.cmp(i->second)) {
-      if (error != CLEAN)
-        errorstream << ", ";
-      error = SHALLOW_ERROR;
-      errorstream << "attr value mismatch " << i->first;
-    }
-  }
-  for (map<string,bufferptr>::const_iterator i = candidate.attrs.begin();
-       i != candidate.attrs.end();
-       ++i) {
-    if (!auth.attrs.count(i->first)) {
-      if (error != CLEAN)
-        errorstream << ", ";
-      error = SHALLOW_ERROR;
-      errorstream << "extra attr " << i->first;
-    }
-  }
-  return error;
-}
-
-
-
-map<int, ScrubMap *>::const_iterator PG::_select_auth_object(
-  const hobject_t &obj,
-  const map<int,ScrubMap*> &maps)
-{
-  map<int, ScrubMap *>::const_iterator auth = maps.end();
-  for (map<int, ScrubMap *>::const_iterator j = maps.begin();
-       j != maps.end();
-       ++j) {
-    map<hobject_t, ScrubMap::object>::iterator i =
-      j->second->objects.find(obj);
-    if (i == j->second->objects.end()) {
-      continue;
-    }
-    if (auth == maps.end()) {
-      // 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
-      auth = j;
-      dout(10) << __func__ << ": selecting osd " << j->first
-              << " for obj " << obj
-              << ", auth == maps.end()"
-              << dendl;
-      continue;
-    }
-    if (i->second.read_error) {
-      // scrub encountered read error, probably corrupt
-      dout(10) << __func__ << ": rejecting osd " << j->first
-              << " for obj " << obj
-              << ", read_error"
-              << dendl;
-      continue;
-    }
-    map<string, bufferptr>::iterator k = i->second.attrs.find(OI_ATTR);
-    if (k == i->second.attrs.end()) {
-      // no object info on object, probably corrupt
-      dout(10) << __func__ << ": rejecting osd " << j->first
-              << " for obj " << obj
-              << ", no oi attr"
-              << dendl;
-      continue;
-    }
-    bufferlist bl;
-    bl.push_back(k->second);
-    object_info_t oi;
-    try {
-      bufferlist::iterator bliter = bl.begin();
-      ::decode(oi, bliter);
-    } catch (...) {
-      dout(10) << __func__ << ": rejecting osd " << j->first
-              << " for obj " << obj
-              << ", corrupt oi attr"
-              << dendl;
-      // invalid object info, probably corrupt
-      continue;
-    }
-    if (oi.size != i->second.size) {
-      // invalid size, probably corrupt
-      dout(10) << __func__ << ": rejecting osd " << j->first
-              << " for obj " << obj
-              << ", size mismatch"
-              << dendl;
-      // invalid object info, probably corrupt
-      continue;
-    }
-    dout(10) << __func__ << ": selecting osd " << j->first
-            << " for obj " << obj
-            << dendl;
-    auth = j;
-  }
-  return auth;
-}
-
-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;
-  map<int, ScrubMap *>::const_iterator j;
-  set<hobject_t> master_set;
-
-  // Construct master set
-  for (j = maps.begin(); j != maps.end(); ++j) {
-    for (i = j->second->objects.begin(); i != j->second->objects.end(); ++i) {
-      master_set.insert(i->first);
-    }
-  }
 
-  // Check maps against master set and each other
-  for (set<hobject_t>::const_iterator k = master_set.begin();
-       k != master_set.end();
-       ++k) {
-    map<int, ScrubMap *>::const_iterator auth = _select_auth_object(*k, maps);
-    assert(auth != maps.end());
-    set<int> cur_missing;
-    set<int> cur_inconsistent;
-    for (j = maps.begin(); j != maps.end(); ++j) {
-      if (j == auth)
-       continue;
-      if (j->second->objects.count(*k)) {
-       // Compare
-       stringstream ss;
-       enum PG::error_type error = _compare_scrub_objects(auth->second->objects[*k],
-           j->second->objects[*k],
-           ss);
-        if (error != CLEAN) {
-         cur_inconsistent.insert(j->first);
-          if (error == SHALLOW_ERROR)
-           ++scrubber.shallow_errors;
-          else
-           ++scrubber.deep_errors;
-         errorstream << info.pgid << " osd." << acting[j->first]
-                     << ": soid " << *k << " " << ss.str() << std::endl;
-       }
-      } else {
-       cur_missing.insert(j->first);
-       ++scrubber.shallow_errors;
-       errorstream << info.pgid
-                   << " osd." << acting[j->first] 
-                   << " missing " << *k << std::endl;
-      }
-    }
-    assert(auth != maps.end());
-    if (!cur_missing.empty()) {
-      missing[*k] = cur_missing;
-    }
-    if (!cur_inconsistent.empty()) {
-      inconsistent[*k] = cur_inconsistent;
-    }
-    if (!cur_inconsistent.empty() || !cur_missing.empty()) {
-      authoritative[*k] = auth->first;
-    }
-  }
-}
 
 void PG::scrub_compare_maps() 
 {
@@ -3982,12 +3777,15 @@ void PG::scrub_compare_maps()
       maps[i] = &scrubber.received_maps[acting[i]];
     }
 
-    _compare_scrubmaps(
+    get_pgbackend()->be_compare_scrubmaps(
       maps,
       scrubber.missing,
       scrubber.inconsistent,
       authoritative,
       scrubber.inconsistent_snapcolls,
+      scrubber.shallow_errors,
+      scrubber.deep_errors,
+      info.pgid, acting,
       ss);
     dout(2) << ss.str() << dendl;
 
index af2a3ce19bb8acb5c2e98ce97b1b310110cfbd34..23c84fddf1629b7a6ece8f8406309f3d2b043a5b 100644 (file)
@@ -939,24 +939,6 @@ public:
   int active_pushes;
 
   void repair_object(const hobject_t& soid, ScrubMap::object *po, int bad_peer, int ok_peer);
-  map<int, ScrubMap *>::const_iterator _select_auth_object(
-    const hobject_t &obj,
-    const map<int,ScrubMap*> &maps);
-
-  enum error_type {
-    CLEAN,
-    DEEP_ERROR,
-    SHALLOW_ERROR
-  };
-  enum error_type _compare_scrub_objects(ScrubMap::object &auth,
-                             ScrubMap::object &candidate,
-                             ostream &errorstream);
-  void _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> > &inconsistent_snapcolls,
-                         ostream &errorstream);
   void scrub(ThreadPool::TPHandle &handle);
   void classic_scrub(ThreadPool::TPHandle &handle);
   void chunky_scrub(ThreadPool::TPHandle &handle);
index d380f5a044893f4034dcb57e566dbb0420242438..52b14908a62b03d28063be7a3b2dfb5ee4e49458 100644 (file)
    virtual bool scrub_supported() { return false; }
    virtual void be_scan_list(ScrubMap &map, vector<hobject_t> &ls, bool deep,
      ThreadPool::TPHandle &handle) { assert(0); }
+   virtual enum scrub_error_type be_compare_scrub_objects(
+                               ScrubMap::object &auth,
+                               ScrubMap::object &candidate,
+                               ostream &errorstream) { assert(0); }
+   virtual map<int, ScrubMap *>::const_iterator be_select_auth_object(
+     const hobject_t &obj,
+     const map<int,ScrubMap*> &maps) { assert(0); }
+   virtual void be_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,
+                           int &shallow_errors, int &deep_errors,
+                           const pg_t pgid,
+                           const vector<int> &acting,
+                           ostream &errorstream) { assert(0); }
  };
 
 #endif
index 92b019abf9c3cc74b5224ac344133b7cd083cca5..81f74c12d4bfa9c84041a47826b840418bd877bb 100644 (file)
@@ -867,3 +867,213 @@ void ReplicatedBackend::be_scan_list(
     }
   }
 }
+
+enum scrub_error_type ReplicatedBackend::be_compare_scrub_objects(
+                               ScrubMap::object &auth,
+                               ScrubMap::object &candidate,
+                               ostream &errorstream)
+{
+  enum scrub_error_type error = CLEAN;
+  if (candidate.read_error) {
+    // This can occur on stat() of a shallow scrub, but in that case size will
+    // be invalid, and this will be over-ridden below.
+    error = DEEP_ERROR;
+    errorstream << "candidate had a read error";
+  }
+  if (auth.digest_present && candidate.digest_present) {
+    if (auth.digest != candidate.digest) {
+      if (error != CLEAN)
+        errorstream << ", ";
+      error = DEEP_ERROR;
+
+      errorstream << "digest " << candidate.digest
+                  << " != known digest " << auth.digest;
+    }
+  }
+  if (auth.omap_digest_present && candidate.omap_digest_present) {
+    if (auth.omap_digest != candidate.omap_digest) {
+      if (error != CLEAN)
+        errorstream << ", ";
+      error = DEEP_ERROR;
+
+      errorstream << "omap_digest " << candidate.omap_digest
+                  << " != known omap_digest " << auth.omap_digest;
+    }
+  }
+  // Shallow error takes precendence because this will be seen by
+  // both types of scrubs.
+  if (auth.size != candidate.size) {
+    if (error != CLEAN)
+      errorstream << ", ";
+    error = SHALLOW_ERROR;
+    errorstream << "size " << candidate.size
+               << " != known size " << auth.size;
+  }
+  for (map<string,bufferptr>::const_iterator i = auth.attrs.begin();
+       i != auth.attrs.end();
+       ++i) {
+    if (!candidate.attrs.count(i->first)) {
+      if (error != CLEAN)
+        errorstream << ", ";
+      error = SHALLOW_ERROR;
+      errorstream << "missing attr " << i->first;
+    } else if (candidate.attrs.find(i->first)->second.cmp(i->second)) {
+      if (error != CLEAN)
+        errorstream << ", ";
+      error = SHALLOW_ERROR;
+      errorstream << "attr value mismatch " << i->first;
+    }
+  }
+  for (map<string,bufferptr>::const_iterator i = candidate.attrs.begin();
+       i != candidate.attrs.end();
+       ++i) {
+    if (!auth.attrs.count(i->first)) {
+      if (error != CLEAN)
+        errorstream << ", ";
+      error = SHALLOW_ERROR;
+      errorstream << "extra attr " << i->first;
+    }
+  }
+  return error;
+}
+
+map<int, ScrubMap *>::const_iterator ReplicatedBackend::be_select_auth_object(
+  const hobject_t &obj,
+  const map<int,ScrubMap*> &maps)
+{
+  map<int, ScrubMap *>::const_iterator auth = maps.end();
+  for (map<int, ScrubMap *>::const_iterator j = maps.begin();
+       j != maps.end();
+       ++j) {
+    map<hobject_t, ScrubMap::object>::iterator i =
+      j->second->objects.find(obj);
+    if (i == j->second->objects.end()) {
+      continue;
+    }
+    if (auth == maps.end()) {
+      // 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
+      auth = j;
+      dout(10) << __func__ << ": selecting osd " << j->first
+              << " for obj " << obj
+              << ", auth == maps.end()"
+              << dendl;
+      continue;
+    }
+    if (i->second.read_error) {
+      // scrub encountered read error, probably corrupt
+      dout(10) << __func__ << ": rejecting osd " << j->first
+              << " for obj " << obj
+              << ", read_error"
+              << dendl;
+      continue;
+    }
+    map<string, bufferptr>::iterator k = i->second.attrs.find(OI_ATTR);
+    if (k == i->second.attrs.end()) {
+      // no object info on object, probably corrupt
+      dout(10) << __func__ << ": rejecting osd " << j->first
+              << " for obj " << obj
+              << ", no oi attr"
+              << dendl;
+      continue;
+    }
+    bufferlist bl;
+    bl.push_back(k->second);
+    object_info_t oi;
+    try {
+      bufferlist::iterator bliter = bl.begin();
+      ::decode(oi, bliter);
+    } catch (...) {
+      dout(10) << __func__ << ": rejecting osd " << j->first
+              << " for obj " << obj
+              << ", corrupt oi attr"
+              << dendl;
+      // invalid object info, probably corrupt
+      continue;
+    }
+    if (oi.size != i->second.size) {
+      // invalid size, probably corrupt
+      dout(10) << __func__ << ": rejecting osd " << j->first
+              << " for obj " << obj
+              << ", size mismatch"
+              << dendl;
+      // invalid object info, probably corrupt
+      continue;
+    }
+    dout(10) << __func__ << ": selecting osd " << j->first
+            << " for obj " << obj
+            << dendl;
+    auth = j;
+  }
+  return auth;
+}
+
+void ReplicatedBackend::be_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,
+                           int &shallow_errors,
+                           int &deep_errors,
+                           const pg_t pgid,
+                           const vector<int> &acting,
+                           ostream &errorstream)
+{
+  map<hobject_t,ScrubMap::object>::const_iterator i;
+  map<int, ScrubMap *>::const_iterator j;
+  set<hobject_t> master_set;
+
+  // Construct master set
+  for (j = maps.begin(); j != maps.end(); ++j) {
+    for (i = j->second->objects.begin(); i != j->second->objects.end(); ++i) {
+      master_set.insert(i->first);
+    }
+  }
+
+  // Check maps against master set and each other
+  for (set<hobject_t>::const_iterator k = master_set.begin();
+       k != master_set.end();
+       ++k) {
+    map<int, ScrubMap *>::const_iterator auth = be_select_auth_object(*k, maps);
+    assert(auth != maps.end());
+    set<int> cur_missing;
+    set<int> cur_inconsistent;
+    for (j = maps.begin(); j != maps.end(); ++j) {
+      if (j == auth)
+       continue;
+      if (j->second->objects.count(*k)) {
+       // Compare
+       stringstream ss;
+       enum scrub_error_type error = be_compare_scrub_objects(auth->second->objects[*k],
+           j->second->objects[*k],
+           ss);
+        if (error != CLEAN) {
+         cur_inconsistent.insert(j->first);
+          if (error == SHALLOW_ERROR)
+           ++shallow_errors;
+          else
+           ++deep_errors;
+         errorstream << pgid << " osd." << acting[j->first]
+                     << ": soid " << *k << " " << ss.str() << std::endl;
+       }
+      } else {
+       cur_missing.insert(j->first);
+       ++shallow_errors;
+       errorstream << pgid
+                   << " osd." << acting[j->first]
+                   << " missing " << *k << std::endl;
+      }
+    }
+    assert(auth != maps.end());
+    if (!cur_missing.empty()) {
+      missing[*k] = cur_missing;
+    }
+    if (!cur_inconsistent.empty()) {
+      inconsistent[*k] = cur_inconsistent;
+    }
+    if (!cur_inconsistent.empty() || !cur_missing.empty()) {
+      authoritative[*k] = auth->first;
+    }
+  }
+}
index c53b5de911127ed8137db06cabbf9623b4c169a2..324607234b205d42e4021b619495fc0cda85d766 100644 (file)
@@ -492,6 +492,22 @@ private:
   bool scrub_supported() { return true; }
   void be_scan_list(ScrubMap &map, vector<hobject_t> &ls, bool deep,
     ThreadPool::TPHandle &handle);
+  enum scrub_error_type be_compare_scrub_objects(
+                               ScrubMap::object &auth,
+                               ScrubMap::object &candidate,
+                               ostream &errorstream);
+  map<int, ScrubMap *>::const_iterator be_select_auth_object(
+    const hobject_t &obj,
+    const map<int,ScrubMap*> &maps);
+  void be_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,
+                           int &shallow_errors, int &deep_errors,
+                           const pg_t pgid,
+                           const vector<int> &acting,
+                           ostream &errorstream);
 };
 
 #endif
index e8252046041cff0adddd6fdb4358b7dc213a2d04..e2a4822a2c497639ca835e9d487d65c539681148 100644 (file)
@@ -3082,4 +3082,9 @@ struct obj_list_snap_response_t {
 
 WRITE_CLASS_ENCODER(obj_list_snap_response_t)
 
+enum scrub_error_type {
+  CLEAN,
+  DEEP_ERROR,
+  SHALLOW_ERROR
+};
 #endif