From be419a1d6fd1e176ab4fdebfaa17726bb63d6ac8 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Thu, 18 Apr 2019 13:17:56 -0400 Subject: [PATCH] librbd: async open/close should free ImageCtx before issuing callback The destructor for ImageCtx attempts to access librados::IoCtx objects that might have been destroyed immediately after the async open (failure) and close actions completed. Fixes: http://tracker.ceph.com/issues/39031 Signed-off-by: Jason Dillaman --- src/librbd/io/AioCompletion.cc | 15 ++++++++++++++- src/librbd/io/AioCompletion.h | 14 ++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/librbd/io/AioCompletion.cc b/src/librbd/io/AioCompletion.cc index c106ee11a78..c933135d621 100644 --- a/src/librbd/io/AioCompletion.cc +++ b/src/librbd/io/AioCompletion.cc @@ -82,6 +82,13 @@ void AioCompletion::complete() { } } + if ((aio_type == AIO_TYPE_CLOSE) || + (aio_type == AIO_TYPE_OPEN && rval < 0)) { + // must destroy ImageCtx prior to invoking callback + delete ictx; + ictx = nullptr; + } + state = AIO_STATE_CALLBACK; if (complete_cb) { lock.Unlock(); @@ -89,7 +96,7 @@ void AioCompletion::complete() { lock.Lock(); } - if (event_notify && ictx->event_socket.is_valid()) { + if (ictx != nullptr && event_notify && ictx->event_socket.is_valid()) { ictx->completed_reqs_lock.Lock(); ictx->completed_reqs.push_back(&m_xlist_item); ictx->completed_reqs_lock.Unlock(); @@ -119,6 +126,12 @@ void AioCompletion::start_op(bool ignore_type) { Mutex::Locker locker(lock); ceph_assert(ictx != nullptr); ceph_assert(!async_op.started()); + + if (aio_type == AIO_TYPE_OPEN || aio_type == AIO_TYPE_CLOSE) { + // no need to track async open/close operations + return; + } + if (state == AIO_STATE_PENDING && (ignore_type || aio_type != AIO_TYPE_FLUSH)) { async_op.start_op(*ictx); diff --git a/src/librbd/io/AioCompletion.h b/src/librbd/io/AioCompletion.h index ffc8129c7e6..f8a96a8fcaa 100644 --- a/src/librbd/io/AioCompletion.h +++ b/src/librbd/io/AioCompletion.h @@ -171,16 +171,10 @@ struct AioCompletion { int n = --ref; lock.Unlock(); if (!n) { - if (ictx) { - if (event_notify) { - ictx->completed_reqs_lock.Lock(); - m_xlist_item.remove_myself(); - ictx->completed_reqs_lock.Unlock(); - } - if (aio_type == AIO_TYPE_CLOSE || - (aio_type == AIO_TYPE_OPEN && rval < 0)) { - delete ictx; - } + if (ictx != nullptr && event_notify) { + ictx->completed_reqs_lock.Lock(); + m_xlist_item.remove_myself(); + ictx->completed_reqs_lock.Unlock(); } delete this; } -- 2.39.5