From: Zhiqiang Wang Date: Wed, 10 Jun 2015 06:21:36 +0000 (+0800) Subject: osd: copy the reqids even if the object is deleted during promotion X-Git-Tag: v9.1.0~345^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b7225a4834ee741fbc710ec875b05b60e69802ca;p=ceph.git osd: copy the reqids even if the object is deleted during promotion 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 --- diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc index 224454a8ab4..329cc67dfc8 100644 --- a/src/osd/ReplicatedPG.cc +++ b/src/osd/ReplicatedPG.cc @@ -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(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, diff --git a/src/osd/ReplicatedPG.h b/src/osd/ReplicatedPG.h index cc3ce84a4b1..81f5130fa86 100644 --- a/src/osd/ReplicatedPG.h +++ b/src/osd/ReplicatedPG.h @@ -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. diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h index 3e514e3e8e4..d3688afbe82 100644 --- a/src/osdc/Objecter.h +++ b/src/osdc/Objecter.h @@ -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)