From: Jason Dillaman Date: Fri, 11 Mar 2016 14:08:15 +0000 (-0500) Subject: librbd: protect against duplicate journal events X-Git-Tag: v10.1.0~133^2~1^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=39b27ef99ab51f776b78dcad45d0ced5c900086d;p=ceph.git librbd: protect against duplicate journal events Signed-off-by: Jason Dillaman --- 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,