lkml.org 
[lkml]   [2002]   [Aug]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    Subject[PATCH] Bio Traversal Changes

    This has been discussed before in principle on lkml and
    mentioned by Jens at the kernel summit. Here's some quick
    information about the changes, and the latest patches
    against 2.5.30, including bio and request documentation
    updates.

    Jens, biotr8 mostly just an update of biotr7 to 2.5.30, and
    minor cleanups like the removal of the commented out debug
    printks I had kept around so far.
    The doc patch got updated a bit since last night - have
    also tried to modify request.txt in addition to biodoc.txt.


    BIO traversal enhancements
    --------------------------
    - Pre-req for full BIO splitting infrastructure [Splits
    in the middle of a segment can also share the same vec]
    - Pre-req for attaching a pre-built vector (not owned by block)
    to a bio (e.g for aio) [Avoids certain subtle side-effects in
    special cases]
    - Pre-req for IDE mult-count PIO write fixes [Ability
    to traverse a bio partially for i/o submission without
    effecting bio completion]

    Patches are based on 2.5.30 (and will follow in subsequent
    mails)

    Many many thanks to Barthlomiej for helping out in review
    and testing, fixing several bugs in the generic code and
    using the bio walking routines in this patch to actually
    get IDE PIO working (single and multi count) !

    The patches must all be applied together to get a
    compiling and booting kernel on some h/w at least, so it
    might make sense to roll them up for submission to ensure
    that they are committed together.

    01biotr8-blk.diff: Contains the core changes for bio traversal,
    including (a) avoidance of alteration of bv_offset/bv_len by
    block (b) introduction of bi_voffset to help in splitting a
    bio via cloning, even when the split has to happen in the
    middle of a segment and (c) clean separation of submission and
    completion state for a request. The bio always reflects the
    state of unfinished i/o, while the request structure also tracks
    the state of unsubmitted i/o (these two may be different,
    e.g. for ide multi-count pio writes). A helper routine
    process_that_request_first() is provided to enable drivers
    to traverse a request for i/o submission without affecting
    completion state. It also has a few fixes for partial
    completion cases in end_that_request_first() (non error
    cases).
    [Andrew, I have uninlined blk_rq_next_segment() and
    process_that_request_first() as you'd suggested and moved
    them into ll_rw_blk.c]

    02biotr8-blkusers.diff: Contains the modifications needed to
    code that uses/accesses bio (e.g mm, filesystems) above blk.
    Most of the changes ensure correct initialisation of the
    bi_voffset field when building a bio.
    (BTW, Looking at the number of places that this touches, a
    helper for building a bio would seem to be good to have).

    03biotr8-drivers.diff: Contains minimal modifications to
    (some) drivers to compile/work with the changed bio
    traversal and mapping assumptions. It would not fix any
    other breakages that exist already in the drivers (e.g.
    doesn't fix any existing IDE problems, and doesn't
    touch LVM).

    Barthlomiej's patch for ATA PIO with IDE driver has
    the correct changes to get to a working version including
    some state machine fixes, and uses the bio traversal helper
    for i/o submission in a clean manner for PIO operations.

    Modifications have also been made in cases like loop,
    floppy to either account for bi_voffset or to have a
    sanity check bugon if they get passed a bio which
    starts/ends in the middle of a segment, as a reminder to
    fix it up later. This would need to be completed, including
    extending to other drivers and appropriate testing to ensure
    compatibility.

    04biotr8-doc.diff: Contains the updates to Documentation/block
    corresponding to the changes. Have taken the liberty to
    update a few other parts of the doc that were strikingly
    obsolete.

    Details:
    =========

    Introduces some new fields in bio and the request structure
    to help maintain traversal state.

    Bio fields:
    ----------

    bi_voffset:

    Offset relative to the start of the first page, which
    indicates where the bio really starts. In general before
    i/o starts this would be the same as bv_offset for the
    first vec (at bi_idx), but in the case of clone bio s where
    the bio may be split in the middle of a segment this could be
    different. As i/o progresses, now instead of changing any
    of the bvec fields, bi_voffset is moved ahead instead.

    The relative offset w.r.t to the start of the first vec
    can be calculated using the macro bio_startoffset(bio)

    bi_endvoffset:

    Offset relative to the last page which indicates
    where the bio really ends. In general this would be the same
    as bv_offset + bv_len for the last vec, but in the case of
    clone bio s where a split piece ends in the middle of a
    segment, it could be different. This field is really used
    mainly for segment boundary and merge checks (it is more
    convenient than having to walk through the entire bio
    and use bi_size to determine the end just to determine
    mergeability).

    The macro bio_endoffset(bio) can be used calculate the
    relative offset w.r.t to the bvec end where the bio
    was broken up.

    The remaining size to be transfered in the current bio
    vec should be calculated using the bio_segsize() routine
    (instead of accessing bv_len directly any more). This
    takes care of adjusting the length for the above offsets.

    Aside:
    An alternative to bi_voffset being an absolute
    offset wrt to the start of the bvec page would be to
    make it relative to bio_io_vec(bio)->bv_offset instead
    (i.e. the value bio_startoffset() returns in the patch). A
    similar change would then apply to bi_endvoffset. Then
    the fields would be initialized to zero by default,
    though it also would make the mergeability check macros
    a little longer, and possibly add a little extra computation
    during request mapping and end_that_request_first.

    Request structure fields:
    ------------------------

    The basic protocol followed all through is that the bio fields
    would always reflect the status w.r.t how much i/o remains
    to be completed. On the other hand submission status would
    only be maintained in the request structure. In most cases
    of course, both move in sync (the generic end_request_first
    code tries to handle that transparently by advancing the
    submission pointers if they are behind the completion pointers
    as would happen in the case of drivers which don't modify
    those themselves), but for things like IDE
    mult-count write, the submission counters/pointers may be
    ahead of the completion pointers.

    The following fields have been added to help maintain
    this distinction.

    hard_bio
    the rq->bio field now reflects the next bio which
    is to be submitted for i/o. Hence, the need for rq->hard_bio
    which keeps track of the next bio to be completed (this
    is the one used by end_that_request_first now, instead
    of rq->bio)

    nr_bio_segments
    this keeps track of how many more vecs remain
    to be submitted in the current bio (rq->bio). It is
    used to compute the current index into rq->bio which
    specifies the segment under submission.
    (rq_map_buffer for example uses this field to map
    the right buffer)

    nr_bio_sectors
    this keeps track of the number of sectors to
    be submitted in the current bio (rq->bio). It can be
    used to compute the remaining sectors in the current
    segment in the situation when it is the last segment.

    Now a subtle point about hard_cur_sectors. It reflects
    the number of sectors left to be completed in the
    _current_ segment under submission (i.e. the segment
    in rq->bio, and _not_ rq->hard_bio). This makes it
    possible to use it in rq_map_buffer to determine the
    relative offset in the current segment w.r.t what
    the bio indices might indicate.

    rq_map_buffer() is a macro that would be used to
    obtain a virtual address mapping corresponding to the
    current segment of the buffer being submitted for i/o.
    (It is expected to replace the use of private driver
    versions of the same operation e.g. ide_map_buffer()

    A new helper, process_that_request_first() has been
    introduced for updating submission state of the request
    without completing the corresponding bios. It can be used
    by code such as mult-count write which need to traverse
    multiple bio segments for each chunk of i/o submitted,
    where the chunk does not cover the entire request.


    Regards
    Suparna
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:22    [W:3.159 / U:1.408 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site