]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
PG: check and repair snap_mapper entries during scrub
authorSamuel Just <sam.just@inktank.com>
Mon, 4 Mar 2013 20:37:46 +0000 (12:37 -0800)
committerSamuel Just <sam.just@inktank.com>
Thu, 14 Mar 2013 02:45:13 +0000 (19:45 -0700)
Signed-off-by: Samuel Just <sam.just@inktank.com>
src/osd/PG.cc
src/osd/PG.h

index b4b298144aa17beb76f28395b14983b9a7d12412..75dfe051db8e4286b09c2148e77088f1db299729 100644 (file)
@@ -3139,7 +3139,6 @@ 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);
 
@@ -3340,6 +3339,76 @@ void PG::scrub_unreserve_replicas()
   }
 }
 
+void PG::_scan_snaps(ScrubMap &smap) {
+  for (map<hobject_t, ScrubMap::object>::iterator i = smap.objects.begin();
+       i != smap.objects.end();
+       ++i) {
+    const hobject_t &hoid = i->first;
+    ScrubMap::object &o = i->second;
+
+    if (hoid.snap < CEPH_MAXSNAP) {
+      // fake nlinks for old primaries
+      bufferlist bl;
+      bl.push_back(o.attrs[OI_ATTR]);
+      object_info_t oi(bl);
+      if (oi.snaps.empty()) {
+       // Just head
+       o.nlinks = 1;
+      } else if (oi.snaps.size() == 1) {
+       // Just head + only snap
+       o.nlinks = 2;
+      } else {
+       // Just head + 1st and last snaps
+       o.nlinks = 3;
+      }
+
+      // check and if necessary fix snap_mapper
+      set<snapid_t> oi_snaps(oi.snaps.begin(), oi.snaps.end());
+      set<snapid_t> cur_snaps;
+      int r = snap_mapper.get_snaps(hoid, &cur_snaps);
+      if (r != 0 && r != -ENOENT) {
+       derr << __func__ << ": get_snaps returned " << cpp_strerror(r) << dendl;
+       assert(0);
+      }
+      if (r == -ENOENT || cur_snaps != oi_snaps) {
+       ObjectStore::Transaction t;
+       OSDriver::OSTransaction _t(osdriver.get_transaction(&t));
+       if (r == 0) {
+         r = snap_mapper.remove_oid(hoid, &_t);
+         if (r != 0) {
+           derr << __func__ << ": remove_oid returned " << cpp_strerror(r)
+                << dendl;
+           assert(0);
+         }
+         osd->clog.error() << "osd." << osd->whoami
+                           << " found snap mapper error on pg "
+                           << info.pgid
+                           << " oid " << hoid << " snaps in mapper: "
+                           << cur_snaps << ", oi: "
+                           << oi_snaps
+                           << "...repaired";
+       } else {
+         osd->clog.error() << "osd." << osd->whoami
+                           << " found snap mapper error on pg "
+                           << info.pgid
+                           << " oid " << hoid << " snaps missing in mapper"
+                           << ", should be: "
+                           << oi_snaps
+                           << "...repaired";
+       }
+       snap_mapper.add_oid(hoid, oi_snaps, &_t);
+       r = osd->store->apply_transaction(t);
+       if (r != 0) {
+         derr << __func__ << ": apply_transaction got " << cpp_strerror(r)
+              << dendl;
+       }
+      }
+    } else {
+      o.nlinks = 1;
+    }
+  }
+}
+
 /*
  * build a scrub map over a chunk without releasing the lock
  * only used by chunky scrub
@@ -3361,6 +3430,7 @@ int PG::build_scrub_map_chunk(ScrubMap &map,
   }
 
   _scan_list(map, ls, deep);
+  _scan_snaps(map);
 
   // pg attrs
   osd->store->collection_getattrs(coll, map.attrs);
@@ -3395,6 +3465,7 @@ void PG::build_scrub_map(ScrubMap &map)
 
   _scan_list(map, ls, false);
   lock();
+  _scan_snaps(map);
 
   if (pg_has_reset_since(epoch)) {
     dout(10) << "scrub  pg changed, aborting" << dendl;
index 0488a7ebaa98b75d096842bf30fe65956d101f02..658eb2d0ac932b9e3696235f65e0075f1ec3652c 100644 (file)
@@ -1017,6 +1017,7 @@ public:
   void scrub_clear_state();
   bool scrub_gather_replica_maps();
   void _scan_list(ScrubMap &map, vector<hobject_t> &ls, bool deep);
+  void _scan_snaps(ScrubMap &map);
   void _request_scrub_map_classic(int replica, eversion_t version);
   void _request_scrub_map(int replica, eversion_t version,
                           hobject_t start, hobject_t end, bool deep);