Skip to content
  • Damien Le Moal's avatar
    dm zoned: Fix target BIO completion handling · d57f9da8
    Damien Le Moal authored
    struct bioctx includes the ref refcount_t to track the number of I/O
    fragments used to process a target BIO as well as ensure that the zone
    of the BIO is kept in the active state throughout the lifetime of the
    BIO. However, since decrementing of this reference count is done in the
    target .end_io method, the function bio_endio() must be called multiple
    times for read and write target BIOs, which causes problems with the
    value of the __bi_remaining struct bio field for chained BIOs (e.g. the
    clone BIO passed by dm core is large and splits into fragments by the
    block layer), resulting in incorrect values and inconsistencies with the
    BIO_CHAIN flag setting. This is turn triggers the BUG_ON() call:
    
    BUG_ON(atomic_read(&bio->__bi_remaining) <= 0);
    
    in bio_remaining_done() called from bio_endio().
    
    Fix this ensuring that bio_endio() is called only once for any target
    BIO by always using internal clone BIOs for processing any read or
    write target BIO. This allows reference counting using the target BIO
    context counter to trigger the target BIO completion bio_endio() call
    once all data, metadata and other zone work triggered by the BIO
    complete.
    
    Overall, this simplifies the code too as the target .end_io becomes
    unnecessary and differences between read and write BIO issuing and
    completion processing disappear.
    
    Fixes: 3b1a94c8
    
     ("dm zoned: drive-managed zoned block device target")
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
    Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
    d57f9da8