<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Immutable biovecs and biovec iterators — The Linux Kernel documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css?v=3918102e" />
<script src="../_static/documentation_options.js?v=5929fcd5"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Multi-Queue Block IO Queueing Mechanism (blk-mq)" href="blk-mq.html" />
<link rel="prev" title="BFQ (Budget Fair Queueing)" href="bfq-iosched.html" />
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
</head><body>
<div class="document">
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/logo.svg" alt="Logo of The Linux Kernel"/>
</a></p>
<h1 class="logo"><a href="../index.html">The Linux Kernel</a></h1>
<p class="blurb">6.18.50</p>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
<p>
<h3 class="kernel-toc-contents">Contents</h3>
<input type="checkbox" class="kernel-toc-toggle" id = "kernel-toc-toggle" checked>
<label class="kernel-toc-title" for="kernel-toc-toggle"></label>
<div class="kerneltoc" id="kerneltoc">
<ul>
<li class="toctree-l1"><a class="reference internal" href="../process/development-process.html">Development process</a></li>
<li class="toctree-l1"><a class="reference internal" href="../process/submitting-patches.html">Submitting patches</a></li>
<li class="toctree-l1"><a class="reference internal" href="../process/code-of-conduct.html">Code of conduct</a></li>
<li class="toctree-l1"><a class="reference internal" href="../maintainer/index.html">Maintainer handbook</a></li>
<li class="toctree-l1"><a class="reference internal" href="../process/index.html">All development-process docs</a></li>
</ul>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../core-api/index.html">Core API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../driver-api/index.html">Driver APIs</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../subsystem-apis.html">Subsystems</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../subsystem-apis.html#core-subsystems">Core subsystems</a></li>
<li class="toctree-l2"><a class="reference internal" href="../subsystem-apis.html#human-interfaces">Human interfaces</a></li>
<li class="toctree-l2"><a class="reference internal" href="../subsystem-apis.html#networking-interfaces">Networking interfaces</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="../subsystem-apis.html#storage-interfaces">Storage interfaces</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="../filesystems/index.html">Filesystems in the Linux kernel</a></li>
<li class="toctree-l3 current"><a class="reference internal" href="index.html">Block</a></li>
<li class="toctree-l3"><a class="reference internal" href="../cdrom/index.html">CD-ROM</a></li>
<li class="toctree-l3"><a class="reference internal" href="../scsi/index.html">SCSI Subsystem</a></li>
<li class="toctree-l3"><a class="reference internal" href="../target/index.html">TCM Virtual Device</a></li>
<li class="toctree-l3"><a class="reference internal" href="../nvme/index.html">NVMe Subsystem</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../subsystem-apis.html#other-subsystems">Other subsystems</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../locking/index.html">Locking</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../process/license-rules.html">Licensing rules</a></li>
<li class="toctree-l1"><a class="reference internal" href="../doc-guide/index.html">Writing documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../dev-tools/index.html">Development tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../dev-tools/testing-overview.html">Testing guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../kernel-hacking/index.html">Hacking guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../trace/index.html">Tracing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../fault-injection/index.html">Fault injection</a></li>
<li class="toctree-l1"><a class="reference internal" href="../livepatch/index.html">Livepatching</a></li>
<li class="toctree-l1"><a class="reference internal" href="../rust/index.html">Rust</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../admin-guide/index.html">Administration</a></li>
<li class="toctree-l1"><a class="reference internal" href="../kbuild/index.html">Build system</a></li>
<li class="toctree-l1"><a class="reference internal" href="../admin-guide/reporting-issues.html">Reporting issues</a></li>
<li class="toctree-l1"><a class="reference internal" href="../tools/index.html">Userspace tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../userspace-api/index.html">Userspace API</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../firmware-guide/index.html">Firmware</a></li>
<li class="toctree-l1"><a class="reference internal" href="../devicetree/index.html">Firmware and Devicetree</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../arch/index.html">CPU architectures</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../staging/index.html">Unsorted documentation</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../translations/index.html">Translations</a></li>
</ul>
</div>
<script type="text/javascript"> <!--
var sbar = document.getElementsByClassName("sphinxsidebar")[0];
let currents = document.getElementsByClassName("current")
if (currents.length) {
sbar.scrollTop = currents[currents.length - 1].offsetTop;
}
--> </script>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/block/biovecs.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="immutable-biovecs-and-biovec-iterators">
<h1>Immutable biovecs and biovec iterators<a class="headerlink" href="#immutable-biovecs-and-biovec-iterators" title="Link to this heading">¶</a></h1>
<p>Kent Overstreet <<a class="reference external" href="mailto:kmo%40daterainc.com">kmo<span>@</span>daterainc<span>.</span>com</a>></p>
<p>As of 3.13, biovecs should never be modified after a bio has been submitted.
Instead, we have a new <code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span> <span class="pre">bvec_iter</span></code> which represents a range of a biovec -
the iterator will be modified as the bio is completed, not the biovec.</p>
<p>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.</p>
<p>In the new scheme of things, everything that must be mutated in order to
partially complete a bio is segregated into <code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span> <span class="pre">bvec_iter</span></code>: bi_sector,
bi_size and bi_idx have been moved there; and instead of modifying bv_offset
and bv_len, <code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span> <span class="pre">bvec_iter</span></code> has bi_bvec_done, which represents the number of
bytes completed in the current bvec.</p>
<p>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.</p>
<blockquote>
<div><ul>
<li><p>Driver code should no longer refer to biovecs directly; we now have
<code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bio_iovec()</span></code> and <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bio_iter_iovec()</span></code> macros that return literal <code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span> <span class="pre">biovecs</span></code>,
constructed from the raw biovecs but taking into account bi_bvec_done and
bi_size.</p>
<p><code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bio_for_each_segment()</span></code> 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
<code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bio_for_each_segment()</span></code>.</p>
</li>
<li><p>Advancing a bvec_iter is done with <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bio_advance_iter()</span></code>; <a class="reference internal" href="../core-api/kernel-api.html#c.bio_advance" title="bio_advance"><code class="xref c c-func docutils literal notranslate"><span class="pre">bio_advance()</span></code></a> is a
wrapper around <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bio_advance_iter()</span></code> that operates on bio->bi_iter, and also
advances the bio integrity’s iter if present.</p>
<p>There is a lower level advance function - <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bvec_iter_advance()</span></code> - which takes
a pointer to a biovec, not a bio; this is used by the bio integrity code.</p>
</li>
</ul>
</div></blockquote>
<p>As of 5.12 bvec segments with zero bv_len are not supported.</p>
<section id="what-s-all-this-get-us">
<h2>What’s all this get us?<a class="headerlink" href="#what-s-all-this-get-us" title="Link to this heading">¶</a></h2>
<p>Having a real iterator, and making biovecs immutable, has a number of
advantages:</p>
<blockquote>
<div><ul>
<li><p>Before, iterating over bios was very awkward when you weren’t processing
exactly one bvec at a time - for example, <a class="reference internal" href="../filesystems/api-summary.html#c.bio_copy_data" title="bio_copy_data"><code class="xref c c-func docutils literal notranslate"><span class="pre">bio_copy_data()</span></code></a> 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.</p>
<p>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.</p>
</li>
<li><p>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.</p></li>
<li><p>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
bios. Note that this means we _only_ use bi_size to determine when we’ve
reached the end of a bio, not bi_vcnt - and the <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bio_iovec()</span></code> macro takes
bi_size into account when constructing biovecs.</p></li>
<li><p>Splitting bios is now much simpler. The old <a class="reference internal" href="../filesystems/api-summary.html#c.bio_split" title="bio_split"><code class="xref c c-func docutils literal notranslate"><span class="pre">bio_split()</span></code></a> didn’t even work on
bios with more than a single bvec! Now, we can efficiently split arbitrary
size bios - because the new bio can share the old bio’s biovec.</p>
<p>Care must be taken to ensure the biovec isn’t freed while the split bio is
still using it, in case the original bio completes first, though. Using
<a class="reference internal" href="../filesystems/api-summary.html#c.bio_chain" title="bio_chain"><code class="xref c c-func docutils literal notranslate"><span class="pre">bio_chain()</span></code></a> when splitting bios helps with this.</p>
</li>
<li><p>Submitting partially completed bios is now perfectly fine - this comes up
occasionally in stacking block drivers and various code (e.g. md and
bcache) had some ugly workarounds for this.</p>
<p>It used to be the case that submitting a partially completed bio would work
fine to _most_ devices, but since accessing the raw bvec array was the
norm, not all drivers would respect bi_idx and those would break. Now,
since all drivers _must_ go through the bvec iterator - and have been
audited to make sure they are - submitting partially completed bios is
perfectly fine.</p>
</li>
</ul>
</div></blockquote>
</section>
<section id="other-implications">
<h2>Other implications:<a class="headerlink" href="#other-implications" title="Link to this heading">¶</a></h2>
<blockquote>
<div><ul>
<li><p>Almost all usage of bi_idx is now incorrect and has been removed; instead,
where previously you would have used bi_idx you’d now use a bvec_iter,
probably passing it to one of the helper macros.</p>
<p>I.e. instead of using <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bio_iovec_idx()</span></code> (or bio->bi_iovec[bio->bi_idx]), you
now use <code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">bio_iter_iovec()</span></code>, which takes a bvec_iter and returns a
literal <code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span> <span class="pre">bio_vec</span></code> - constructed on the fly from the raw biovec but
taking into account bi_bvec_done (and bi_size).</p>
</li>
<li><p>bi_vcnt can’t be trusted or relied upon by driver code - i.e. anything that
doesn’t actually own the bio. The reason is twofold: firstly, it’s not
actually needed for iterating over the bio anymore - we only use bi_size.
Secondly, when cloning a bio and reusing (a portion of) the original bio’s
biovec, in order to calculate bi_vcnt for the new bio we’d have to iterate
over all the biovecs in the new bio - which is silly as it’s not needed.</p>
<p>So, don’t use bi_vcnt anymore.</p>
</li>
<li><p>The current interface allows the block layer to split bios as needed, so we
could eliminate a lot of complexity particularly in stacked drivers. Code
that creates bios can then create whatever size bios are convenient, and
more importantly stacked drivers don’t have to deal with both their own bio
size limitations and the limitations of the underlying devices. Thus
there’s no need to define -><code class="xref c c-func broken_xref docutils literal notranslate"><span class="pre">merge_bvec_fn()</span></code> callbacks for individual block
drivers.</p></li>
</ul>
</div></blockquote>
</section>
<section id="usage-of-helpers">
<h2>Usage of helpers:<a class="headerlink" href="#usage-of-helpers" title="Link to this heading">¶</a></h2>
<ul class="simple">
<li><p>The following helpers whose names have the suffix of <cite>_all</cite> can only be used
on non-BIO_CLONED bio. They are usually used by filesystem code. Drivers
shouldn’t use them because the bio may have been split before it reached the
driver.</p></li>
</ul>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>bio_for_each_segment_all()
bio_for_each_bvec_all()
bio_first_bvec_all()
bio_first_page_all()
bio_first_folio_all()
bio_last_bvec_all()
</pre></div>
</div>
<ul>
<li><p>The following helpers iterate over single-page segment. The passed ‘<code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span>
<span class="pre">bio_vec</span></code>’ will contain a single-page IO vector during the iteration:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>bio_for_each_segment()
bio_for_each_segment_all()
</pre></div>
</div>
</li>
<li><p>The following helpers iterate over multi-page bvec. The passed ‘<code class="xref c c-struct broken_xref docutils literal notranslate"><span class="pre">struct</span>
<span class="pre">bio_vec</span></code>’ will contain a multi-page IO vector during the iteration:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>bio_for_each_bvec()
bio_for_each_bvec_all()
rq_for_each_bvec()
</pre></div>
</div>
</li>
</ul>
</section>
</section>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©The kernel development community.
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 8.1.3</a>
& <a href="https://alabaster.readthedocs.io">Alabaster 0.7.16</a>
|
<a href="../_sources/block/biovecs.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>