Project

General

Profile

Actions

Bug #21009

closed

hammer:librbd: The qemu VMs hang occasionally after a snapshot is created.

Added by yupeng chen over 6 years ago. Updated over 6 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
% Done:

0%

Source:
other
Tags:
librbd,qemu
Backport:
hammer
Regression:
No
Severity:
2 - major
Reviewed:
ceph-qa-suite:
rbd
Pull request ID:
Crash signature (v1):
Crash signature (v2):

Description

We're hosting hundreds of VMs with qemu and ceph as core infrastructure in the production environment. The ceph base version is 0.94.5 with 'rbd_non_blocking_aio' set to true.

For the security reasons, a snapshot of each rbd image is created, and then that snapshot is exported from the source cluster and reimported to another ceph cluster.

However, we found that several VMs hung during the backup phase.

And after googling, we find that http://tracker.ceph.com/issues/15033 mentions what we met.

So we applied the patch from https://github.com/ceph/ceph/pull/8011 hoping to resolve the problem. But when doing regression test, the VMs still hung occasionally.

Actions #1

Updated by yupeng chen over 6 years ago

After investigating the backtrace and logs, we find a deadlock is possible in the following scenario:

1) OPs issued by qemu are queued in the aio_work_queue, and finally an aio_flush. After the aio_flush is processed,the Imagectx's async_ops looks like:
async_ops --> [aio_flush, aio_op_1, ] | |---> flush_contexts [C_AsyncCallback(C_AioWrite(AioCompletion))]

2) A snapshot is then created and more OPs arrive. When ThreadPool thread tries to process an OP, the newly create snapshot requires the ImageCtx be refreshed, leading to flush_async_operations(), so the thread blocks waiting for all the OPs in async_ops to complete.

async_ops -->  [aio_op_2, ..., aio_flush, aio_op_1, ]
                   |                        |
                   |                        |---> flush_contexts [C_AsyncCallback(C_AioWrite(AioCompletion))]
                   |
                   |-> flush_contexts [C_SafeCond]

3) aio_op_1 completes, triggering C_AsyncCallback's finish(), which then queue C_AioWrite(AioCompletion) to the ImageCtx's op_work_queue, waiting for the ThreadPool to process it but the thread blocks in flush_async_operations(). So the deadlock occurs.

After investigating the backtrace and logs, we find a deadlock is possible in the following scenario:

1) OPs issued by qemu are queued in the aio_work_queue, and finally an aio_flush. After the aio_flush is processed,the Imagectx's async_ops looks like:
async_ops --> [aio_flush, aio_op_1, ] | |---> flush_contexts [C_AsyncCallback(C_AioWrite(AioCompletion))]

2) A snapshot is created and more OPs arrive. When ThreadPool thread tries to process an OP, the newly create snapshot requires the ImageCtx be refreshed, leading to flush_async_operations(), so the thread blocks waiting for all the OPs in async_ops to complete.

async_ops -->  [aio_op_2, ..., aio_flush, aio_op_1, ]
                   |                        |
                   |                        |---> flush_contexts [C_AsyncCallback(C_AioWrite(AioCompletion))]
                   |
                   |-> flush_contexts [C_SafeCond]

3) aio_op_1 completes, triggering C_AsyncCallback's finish(), which then queue C_AioWrite(AioCompletion) to the ImageCtx's op_work_queue, waiting for the ThreadPool to process it but the thread blocks in flush_async_operations(). So the deadlock occurs.

What we did to break the deadlock is to queue C_AioWrite(AioCompletion) using the ImageCtx's writeback_handler in C_AsyncCallback's finish() as https://github.com/ceph/ceph/pull/8011 did.

PR: https://github.com/ceph/ceph/pull/17045

Actions #2

Updated by yupeng chen over 6 years ago

Sorry for the repeat.

Actions #3

Updated by yupeng chen over 6 years ago

After investigating the backtrace and logs, we find a deadlock is possible in the following scenario:

1) OPs issued by qemu are queued in the aio_work_queue, and finally an aio_flush. After the aio_flush is processed,the Imagectx's async_ops looks like:

async_ops -->  [aio_flush, aio_op_1, ]
                            |
                            |---> flush_contexts [C_AsyncCallback(C_AioWrite(AioCompletion))]

2) A snapshot is created and more OPs arrive. When ThreadPool thread tries to process an OP, the newly create snapshot requires the ImageCtx be refreshed, leading to flush_async_operations(), so the thread blocks waiting for all the OPs in async_ops to complete.

async_ops -->  [aio_op_2, ..., aio_flush, aio_op_1, ]
                   |                        |
                   |                        |---> flush_contexts [C_AsyncCallback(C_AioWrite(AioCompletion))]
                   |
                   |-> flush_contexts [C_SafeCond]

3) aio_op_1 completes, triggering C_AsyncCallback's finish(), which then queue C_AioWrite(AioCompletion) to the ImageCtx's op_work_queue, waiting for the ThreadPool to process it but the thread blocks in flush_async_operations(). So the deadlock occurs.

What we did to break the deadlock is to queue C_AioWrite(AioCompletion) using the ImageCtx's writeback_handler in C_AsyncCallback's finish() as https://github.com/ceph/ceph/pull/8011 did.

PR: https://github.com/ceph/ceph/pull/17045

Actions #4

Updated by Mykola Golub over 6 years ago

  • Status changed from New to Fix Under Review
Actions #5

Updated by Nathan Cutler over 6 years ago

  • Status changed from Fix Under Review to Rejected

Hammer is EOL.

Actions

Also available in: Atom PDF