]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: copy the reqids even if the object is deleted during promotion
authorZhiqiang Wang <zhiqiang.wang@intel.com>
Wed, 10 Jun 2015 06:21:36 +0000 (14:21 +0800)
committerSamuel Just <sjust@redhat.com>
Tue, 18 Aug 2015 18:25:24 +0000 (11:25 -0700)
If the object is deleted on the base tier, and the reqids are not copied
during promotion, this again leads to the 'ops not idempotent' problem.
For the copy-get op, this fix copies the reqids even if the object doesn't
exist.

Signed-off-by: Zhiqiang Wang <zhiqiang.wang@intel.com>
src/osd/ReplicatedPG.cc
src/osd/ReplicatedPG.h
src/osdc/Objecter.h

index 224454a8ab4b2546b5c51be34308e046589a9218..329cc67dfc84e077ec1081d0c5b24875f7719f77 100644 (file)
@@ -1567,6 +1567,17 @@ void ReplicatedPG::do_op(OpRequestRef& op)
     return;
 
   if (r && (r != -ENOENT || !obc)) {
+    // copy the reqids for copy get on ENOENT
+    if (r == -ENOENT &&
+       (m->ops[0].op.op == CEPH_OSD_OP_COPY_GET_CLASSIC ||
+        m->ops[0].op.op == CEPH_OSD_OP_COPY_GET)) {
+      bool classic = false;
+      if (m->ops[0].op.op == CEPH_OSD_OP_COPY_GET_CLASSIC) {
+       classic = true;
+      }
+      fill_in_copy_get_noent(op, oid, m->ops[0], classic);
+      return;
+    }
     dout(20) << __func__ << "find_object_context got error " << r << dendl;
     osd->reply_op_error(op, r);
     return;
@@ -1760,6 +1771,17 @@ void ReplicatedPG::do_op(OpRequestRef& op)
       (!obc->obs.exists ||
        ((m->get_snapid() != CEPH_SNAPDIR) &&
        obc->obs.oi.is_whiteout()))) {
+    // copy the reqids for copy get on ENOENT
+    if (m->ops[0].op.op == CEPH_OSD_OP_COPY_GET_CLASSIC ||
+       m->ops[0].op.op == CEPH_OSD_OP_COPY_GET) {
+      bool classic = false;
+      if (m->ops[0].op.op == CEPH_OSD_OP_COPY_GET_CLASSIC) {
+       classic = true;
+      }
+      fill_in_copy_get_noent(op, oid, m->ops[0], classic);
+      close_op_ctx(ctx, -ENOENT);
+      return;
+    }
     reply_ctx(ctx, -ENOENT);
     return;
   }
@@ -6382,6 +6404,28 @@ int ReplicatedPG::fill_in_copy_get(
   return result;
 }
 
+void ReplicatedPG::fill_in_copy_get_noent(OpRequestRef& op, hobject_t oid,
+                                          OSDOp& osd_op, bool classic)
+{
+  MOSDOp *m = static_cast<MOSDOp*>(op->get_req());
+  uint64_t features = m->get_features();
+  object_copy_data_t reply_obj;
+
+  pg_log.get_log().get_object_reqids(oid, 10, &reply_obj.reqids);
+  dout(20) << __func__ << " got reqids " << reply_obj.reqids << dendl;
+  if (classic) {
+    reply_obj.encode_classic(osd_op.outdata);
+  } else {
+    ::encode(reply_obj, osd_op.outdata, features);
+  }
+  osd_op.rval = -ENOENT;
+  MOSDOpReply *reply = new MOSDOpReply(m, 0, get_osdmap()->get_epoch(), 0, false);
+  reply->claim_op_out_data(m->ops);
+  reply->set_result(-ENOENT);
+  reply->add_flags(CEPH_OSD_FLAG_ACK | CEPH_OSD_FLAG_ONDISK);
+  osd->send_message_osd_client(reply, m->get_connection());
+}
+
 void ReplicatedPG::start_copy(CopyCallback *cb, ObjectContextRef obc,
                              hobject_t src, object_locator_t oloc,
                              version_t version, unsigned flags,
index cc3ce84a4b1a82c2ab468c7b07c9b6fc9cbfc21c..81f5130fa86d2d5c0b7da9e85596e871c140c137 100644 (file)
@@ -1354,6 +1354,8 @@ protected:
     OSDOp& op,
     ObjectContextRef& obc,
     bool classic);
+  void fill_in_copy_get_noent(OpRequestRef& op, hobject_t oid,
+                              OSDOp& osd_op, bool classic);
 
   /**
    * To copy an object, call start_copy.
index 3e514e3e8e48cca0b44127201925b055f16f04b3..d3688afbe821ba1db3f02dc73779d3a9769779c5 100644 (file)
@@ -654,12 +654,18 @@ struct ObjectOperation {
        out_flags(flags), out_data_digest(dd), out_omap_digest(od),
         out_reqids(oreqids), prval(r) {}
     void finish(int r) {
-      if (r < 0)
+      // reqids are copied on ENOENT
+      if (r < 0 && r != -ENOENT)
        return;
       try {
        bufferlist::iterator p = bl.begin();
        object_copy_data_t copy_reply;
        ::decode(copy_reply, p);
+       if (r == -ENOENT) {
+         if (out_reqids)
+           *out_reqids = copy_reply.reqids;
+         return;
+       }
        if (out_size)
          *out_size = copy_reply.size;
        if (out_mtime)