Skip to content
  • Greg Kurz's avatar
    1a6d3bd2
    block: End quiescent sections when a BDS is deleted · 1a6d3bd2
    Greg Kurz authored
    If a BDS gets deleted during blk_drain_all(), it might miss a
    call to bdrv_do_drained_end(). This means missing a call to
    aio_enable_external() and the AIO context remains disabled for
    ever. This can cause a device to become irresponsive and to
    disrupt the guest execution, ie. hang, loop forever or worse.
    
    This scenario is quite easy to encounter with virtio-scsi
    on POWER when punching multiple blockdev-create QMP commands
    while the guest is booting and it is still running the SLOF
    firmware. This happens because SLOF disables/re-enables PCI
    devices multiple times via IO/MEM/MASTER bits of PCI_COMMAND
    register after the initial probe/feature negotiation, as it
    tends to work with a single device at a time at various stages
    like probing and running block/network bootloaders without
    doing a full reset in-between. This naturally generates many
    dataplane stops and starts, and thus many drain sections that
    can race with blockdev_create_run(). In the end, SLOF bails
    out.
    
    It is somehow reproducible on x86 but it requires to generate
    articial dataplane start/stop activity with stop/cont QMP
    commands. In this case, seabios ends up looping for ever,
    waiting for the virtio-scsi device to send a response to
    a command it never received.
    
    Add a helper that pairs all previously called bdrv_do_drained_begin()
    with a bdrv_do_drained_end() and call it from bdrv_close().
    While at it, update the "/bdrv-drain/graph-change/drain_all"
    test in test-bdrv-drain so that it can catch the issue.
    
    BugId: https://bugzilla.redhat.com/show_bug.cgi?id=1874441
    
    
    Signed-off-by: default avatarGreg Kurz <groug@kaod.org>
    Message-Id: <160346526998.272601.9045392804399803158.stgit@bahia.lan>
    Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
    1a6d3bd2
    block: End quiescent sections when a BDS is deleted
    Greg Kurz authored
    If a BDS gets deleted during blk_drain_all(), it might miss a
    call to bdrv_do_drained_end(). This means missing a call to
    aio_enable_external() and the AIO context remains disabled for
    ever. This can cause a device to become irresponsive and to
    disrupt the guest execution, ie. hang, loop forever or worse.
    
    This scenario is quite easy to encounter with virtio-scsi
    on POWER when punching multiple blockdev-create QMP commands
    while the guest is booting and it is still running the SLOF
    firmware. This happens because SLOF disables/re-enables PCI
    devices multiple times via IO/MEM/MASTER bits of PCI_COMMAND
    register after the initial probe/feature negotiation, as it
    tends to work with a single device at a time at various stages
    like probing and running block/network bootloaders without
    doing a full reset in-between. This naturally generates many
    dataplane stops and starts, and thus many drain sections that
    can race with blockdev_create_run(). In the end, SLOF bails
    out.
    
    It is somehow reproducible on x86 but it requires to generate
    articial dataplane start/stop activity with stop/cont QMP
    commands. In this case, seabios ends up looping for ever,
    waiting for the virtio-scsi device to send a response to
    a command it never received.
    
    Add a helper that pairs all previously called bdrv_do_drained_begin()
    with a bdrv_do_drained_end() and call it from bdrv_close().
    While at it, update the "/bdrv-drain/graph-change/drain_all"
    test in test-bdrv-drain so that it can catch the issue.
    
    BugId: https://bugzilla.redhat.com/show_bug.cgi?id=1874441
    
    
    Signed-off-by: default avatarGreg Kurz <groug@kaod.org>
    Message-Id: <160346526998.272601.9045392804399803158.stgit@bahia.lan>
    Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
Loading