• E
    block: fix deadlock in bdrv_co_flush · ce83ee57
    Evgeny Yakovlev 提交于
    The following commit
        commit 3ff2f67a
        Author: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
        Date:   Mon Jul 18 22:39:52 2016 +0300
        block: ignore flush requests when storage is clean
    has introduced a regression.
    
    There is a problem that it is still possible for 2 requests to execute
    in non sequential fashion and sometimes this results in a deadlock
    when bdrv_drain_one/all are called for BDS with such stalled requests.
    
    1. Current flushed_gen and flush_started_gen is 1.
    2. Request 1 enters bdrv_co_flush to with write_gen 1 (i.e. the same
       as flushed_gen). It gets past flushed_gen != flush_started_gen and
       sets flush_started_gen to 1 (again, the same it was before).
    3. Request 1 yields somewhere before exiting bdrv_co_flush
    4. Request 2 enters bdrv_co_flush with write_gen 2. It gets past
       flushed_gen != flush_started_gen and sets flush_started_gen to 2.
    5. Request 2 runs to completion and sets flushed_gen to 2
    6. Request 1 is resumed, runs to completion and sets flushed_gen to 1.
       However flush_started_gen is now 2.
    
    From here on out flushed_gen is always != to flush_started_gen and all
    further requests will wait on flush_queue. This change replaces
    flush_started_gen with an explicitly tracked active flush request.
    Signed-off-by: NEvgeny Yakovlev <eyakovlev@virtuozzo.com>
    Signed-off-by: NDenis V. Lunev <den@openvz.org>
    Message-id: 1471457214-3994-2-git-send-email-den@openvz.org
    CC: Stefan Hajnoczi <stefanha@redhat.com>
    CC: Fam Zheng <famz@redhat.com>
    CC: Kevin Wolf <kwolf@redhat.com>
    CC: Max Reitz <mreitz@redhat.com>
    Signed-off-by: NStefan Hajnoczi <stefanha@redhat.com>
    ce83ee57
io.c 78.7 KB