From: Yunchuan Wen Date: Tue, 20 Sep 2016 03:54:56 +0000 (+0800) Subject: RADOS: fix write op hangs X-Git-Tag: v11.1.0~528^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d80784e5dffa5f0d5e725a4adf4ff26df215415d;p=ceph.git RADOS: fix write op hangs if primary OSD handle a write op and do_osd_ops return errro code, record_write_error will try to record it into pglog and send log message to replica. but if replica OSD crash right now, the primary OSD will call on_change to free all repop, and do_update_log_missing_reply will not be called, so the write op will lost and hangs. this patch fix it. Signed-off-by: Yunchuan Wen --- diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc index cd8d91f598c5..7a342fff7546 100644 --- a/src/osd/ReplicatedPG.cc +++ b/src/osd/ReplicatedPG.cc @@ -2309,7 +2309,9 @@ void ReplicatedPG::record_write_error(OpRequestRef op, const hobject_t &soid, dout(10) << " sending commit on " << *m << " " << reply << dendl; osd->send_message_osd_client(reply, m->get_connection()); } - )); + ), + op + ); } ReplicatedPG::cache_result_t ReplicatedPG::maybe_handle_cache_detail( @@ -8753,10 +8755,12 @@ ReplicatedPG::RepGather *ReplicatedPG::new_repop( boost::intrusive_ptr ReplicatedPG::new_repop( ObcLockManager &&manager, + OpRequestRef &&op, boost::optional > &&on_complete) { RepGather *repop = new RepGather( std::move(manager), + std::move(op), std::move(on_complete), osd->get_tid(), info.last_complete); @@ -8812,7 +8816,8 @@ void ReplicatedPG::simple_opc_submit(OpContextUPtr ctx) void ReplicatedPG::submit_log_entries( const list &entries, ObcLockManager &&manager, - boost::optional > &&on_complete) + boost::optional > &&on_complete, + OpRequestRef op) { dout(10) << __func__ << entries << dendl; assert(is_primary()); @@ -8827,6 +8832,7 @@ void ReplicatedPG::submit_log_entries( if (get_osdmap()->test_flag(CEPH_OSDMAP_REQUIRE_JEWEL)) { repop = new_repop( std::move(manager), + std::move(op), std::move(on_complete)); } for (set::const_iterator i = actingbackfill.begin(); @@ -10325,6 +10331,7 @@ void ReplicatedPG::on_change(ObjectStore::Transaction *t) // this will requeue ops we were working on but didn't finish, and // any dups apply_and_flush_repops(is_primary()); + cancel_log_updates(); // do this *after* apply_and_flush_repops so that we catch any newly // registered watches. diff --git a/src/osd/ReplicatedPG.h b/src/osd/ReplicatedPG.h index 66bc96827aa1..fa2895a1c2ad 100644 --- a/src/osd/ReplicatedPG.h +++ b/src/osd/ReplicatedPG.h @@ -699,9 +699,11 @@ public: RepGather( ObcLockManager &&manager, + OpRequestRef &&o, boost::optional > &&on_complete, ceph_tid_t rt, eversion_t lc) : + op(o), queue_item(this), nref(1), rep_tid(rt), @@ -845,6 +847,7 @@ protected: ceph_tid_t rep_tid); boost::intrusive_ptr new_repop( ObcLockManager &&manager, + OpRequestRef &&op, boost::optional > &&on_complete); void remove_repop(RepGather *repop); @@ -860,7 +863,8 @@ protected: void submit_log_entries( const list &entries, ObcLockManager &&manager, - boost::optional > &&on_complete); + boost::optional > &&on_complete, + OpRequestRef op = OpRequestRef()); struct LogUpdateCtx { boost::intrusive_ptr repop; set waiting_on;