]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
ReplicatedPG::record_write_error: don't leak orig_reply on cancel 12450/head
authorSamuel Just <sjust@redhat.com>
Wed, 7 Dec 2016 22:29:44 +0000 (14:29 -0800)
committerSamuel Just <sjust@redhat.com>
Wed, 7 Dec 2016 22:29:49 +0000 (14:29 -0800)
The submit_log_entries machinery depends on the destructor for the
functor cleaning up after itself to handle cancelation.  I could have
introduced a local intrusive_ptr and captured that instead, but this is
slightly less magic.

Fixes: http://tracker.ceph.com/issues/18180
Signed-off-by: Samuel Just <sjust@redhat.com>
src/osd/ReplicatedPG.cc

index 2a12fda436bf4802840002a9b76c6ff3f3eaaf57..50a3cbb56db925f29700f4ce4593bcc32a29cc28 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "boost/tuple/tuple.hpp"
+#include "boost/intrusive_ptr.hpp"
 #include "PG.h"
 #include "ReplicatedPG.h"
 #include "OSD.h"
@@ -2335,27 +2336,42 @@ void ReplicatedPG::record_write_error(OpRequestRef op, const hobject_t &soid,
   entries.push_back(pg_log_entry_t(pg_log_entry_t::ERROR, soid,
                                   get_next_version(), eversion_t(), 0,
                                   reqid, utime_t(), r));
+
+  struct OnComplete {
+    ReplicatedPG *pg;
+    OpRequestRef op;
+    boost::intrusive_ptr<MOSDOpReply> orig_reply;
+    int r;
+    OnComplete(
+      ReplicatedPG *pg,
+      OpRequestRef op,
+      MOSDOpReply *orig_reply,
+      int r)
+      : pg(pg), op(op),
+       orig_reply(orig_reply, false /* take over ref */), r(r)
+      {}
+    void operator()() {
+      ldpp_dout(pg, 20) << "finished " << __func__ << " r=" << r << dendl;
+      MOSDOp *m = static_cast<MOSDOp*>(op->get_req());
+      int flags = m->get_flags() & (CEPH_OSD_FLAG_ACK | CEPH_OSD_FLAG_ONDISK);
+      MOSDOpReply *reply = orig_reply.detach();
+      if (reply == nullptr) {
+       reply = new MOSDOpReply(m, r, pg->get_osdmap()->get_epoch(),
+                               flags, true);
+      }
+      ldpp_dout(pg, 10) << " sending commit on " << *m << " " << reply << dendl;
+      pg->osd->send_message_osd_client(reply, m->get_connection());
+    }
+  };
+
   ObcLockManager lock_manager;
   submit_log_entries(
     entries,
     std::move(lock_manager),
     boost::optional<std::function<void(void)> >(
-      [=]() {
-       dout(20) << "finished " << __func__ << " r=" << r << dendl;
-       MOSDOp *m = static_cast<MOSDOp*>(op->get_req());
-       int flags = m->get_flags() & (CEPH_OSD_FLAG_ACK | CEPH_OSD_FLAG_ONDISK);
-       MOSDOpReply *reply = orig_reply;
-       if (reply == nullptr) {
-         reply = new MOSDOpReply(m, r, get_osdmap()->get_epoch(),
-                                 flags, true);
-       }
-       dout(10) << " sending commit on " << *m << " " << reply << dendl;
-       osd->send_message_osd_client(reply, m->get_connection());
-      }
-      ),
+      OnComplete(this, op, orig_reply, r)),
     op,
-    r
-  );
+    r);
 }
 
 ReplicatedPG::cache_result_t ReplicatedPG::maybe_handle_cache_detail(