]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/net: don't fail when nothing queued for sweep
authorYingxin Cheng <yingxin.cheng@intel.com>
Sat, 12 Oct 2019 07:39:00 +0000 (15:39 +0800)
committerYingxin Cheng <yingxin.cheng@intel.com>
Wed, 16 Oct 2019 01:29:46 +0000 (09:29 +0800)
Fix a corner case when write is dispatching but the queued events are
cleared by a remote reset.

Signed-off-by: Yingxin Cheng <yingxin.cheng@intel.com>
src/crimson/net/Protocol.cc
src/crimson/net/Protocol.h

index fc0d73d2e64256c5dd4433d82ab18d70cddfa64b..1fad3a499d3d34e666c5871c506903cf9f89c1bc 100644 (file)
@@ -171,14 +171,39 @@ void Protocol::ack_writes(seq_num_t seq)
   }
 }
 
+seastar::future<stop_t> Protocol::try_exit_sweep() {
+  assert(!is_queued());
+  return socket->flush().then([this] {
+    if (!is_queued()) {
+      // still nothing pending to send after flush,
+      // the dispatching can ONLY stop now
+      ceph_assert(write_dispatching);
+      write_dispatching = false;
+      if (unlikely(exit_open.has_value())) {
+        exit_open->set_value();
+        exit_open = std::nullopt;
+        logger().info("{} write_event: nothing queued at {},"
+                      " set exit_open",
+                      conn, get_state_name(write_state));
+      }
+      return seastar::make_ready_future<stop_t>(stop_t::yes);
+    } else {
+      // something is pending to send during flushing
+      return seastar::make_ready_future<stop_t>(stop_t::no);
+    }
+  });
+}
+
 seastar::future<> Protocol::do_write_dispatch_sweep()
 {
   return seastar::repeat([this] {
     switch (write_state) {
      case write_state_t::open: {
       size_t num_msgs = conn.out_q.size();
-      // we must have something to write...
-      ceph_assert(is_queued());
+      bool still_queued = is_queued();
+      if (unlikely(!still_queued)) {
+        return try_exit_sweep();
+      }
       conn.pending_q.clear();
       conn.pending_q.swap(conn.out_q);
       if (!conn.policy.lossy) {
@@ -199,26 +224,7 @@ seastar::future<> Protocol::do_write_dispatch_sweep()
         assert(ack_left >= acked);
         ack_left -= acked;
         if (!is_queued()) {
-          // good, we have nothing pending to send now.
-          return socket->flush().then([this] {
-            if (!is_queued()) {
-              // still nothing pending to send after flush,
-              // the dispatching can ONLY stop now
-              ceph_assert(write_dispatching);
-              write_dispatching = false;
-              if (unlikely(exit_open.has_value())) {
-                exit_open->set_value();
-                exit_open = std::nullopt;
-                logger().info("{} write_event: nothing queued at {},"
-                              " set exit_open",
-                              conn, get_state_name(write_state));
-              }
-              return seastar::make_ready_future<stop_t>(stop_t::yes);
-            } else {
-              // something is pending to send during flushing
-              return seastar::make_ready_future<stop_t>(stop_t::no);
-            }
-          });
+          return try_exit_sweep();
         } else {
           // messages were enqueued during socket write
           return seastar::make_ready_future<stop_t>(stop_t::no);
index ea7c5d0294921b1156972a50c76ee74c8b66f097..688b5e3d607f618e2f3b45eb85862be8cf2286bc 100644 (file)
@@ -144,6 +144,7 @@ class Protocol {
   // it needs to wait for exit_open until writing is stopped or failed.
   std::optional<seastar::shared_promise<>> exit_open;
 
+  seastar::future<stop_t> try_exit_sweep();
   seastar::future<> do_write_dispatch_sweep();
   void write_event();
 };