]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: verify object version during push
authorSage Weil <sage.weil@dreamhost.com>
Tue, 22 Feb 2011 20:20:40 +0000 (12:20 -0800)
committerSage Weil <sage.weil@dreamhost.com>
Tue, 22 Feb 2011 20:20:40 +0000 (12:20 -0800)
Fail to push if the ondisk version doesn't match the version we want to
send.

This isn't supposed to happen. If it does it means we have a bug somewhere
else.  Log something to the error log and don't push.  This is better than
the current behavior, which goes into a loop (repeatedly pulling the object
and retrying when it's not the right version).

Signed-off-by: Sage Weil <sage.weil@dreamhost.com>
src/osd/ReplicatedPG.cc
src/osd/ReplicatedPG.h

index cbe29e2257da8692179850980217a11ec003ebe1..9d142640ef91787c27d1e329f742f4b3e4584148 100644 (file)
@@ -3386,7 +3386,7 @@ void ReplicatedPG::push_start(const sobject_t& soid, int peer,
 
   dout(10) << "push_start " << soid << " size " << size << " data " << data_subset
           << " cloning " << clone_subsets << dendl;    
-  send_push_op(soid, peer, size, true, complete, pi->data_subset_pushing, pi->clone_subsets);
+  send_push_op(soid, version, peer, size, true, complete, pi->data_subset_pushing, pi->clone_subsets);
 }
 
 
@@ -3394,7 +3394,7 @@ void ReplicatedPG::push_start(const sobject_t& soid, int peer,
  * push - send object to a peer
  */
 
-void ReplicatedPG::send_push_op(const sobject_t& soid, int peer, 
+void ReplicatedPG::send_push_op(const sobject_t& soid, eversion_t version, int peer, 
                                uint64_t size, bool first, bool complete,
                                interval_set<uint64_t> &data_subset,
                                map<sobject_t, interval_set<uint64_t> >& clone_subsets)
@@ -3423,6 +3423,12 @@ void ReplicatedPG::send_push_op(const sobject_t& soid, int peer,
   bv.push_back(attrset[OI_ATTR]);
   object_info_t oi(bv);
 
+  if (oi.version != version) {
+    osd->clog.error() << "push " << soid << " v " << version << " to osd" << peer
+                     << " failed because local copy is " << oi.version << "\n";
+    return;
+  }
+
   // ok
   dout(7) << "send_push_op " << soid << " v " << oi.version 
          << " size " << size
@@ -3482,7 +3488,8 @@ void ReplicatedPG::sub_op_push_reply(MOSDSubOpReply *reply)
       pi->data_subset_pushing.span_of(pi->data_subset, from, g_conf.osd_recovery_max_chunk);
       dout(10) << " pushing more, " << pi->data_subset_pushing << " of " << pi->data_subset << dendl;
       complete = pi->data_subset.range_end() == pi->data_subset_pushing.range_end();
-      send_push_op(soid, peer, pi->size, false, complete, pi->data_subset_pushing, pi->clone_subsets);
+      send_push_op(soid, pi->version, peer, pi->size, false, complete,
+                  pi->data_subset_pushing, pi->clone_subsets);
     } else {
       // done!
       peer_missing[peer].got(soid, pi->version);
@@ -3543,7 +3550,7 @@ void ReplicatedPG::sub_op_pull(MOSDSubOp *op)
     // complete==false means nothing.  we don't know because the primary may
     // not be pulling the entire object.
 
-    send_push_op(soid, op->get_source().num(), size, op->first, complete, op->data_subset, op->clone_subsets);
+    send_push_op(soid, op->version, op->get_source().num(), size, op->first, complete, op->data_subset, op->clone_subsets);
   }
   op->put();
 }
index b89c5aa0c080f1bfd9d74cc3e1e2b9093d793ba6..5079f0b8ed2fb958da50f32e7650a439c3f7ad63 100644 (file)
@@ -525,7 +525,7 @@ protected:
                  uint64_t size, eversion_t version,
                  interval_set<uint64_t> &data_subset,
                  map<sobject_t, interval_set<uint64_t> >& clone_subsets);
-  void send_push_op(const sobject_t& oid, int dest,
+  void send_push_op(const sobject_t& oid, eversion_t version, int dest,
                    uint64_t size, bool first, bool complete,
                    interval_set<uint64_t>& data_subset, 
                    map<sobject_t, interval_set<uint64_t> >& clone_subsets);