• Ming Lei's avatar
    dm: add dm_bio_rewind() API to DM core · 61cbe788
    Ming Lei authored
    Commit 7759eb23 ("block: remove bio_rewind_iter()") removed
    a similar API for the following reasons:
        ```
        It is pointed that bio_rewind_iter() is one very bad API[1]:
    
        1) bio size may not be restored after rewinding
    
        2) it causes some bogus change, such as 5151842b (block: reset
        bi_iter.bi_done after splitting bio)
    
        3) rewinding really makes things complicated wrt. bio splitting
    
        4) unnecessary updating of .bi_done in fast path
    
        [1] https://marc.info/?t=153549924200005&r=1&w=2
    
        So this patch takes Kent's suggestion to restore one bio into its original
        state via saving bio iterator(struct bvec_iter) in bio_integrity_prep(),
        given now bio_rewind_iter() is only used by bio integrity code.
        ```
    However, saving off a copy of the 32 bytes bio->bi_iter in case rewind
    needed isn't efficient because it bloats per-bio-data for what is an
    unlikely case. That suggestion also ignores the need to restore
    crypto and integrity info.
    
    Add dm_bio_rewind() API for a specific use-case that is much more narrow
    than the previous more generic rewind code that was reverted:
    
    1) most bios have a fixed end sector since bio split is done from front
       of the bio, if driver just records how many sectors between current
       bio's start sector and the original bio's end sector, the original
       position can be restored. Keeping the original bio's end sector
       fixed is a _hard_ requirement for this interface!
    
    2) if a bio's end sector won't change (usually bio_trim() isn't
       called, or in the case of DM it preserves original bio), user can
       restore the original position by storing sector offset from the
       current ->bi_iter.bi_sector to bio's end sector; together with
       saving bio size, only 8 bytes is needed to restore to original
       bio.
    
    3) DM's requeue use case: when BLK_STS_DM_REQUEUE happens, DM core
       needs to restore to an "original bio" which represents the current
       dm_io to be requeued (which may be a subset of the original bio).
       By storing the sector offset from the original bio's end sector and
       dm_io's size, dm_bio_rewind() can restore such original bio. See
       commit 7dd76d1f ("dm: improve bio splitting and associated IO
       accounting") for more details on how DM does this. Leveraging this,
       allows DM core to shift the need for bio cloning from bio-split
       time (during IO submission) to the less likely BLK_STS_DM_REQUEUE
       handling (after IO completes with that error).
    
    4) Unlike the original rewind API, dm_bio_rewind() doesn't add .bi_done
       to bvec_iter and there is no effect on the fast path.
    
    Implement dm_bio_rewind() by factoring out clear helpers that it calls:
    dm_bio_integrity_rewind, dm_bio_crypt_rewind and dm_bio_rewind_iter.
    
    DM is able to ensure that dm_bio_rewind() is used safely but, given
    the constraint that the bio's end must never change, other
    hypothetical future callers may not take the same care. So make
    dm_bio_rewind() and all supporting code local to DM to avoid risk of
    hypothetical abuse. A "dm_" prefix was added to all functions to avoid
    any namespace collisions.
    Suggested-by: default avatarJens Axboe <axboe@kernel.dk>
    Signed-off-by: default avatarMing Lei <ming.lei@redhat.com>
    Signed-off-by: default avatarMike Snitzer <snitzer@kernel.org>
    61cbe788
dm-core.h 6.84 KB