The perfcounters (and the ictx) are only valid while the image is
still open. If the librbd user gets the callback for its last I/O,
then closes the image, the ictx and its perfcounters will be
invalid. If the AioCompletion object is has not run the rest of its
complete() method yet, it will access these now-invalid addresses,
possibly leading to a crash.
The AioCompletion object is independent of the ictx and does not
access it again after incrementing perfcounters, so avoid this race by
calling the user's callback after this step. The AioCompletion object
will be cleaned up by the rest of complete_request(), independent of
the ImageCtx.
Fixes: #5426
Backport: dumpling, emperor
Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
utime_t elapsed;
assert(lock.is_locked());
elapsed = ceph_clock_now(ictx->cct) - start_time;
- if (complete_cb) {
- complete_cb(rbd_comp, complete_arg);
- }
switch (aio_type) {
case AIO_TYPE_READ:
ictx->perfcounter->tinc(l_librbd_aio_rd_latency, elapsed); break;
lderr(ictx->cct) << "completed invalid aio_type: " << aio_type << dendl;
break;
}
+ if (complete_cb) {
+ complete_cb(rbd_comp, complete_arg);
+ }
done = true;
cond.Signal();
}