]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: async open/close should free ImageCtx before issuing callback
authorJason Dillaman <dillaman@redhat.com>
Thu, 18 Apr 2019 17:17:56 +0000 (13:17 -0400)
committerJason Dillaman <dillaman@redhat.com>
Thu, 18 Apr 2019 17:24:20 +0000 (13:24 -0400)
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 <dillaman@redhat.com>
src/librbd/io/AioCompletion.cc
src/librbd/io/AioCompletion.h

index c106ee11a78a8e2380bdcc637e4b3c37ecbb7796..c933135d621d78d81e5e5b841bb8f4674279680f 100644 (file)
@@ -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);
index ffc8129c7e6a0187fb2dd1cbffa50e4bfade048c..f8a96a8fcaa1ccc6756d8220e77cf4048e301eaf 100644 (file)
@@ -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;
     }