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 224454a8ab4b..329cc67dfc84 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 cc3ce84a4b1a..81f5130fa86d 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 3e514e3e8e48..d3688afbe821 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)