From 39b27ef99ab51f776b78dcad45d0ced5c900086d Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Fri, 11 Mar 2016 09:08:15 -0500 Subject: [PATCH] librbd: protect against duplicate journal events Signed-off-by: Jason Dillaman --- src/librbd/journal/Replay.cc | 79 ++++++++++++++++++++++++++++-------- src/librbd/journal/Replay.h | 4 +- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/librbd/journal/Replay.cc b/src/librbd/journal/Replay.cc index 87781194bb75..02625791977e 100644 --- a/src/librbd/journal/Replay.cc +++ b/src/librbd/journal/Replay.cc @@ -367,8 +367,11 @@ void Replay::handle_event(const journal::SnapCreateEvent &event, Mutex::Locker locker(m_lock); OpEvent *op_event; - Context *on_op_complete = create_op_context_callback(event.op_tid, on_safe, - &op_event); + Context *on_op_complete = create_op_context_callback(event.op_tid, on_ready, + on_safe, &op_event); + if (on_op_complete == nullptr) { + return; + } // ignore errors caused due to replay op_event->ignore_error_codes = {-EEXIST}; @@ -393,8 +396,12 @@ void Replay::handle_event(const journal::SnapRemoveEvent &event, Mutex::Locker locker(m_lock); OpEvent *op_event; - Context *on_op_complete = create_op_context_callback(event.op_tid, on_safe, - &op_event); + Context *on_op_complete = create_op_context_callback(event.op_tid, on_ready, + on_safe, &op_event); + if (on_op_complete == nullptr) { + return; + } + op_event->on_op_finish_event = new C_RefreshIfRequired( m_image_ctx, new ExecuteOp(m_image_ctx, event, on_op_complete)); @@ -413,8 +420,12 @@ void Replay::handle_event(const journal::SnapRenameEvent &event, Mutex::Locker locker(m_lock); OpEvent *op_event; - Context *on_op_complete = create_op_context_callback(event.op_tid, on_safe, - &op_event); + Context *on_op_complete = create_op_context_callback(event.op_tid, on_ready, + on_safe, &op_event); + if (on_op_complete == nullptr) { + return; + } + op_event->on_op_finish_event = new C_RefreshIfRequired( m_image_ctx, new ExecuteOp(m_image_ctx, event, on_op_complete)); @@ -433,8 +444,12 @@ void Replay::handle_event(const journal::SnapProtectEvent &event, Mutex::Locker locker(m_lock); OpEvent *op_event; - Context *on_op_complete = create_op_context_callback(event.op_tid, on_safe, - &op_event); + Context *on_op_complete = create_op_context_callback(event.op_tid, on_ready, + on_safe, &op_event); + if (on_op_complete == nullptr) { + return; + } + op_event->on_op_finish_event = new C_RefreshIfRequired( m_image_ctx, new ExecuteOp(m_image_ctx, event, on_op_complete)); @@ -454,8 +469,12 @@ void Replay::handle_event(const journal::SnapUnprotectEvent &event, Mutex::Locker locker(m_lock); OpEvent *op_event; - Context *on_op_complete = create_op_context_callback(event.op_tid, on_safe, - &op_event); + Context *on_op_complete = create_op_context_callback(event.op_tid, on_ready, + on_safe, &op_event); + if (on_op_complete == nullptr) { + return; + } + op_event->on_op_finish_event = new C_RefreshIfRequired( m_image_ctx, new ExecuteOp(m_image_ctx, event, @@ -476,8 +495,12 @@ void Replay::handle_event(const journal::SnapRollbackEvent &event, Mutex::Locker locker(m_lock); OpEvent *op_event; - Context *on_op_complete = create_op_context_callback(event.op_tid, on_safe, - &op_event); + Context *on_op_complete = create_op_context_callback(event.op_tid, on_ready, + on_safe, &op_event); + if (on_op_complete == nullptr) { + return; + } + op_event->on_op_finish_event = new C_RefreshIfRequired( m_image_ctx, new ExecuteOp(m_image_ctx, event, @@ -494,8 +517,12 @@ void Replay::handle_event(const journal::RenameEvent &event, Mutex::Locker locker(m_lock); OpEvent *op_event; - Context *on_op_complete = create_op_context_callback(event.op_tid, on_safe, - &op_event); + Context *on_op_complete = create_op_context_callback(event.op_tid, on_ready, + on_safe, &op_event); + if (on_op_complete == nullptr) { + return; + } + op_event->on_op_finish_event = new C_RefreshIfRequired( m_image_ctx, new ExecuteOp(m_image_ctx, event, on_op_complete)); @@ -514,8 +541,11 @@ void Replay::handle_event(const journal::ResizeEvent &event, Mutex::Locker locker(m_lock); OpEvent *op_event; - Context *on_op_complete = create_op_context_callback(event.op_tid, on_safe, - &op_event); + Context *on_op_complete = create_op_context_callback(event.op_tid, on_ready, + on_safe, &op_event); + if (on_op_complete == nullptr) { + return; + } // avoid lock cycles m_image_ctx.op_work_queue->queue(new C_RefreshIfRequired( @@ -536,8 +566,12 @@ void Replay::handle_event(const journal::FlattenEvent &event, Mutex::Locker locker(m_lock); OpEvent *op_event; - Context *on_op_complete = create_op_context_callback(event.op_tid, on_safe, - &op_event); + Context *on_op_complete = create_op_context_callback(event.op_tid, on_ready, + on_safe, &op_event); + if (on_op_complete == nullptr) { + return; + } + op_event->on_op_finish_event = new C_RefreshIfRequired( m_image_ctx, new ExecuteOp(m_image_ctx, event, on_op_complete)); @@ -634,9 +668,18 @@ void Replay::handle_aio_flush_complete(Context *on_flush_safe, template Context *Replay::create_op_context_callback(uint64_t op_tid, + Context *on_ready, Context *on_safe, OpEvent **op_event) { + CephContext *cct = m_image_ctx.cct; + assert(m_lock.is_locked()); + if (m_op_events.count(op_tid) != 0) { + lderr(cct) << "duplicate op tid detected: " << op_tid << dendl; + on_ready->complete(0); + on_safe->complete(-EINVAL); + return nullptr; + } *op_event = &m_op_events[op_tid]; (*op_event)->on_start_safe = on_safe; diff --git a/src/librbd/journal/Replay.h b/src/librbd/journal/Replay.h index c617dfb25d78..5be3406b8aae 100644 --- a/src/librbd/journal/Replay.h +++ b/src/librbd/journal/Replay.h @@ -159,8 +159,8 @@ private: void handle_aio_flush_complete(Context *on_flush_safe, Contexts &on_safe_ctxs, int r); - Context *create_op_context_callback(uint64_t op_tid, Context *on_safe, - OpEvent **op_event); + Context *create_op_context_callback(uint64_t op_tid, Context *on_ready, + Context *on_safe, OpEvent **op_event); void handle_op_complete(uint64_t op_tid, int r); AioCompletion *create_aio_modify_completion(Context *on_ready, -- 2.47.3