]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
librbd: track the originating source of a flush request
authorJason Dillaman <dillaman@redhat.com>
Mon, 19 Feb 2018 21:09:51 +0000 (16:09 -0500)
committerJason Dillaman <dillaman@redhat.com>
Mon, 26 Feb 2018 17:29:37 +0000 (12:29 -0500)
This will be used in a later cleanup to remove the IO flush handling
from ImageCtx.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/cache/ImageWriteback.cc
src/librbd/io/ImageDispatchSpec.cc
src/librbd/io/ImageRequest.cc
src/librbd/io/ImageRequest.h
src/librbd/io/ImageRequestWQ.cc
src/librbd/io/Types.h
src/librbd/journal/Replay.cc
src/test/librbd/io/test_mock_ImageRequest.cc
src/test/librbd/journal/test_mock_Replay.cc

index be366935b36fdf02f9a2c5aa5753d170b69374fb..54b964d9091582d27d4eea27fb6dbf82043a2aea 100644 (file)
@@ -75,7 +75,8 @@ void ImageWriteback<I>::aio_flush(Context *on_finish) {
 
   auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx,
                                                       io::AIO_TYPE_FLUSH);
-  io::ImageFlushRequest<I> req(m_image_ctx, aio_comp, {});
+  io::ImageFlushRequest<I> req(m_image_ctx, aio_comp, io::FLUSH_SOURCE_INTERNAL,
+                               {});
   req.set_bypass_image_cache();
   req.send();
 }
index 897617d18126fe90968c710422fa7a68b39bcf1b..6064bae665797c63b0399154d67097cd4679d85a 100644 (file)
@@ -53,7 +53,7 @@ struct ImageDispatchSpec<I>::SendVisitor
 
   void operator()(Flush& flush) const {
     ImageRequest<I>::aio_flush(
-      &spec->m_image_ctx, spec->m_aio_comp,
+      &spec->m_image_ctx, spec->m_aio_comp, FLUSH_SOURCE_USER,
       spec->m_parent_trace);
   }
 };
index 0cfc786cbdb36542713f944bacb33daa9a263658..fdd7b18db438ade512b83e698c7f26e052fd21cf 100644 (file)
@@ -113,8 +113,9 @@ void ImageRequest<I>::aio_discard(I *ictx, AioCompletion *c,
 
 template <typename I>
 void ImageRequest<I>::aio_flush(I *ictx, AioCompletion *c,
-                               const ZTracer::Trace &parent_trace) {
-  ImageFlushRequest<I> req(*ictx, c, parent_trace);
+                                FlushSource flush_source,
+                                const ZTracer::Trace &parent_trace) {
+  ImageFlushRequest<I> req(*ictx, c, flush_source, parent_trace);
   req.send();
 }
 
@@ -593,47 +594,50 @@ void ImageDiscardRequest<I>::update_stats(size_t length) {
 template <typename I>
 void ImageFlushRequest<I>::send_request() {
   I &image_ctx = this->m_image_ctx;
-  image_ctx.user_flushed();
+  if (m_flush_source == FLUSH_SOURCE_USER) {
+    // flag cache for writeback mode if configured
+    image_ctx.user_flushed();
+  }
 
   bool journaling = false;
   {
     RWLock::RLocker snap_locker(image_ctx.snap_lock);
-    journaling = (image_ctx.journal != nullptr &&
+    journaling = (m_flush_source == FLUSH_SOURCE_USER &&
+                  image_ctx.journal != nullptr &&
                   image_ctx.journal->is_journal_appending());
   }
 
   AioCompletion *aio_comp = this->m_aio_comp;
+  aio_comp->set_request_count(1);
+
+  Context *ctx;
   if (journaling) {
     // in-flight ops are flushed prior to closing the journal
     uint64_t journal_tid = image_ctx.journal->append_io_event(
       journal::EventEntry(journal::AioFlushEvent()),
       ObjectRequests(), 0, 0, false, 0);
-
-    aio_comp->set_request_count(1);
     aio_comp->associate_journal_event(journal_tid);
 
-    FunctionContext *flush_ctx = new FunctionContext(
-      [aio_comp, &image_ctx, journal_tid] (int r) {
-        auto ctx = new C_FlushJournalCommit<I>(image_ctx, aio_comp,
-                                               journal_tid);
+    ctx = new C_FlushJournalCommit<I>(image_ctx, aio_comp, journal_tid);
+    ctx = new FunctionContext(
+      [&image_ctx, journal_tid, ctx] (int r) {
         image_ctx.journal->flush_event(journal_tid, ctx);
-
-        // track flush op for block writes
-        aio_comp->start_op(true);
-        aio_comp->put();
-    });
-
-    image_ctx.flush_async_operations(flush_ctx);
+      });
   } else {
     // flush rbd cache only when journaling is not enabled
-    aio_comp->set_request_count(1);
-    C_AioRequest *req_comp = new C_AioRequest(aio_comp);
-    image_ctx.flush(req_comp);
-
-    aio_comp->start_op(true);
-    aio_comp->put();
+    ctx = new C_AioRequest(aio_comp);
+    if (image_ctx.object_cacher != nullptr) {
+      ctx = new FunctionContext([aio_comp, &image_ctx, ctx](int r) {
+          image_ctx.flush_cache(ctx);
+        });
+    }
   }
 
+  // ensure all in-flight IOs are settled if non-user flush request
+  image_ctx.flush_async_operations(ctx);
+  aio_comp->start_op(true);
+  aio_comp->put();
+
   image_ctx.perfcounter->inc(l_librbd_flush);
 }
 
index a24f566c2303b5bb0b2364a9dc26bfff4ce88f6b..ec91582cebb31ae7b503ab82fee033622d50ec80 100644 (file)
@@ -43,7 +43,8 @@ public:
                           Extents &&image_extents, bool skip_partial_discard,
                          const ZTracer::Trace &parent_trace);
   static void aio_flush(ImageCtxT *ictx, AioCompletion *c,
-                       const ZTracer::Trace &parent_trace);
+                        FlushSource flush_source,
+                        const ZTracer::Trace &parent_trace);
   static void aio_writesame(ImageCtxT *ictx, AioCompletion *c,
                             Extents &&image_extents, bufferlist &&bl,
                             int op_flags, const ZTracer::Trace &parent_trace);
@@ -255,8 +256,10 @@ template <typename ImageCtxT = ImageCtx>
 class ImageFlushRequest : public ImageRequest<ImageCtxT> {
 public:
   ImageFlushRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp,
-                   const ZTracer::Trace &parent_trace)
-    : ImageRequest<ImageCtxT>(image_ctx, aio_comp, {}, "flush", parent_trace) {
+                    FlushSource flush_source,
+                    const ZTracer::Trace &parent_trace)
+    : ImageRequest<ImageCtxT>(image_ctx, aio_comp, {}, "flush", parent_trace),
+      m_flush_source(flush_source) {
   }
 
 protected:
@@ -274,6 +277,10 @@ protected:
   const char *get_request_type() const override {
     return "aio_flush";
   }
+
+private:
+  FlushSource m_flush_source;
+
 };
 
 template <typename ImageCtxT = ImageCtx>
index 0ce9171e59f4a10a104b3d3227ffd5b78f666f54..ca77c68431426f93a698d77983c2898824a87955 100644 (file)
@@ -369,7 +369,7 @@ void ImageRequestWQ<I>::aio_flush(AioCompletion *c, bool native_async) {
   if (m_image_ctx.non_blocking_aio || writes_blocked() || !writes_empty()) {
     queue(ImageDispatchSpec<I>::create_flush_request(m_image_ctx, c, trace));
   } else {
-    ImageRequest<I>::aio_flush(&m_image_ctx, c, trace);
+    ImageRequest<I>::aio_flush(&m_image_ctx, c, FLUSH_SOURCE_USER, trace);
     finish_in_flight_io();
   }
   trace.event("finish");
index 2b69d7bbcf032128e833885050e3cd75791829d9..7360bc3af40a9c9c068d3460ee52562acecc0cc3 100644 (file)
@@ -24,6 +24,12 @@ typedef enum {
   AIO_TYPE_COMPARE_AND_WRITE,
 } aio_type_t;
 
+enum FlushSource {
+  FLUSH_SOURCE_USER,
+  FLUSH_SOURCE_INTERNAL,
+  FLUSH_SOURCE_SHUTDOWN
+};
+
 enum Direction {
   DIRECTION_READ,
   DIRECTION_WRITE,
index 993d6f230b85b995c3db9c6270f5903a5b4e72b5..da91f28bc0d315da3c501220d6232434bb707a52 100644 (file)
@@ -271,7 +271,8 @@ void Replay<I>::shut_down(bool cancel_ops, Context *on_finish) {
   // execute the following outside of lock scope
   if (flush_comp != nullptr) {
     RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
-    io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp, {});
+    io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp,
+                                   io::FLUSH_SOURCE_INTERNAL, {});
   }
   if (on_finish != nullptr) {
     on_finish->complete(0);
@@ -291,7 +292,8 @@ void Replay<I>::flush(Context *on_finish) {
   }
 
   RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
-  io::ImageRequest<I>::aio_flush(&m_image_ctx, aio_comp, {});
+  io::ImageRequest<I>::aio_flush(&m_image_ctx, aio_comp,
+                                 io::FLUSH_SOURCE_INTERNAL, {});
 }
 
 template <typename I>
@@ -357,7 +359,8 @@ void Replay<I>::handle_event(const journal::AioDiscardEvent &event,
     m_lock.Unlock();
 
     if (flush_comp != nullptr) {
-      io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp, {});
+      io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp,
+                                     io::FLUSH_SOURCE_INTERNAL, {});
     }
   }
 }
@@ -387,7 +390,8 @@ void Replay<I>::handle_event(const journal::AioWriteEvent &event,
     m_lock.Unlock();
 
     if (flush_comp != nullptr) {
-      io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp, {});
+      io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp,
+                                     io::FLUSH_SOURCE_INTERNAL, {});
     }
   }
 }
@@ -405,7 +409,8 @@ void Replay<I>::handle_event(const journal::AioFlushEvent &event,
   }
 
   if (aio_comp != nullptr) {
-    io::ImageRequest<I>::aio_flush(&m_image_ctx, aio_comp, {});
+    io::ImageRequest<I>::aio_flush(&m_image_ctx, aio_comp,
+                                   io::FLUSH_SOURCE_INTERNAL, {});
   }
   on_ready->complete(0);
 }
@@ -435,7 +440,8 @@ void Replay<I>::handle_event(const journal::AioWriteSameEvent &event,
     m_lock.Unlock();
 
     if (flush_comp != nullptr) {
-      io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp, {});
+      io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp,
+                                     io::FLUSH_SOURCE_INTERNAL, {});
     }
   }
 }
@@ -463,7 +469,8 @@ void Replay<I>::handle_event(const journal::AioWriteSameEvent &event,
     auto flush_comp = create_aio_flush_completion(nullptr);
     m_lock.Unlock();
 
-    io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp, {});
+    io::ImageRequest<I>::aio_flush(&m_image_ctx, flush_comp,
+                                   io::FLUSH_SOURCE_INTERNAL, {});
   }
 }
 
index bfea417ef24c82b6f8aaf68df60f2783b2307b88..17ca3abd60463296709e1b47ac2888c349caa2de 100644 (file)
@@ -197,7 +197,12 @@ struct TestMockIoImageRequest : public TestMockFixture {
   }
 
   void expect_flush(MockImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(mock_image_ctx, flush(_))
+    EXPECT_CALL(mock_image_ctx, flush_cache(_))
+      .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_flush_async_operations(MockImageCtx &mock_image_ctx, int r) {
+    EXPECT_CALL(mock_image_ctx, flush_async_operations(_))
       .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
   }
 };
@@ -281,12 +286,14 @@ TEST_F(TestMockIoImageRequest, AioFlushJournalAppendDisabled) {
   InSequence seq;
   expect_user_flushed(mock_image_ctx);
   expect_is_journal_appending(mock_journal, false);
+  expect_flush_async_operations(mock_image_ctx, 0);
   expect_flush(mock_image_ctx, 0);
 
   C_SaferCond aio_comp_ctx;
   AioCompletion *aio_comp = AioCompletion::create_and_start(
     &aio_comp_ctx, ictx, AIO_TYPE_FLUSH);
-  MockImageFlushRequest mock_aio_image_flush(mock_image_ctx, aio_comp, {});
+  MockImageFlushRequest mock_aio_image_flush(mock_image_ctx, aio_comp,
+                                             FLUSH_SOURCE_USER, {});
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
     mock_aio_image_flush.send();
index 4e91bb564b797fdc635f9a0eaafa4a82c888485c..d5b5da852e4497a820392dda5bb58b460207f079 100644 (file)
@@ -48,7 +48,7 @@ struct ImageRequest<MockReplayImageCtx> {
 
   MOCK_METHOD1(aio_flush, void(AioCompletion *c));
   static void aio_flush(MockReplayImageCtx *ictx, AioCompletion *c,
-                        const ZTracer::Trace &parent_trace) {
+                        FlushSource, const ZTracer::Trace &parent_trace) {
     assert(s_instance != nullptr);
     s_instance->aio_flush(c);
   }