Documentation/block/biovecs.rst

Source file repositories/reference/linux-study-clean/Documentation/block/biovecs.rst

File Facts

System
Linux kernel
Corpus path
Documentation/block/biovecs.rst
Extension
.rst
Size
6994 bytes
Lines
151
Domain
Support Tooling And Documentation
Bucket
Documentation
Inferred role
Support Tooling And Documentation: documentation
Status
atlas-only

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

======================================
Immutable biovecs and biovec iterators
======================================

Kent Overstreet <kmo@daterainc.com>

As of 3.13, biovecs should never be modified after a bio has been submitted.
Instead, we have a new struct bvec_iter which represents a range of a biovec -
the iterator will be modified as the bio is completed, not the biovec.

More specifically, old code that needed to partially complete a bio would
update bi_sector and bi_size, and advance bi_idx to the next biovec. If it
ended up partway through a biovec, it would increment bv_offset and decrement
bv_len by the number of bytes completed in that biovec.

In the new scheme of things, everything that must be mutated in order to
partially complete a bio is segregated into struct bvec_iter: bi_sector,
bi_size and bi_idx have been moved there; and instead of modifying bv_offset
and bv_len, struct bvec_iter has bi_bvec_done, which represents the number of
bytes completed in the current bvec.

There are a bunch of new helper macros for hiding the gory details - in
particular, presenting the illusion of partially completed biovecs so that
normal code doesn't have to deal with bi_bvec_done.

 * Driver code should no longer refer to biovecs directly; we now have
   bio_iovec() and bio_iter_iovec() macros that return literal struct biovecs,
   constructed from the raw biovecs but taking into account bi_bvec_done and
   bi_size.

   bio_for_each_segment() has been updated to take a bvec_iter argument
   instead of an integer (that corresponded to bi_idx); for a lot of code the
   conversion just required changing the types of the arguments to
   bio_for_each_segment().

 * Advancing a bvec_iter is done with bio_advance_iter(); bio_advance() is a
   wrapper around bio_advance_iter() that operates on bio->bi_iter, and also
   advances the bio integrity's iter if present.

   There is a lower level advance function - bvec_iter_advance() - which takes
   a pointer to a biovec, not a bio; this is used by the bio integrity code.

As of 5.12 bvec segments with zero bv_len are not supported.

What's all this get us?
=======================

Having a real iterator, and making biovecs immutable, has a number of
advantages:

 * Before, iterating over bios was very awkward when you weren't processing
   exactly one bvec at a time - for example, bio_copy_data() in block/bio.c,
   which copies the contents of one bio into another. Because the biovecs
   wouldn't necessarily be the same size, the old code was tricky convoluted -
   it had to walk two different bios at the same time, keeping both bi_idx and
   and offset into the current biovec for each.

   The new code is much more straightforward - have a look. This sort of
   pattern comes up in a lot of places; a lot of drivers were essentially open
   coding bvec iterators before, and having common implementation considerably
   simplifies a lot of code.

 * Before, any code that might need to use the biovec after the bio had been
   completed (perhaps to copy the data somewhere else, or perhaps to resubmit
   it somewhere else if there was an error) had to save the entire bvec array
   - again, this was being done in a fair number of places.

 * Biovecs can be shared between multiple bios - a bvec iter can represent an
   arbitrary range of an existing biovec, both starting and ending midway
   through biovecs. This is what enables efficient splitting of arbitrary

Annotation

Implementation Notes