]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
OSD: introduce require_up_osd_peer() function for gating replica ops
authorGreg Farnum <greg@inktank.com>
Tue, 22 Jul 2014 23:57:00 +0000 (16:57 -0700)
committerSage Weil <sage@redhat.com>
Tue, 12 Aug 2014 22:25:27 +0000 (15:25 -0700)
This checks both that a Message originates from an OSD, and that the OSD
is up in the given map epoch.
We use it in handle_replica_op so that we don't inadvertently add operations
from down peers, who might or might not know it.

Signed-off-by: Greg Farnum <greg@inktank.com>
(cherry picked from commit ccd0eec50103b919b3eb6eea96f7dc6438520ed3)

src/osd/OSD.cc
src/osd/OSD.h

index 5c8f0d68b833494807894d95ffc8619b92774cba..3ccedcb3e83774a754af776b9f09d15a23d73c4d 100644 (file)
@@ -6137,6 +6137,36 @@ bool OSD::require_osd_peer(OpRequestRef op)
   return true;
 }
 
+bool OSD::require_up_osd_peer(OpRequestRef& op, OSDMapRef& map,
+                              epoch_t their_epoch)
+{
+  int from = op->get_req()->get_source().num();
+  if (!require_osd_peer(op)) {
+    return false;
+  } else if (map->get_epoch() >= their_epoch &&
+      (!map->have_inst(from) ||
+      map->get_cluster_addr(from) != op->get_req()->get_source_inst().addr)) {
+    dout(0) << "require_osd_peer_up received from non-up osd "
+            << op->get_req()->get_connection()->get_peer_addr()
+            << " " << *op->get_req() << dendl;
+
+    ConnectionRef con = op->get_req()->get_connection();
+    cluster_messenger->mark_down(con.get());
+    Session *s = static_cast<Session*>(con->get_priv());
+    if (s) {
+      s->session_dispatch_lock.Lock();
+      clear_session_waiting_on_map(s);
+      con->set_priv(NULL);   // break ref <-> session cycle, if any
+      s->session_dispatch_lock.Unlock();
+      s->put();
+    }
+
+    return false;
+  }
+
+  return true;
+}
+
 /*
  * require that we have same (or newer) map, and that
  * the source is the pg primary.
@@ -7555,7 +7585,7 @@ void OSD::handle_replica_op(OpRequestRef op)
     return;
   }
 
-  if (!require_osd_peer(op))
+  if (!require_up_osd_peer(op, osdmap, m->map_epoch))
     return;
 
   // must be a rep op.
index ae8d74edd92f986c1cae9e715cd25c434cc512c0..080be8c13f4e172859f00630865578b6bc4b9a20 100644 (file)
@@ -1514,6 +1514,8 @@ protected:
 
   bool require_mon_peer(Message *m);
   bool require_osd_peer(OpRequestRef op);
+  bool require_up_osd_peer(OpRequestRef& Op, OSDMapRef& map,
+                           epoch_t their_epoch);
 
   bool require_same_or_newer_map(OpRequestRef op, epoch_t e);