<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>dxu&apos;s blog</title><id>https://dxuuu.xyz/</id><updated>2026-01-01T10:04:04-08:00</updated><author><name>Daniel Xu</name></author><link href="https://dxuuu.xyz/atom.xml" rel="self"/><link href="https://dxuuu.xyz" rel="alternate"/><entry><title>Optimistic concurrency control in ATS</title><id>https://dxuuu.xyz/optimistic-concurrency.html</id><updated>2017-04-09T17:12:48-07:00</updated><link href="https://dxuuu.xyz/optimistic-concurrency.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Optimistic concurrency control in ATS&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Optimistic concurrency control in ATS&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;&lt;a
href=&quot;https://en.wikipedia.org/wiki/Optimistic_concurrency_control&quot;&gt;Optimistic
concurrency control&lt;/a&gt; is one of the tools ATS uses to create a high
performance logging subsystem. &lt;a
href=&quot;http://stackoverflow.com/questions/15056237/which-is-more-efficient-basic-mutex-lock-or-atomic-integer&quot;&gt;For
various reasons&lt;/a&gt;, mutexes were deemed to be too expensive to be used
in the logging fast path. Instead, ATS uses an optimistic
commit/rollback strategy to synchronize shared memory. The most typical
use of the commit/rollback strategy in the logging subsystem is when the
current &lt;a
href=&quot;https://github.com/apache/trafficserver/blob/master/proxy/logging/LogBuffer.h&quot;&gt;LogBuffer&lt;/a&gt;
is full and we need to allocate a new LogBuffer. Since multiple threads
can be writing to the current LogBuffer at any given time, ATS needs a
way to synchronize access to the current LogBuffer.&lt;/p&gt;
&lt;p&gt;The pointer to the current LogBuffer is defined &lt;a
href=&quot;https://github.com/apache/trafficserver/blob/master/proxy/logging/LogObject.h#L298&quot;&gt;here&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;298&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot; style=&quot;counter-reset: source-line 297;&quot;&gt;&lt;span id=&quot;function-298&quot;&gt;&lt;a href=&quot;#function-298&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;volatile&lt;/span&gt; head_p &lt;span class=&quot;va&quot;&gt;m_log_buffer&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;// current work buffer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;head_p&lt;/code&gt; is defined &lt;a
href=&quot;https://github.com/apache/trafficserver/blob/master/lib/ts/ink_queue.h#L86&quot;&gt;in
lib/ts/ink_queue.h&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;86&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot; style=&quot;counter-reset: source-line 85;&quot;&gt;&lt;span id=&quot;function-86&quot;&gt;&lt;a href=&quot;#function-86&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#if (defined(&lt;/span&gt;&lt;span class=&quot;ot&quot;&gt;__i386__&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;) || defined(__arm__) || defined(__mips__)) &amp;amp;&amp;amp; (SIZEOF_VOIDP == 4)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-87&quot;&gt;&lt;a href=&quot;#function-87&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int32_t&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;version_type&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-88&quot;&gt;&lt;a href=&quot;#function-88&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int64_t&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;data_type&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-89&quot;&gt;&lt;a href=&quot;#function-89&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#elif TS_HAS_128BIT_CAS&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-90&quot;&gt;&lt;a href=&quot;#function-90&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int64_t&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;version_type&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-91&quot;&gt;&lt;a href=&quot;#function-91&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;typedef&lt;/span&gt; __int128_t &lt;span class=&quot;dt&quot;&gt;data_type&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-92&quot;&gt;&lt;a href=&quot;#function-92&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#else&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-93&quot;&gt;&lt;a href=&quot;#function-93&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int64_t&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;version_type&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-94&quot;&gt;&lt;a href=&quot;#function-94&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int64_t&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;data_type&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-95&quot;&gt;&lt;a href=&quot;#function-95&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#endif&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-96&quot;&gt;&lt;a href=&quot;#function-96&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-97&quot;&gt;&lt;a href=&quot;#function-97&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-98&quot;&gt;&lt;a href=&quot;#function-98&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;pointer&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-99&quot;&gt;&lt;a href=&quot;#function-99&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;version_type&lt;/span&gt; version&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-100&quot;&gt;&lt;a href=&quot;#function-100&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; s&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-101&quot;&gt;&lt;a href=&quot;#function-101&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-102&quot;&gt;&lt;a href=&quot;#function-102&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;data_type&lt;/span&gt; data&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-103&quot;&gt;&lt;a href=&quot;#function-103&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; head_p&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;where &lt;code&gt;s.pointer&lt;/code&gt; is a pointer we want to serialize access
for and &lt;code&gt;s.version&lt;/code&gt; is a counter to tell when
&lt;code&gt;head_p&lt;/code&gt; has been modified. The version, at least in the
context of a LogBuffer, lets us know how many threads are currently
holding a reference to &lt;code&gt;s.pointer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But why a union? The key insight here is that &lt;code&gt;data_type&lt;/code&gt;
and &lt;code&gt;struct s&lt;/code&gt; are the same size. This means that we can do
an atomic &lt;a
href=&quot;https://en.wikipedia.org/wiki/Compare-and-swap&quot;&gt;CAS&lt;/a&gt; on
&lt;code&gt;s&lt;/code&gt; by simply referring to &lt;code&gt;head_p.data&lt;/code&gt;. This
lets us avoid complicated bit fiddling while still being able to still
do accesses like &lt;code&gt;head_p.s.pointer&lt;/code&gt;. But wait, isn’t this
undefined? As it turns out, according to the &lt;a
href=&quot;http://en.cppreference.com/w/cpp/language/union&quot;&gt;C++ spec&lt;/a&gt;, it
is in fact&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“undefined behavior to read from the member of the union that wasn’t
most recently written.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;However, that sentence is quickly followed by&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Many compilers implement, as a non-standard language extension, the
ability to read inactive members of a union.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ATS is relying on non-standard language extensions, whoopee. That
being said, ATS has been in use for the better part of two decades, so
if I were you I wouldn’t start losing sleep over this just yet.&lt;/p&gt;
&lt;p&gt;When we actually want to change the values held in
&lt;code&gt;head_p&lt;/code&gt;, we obey this pattern:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;415&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot; style=&quot;counter-reset: source-line 414;&quot;&gt;&lt;span id=&quot;function-415&quot;&gt;&lt;a href=&quot;#function-415&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-416&quot;&gt;&lt;a href=&quot;#function-416&quot;&gt;&lt;/a&gt;  INK_QUEUE_LD&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old_h&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;m_log_buffer&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-417&quot;&gt;&lt;a href=&quot;#function-417&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;FREELIST_POINTER&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old_h&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; FREELIST_POINTER&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;h&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-418&quot;&gt;&lt;a href=&quot;#function-418&quot;&gt;&lt;/a&gt;    ink_atomic_increment&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;buffer&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;m_references&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-419&quot;&gt;&lt;a href=&quot;#function-419&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-420&quot;&gt;&lt;a href=&quot;#function-420&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// another thread should be taking care of creating a new&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-421&quot;&gt;&lt;a href=&quot;#function-421&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// buffer, so delete new_buffer and try again&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-422&quot;&gt;&lt;a href=&quot;#function-422&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;delete&lt;/span&gt; new_buffer&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-423&quot;&gt;&lt;a href=&quot;#function-423&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-424&quot;&gt;&lt;a href=&quot;#function-424&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-425&quot;&gt;&lt;a href=&quot;#function-425&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;write_pointer_version&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;m_log_buffer&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; old_h&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; new_buffer&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There’s a lot of macro magic going on here. To spare you the details,
here’s a quick summary of what each macro does:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;INK_QUEUE_LD(x, y)&lt;/code&gt;: Atomic copy-by-value of
&lt;code&gt;y&lt;/code&gt; into &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FREELIST_POINTER(x)&lt;/code&gt;: Maps to
&lt;code&gt;x.s.pointer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ink_atomic_increment(x, y)&lt;/code&gt;: Atomically increments
&lt;code&gt;x&lt;/code&gt; by &lt;code&gt;y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;write_pointer_version(a, b, c, d)&lt;/code&gt;: Atomic CAS between
&lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; with the new value being a
&lt;code&gt;head_p&lt;/code&gt; with &lt;code&gt;s.pointer = c&lt;/code&gt; and
&lt;code&gt;s.version = d&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The entire do-while loop of goodness guarantees that anything
executed inside of the loop body is done so atomically. This is
opportunistic because if another thread comes along and changes
&lt;code&gt;m_log_buffer&lt;/code&gt; right after we call
&lt;code&gt;INK_QUEUE_LD()&lt;/code&gt;, the CAS inside
&lt;code&gt;write_pointer_version(..)&lt;/code&gt; will catch the change and abort
the write. The loop repeats until we succeed in atomically performing
the actions inside the loop body.&lt;/p&gt;
&lt;p&gt;At first this may seem like a better, more lightweight solution over
locks, but it does come with certain drawbacks:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;If the critical section is highly contested, then performance
quickly degrades. Every failed transaction generates more work, and more
work generates more failed transactions. On the other hand, mutexes will
put the thread to sleep at the added cost of a context switch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is easy to create a &lt;a
href=&quot;https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use&quot;&gt;time
to check to time of use&lt;/a&gt; bug with this method. If we forget to wrap
the expression in a do-while with the correct terminating condition, we
expose ourselves to a TOCTTOU bug. As with the C++ language itself, this
form of concurrency control gives the programmer a lot of power at the
expense of naive safety.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Tracking down a race condition in the Apache Trafficserver logging subsystem</title><id>https://dxuuu.xyz/ats-logging-race-condition.html</id><updated>2017-04-22T09:44:10-07:00</updated><link href="https://dxuuu.xyz/ats-logging-race-condition.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Tracking down a race condition in the Apache Trafficserver logging subsystem&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Tracking down a race condition in the Apache
Trafficserver logging subsystem&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;TODO: make this post more coherent&lt;/p&gt;
&lt;p&gt;Lately at work, I’ve been tracking down a log corruption issue inside
of &lt;a href=&quot;https://github.com/apache/trafficserver&quot;&gt;Trafficserver’s&lt;/a&gt;
&lt;a
href=&quot;https://github.com/apache/trafficserver/tree/master/proxy/logging&quot;&gt;logging
subsystem&lt;/a&gt;. The issue is that there’s often random data inserted into
the middle of log statements. Specifically, these are access logs that a
lot of Yahoo’s analytics are based off of, so this is kind of an
important issue.&lt;/p&gt;
&lt;p&gt;Now before we get into the details of the bug, there are a few things
I have to say about the logging subsystem. I’ve not had too much
experience with the rest of the code, but ATS is one of those old code
bases where documentation is very sparse. In some cases, the only
existing documentation is &lt;a
href=&quot;https://github.com/apache/trafficserver/blob/master/proxy/logging/Log.h#L47&quot;&gt;flat
out wrong&lt;/a&gt;. Furthermore, when Yahoo open sourced this project about 8
years ago, the project lost all of the commit history. This means that
git-blame will take us only as far back as the initial open source
commit in 2009. This makes for a very unpleasant time tracking down the
reason a particular section of code is the way it is.&lt;/p&gt;
&lt;p&gt;Now back to the bug. To make things even more challenging, this
corruption issue only occurs under high load. What I’m really trying to
say is that this bug not only happens in production, but also in a very
specific region of the United States. Fancy that. Needless to say, this
isn’t something I can debug live, much less reproduce locally. For those
of you that have experienced this pain before, you’re probably screaming
“RACE CONDITION”. Unfortunately, you’re probably right. Seeing as I
haven’t quite solved this bug yet, I’ll keep this post updated with all
of the strategies and dead ends I come across.&lt;/p&gt;
&lt;h2 id=&quot;the-logbuffer&quot;&gt;The LogBuffer&lt;/h2&gt;
&lt;p&gt;There’s a lot of interesting design choices that go into making a
high performance logging system. I’m not going to claim I’m some expert
(yet), so I’ll just jot down the things I’ve noticed and/or
surmised.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Heap allocations are expensive.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Heap allocations are many times more expensive than stack
allocations, so we want to be avoiding heap allocations as often as we
can. This kind of incentive often leads to things like memory pools and
buffer spaces.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Excessivily writing to disk is expensive.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We don’t want to write each individual log line to disk immediately,
since that incurs significant overhead. Instead, we want to buffer a
bunch of log entries and flush them all at once. This is where the
LogBuffer comes in.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;a
href=&quot;https://github.com/apache/trafficserver/blob/master/proxy/logging/LogBuffer.h&quot;&gt;LogBuffer&lt;/a&gt;
class is designed to provide a thread-safe mechanism to store log
entries before they’re flushed. To reduce system call overhead,
LogBuffers are designed to avoid heavy-weight mutexes in favor of using
lightweight atomics built on top of &lt;a
href=&quot;https://en.wikipedia.org/wiki/Compare-and-swap&quot;&gt;compare-and-swap&lt;/a&gt;
&lt;a
href=&quot;https://github.com/apache/trafficserver/blob/master/proxy/logging/LogBuffer.cc#L270&quot;&gt;operations&lt;/a&gt;.
When a caller wants to write into a LogBuffer, the caller “checks out” a
segment of the buffer to write into. LogBuffer makes sure that no two
callers are served overlapping segments. To illustrate this point,
consider this diagram of a buffer:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          +--------------------------------+
          | thread_1&amp;#39;s segment             |
          |--------------------------------|
          | thread_2&amp;#39;s segment             |
          |                                |
          |                                |
          |--------------------------------|
          | thread_3&amp;#39;s segment             |
          |                                |
          |                                |
          |                                |
          |--------------------------------|
          | thread_4&amp;#39;s segment             |
          |--------------------------------|
          | &amp;lt;unused&amp;gt;                       |
          |                                |
          |                                |
          |                                |
          |                                |
          |                                |
          |                                |
          |                                |
          +--------------------------------+&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this manner, since no two threads are writing in the other’s
segment, we avoid race conditions on the actual logging. This also makes
LogBuffer’s critical section extremely small. In fact, the only time we
need to enter a critical section is when we do the book keeping to keep
track of which segments are checked out.&lt;/p&gt;
&lt;p&gt;When a thread wants to write a log entry, it does so by calling the
global &lt;code&gt;Log::access(...)&lt;/code&gt; function.
&lt;code&gt;Log::access(...)&lt;/code&gt; in turn does a bunch of work eventually
culminating in checking out a buffer segment from an active LogBuffer,
serializing the log entry into the LogBuffer segment, and checking the
LogBuffer segment back in. Between the inclusive checkout and checkin
operations is where I currently believe the bug to be.&lt;/p&gt;
&lt;h2 id=&quot;lead-1&quot;&gt;Lead 1&lt;/h2&gt;
&lt;p&gt;The first step I took to try and narrow down this bug was to run &lt;a
href=&quot;https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual&quot;&gt;TSan&lt;/a&gt;
on a local instance. TSan suggested that (1) could be an issue:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;LogBuffer&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;LB_ResultCode&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;LogBuffer&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;checkout_write&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;write_offset&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;size_t&lt;/span&gt; write_size&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;    new_s &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; old_s &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;m_state&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;co&quot;&gt;// (1)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old_s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;full&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;       &lt;span class=&quot;co&quot;&gt;// (2)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;++&lt;/span&gt;new_s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;num_writers&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;      new_s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset &lt;span class=&quot;op&quot;&gt;+=&lt;/span&gt; actual_write_size&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;++&lt;/span&gt;new_s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;s&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;num_entries&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;co&quot;&gt;// essentially cas(m_state, old_s, new_s)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;switch_state&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old_s&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; new_s&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;   &lt;span class=&quot;co&quot;&gt;// (3)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;// we succeded in setting the new state&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(--&lt;/span&gt;retries&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After reasoning with this code for a bit, I realized that if
&lt;code&gt;m_state&lt;/code&gt; was changed by another thread between assignments
of &lt;code&gt;new_s&lt;/code&gt; and &lt;code&gt;old_s&lt;/code&gt;, then this could very well
explain the data corruption issue I was facing. The reason being is that
another thread could have given away the last available segment of the
current LogBuffer object and marked &lt;code&gt;m_state&lt;/code&gt; as full.
However, our current thread’s &lt;code&gt;old_s&lt;/code&gt; still reports the state
as being NOT full on (2). I let myself celebrate for a few minutes
before realizing it couldn’t be &lt;em&gt;this&lt;/em&gt; easy. Unfortunately I was
right.&lt;/p&gt;
&lt;p&gt;My previous assumtion that &lt;code&gt;new_s&lt;/code&gt; and &lt;code&gt;old_s&lt;/code&gt;
could hold different values was wrong. If you decompile the expression
&lt;code&gt;new_s = old_s = m_state&lt;/code&gt;, you’ll see something like
this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        movl    -20(%rbp), %eax
        movl    %eax, -4(%rbp)
        movl    -4(%rbp), %eax
        movl    %eax, -8(%rbp)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;-4(%rbp)&lt;/code&gt; is &lt;code&gt;old_s&lt;/code&gt; and
&lt;code&gt;-8(%rbp)&lt;/code&gt; is &lt;code&gt;new_s&lt;/code&gt;. What this snippet of
assembly is saying is essentially this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        %eax = m_state
        old_s = %eax
        %eax = old_s
        new_s = %eax&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Too bad for me, this means that &lt;code&gt;old_s&lt;/code&gt; and
&lt;code&gt;new_s&lt;/code&gt; &lt;strong&gt;have&lt;/strong&gt; to be the same value. Dead end
:(. However, I’m not convinced the race condition &lt;em&gt;isn’t&lt;/em&gt; in
LogBuffer just yet.&lt;/p&gt;
&lt;h2 id=&quot;lead-2&quot;&gt;Lead 2&lt;/h2&gt;
&lt;p&gt;After delving into the depths of the LogBuffer code, I felt safe in
assuming there weren’t any bugs in that area of the codebase. So I took
a step back and examined the LogObject code. The way LogObjects and
LogBuffers interact is not unnatural. The general gist of it is that
each LogObject instance represents one logical logging “object” in ATS.
For example, if there was one access log in squid format and another as
a named pipe, then ATS would be keeping track of two LogObjects. The
details of where all the bits and bytes should go are encapsulated in
the LogObject implementation. This is orthogonal to the LogBuffer
because as we discussed earlier, the LogBuffer is a mechanism to prevent
excessive disk flushes whereas the LogObject is a logical object.&lt;/p&gt;
&lt;p&gt;I also recently wrote an architectural overview of the ATS logging
subsystem. As of the time of this writing, the pull request is sitting
in a review queue in the upstream project. Hopefully when it’s merged,
I’ll remember to update it here.&lt;/p&gt;
&lt;p&gt;Now to the details of the issue. Every LogObject holds on to at most
one LogBuffer at any given time. The LogObject uses the LogBuffer to
cache writes into the filesystem/network/OS. It is safe to assume that
at some point every LogBuffer will get full. When said LogBuffer is
full, we need to 1) flush the LogBuffer to some underlying structure and
2) allocate a new LogBuffer for the LogObject and do an atomic swap. The
following code is used to swap the old LogBuffer with the freshly
allocated LogBuffer:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;407&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot; style=&quot;counter-reset: source-line 406;&quot;&gt;&lt;span id=&quot;function-407&quot;&gt;&lt;a href=&quot;#function-407&quot;&gt;&lt;/a&gt; &lt;span class=&quot;cf&quot;&gt;case&lt;/span&gt; LogBuffer&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;LB_FULL_NO_WRITERS&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-408&quot;&gt;&lt;a href=&quot;#function-408&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;co&quot;&gt;// no more room in current buffer, create a new one&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-409&quot;&gt;&lt;a href=&quot;#function-409&quot;&gt;&lt;/a&gt;      new_buffer &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;new&lt;/span&gt; LogBuffer&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Log&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;config&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;log_buffer_size&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-410&quot;&gt;&lt;a href=&quot;#function-410&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-411&quot;&gt;&lt;a href=&quot;#function-411&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;co&quot;&gt;// swap the new buffer for the old one&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-412&quot;&gt;&lt;a href=&quot;#function-412&quot;&gt;&lt;/a&gt;      INK_WRITE_MEMORY_BARRIER&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-413&quot;&gt;&lt;a href=&quot;#function-413&quot;&gt;&lt;/a&gt;      head_p old_h&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-414&quot;&gt;&lt;a href=&quot;#function-414&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-415&quot;&gt;&lt;a href=&quot;#function-415&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-416&quot;&gt;&lt;a href=&quot;#function-416&quot;&gt;&lt;/a&gt;        INK_QUEUE_LD&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old_h&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;m_log_buffer&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-417&quot;&gt;&lt;a href=&quot;#function-417&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;FREELIST_POINTER&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old_h&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; FREELIST_POINTER&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;h&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-418&quot;&gt;&lt;a href=&quot;#function-418&quot;&gt;&lt;/a&gt;          ink_atomic_increment&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;buffer&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;m_references&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-419&quot;&gt;&lt;a href=&quot;#function-419&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-420&quot;&gt;&lt;a href=&quot;#function-420&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;co&quot;&gt;// another thread should be taking care of creating a new&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-421&quot;&gt;&lt;a href=&quot;#function-421&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;co&quot;&gt;// buffer, so delete new_buffer and try again&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-422&quot;&gt;&lt;a href=&quot;#function-422&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;kw&quot;&gt;delete&lt;/span&gt; new_buffer&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-423&quot;&gt;&lt;a href=&quot;#function-423&quot;&gt;&lt;/a&gt;          &lt;span class=&quot;cf&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-424&quot;&gt;&lt;a href=&quot;#function-424&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-425&quot;&gt;&lt;a href=&quot;#function-425&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;write_pointer_version&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;m_log_buffer&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; old_h&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; new_buffer&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-426&quot;&gt;&lt;a href=&quot;#function-426&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-427&quot;&gt;&lt;a href=&quot;#function-427&quot;&gt;&lt;/a&gt;     &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;FREELIST_POINTER&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old_h&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; FREELIST_POINTER&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;h&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-428&quot;&gt;&lt;a href=&quot;#function-428&quot;&gt;&lt;/a&gt;        ink_atomic_increment&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;buffer&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;m_references&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; FREELIST_VERSION&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old_h&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-429&quot;&gt;&lt;a href=&quot;#function-429&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-430&quot;&gt;&lt;a href=&quot;#function-430&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; idx &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;m_buffer_manager_idx&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;m_flush_threads&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-431&quot;&gt;&lt;a href=&quot;#function-431&quot;&gt;&lt;/a&gt;        Debug&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;log-logbuffer&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;adding buffer &lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;st&quot;&gt; to flush list after checkout&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;get_id&lt;span class=&quot;op&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-432&quot;&gt;&lt;a href=&quot;#function-432&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;va&quot;&gt;m_buffer_manager&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;idx&lt;span class=&quot;op&quot;&gt;].&lt;/span&gt;add_to_flush_queue&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-433&quot;&gt;&lt;a href=&quot;#function-433&quot;&gt;&lt;/a&gt;        Log&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;preproc_notify&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;idx&lt;span class=&quot;op&quot;&gt;].&lt;/span&gt;signal&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-434&quot;&gt;&lt;a href=&quot;#function-434&quot;&gt;&lt;/a&gt;        buffer &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-435&quot;&gt;&lt;a href=&quot;#function-435&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-436&quot;&gt;&lt;a href=&quot;#function-436&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-437&quot;&gt;&lt;a href=&quot;#function-437&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we look closely at line 417, we notice that we identify potential
race conditions very strangely. So the current thread, thread 1, attemps
to swap the old LogBuffer with the new LogBuffer. Suppose that another
thread, thread 2, is also doing the same thing at the same time. Only
one of these operations should succeed because otherwise we start
leaking memory. So naturally, thread 1 needs a mechanism to detect when
a LogBuffer has been pulled out from underneath it. On line 417, we see
that we identify this pulling out by comparing pointers. It makes the
implicit assumption that if the pointer value has changed, then the
LogBuffer must have changed. While this logic is sound in the “forward
direction” (ie if the pointer changes then the buffer has changed), the
converse is not true. Suppose we free the old LogBuffer and then
immediately allocate another LogBuffer. It is conceivable that the
pointer will remain the same. That is to say, if the LogBuffer has
changed, there is no guarantee that the pointer to the new LogBuffer
will be any different than the old pointer. You might imagine this can
cause a few issues. And while you’re probably not wrong, the truth is
equally unappealing.&lt;/p&gt;
&lt;p&gt;As it turns out, we always allocate a new LogBuffer before we free
the old LogBuffer. On line 409, we allocate the new LogBuffer. Later on
in line 432, we free the old LogBuffer. If these operations are
sequential (and we have no reason to believe otherwise), then no race
condition is possible. While this was an interesting examination into
the LogBuffer swapping code, it was ultimately another dead end.&lt;/p&gt;
&lt;h2 id=&quot;the-end-for-now&quot;&gt;The end… for now?&lt;/h2&gt;
&lt;p&gt;It’s been about a week and a half into the investigation. I thought
it might be good to get some fresh samples of the log corruption to see
if anything new or novel has happened to further my debugging, so I
asked for some new samples. As it turns out, the issue has stopped
happening in production. What this means is that even if I found a
potential fix, there would be no way to verify the effectiveness of the
fix. That means if there’s not an obvious problem, then there isn’t an
obvious solution.&lt;/p&gt;
&lt;p&gt;So until this issue crops up again, work on this bug has to be put on
hold.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Creating a basic Linux kernel development setup</title><id>https://dxuuu.xyz/kernel-development-setup.html</id><updated>2017-05-09T21:25:02-07:00</updated><link href="https://dxuuu.xyz/kernel-development-setup.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Creating a basic Linux kernel development setup&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Creating a basic Linux kernel development setup&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Linux kernel development is something I’ve been wanting to get into
for a long time now. I’ve tried and failed to get started over the
years, but I finally think I’m in a place where I can do some real
kernel work. But before we can dive into kernel development, we have to
have a working development setup.&lt;/p&gt;
&lt;p&gt;This document will be a rough outline into&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Compiling the kernel&lt;/li&gt;
&lt;li&gt;Setting up a initramfs for the kernel to boot into&lt;/li&gt;
&lt;li&gt;Booting into our setup&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;compiling-the-kernel&quot;&gt;Compiling the kernel&lt;/h3&gt;
&lt;p&gt;Compiling the kernel is a relatively straightforward task. First, do
as you would any other open source project and fork Linus’ &lt;a
href=&quot;https://github.com/torvalds/linux&quot;&gt;kernel repo&lt;/a&gt; on Github.
Alternatively, you could clone his kernel.org repo, but it doesn’t
really matter.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into your cloned repo and run
&lt;code&gt;make defconfig; make x86_64_defconfig; make kvmconfig&lt;/code&gt;. This
will generate a pretty good set of default configs (located in
&lt;code&gt;.config&lt;/code&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make defconfig&lt;/code&gt; generates a default
&lt;code&gt;.config&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make x86_64_defconfig&lt;/code&gt; makes some x86 specific changes
to the new &lt;code&gt;.config&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make kvmconfig&lt;/code&gt; enables some kvm specific kernel options
that we will later take advantage of&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally run &lt;code&gt;make&lt;/code&gt; to compile the kernel. Hint: use
&lt;code&gt;make -jN&lt;/code&gt;, where &lt;code&gt;N&lt;/code&gt; is the number of logical
cores you have on your CPU for faster compilation.&lt;/p&gt;
&lt;h3 id=&quot;setting-up-initramfs&quot;&gt;Setting up initramfs&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Initramfs&quot;&gt;initramfs&lt;/a&gt; is
the initial memory only filesystem the Linux kernel uses during boot. It
is necessary to solve some of the boot time chicken-or-egg type problems
that may arise. Read more from the link if curious. If we were to try
and boot into a bare kernel, we would get a kernel panic about not being
able to mount a rootfs. This is expected because of the previous
reasons. Thus, we need to create our own initramfs.&lt;/p&gt;
&lt;p&gt;There are a number of ways to create an initial ramdisk. We are going
to roll our own busybox ramdisk. Although it’s not the easiest way, it’s
rather transparent and somewhat easy to understand.&lt;/p&gt;
&lt;p&gt;First, clone the &lt;a href=&quot;https://git.busybox.net/busybox&quot;&gt;busybox
repo&lt;/a&gt;. Then, &lt;code&gt;cd&lt;/code&gt; into the directory and run
&lt;code&gt;make defconfig&lt;/code&gt;. Sounds familiar, right? Next, run
&lt;code&gt;make menuconfig&lt;/code&gt; and make sure the static binary option is
ticked. You may need to dig around in that interface, but it’s there.
Finding it is left as an exercise to the reader. Finally, run
&lt;code&gt;make; make install&lt;/code&gt;. This will put all the symlinked busybox
“binaries” into &lt;code&gt;_install&lt;/code&gt; of the current directory.&lt;/p&gt;
&lt;p&gt;As for the initramfs, create a folder for holding all the
intermediate files. For this guide, we’ll assume it’s in
&lt;code&gt;~/dev/initramfs&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir -pv ~/dev/initramfs/x86-busybox
cd !$
mkdir -pv {bin,sbin,etc,proc,sys,usr/{bin,sbin}}
cp -av ~/dev/busybox/_install/* .&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What this does is create a basic filesystem layout for our custom
Linux kernel to boot into. Obviously some utilities that rely on a more
complicated filesystem layout won’t work. Finding out which ones is
another exercise left to the reader.&lt;/p&gt;
&lt;p&gt;Now we need an init script. All Linux systems need an inital process
to startup all the userspace fun, and this is no different. Plop this
simple init script into &lt;code&gt;~/dev/initramfs&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/sh

mount -t proc none /proc
mount -t sysfs none /sys

echo -e &amp;quot;\nBoot took $(cut -d&amp;#39; &amp;#39; -f1 /proc/uptime) seconds\n&amp;quot;

exec /bin/sh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Afterwards, run &lt;code&gt;chmod +x init&lt;/code&gt; to give the init script
execution bits. After this, we’re ready to &lt;code&gt;cpio&lt;/code&gt; the whole
initramfs up. This &lt;code&gt;cpio&lt;/code&gt; command will (g)zip up all of our
files and folders up into something the kernel can work with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find . -print0 \
    | cpio --null -ov --format=newc \
    | gzip -9 &amp;gt; ~/dev/initramfs/initramfs-busybox-x86.cpio.gz&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;booting&quot;&gt;Booting&lt;/h3&gt;
&lt;p&gt;Ah, for the moment of truth. Truth to be told, it’s a rather
underwhelming command. But the results are exciting!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;qemu-system-x86_64 \
    -kernel ~/dev/linux/arch/x86_64/boot/bzImage \
    -initrd ~/dev/initramfs/initramfs-busybox-x86.cpio.gz \
    -enable-kvm&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice how we use those fancy kvm settings after all. The qemu
command should pop open a small window with a small Linux environment
running inside. All your classic userspace utilities should be working
courtesy of busybox.&lt;/p&gt;
&lt;h3 id=&quot;addendums&quot;&gt;Addendums&lt;/h3&gt;
&lt;p&gt;I used a lot of resources on the internet to arrive at this process,
&lt;a
href=&quot;https://mgalgs.github.io/2015/05/16/how-to-build-a-custom-linux-kernel-for-qemu-2015-edition.html&quot;&gt;but
one resource stands out in particular&lt;/a&gt;.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>systemd and sd_notify(3)</title><id>https://dxuuu.xyz/systemd-sdnotify.html</id><updated>2017-11-13T07:59:14-08:00</updated><link href="https://dxuuu.xyz/systemd-sdnotify.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;systemd and sd_notify(3)&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;systemd and sd_notify(3)&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;A little bit of background first: I’ve been spending a lot of time
recently mucking around with systemd and its process management
features. The latest project I was working on involved implementing hot
upgrades on a running server. This means that when used, clients of said
server don’t experience any disruption other than a very small latency
bubble. No connections are torn down and no sockets are closed
client-side. Fancy right? I’ll save the details for how that was done in
a later post. For now, we discuss onto the systemd side of the
equation.&lt;/p&gt;
&lt;p&gt;So implementing 0-downtime was fun and tricky, but the feature itself
was largely contained in C++ land, far away from systemd. The systemd
interaction with the server binary works a little something like
this.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;         Process 1                       Process 2
----------------------------|---------------------------------
systemctl start server

&amp;lt;serving clients&amp;gt;

                                   &amp;lt;want to upgrade server&amp;gt;
                                     ./server -upgrade

&amp;lt;hands over client conns&amp;gt;


                                   &amp;lt;receives client conns&amp;gt;
                                            (1)

&amp;lt;exits&amp;gt;
  (2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty straight forward right? Assuming that Process 1 is a systemd
controlled process (meaning systemd started the process), as point (2),
systemd is going to detect Process 1 exited, and will
&lt;code&gt;systemctl restart&lt;/code&gt; the process, negating the hot upgrade we
worked so hard to implement. How do we prevent this?&lt;/p&gt;
&lt;p&gt;As it turns out, systemd has a little know (to me) service type
called &lt;code&gt;Type=notify&lt;/code&gt;. This means that the process will link
with systemd headers and explicitly tell systemd about the service state
and optionally, &lt;em&gt;gasp&lt;/em&gt;, the main PID of the running process,
typically at point (1).&lt;/p&gt;
&lt;h2 id=&quot;proof-of-concept-aka-show-me-the-code&quot;&gt;Proof of concept (aka
show me the code)&lt;/h2&gt;
&lt;h3 id=&quot;server.c&quot;&gt;server.c&lt;/h3&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;pid_t&lt;/span&gt; pid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; fork&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;pid&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;We&amp;#39;re the new server process!&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;        sleep&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;co&quot;&gt;// so we can examine systemd state&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pid &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Fork failed :(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;        perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;fork&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;We&amp;#39;re the parent&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;        exit&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Build: &lt;code&gt;cc server.c -o server&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;example_server.service&quot;&gt;example_server.service&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;[Unit]
Description=Example server process

[Service]
Type=simple
ExecStart=/home/daniel/dev/dxuuu.xyz/examples/systemd-sdnotify/server
Restart=always

[Install]
WantedBy=multi-user.target&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running this service will cause &lt;code&gt;example_server.service&lt;/code&gt;
to flap. You can confirm that’s happening by checking
&lt;code&gt;systemctl status example_server&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● example_server.service - Example server process
   Loaded: loaded (/etc/systemd/system/example_server.service; disabled; vendor preset: disabled)
      Active: failed (Result: start-limit-hit) since Mon 2017-11-13 07:28:29 PST; 4s ago
     Process: 4723 ExecStart=/home/daniel/dev/dxuuu.xyz/examples/systemd-sdnotify/server (code=exited, status=0/SUCCESS)
   Main PID: 4723 (code=exited, status=0/SUCCESS)

Nov 13 07:28:29 maharaja systemd[1]: example_server.service: Service hold-off time over, scheduling restart.
Nov 13 07:28:29 maharaja systemd[1]: example_server.service: Scheduled restart job, restart counter is at 5.
Nov 13 07:28:29 maharaja systemd[1]: Stopped Example server process.
Nov 13 07:28:29 maharaja systemd[1]: example_server.service: Start request repeated too quickly.
Nov 13 07:28:29 maharaja systemd[1]: example_server.service: Failed with result &amp;#39;start-limit-hit&amp;#39;.
Nov 13 07:28:29 maharaja systemd[1]: Failed to start Example server process.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, if we use &lt;code&gt;sd_notify(3)&lt;/code&gt;, we get much better
results.&lt;/p&gt;
&lt;h3 id=&quot;server_sdnotify.c&quot;&gt;server_sdnotify.c&lt;/h3&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;systemd/sd-daemon.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;pid_t&lt;/span&gt; pid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; fork&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;pid&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;We&amp;#39;re the new server process!&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;// tell systemd we&amp;#39;re ready&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;        sd_notify&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;READY=1&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;        sleep&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;co&quot;&gt;// so we can examine systemd state&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pid &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Fork failed :(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;        perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;fork&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;We&amp;#39;re the parent&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;// tell systemd the child is the main process now&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;        sd_notifyf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;MAINPID=&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%lu&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;                      &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; pid&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot;&gt;&lt;/a&gt;        exit&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Build:
&lt;code&gt;cc server_sdnotify.c -o server_sdnotify -lsystemd&lt;/code&gt;&lt;/p&gt;
&lt;h3
id=&quot;example_server_sdnotify.service&quot;&gt;example_server_sdnotify.service&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;[Unit]
Description=Example server process with sd_notify

[Service]
Type=notify
ExecStart=/home/daniel/dev/dxuuu.xyz/examples/systemd-sdnotify/server_sdnotify
Restart=always
NotifyAccess=all

[Install]
WantedBy=multi-user.target&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now when you run &lt;code&gt;systemctl start server_sdnotify&lt;/code&gt;,
you’ll see everything works nicely:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● example_server_sdnotify.service - Example server process
   Loaded: loaded (/etc/systemd/system/example_server_sdnotify.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2017-11-13 07:40:08 PST; 3s ago
 Main PID: 11445 (server_sdnotify)
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/example_server_sdnotify.service
           └─11445 /home/daniel/dev/dxuuu.xyz/examples/systemd-sdnotify/server_sdnotify

Nov 13 07:40:08 maharaja systemd[1]: Starting Example server process...
Nov 13 07:40:08 maharaja server_sdnotify[11444]: We&amp;#39;re the parent
Nov 13 07:40:08 maharaja systemd[1]: example_server_sdnotify.service: Supervising process 11445 which is not our child. We&amp;#39;ll most likely not notice when it exits.
Nov 13 07:40:08 maharaja systemd[1]: Started Example server process.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the “Supervising process 11445 which is not our child”
warning is a bit bogus. Since the parent dies after forking the child,
the child now belongs to PID 1. As such, systemd can listen to SIGCHLD.
If you read through the systemd source code, you can confirm this
behavior is true.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>std::vector and emplace_back</title><id>https://dxuuu.xyz/cpp-emplace.html</id><updated>2018-03-30T18:58:11-07:00</updated><link href="https://dxuuu.xyz/cpp-emplace.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;std::vector and emplace_back&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;std::vector and emplace_back&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;There are some interesting bits about the C++ runtime. Consider this
problem: you want to add an element to a vector of type
&lt;code&gt;std::vector&amp;lt;std::pair&amp;lt;int, Foo&amp;gt;&amp;gt;&lt;/code&gt; with as little
overhead as possible. That means one construction – no extra moves, no
extra copies, nothing.&lt;/p&gt;
&lt;p&gt;For this problem, let us use this implementation of Foo:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;class&lt;/span&gt; Foo &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;    Foo&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;constructor&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;    Foo&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; x&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;constructor2&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;    Foo&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;const&lt;/span&gt; Foo&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt; f&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;copy constructor&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;    Foo&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;Foo&lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; f&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;move constructor&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Obviously we want to use &lt;code&gt;emplace_back&lt;/code&gt; to elide the move
you would traditionally get from something like
&lt;code&gt;vec.push_back(std::move(f))&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;vector&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;pair&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Foo&lt;span class=&quot;op&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; list&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;emplace_back&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Foo&lt;span class=&quot;op&quot;&gt;{});&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./a.out
constructor
move constructor&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what happened? Clearly &lt;code&gt;Foo&lt;/code&gt; was
&lt;code&gt;std::move&lt;/code&gt;d at least once. In fact, it happens when
&lt;code&gt;emplace_back&lt;/code&gt; is evaluated, since we constructed an rvalue
&lt;code&gt;Foo{}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ok, so we need a different approach. How about forwarding through the
arguments to &lt;code&gt;Foo&lt;/code&gt;, so &lt;code&gt;Foo&lt;/code&gt; is constructed as
late as possible?&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;tuple&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;vector&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;pair&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Foo&lt;span class=&quot;op&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; list&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;emplace_back&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;piecewise_construct&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;forward_as_tuple&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;forward_as_tuple&lt;span class=&quot;op&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;$ ./a.out
constructor&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we use &lt;code&gt;std::forward_as_tuple&lt;/code&gt; to tell the compiler
that we want to call the 0-arg constructor. If using fancy C++ standard
library features isn’t your cup of tea, you could alternatively use a
dummy constructor:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;vector&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;pair&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Foo&lt;span class=&quot;op&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; list&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;emplace_back&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;$ ./a.out
constructor2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Great! So we solved our original problem. Or did we? Consider
this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;vector&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;pair&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Foo&lt;span class=&quot;op&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; list&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;emplace_back&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;---&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;emplace_back&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Foo&lt;span class=&quot;op&quot;&gt;{});&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;---&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;emplace_back&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;$ ./a.out
constructor2
---
constructor
move constructor
copy constructor
---
constructor2
copy constructor
copy constructor&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Woah, what’s with all the extra copies? Well, as it turns out, when a
vector needs to be resized, enough contiguous memory for all elements
needs to be allocated. Then, the contents of the old vector need to be
move or copy constructed into the new memory. To elide this issue, we
can preallocate memory for our vector.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;vector&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;pair&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Foo&lt;span class=&quot;op&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; list&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;reserve&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;emplace_back&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;---&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;emplace_back&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Foo&lt;span class=&quot;op&quot;&gt;{});&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;---&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;  list&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;emplace_back&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;$ ./a.out
constructor2
---
constructor
move constructor
---
constructor2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hey, now this is Looking good. But wait! There’s one outstanding
question: what’s with all the copies in the previous snippet? Shouldn’t
they be moves? We have a move constructor defined for
&lt;code&gt;Foo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Well, it turns out due to exception-safe guarantees, C++ standard
collections will not use non-exception-safe move constructors. So how do
we fix this? Add &lt;code&gt;noexcept&lt;/code&gt; to the move constructor, like
so:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;Foo&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;Foo&lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; f&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;noexcept&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;move constructor&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then run the example without the &lt;code&gt;list.reserve(3)&lt;/code&gt;
again:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./a.out
constructor2
---
constructor
move constructor
move constructor
---
constructor2
move constructor
move constructor&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Congratulations, now you know more about &lt;code&gt;std::vector&lt;/code&gt;
than you wanted to know.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Comparing interned strings</title><id>https://dxuuu.xyz/interned-strings.html</id><updated>2019-06-19T17:41:08-07:00</updated><link href="https://dxuuu.xyz/interned-strings.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Comparing interned strings&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Comparing interned strings&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;C/C++ has this interesting property where if you define a string
literal, the compiler will make sure to only keep one copy of it. This
makes sense as it reduces how much static storage is required.&lt;/p&gt;
&lt;p&gt;For example, if you have:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const char* s = &amp;quot;asdf&amp;quot;;
const char* s2 = &amp;quot;asdf&amp;quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the compiler will make sure “asdf” is stored once in the resulting
binary.&lt;/p&gt;
&lt;p&gt;This opens up an interesting property where you can compare string
pointers as if you were calling &lt;code&gt;strcmp&lt;/code&gt;. For example:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;constexpr&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; s1 &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;string one&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;constexpr&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; s2 &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;string two&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;constexpr&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; s1_copy &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;string one&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;s1 &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; s2&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;s1 == s2&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;s1 != s2&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;s1 &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; s1_copy&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;s1 == s1_copy&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;s1 != s1_copy&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;s1 &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;string one&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;s1 == string one&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;s1 != string one&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;outputs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./interned_string
s1 != s2
s1 == s1_copy
s1 == string one&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;note&quot;&gt;Note&lt;/h3&gt;
&lt;p&gt;According to cppreference:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The compiler is allowed, but not required, to combine storage for
equal or overlapping string literals. That means that identical string
literals may or may not compare equal when compared by pointer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That being said, no sane compiler would omit this.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>/proc/[pid] and the missing threads</title><id>https://dxuuu.xyz/proc-threads.html</id><updated>2020-04-23T13:25:15-07:00</updated><link href="https://dxuuu.xyz/proc-threads.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;/proc/[pid] and the missing threads&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;&lt;code&gt;/proc/[pid]&lt;/code&gt; and the missing threads&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Suppose you run the following program:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource rs numberLines&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;std::&lt;/span&gt;time&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;std::&lt;/span&gt;thread&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; main() &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;pp&quot;&gt;println!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;My TID: {}&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;nix::unistd::&lt;/span&gt;gettid())&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; child &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;thread::&lt;/span&gt;spawn(&lt;span class=&quot;kw&quot;&gt;move&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;pp&quot;&gt;println!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;My thread&amp;#39;s TID: {}&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;nix::unistd::&lt;/span&gt;gettid())&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;pp&quot;&gt;thread::&lt;/span&gt;sleep(&lt;span class=&quot;pp&quot;&gt;time::Duration::&lt;/span&gt;from_secs(&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;    child&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;join()&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;unwrap()&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and get the following output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;My TID: 840680
My thread&amp;#39;s TID: 840695&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inspecting thread state through &lt;code&gt;/proc&lt;/code&gt; works as
expected:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat /proc/840680/comm
thread_id

$ cat /proc/840695/comm
thread_id&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, if you happened to browse through &lt;code&gt;/proc/&lt;/code&gt; (via
&lt;code&gt;ls&lt;/code&gt; or other), you’ll notice a strange inconsistency:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ls -l /proc | grep 840680 &amp;amp;&amp;gt; /dev/null; echo $?
0

$ ls -l /proc | grep 840695 &amp;amp;&amp;gt; /dev/null; echo $?
1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, there’s no directory entry for the
&lt;em&gt;thread&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Why is this the case? We have to look at the kernel code to find out.
First let’s look at where all the entries in &lt;code&gt;/proc&lt;/code&gt; are
instantiated. Remember that &lt;code&gt;/proc&lt;/code&gt;, or &lt;code&gt;procfs&lt;/code&gt;,
is a virtual file system so there’s not actually anything on disk
backing the fileystem. Everything is generated when we request it.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;fs/proc/root.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;283&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 282;&quot;&gt;&lt;span id=&quot;function-283&quot;&gt;&lt;a href=&quot;#function-283&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;/*&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-284&quot;&gt;&lt;a href=&quot;#function-284&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * This is the root &amp;quot;inode&amp;quot; in the /proc tree..&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-285&quot;&gt;&lt;a href=&quot;#function-285&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-286&quot;&gt;&lt;a href=&quot;#function-286&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; proc_dir_entry proc_root &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-287&quot;&gt;&lt;a href=&quot;#function-287&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;low_ino        &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; PROC_ROOT_INO&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-288&quot;&gt;&lt;a href=&quot;#function-288&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;namelen        &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-289&quot;&gt;&lt;a href=&quot;#function-289&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;mode           &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; S_IFDIR &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; S_IRUGO &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; S_IXUGO&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-290&quot;&gt;&lt;a href=&quot;#function-290&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;nlink          &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-291&quot;&gt;&lt;a href=&quot;#function-291&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;refcnt         &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; REFCOUNT_INIT&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-292&quot;&gt;&lt;a href=&quot;#function-292&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;proc_iops      &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;proc_root_inode_operations&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-293&quot;&gt;&lt;a href=&quot;#function-293&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;proc_dir_ops   &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;proc_root_operations&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-294&quot;&gt;&lt;a href=&quot;#function-294&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;parent         &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;proc_root&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-295&quot;&gt;&lt;a href=&quot;#function-295&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;subdir         &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; RB_ROOT&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-296&quot;&gt;&lt;a href=&quot;#function-296&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;name           &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;/proc&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-297&quot;&gt;&lt;a href=&quot;#function-297&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;&amp;amp;proc_root_operations&lt;/code&gt; seems like a likely suspect
for &lt;strong&gt;dir&lt;/strong&gt;ectory
&lt;strong&gt;op&lt;/strong&gt;eration&lt;strong&gt;s&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;261&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 260;&quot;&gt;&lt;span id=&quot;function-261&quot;&gt;&lt;a href=&quot;#function-261&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;/*&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-262&quot;&gt;&lt;a href=&quot;#function-262&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * The root /proc directory is special, as it has the&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-263&quot;&gt;&lt;a href=&quot;#function-263&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * &amp;lt;pid&amp;gt; directories. Thus we don&amp;#39;t use the generic&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-264&quot;&gt;&lt;a href=&quot;#function-264&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * directory handling functions for that..&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-265&quot;&gt;&lt;a href=&quot;#function-265&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-266&quot;&gt;&lt;a href=&quot;#function-266&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; file_operations proc_root_operations &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-267&quot;&gt;&lt;a href=&quot;#function-267&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;read            &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; generic_read_dir&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-268&quot;&gt;&lt;a href=&quot;#function-268&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;iterate_shared  &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; proc_root_readdir&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-269&quot;&gt;&lt;a href=&quot;#function-269&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;llseek         &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; generic_file_llseek&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-270&quot;&gt;&lt;a href=&quot;#function-270&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So far the comments confirm our understanding. However, it’s somewhat
unclear which callback is called when we run &lt;code&gt;ls&lt;/code&gt; versus
directly &lt;code&gt;cat&lt;/code&gt; a file. Let’s use bpftrace to investigate.&lt;/p&gt;
&lt;p&gt;In one terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -e &amp;#39;kprobe:generic_read_dir { printf(&amp;quot;%s\n&amp;quot;, kstack); }&amp;#39;
Attaching 1 probe...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In another terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ls -l /proc&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing in the first terminal. Let’s try the next function.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -e &amp;#39;kprobe:proc_root_readdir { printf(&amp;quot;%s\n&amp;quot;, kstack); }&amp;#39;
Attaching 1 probe...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run &lt;code&gt;ls&lt;/code&gt; again and we get the following output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;        proc_root_readdir+1
        iterate_dir+323
        ksys_getdents64+156
        __x64_sys_getdents64+22
        do_syscall_64+78
        entry_SYSCALL_64_after_hwframe+68


        proc_root_readdir+1
        iterate_dir+323
        ksys_getdents64+156
        __x64_sys_getdents64+22
        do_syscall_64+78
        entry_SYSCALL_64_after_hwframe+68
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nice, so we know running &lt;code&gt;ls&lt;/code&gt; generates a
&lt;code&gt;proc_root_readdir&lt;/code&gt; callback. Let’s look at the code:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;249&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 248;&quot;&gt;&lt;span id=&quot;function-249&quot;&gt;&lt;a href=&quot;#function-249&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; proc_root_readdir&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; file &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;file&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; dir_context &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;ctx&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-250&quot;&gt;&lt;a href=&quot;#function-250&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-251&quot;&gt;&lt;a href=&quot;#function-251&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ctx&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;pos &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; FIRST_PROCESS_ENTRY&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-252&quot;&gt;&lt;a href=&quot;#function-252&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; error &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; proc_readdir&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; ctx&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-253&quot;&gt;&lt;a href=&quot;#function-253&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;unlikely&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;error &lt;span class=&quot;op&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-254&quot;&gt;&lt;a href=&quot;#function-254&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; error&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-255&quot;&gt;&lt;a href=&quot;#function-255&quot;&gt;&lt;/a&gt;                ctx&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;pos &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; FIRST_PROCESS_ENTRY&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-256&quot;&gt;&lt;a href=&quot;#function-256&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-257&quot;&gt;&lt;a href=&quot;#function-257&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-258&quot;&gt;&lt;a href=&quot;#function-258&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; proc_pid_readdir&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; ctx&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-259&quot;&gt;&lt;a href=&quot;#function-259&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;FIRST_PROCESS_ENTRY&lt;/code&gt; is defined as:&lt;/p&gt;
&lt;p&gt;in &lt;code&gt;fs/proc/internal.h&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;137&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 136;&quot;&gt;&lt;span id=&quot;function-137&quot;&gt;&lt;a href=&quot;#function-137&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;/*&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-138&quot;&gt;&lt;a href=&quot;#function-138&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * Offset of the first process in the /proc root directory..&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-139&quot;&gt;&lt;a href=&quot;#function-139&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-140&quot;&gt;&lt;a href=&quot;#function-140&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#define FIRST_PROCESS_ENTRY &lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;256&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and we see &lt;code&gt;proc_readdir&lt;/code&gt; incrementing &lt;code&gt;pos&lt;/code&gt; in
&lt;code&gt;proc_readdir_de&lt;/code&gt; (a later callee). So this code probably
handles all the non-process entries in &lt;code&gt;/proc&lt;/code&gt; and we can
ignore it for now and focus on &lt;code&gt;proc_pid_readdir&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;fs/proc/base.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;3371&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 3370;&quot;&gt;&lt;span id=&quot;function-3371&quot;&gt;&lt;a href=&quot;#function-3371&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;/* for the /proc/ directory itself, after non-process stuff has been done */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3372&quot;&gt;&lt;a href=&quot;#function-3372&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; proc_pid_readdir&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; file &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;file&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; dir_context &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;ctx&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3373&quot;&gt;&lt;a href=&quot;#function-3373&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3374&quot;&gt;&lt;a href=&quot;#function-3374&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; tgid_iter iter&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3375&quot;&gt;&lt;a href=&quot;#function-3375&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; pid_namespace &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;ns &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; proc_pid_ns&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;file_inode&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;op&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3376&quot;&gt;&lt;a href=&quot;#function-3376&quot;&gt;&lt;/a&gt;        loff_t pos &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; ctx&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;pos&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code just sets up some variables by pulling context information
out. Not really important.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;3378&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 3377;&quot;&gt;&lt;span id=&quot;function-3378&quot;&gt;&lt;a href=&quot;#function-3378&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pos &lt;span class=&quot;op&quot;&gt;&amp;gt;=&lt;/span&gt; PID_MAX_LIMIT &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; TGID_OFFSET&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3379&quot;&gt;&lt;a href=&quot;#function-3379&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3380&quot;&gt;&lt;a href=&quot;#function-3380&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-3381&quot;&gt;&lt;a href=&quot;#function-3381&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pos &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; TGID_OFFSET &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3382&quot;&gt;&lt;a href=&quot;#function-3382&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; inode &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;inode &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; d_inode&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ns&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;proc_self&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3383&quot;&gt;&lt;a href=&quot;#function-3383&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;dir_emit&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ctx&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;self&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; inode&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;i_ino&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; DT_LNK&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3384&quot;&gt;&lt;a href=&quot;#function-3384&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3385&quot;&gt;&lt;a href=&quot;#function-3385&quot;&gt;&lt;/a&gt;                ctx&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;pos &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; pos &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; pos &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3386&quot;&gt;&lt;a href=&quot;#function-3386&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3387&quot;&gt;&lt;a href=&quot;#function-3387&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pos &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; TGID_OFFSET &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3388&quot;&gt;&lt;a href=&quot;#function-3388&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; inode &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;inode &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; d_inode&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ns&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;proc_thread_self&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3389&quot;&gt;&lt;a href=&quot;#function-3389&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;dir_emit&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ctx&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;thread-self&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; inode&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;i_ino&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; DT_LNK&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3390&quot;&gt;&lt;a href=&quot;#function-3390&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3391&quot;&gt;&lt;a href=&quot;#function-3391&quot;&gt;&lt;/a&gt;                ctx&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;pos &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; pos &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; pos &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3392&quot;&gt;&lt;a href=&quot;#function-3392&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code does 3 things:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Impose a limit on the number of entries&lt;/li&gt;
&lt;li&gt;Emit the &lt;code&gt;/proc/self&lt;/code&gt; entry&lt;/li&gt;
&lt;li&gt;Emit the &lt;code&gt;/proc/thread-self&lt;/code&gt; entry&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Interesting to note but not important for this article.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;3393&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 3392;&quot;&gt;&lt;span id=&quot;function-3393&quot;&gt;&lt;a href=&quot;#function-3393&quot;&gt;&lt;/a&gt;        iter&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;tgid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; pos &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; TGID_OFFSET&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3394&quot;&gt;&lt;a href=&quot;#function-3394&quot;&gt;&lt;/a&gt;        iter&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;task &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; NULL&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3395&quot;&gt;&lt;a href=&quot;#function-3395&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;iter &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; next_tgid&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ns&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; iter&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3396&quot;&gt;&lt;a href=&quot;#function-3396&quot;&gt;&lt;/a&gt;             iter&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3397&quot;&gt;&lt;a href=&quot;#function-3397&quot;&gt;&lt;/a&gt;             iter&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;tgid &lt;span class=&quot;op&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; iter &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; next_tgid&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ns&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; iter&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now this is the interesting bit. Now we’re iterating through all the
thread group IDs (tgid) via &lt;strong&gt;&lt;code&gt;next_tgid&lt;/code&gt;&lt;/strong&gt;.
TGIDs are better understood from userspace as the PIDs we see, where
each process can have multiple threads (each with their own TID).&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;3398&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 3397;&quot;&gt;&lt;span id=&quot;function-3398&quot;&gt;&lt;a href=&quot;#function-3398&quot;&gt;&lt;/a&gt;             &lt;span class=&quot;op&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3399&quot;&gt;&lt;a href=&quot;#function-3399&quot;&gt;&lt;/a&gt;             &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;fill dcache entry&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3400&quot;&gt;&lt;a href=&quot;#function-3400&quot;&gt;&lt;/a&gt;             &lt;span class=&quot;op&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3401&quot;&gt;&lt;a href=&quot;#function-3401&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3402&quot;&gt;&lt;a href=&quot;#function-3402&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There’s more code that follows but it’s not very interesting for
us.&lt;/p&gt;
&lt;p&gt;So we know why &lt;code&gt;ls /proc&lt;/code&gt; does not show threads now. But
how does directly accessing &lt;code&gt;/proc/[TID]/comm&lt;/code&gt; work?&lt;/p&gt;
&lt;p&gt;We follow the same process with bpftrace and try some more functions.
Finally, we discover that the following triggers output when we run
&lt;code&gt;cat /proc/864518/comm&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -e &amp;#39;kprobe:proc_root_lookup / comm == &amp;quot;cat&amp;quot; / { printf(&amp;quot;%s\n&amp;quot;, kstack); }&amp;#39;
Attaching 1 probe...

        proc_root_lookup+1
        __lookup_slow+140
        walk_component+513
        link_path_walk+759
        path_openat+157
        do_filp_open+171
        do_sys_openat2+534
        do_sys_open+68
        do_syscall_64+78
        entry_SYSCALL_64_after_hwframe+68&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we used a filter in our bpftrace script to limit output to
our command.&lt;/p&gt;
&lt;p&gt;Astute readers might have noted that our &lt;code&gt;cat&lt;/code&gt; command
used a different TID. That’s because we only trigger output once per
lifetime (or some other period of time) of the TID. That’s because the
kernel is probably caching directory entries in memory so it doesn’t
have to do a full lookup every time.&lt;/p&gt;
&lt;p&gt;Now look at &lt;code&gt;proc_root_lookup&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;fs/proc/root.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;241&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 240;&quot;&gt;&lt;span id=&quot;function-241&quot;&gt;&lt;a href=&quot;#function-241&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; dentry &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;proc_root_lookup&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; inode &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; dir&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; dentry &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; dentry&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; flags&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-242&quot;&gt;&lt;a href=&quot;#function-242&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-243&quot;&gt;&lt;a href=&quot;#function-243&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;proc_pid_lookup&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;dentry&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; flags&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-244&quot;&gt;&lt;a href=&quot;#function-244&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; NULL&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-245&quot;&gt;&lt;a href=&quot;#function-245&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-246&quot;&gt;&lt;a href=&quot;#function-246&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; proc_lookup&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;dir&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; dentry&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; flags&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-247&quot;&gt;&lt;a href=&quot;#function-247&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code&gt;fs/proc/base.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;3300&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 3299;&quot;&gt;&lt;span id=&quot;function-3300&quot;&gt;&lt;a href=&quot;#function-3300&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; dentry &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;proc_pid_lookup&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; dentry &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;dentry&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; flags&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3301&quot;&gt;&lt;a href=&quot;#function-3301&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3302&quot;&gt;&lt;a href=&quot;#function-3302&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; task_struct &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3303&quot;&gt;&lt;a href=&quot;#function-3303&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;unsigned&lt;/span&gt; tgid&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3304&quot;&gt;&lt;a href=&quot;#function-3304&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; pid_namespace &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;ns&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3305&quot;&gt;&lt;a href=&quot;#function-3305&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; dentry &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;result &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; ERR_PTR&lt;span class=&quot;op&quot;&gt;(-&lt;/span&gt;ENOENT&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3306&quot;&gt;&lt;a href=&quot;#function-3306&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-3307&quot;&gt;&lt;a href=&quot;#function-3307&quot;&gt;&lt;/a&gt;        tgid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; name_to_int&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;dentry&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;d_name&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3308&quot;&gt;&lt;a href=&quot;#function-3308&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;tgid &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3309&quot;&gt;&lt;a href=&quot;#function-3309&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;goto&lt;/span&gt; out&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Some setup and error checks. Not too interesting.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;3311&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 3310;&quot;&gt;&lt;span id=&quot;function-3311&quot;&gt;&lt;a href=&quot;#function-3311&quot;&gt;&lt;/a&gt;        ns &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; dentry&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;d_sb&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;s_fs_info&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3312&quot;&gt;&lt;a href=&quot;#function-3312&quot;&gt;&lt;/a&gt;        rcu_read_lock&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3313&quot;&gt;&lt;a href=&quot;#function-3313&quot;&gt;&lt;/a&gt;        task &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; find_task_by_pid_ns&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;tgid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; ns&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is more interesting: we do a lookup on the requested tgid. Note
that &lt;code&gt;tgid&lt;/code&gt; here is somewhat improperly named. We’re doing a
lookup based on a &lt;code&gt;task&lt;/code&gt; which does not have to be a thread
group leader.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;3314&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 3313;&quot;&gt;&lt;span id=&quot;function-3314&quot;&gt;&lt;a href=&quot;#function-3314&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3315&quot;&gt;&lt;a href=&quot;#function-3315&quot;&gt;&lt;/a&gt;                get_task_struct&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3316&quot;&gt;&lt;a href=&quot;#function-3316&quot;&gt;&lt;/a&gt;        rcu_read_unlock&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3317&quot;&gt;&lt;a href=&quot;#function-3317&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3318&quot;&gt;&lt;a href=&quot;#function-3318&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;goto&lt;/span&gt; out&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3319&quot;&gt;&lt;a href=&quot;#function-3319&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-3320&quot;&gt;&lt;a href=&quot;#function-3320&quot;&gt;&lt;/a&gt;        result &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; proc_pid_instantiate&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;dentry&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; task&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; NULL&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3321&quot;&gt;&lt;a href=&quot;#function-3321&quot;&gt;&lt;/a&gt;        put_task_struct&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3322&quot;&gt;&lt;a href=&quot;#function-3322&quot;&gt;&lt;/a&gt;out&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3323&quot;&gt;&lt;a href=&quot;#function-3323&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3324&quot;&gt;&lt;a href=&quot;#function-3324&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The remainder of the function instantiates an inode for
&lt;code&gt;/proc/[TID]&lt;/code&gt; and most likely populates it as well. Then in
&lt;code&gt;proc_root_lookup&lt;/code&gt;, &lt;code&gt;proc_lookup&lt;/code&gt; probably walks
the FS structure and finds the new inode.&lt;/p&gt;
&lt;p&gt;Mystery solved.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>GDB hacking</title><id>https://dxuuu.xyz/gdb-hacking.html</id><updated>2020-07-04T20:05:46-07:00</updated><link href="https://dxuuu.xyz/gdb-hacking.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;GDB hacking&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;GDB hacking&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This past weekend I spent some time hacking on GDB where the overall
goal was to improve rust debugging support. I considered hacking on LLDB
but their upstream stance on language support is &lt;a
href=&quot;http://lists.llvm.org/pipermail/lldb-dev/2018-January/013171.html&quot;&gt;fairly
conservative&lt;/a&gt;. The current state is that they want non C-family
languages to be maintained out of tree. Anyone who’s done open source
software maintenance knows that’s an enormous burden on a team – to say
nothing of a single person. In fact, such an out of tree LLDB has been
attempted before but the sole maintainer got a new job and the patches
ended up being &lt;a
href=&quot;https://github.com/rust-lang/llvm-project/pull/19&quot;&gt;too difficult
to rebase&lt;/a&gt;. So support was dropped. And that’s how I decided to hack
on GDB.&lt;/p&gt;
&lt;p&gt;Despite being released &lt;a
href=&quot;https://en.wikipedia.org/wiki/GNU_Debugger&quot;&gt;over 30 years ago&lt;/a&gt;,
the codebase is still in fairly great shape. In fact, the entire GDB
codebase uses C++11. The current developers/maintainers have obviously
taken great care to keep things modern. This is evidenced by the
tasteful use of C++11 features (smart pointers, &lt;code&gt;override&lt;/code&gt;,
limited use of templates).&lt;/p&gt;
&lt;p&gt;It took about a day, but I did manage to get a couple small patches
out. The only patch worth noting is &lt;a
href=&quot;https://sourceware.org/pipermail/gdb-patches/2020-July/170140.html&quot;&gt;adding
support for raw identifiers&lt;/a&gt;, a fairly useless but educational
feature. My hope is to steadily send patches for at least a little
while.&lt;/p&gt;
&lt;p&gt;To end this post, I’ll share one cool trick: debugging GDB with
GDB:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cd ~/dev/gdb/build/gdb
$ make GDBFLAGS=./gdb run
[...]

(top-gdb) b print_command_1
Breakpoint 3 at 0xd7374: print_command_1. (2 locations)
(top-gdb) r

Starting program: /home/daniel/dev/gdb/build/gdb/gdb
[...]
(gdb) p 0

Thread 1 &amp;quot;gdb&amp;quot; hit Breakpoint 3, print_command_1 (During symbol reading: incomplete CFI data; unspecified registers (e.g., rax) at 0x55555589f362
args=0x555555eb9682 &amp;quot;0&amp;quot;, voidprint=1) at ../../gdb/printcmd.c:1198
1198    {
(top-gdb) set print frame-info short-location
(top-gdb) where
#0  print_command_1 (args=..., voidprint=...)
#1  0x00005555556d4592 in cmd_func (cmd=..., args=..., from_tty=...)
#2  0x0000555555994aac in execute_command (p=..., from_tty=...)
#3  0x000055555578e65d in command_handler (command=...)
#4  0x000055555578e9dd in command_line_handler (rl=...)
#5  0x000055555578efde in gdb_rl_callback_handler (rl=...)
#6  0x0000555555a15d90 in rl_callback_read_char ()
#7  0x000055555578dc1e in gdb_rl_callback_read_char_wrapper_noexcept ()
#8  0x000055555578ee91 in gdb_rl_callback_read_char_wrapper (client_data=...)
#9  0x000055555578d950 in stdin_event_handler (error=..., client_data=...)
#10 0x0000555555ade2b6 in gdb_wait_for_event (block=...)
#11 0x0000555555ade55d in gdb_wait_for_event (block=...)
#12 gdb_do_one_event ()
#13 0x00005555558509f5 in start_event_loop ()
#14 captured_command_loop ()
#15 0x0000555555852c75 in captured_main (data=...)
#16 gdb_main (args=...)
#17 0x000055555563aa2c in main (argc=..., argv=...)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The neat part is that &lt;em&gt;something&lt;/em&gt; is detecting the gdb-gdb
debug and changing the top level gdb prompt to &lt;code&gt;top-gdb&lt;/code&gt;.
This is quite helpful when debugging changes or tracing code paths.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Playing with C++ templates</title><id>https://dxuuu.xyz/cpp-templates.html</id><updated>2020-07-04T20:09:14-07:00</updated><link href="https://dxuuu.xyz/cpp-templates.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Playing with C++ templates&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Playing with C++ templates&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Last week I found myself quite sick. Rather than wallow in it, I
played around with C++ templates. Until now, I’ve only parameterized
classes into generic functions. As a daily user of &lt;a
href=&quot;https://github.com/facebook/folly&quot;&gt;folly&lt;/a&gt;, I’ve spent quite
some time puzzling over C++ template magic. It’s time I got my feet
wet.&lt;/p&gt;
&lt;h3 id=&quot;simple-example&quot;&gt;Simple example&lt;/h3&gt;
&lt;p&gt;We want a generic function to call a standard interface:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; A &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; a&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; B &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; a&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;typename&lt;/span&gt; T&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; foo&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;    T t&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; t&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;a&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;    foo&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;op&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;    foo&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;B&lt;span class=&quot;op&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When compiled and run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ g++ typename.cpp
$ ./a.out
1
2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we &lt;em&gt;may&lt;/em&gt; choose to use old-style &lt;code&gt;class&lt;/code&gt;
instead of &lt;code&gt;typename&lt;/code&gt; on line 15. However, for clarity,
&lt;code&gt;class&lt;/code&gt; should be avoided. Trivia: Bjarne originally reused
the &lt;code&gt;class&lt;/code&gt; keyword in template declarations to avoid another
reserved keyword.&lt;/p&gt;
&lt;h3 id=&quot;integers-inside-templates&quot;&gt;Integers inside templates&lt;/h3&gt;
&lt;p&gt;Now another example. Did you know templates declarations can specify
more than class types? In fact, according to the &lt;a
href=&quot;http://en.cppreference.com/w/cpp/language/template_parameters&quot;&gt;cppreference&lt;/a&gt;,
we can use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;std::nullptr_t (since C++11)&lt;/li&gt;
&lt;li&gt;integral type&lt;/li&gt;
&lt;li&gt;lvalue reference type (to object or to function)&lt;/li&gt;
&lt;li&gt;pointer type (to object or to function)&lt;/li&gt;
&lt;li&gt;pointer to member type (to member object or to member function)&lt;/li&gt;
&lt;li&gt;enumeration type&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s play around with an integer type inside a template:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; N &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; foo&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; N &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;    foo&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;    foo&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;    foo&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When compiled and run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ g++ int.cpp
$ ./a.out
1
2
10&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One can see how this might be useful to flexibly declare static array
sizes at compile time (to avoid &lt;a
href=&quot;https://en.wikipedia.org/wiki/Variable-length_array&quot;&gt;variable-length
arrays&lt;/a&gt;, whose ugliness is &lt;a
href=&quot;https://lwn.net/Articles/749064/&quot;&gt;described in last week’s
LWN&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;template-metaprogramming&quot;&gt;Template metaprogramming&lt;/h3&gt;
&lt;p&gt;Now that we’ve covered some template basics, let’s play around with
template metaprogramming. Succinctly, template metaprogramming is the
ability to do fancy compile time things. For example, a library
developer can optimize a templated routine for certain template
parameter types. One way to do this is through &lt;a
href=&quot;http://en.cppreference.com/w/cpp/types/enable_if&quot;&gt;&lt;code&gt;std::enable_if&lt;/code&gt;&lt;/a&gt;.
In folly, &lt;a
href=&quot;https://github.com/facebook/folly/blob/master/folly/futures/Future.h#L629-L674&quot;&gt;the
futures library&lt;/a&gt; overloads &lt;code&gt;onError(F&amp;amp;&amp;amp; func)&lt;/code&gt; to
return a different return type based on the template parameter type.&lt;/p&gt;
&lt;p&gt;We will do something far less complicated. We will play with &lt;a
href=&quot;http://en.cppreference.com/w/cpp/types/decay&quot;&gt;&lt;code&gt;std::decay&lt;/code&gt;&lt;/a&gt;,
a C++ standard library function that “decays” types. For example, the
type &lt;code&gt;Foo&amp;amp;&lt;/code&gt; and &lt;code&gt;Foo&lt;/code&gt; should, in many cases,
be considered the same. However, a C++ compiler cannot safely assume
that is always the case, especially for functions like &lt;a
href=&quot;http://en.cppreference.com/w/cpp/types/is_same&quot;&gt;&lt;code&gt;std::is_same&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the spirit of flexibility, the C++ committee provides a mechanism
to “decay” types into “base” types. Hopefully that makes more sense than
the official documentation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Applies lvalue-to-rvalue, array-to-pointer, and function-to-pointer implicit conversions to the type T, removes cv-qualifiers, and defines the resulting type as the member typedef type.&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;type_traits&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; A &lt;span class=&quot;op&quot;&gt;{};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; B &lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; A &lt;span class=&quot;op&quot;&gt;{};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;boolalpha&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt; &lt;/span&gt;       &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;is_same&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; B&lt;span class=&quot;op&quot;&gt;&amp;gt;::&lt;/span&gt;value &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;is_same&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; A&lt;span class=&quot;op&quot;&gt;&amp;gt;::&lt;/span&gt;value &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;is_same&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;decay&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;op&quot;&gt;*&amp;gt;::&lt;/span&gt;type&lt;span class=&quot;op&quot;&gt;&amp;gt;::&lt;/span&gt;value &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;is_same&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;decay&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;A&lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;gt;::&lt;/span&gt;type&lt;span class=&quot;op&quot;&gt;&amp;gt;::&lt;/span&gt;value &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While seemingly complicated, this snippet is quite simple. We perform
4 checks on lines 9-12: if&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;types &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; are equivalent (one should
hope not)&lt;/li&gt;
&lt;li&gt;types &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;A&lt;/code&gt; are equivalent (one should
hope so)&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;A*&lt;/code&gt; decays into &lt;code&gt;A&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;A&amp;amp;&lt;/code&gt; decays into &lt;code&gt;A&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When compiled and run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ g++ decay.cpp
$ ./a.out
false
true
false
true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hopefully checks 1 and 2 are not surprising. Checks 3 and 4 deserve a
brief explanation:&lt;/p&gt;
&lt;p&gt;Check 3 shows that &lt;code&gt;A*&lt;/code&gt; does not decay into
&lt;code&gt;A&lt;/code&gt;. This makes sense because at runtime, one cannot perform
the same operations on &lt;code&gt;A*&lt;/code&gt; as on &lt;code&gt;A&lt;/code&gt;. For
instance, if &lt;code&gt;A&lt;/code&gt; were a class, to call a method on type
&lt;code&gt;A&lt;/code&gt;, one does &lt;code&gt;A.foo()&lt;/code&gt;. One cannot do the same
with &lt;code&gt;A*&lt;/code&gt;. &lt;code&gt;A*&lt;/code&gt; needs to be dereferenced
first.&lt;/p&gt;
&lt;p&gt;Check 4 shows that &lt;code&gt;A&amp;amp;&lt;/code&gt; decays into &lt;code&gt;A&lt;/code&gt;.
This makes sense because at runtime, most non-metaprogramming operations
work the same.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>GDB hacking part 2</title><id>https://dxuuu.xyz/gdb-hacking-2.html</id><updated>2020-07-09T10:34:59-07:00</updated><link href="https://dxuuu.xyz/gdb-hacking-2.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;GDB hacking part 2&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;GDB hacking part 2&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;One of the issues I’ve had with GDB is reliably building the code.
The project apparently checks in automake-1.15 artifacts and my host has
automake-1.16, so that means any code changes that trigger automake
regeneration causes failures. Arch linux doesn’t package auotmake-1.15
like some other distros so I’ve had to get clever.&lt;/p&gt;
&lt;p&gt;My solution was to wrap the build in a docker container to
effectively document the build. The thinking goes that I only need to
get the build to work once and then it’ll work forever.&lt;/p&gt;
&lt;p&gt;The way it works is I have an &lt;code&gt;x.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre
class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;$&lt;/span&gt; ./x.py help&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;usage:&lt;/span&gt; x &lt;span class=&quot;pp&quot;&gt;[-&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;]&lt;/span&gt; [-s SOURCE_DIR] [-b BUILD_DIR] &lt;span class=&quot;dt&quot;&gt;{conf&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;help}&lt;/span&gt; ...&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;positional&lt;/span&gt; arguments:&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;{conf&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;shell&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;help}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;ex&quot;&gt;subcommands&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;conf&lt;/span&gt;                configure and build gdb container image&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;build&lt;/span&gt;               build gdb&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;run&lt;/span&gt;                 run gdb&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;ex&quot;&gt;shell&lt;/span&gt;               open shell&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;test&lt;/span&gt;                run &lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;make&lt;/span&gt; check tests&lt;span class=&quot;kw&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;help&lt;/span&gt;                print help&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;optional&lt;/span&gt; arguments:&lt;/span&gt;
&lt;span id=&quot;cb1-15&quot;&gt;&lt;a href=&quot;#cb1-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;ex&quot;&gt;-h,&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--help&lt;/span&gt;            show this help message and exit&lt;/span&gt;
&lt;span id=&quot;cb1-16&quot;&gt;&lt;a href=&quot;#cb1-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;ex&quot;&gt;-s&lt;/span&gt; SOURCE_DIR, &lt;span class=&quot;at&quot;&gt;--source-dir&lt;/span&gt; SOURCE_DIR&lt;/span&gt;
&lt;span id=&quot;cb1-17&quot;&gt;&lt;a href=&quot;#cb1-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;bu&quot;&gt;source&lt;/span&gt; code directory &lt;span class=&quot;er&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;default:&lt;/span&gt; ~/dev/gdb&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-18&quot;&gt;&lt;a href=&quot;#cb1-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;ex&quot;&gt;-b&lt;/span&gt; BUILD_DIR, &lt;span class=&quot;at&quot;&gt;--build-dir&lt;/span&gt; BUILD_DIR&lt;/span&gt;
&lt;span id=&quot;cb1-19&quot;&gt;&lt;a href=&quot;#cb1-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;ex&quot;&gt;build&lt;/span&gt; directory &lt;span class=&quot;er&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;default:&lt;/span&gt; /tmp/gdb-build&lt;span class=&quot;kw&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Running something like &lt;code&gt;./x.py build&lt;/code&gt; effectively expands
to:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre
class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;podman&lt;/span&gt; run                         &lt;span class=&quot;dt&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;at&quot;&gt;-v&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;/home/daniel/dev/gdb:/gdb/src &lt;span class=&quot;dt&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;at&quot;&gt;-v&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;/tmp/gdb-build:/gdb/build     &lt;span class=&quot;dt&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  localhost/gdb-builder            &lt;span class=&quot;dt&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  make &lt;span class=&quot;at&quot;&gt;-C&lt;/span&gt; build &lt;span class=&quot;at&quot;&gt;-j4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To those not familiar with &lt;code&gt;docker&lt;/code&gt;, the command bind
mounts the source and build directories to directories inside the
container and then it runs &lt;code&gt;make -C build -j4&lt;/code&gt;. Note I’ve had
to use &lt;code&gt;podman&lt;/code&gt;/&lt;code&gt;crun&lt;/code&gt; instead of the usual
&lt;code&gt;docker&lt;/code&gt;/&lt;code&gt;runc&lt;/code&gt; because I run &lt;code&gt;cgroup2&lt;/code&gt;
on my host (I do some cgroup2 related development) and docker doesn’t
support cgroup2 yet.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;gdb-builder&lt;/code&gt; image is built by the (simplified for
post) &lt;code&gt;Containerfile&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;docker&quot;&gt;&lt;code&gt;FROM ubuntu

RUN apt-get update
RUN apt-get install -y \
  automake-1.15 \
  bash \
  bison \
  build-essential \
  curl \
  dejagnu \
  flex \
  g++ \
  libncurses-dev \
  libreadline-dev \
  texinfo \
  xsltproc \
  zlib1g-dev

WORKDIR /gdb

COPY scripts/configure.sh configure.sh
RUN chmod 755 configure.sh&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h3&gt;
&lt;p&gt;I’ve never really used docker before and I thought this
infrastructure would be a good way to play around. I’m happy I did this
because docker ended up being a fairly ergonomic way to document the
build. Every time I need something new, it’s easy to add another
subcommand to save the command line invocation. The command line
invocation is certain to work b/c it’s all done inside a reproducible
container.&lt;/p&gt;
&lt;h3 id=&quot;code&quot;&gt;Code&lt;/h3&gt;
&lt;p&gt;The full script repository is &lt;a
href=&quot;https://github.com/danobi/gdb-scripts&quot;&gt;available here&lt;/a&gt;.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Understanding btrfs internals</title><id>https://dxuuu.xyz/btrfs-internals.html</id><updated>2020-09-12T18:00:01-07:00</updated><link href="https://dxuuu.xyz/btrfs-internals.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Understanding btrfs internals&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Understanding btrfs internals&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This is the first of a multipart series that explains the basics of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Btrfs&quot;&gt;btrfs&lt;/a&gt;’s on-disk
format.&lt;/p&gt;
&lt;p&gt;At the end of this series, we’ll have a program that can print out
the absolute path of every regular file in an unmounted btrfs filesystem
image without external libraries or &lt;code&gt;ioctl(2)&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;Example code is available &lt;a
href=&quot;https://github.com/danobi/btrfs-walk&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;
&lt;p&gt;Before we begin, it might be helpful to go over some filesystem
basics. First, there’s &lt;a
href=&quot;https://en.wikipedia.org/wiki/Device_file#BLOCKDEV&quot;&gt;block
devices&lt;/a&gt;. Block devices are a level of abstraction over physical (or
virtual) hardware. You can think of a block device as a linear series of
bytes, of which you can read or write at any offset or size. Filesystems
are typically built on top of block devices and offers structure and
other very useful functionality for storing your data. Such
functionality might include files, directories, data checksums, striping
over multiple block devices, compression, etc. To support these
features, filesystems need to store metadata on the block device in
addition to user data.&lt;/p&gt;
&lt;p&gt;Second, what you typically think of when I say “filesystem” is
probably a &lt;a href=&quot;https://en.wikipedia.org/wiki/POSIX&quot;&gt;POSIX&lt;/a&gt;
filesystem. A POSIX filesystem has all the unix-y things we’ve come to
love: files, “.” and “..” directories, a filesystem tree, as well as the
standard APIs (eg &lt;code&gt;read()&lt;/code&gt;, &lt;code&gt;write()&lt;/code&gt;,
&lt;code&gt;lseek()&lt;/code&gt;, etc). If the APIs are implemented as system calls
(they usually are), the kernel has to be filesystem aware. For linux,
most filesystems are either compiled into the kernel or loaded as kernel
modules.&lt;/p&gt;
&lt;p&gt;Third, a filesystem image can be thought of as the contents of the
entire block device a filesystem is in charge of. It’s usually not a
great idea to manually modify a filesystem image. However, it’s totally
safe to read from a mounted or unmounted one. “Safe” here means you
probably won’t corrupt any data but you might get inconsistent data if
you read from a mounted image (b/c the kernel could be making
changes).&lt;/p&gt;
&lt;h3 id=&quot;notes&quot;&gt;Notes&lt;/h3&gt;
&lt;p&gt;A couple notes to keep in mind while reading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The code samples here may not compile – certain necessary
boilerplate may be omitted in the interest of legibility&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There’s a lot of uninteresting details I’ll skip over (as well as
interesting details, but unfortunately I can’t cover it all)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;creating-a-btrfs-image&quot;&gt;Creating a btrfs image&lt;/h3&gt;
&lt;p&gt;Instead of a “real” block device with a real physical drive behind
it, we’ll use a fake block device (a loopback) to keep things simple (or
even more complicated, if you know how a loopback device works under the
hood). To create a loopback btrfs image and mount it, run:&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ truncate -s 1G image

$ mkfs.btrfs image
btrfs-progs v5.7
See http://btrfs.wiki.kernel.org for more information.

Label:              (null)
UUID:               a32cd5e8-2729-4281-b41b-153ea353ffd3
Node size:          16384
Sector size:        4096
Filesystem size:    1.00GiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP              51.19MiB
  System:           DUP               8.00MiB
SSD detected:       no
Incompat features:  extref, skinny-metadata
Runtime features:
Checksum:           crc32c
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1     1.00GiB  image

$ sudo mkdir /mnt/btrfs

$ sudo mount image /mnt/btrfs

$ findmnt /mnt/btrfs
TARGET     SOURCE     FSTYPE OPTIONS
/mnt/btrfs /dev/loop0 btrfs  rw,relatime,ssd,space_cache,subvolid=5,subvol=/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that &lt;code&gt;image&lt;/code&gt; is a regular file with some bytes in it.
If you choose to leave the image mounted, remember to run
&lt;code&gt;sync&lt;/code&gt; after modifying anything in the filesystem so that the
changes are persisted to “disk”, or in our case, our &lt;code&gt;image&lt;/code&gt;
file.&lt;/p&gt;
&lt;h3 id=&quot;parsing-the-superblock&quot;&gt;Parsing the superblock&lt;/h3&gt;
&lt;p&gt;The superblock is the starting point of any filesystem. It’s a
structure of predefined size written to a predefined location inside the
filesystem image. The key property is that it has all the information
necessary to bootstrap and initialize filesystem data structures.&lt;/p&gt;
&lt;p&gt;First we’ll define the on-disk superblock structure:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsSuperblock &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; csum&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_CSUM_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; fsid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_FSID_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// Physical address of this block&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; bytenr&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; flags&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; magic&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0x8&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; generation&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// Logical address of the root tree root&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; root&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// Logical address of the chunk tree root&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; chunk_root&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// Logical address of the log tree root&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; log_root&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; log_root_transid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; total_bytes&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; bytes_used&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; root_dir_objectid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; num_devices&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; sector_size&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; node_size&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// Unused and must be equal to `nodesize`&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; leafsize&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; stripesize&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; sys_chunk_array_size&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; chunk_root_generation&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; compat_flags&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; compat_ro_flags&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; incompat_flags&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; csum_type&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-33&quot;&gt;&lt;a href=&quot;#function-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; root_level&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-34&quot;&gt;&lt;a href=&quot;#function-34&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; chunk_root_level&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-35&quot;&gt;&lt;a href=&quot;#function-35&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; log_root_level&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-36&quot;&gt;&lt;a href=&quot;#function-36&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; dev_item&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsDevItem&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-37&quot;&gt;&lt;a href=&quot;#function-37&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; label&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_LABEL_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-38&quot;&gt;&lt;a href=&quot;#function-38&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; cache_generation&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-39&quot;&gt;&lt;a href=&quot;#function-39&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; uuid_tree_generation&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-40&quot;&gt;&lt;a href=&quot;#function-40&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; metadata_uuid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_FSID_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-41&quot;&gt;&lt;a href=&quot;#function-41&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// Future expansion&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-42&quot;&gt;&lt;a href=&quot;#function-42&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; _reserved&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;28&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-43&quot;&gt;&lt;a href=&quot;#function-43&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; sys_chunk_array&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-44&quot;&gt;&lt;a href=&quot;#function-44&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; root_backups&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [BtrfsRootBackup&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-45&quot;&gt;&lt;a href=&quot;#function-45&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To parse the superblock, we write the following code:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; BTRFS_SUPERBLOCK_OFFSET&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0x10_000&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first &lt;a
href=&quot;https://btrfs.wiki.kernel.org/index.php/On-disk_Format#Superblock&quot;&gt;btrfs
superblock&lt;/a&gt; (of possibly 3) starts at offset
&lt;code&gt;0x10000&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; BTRFS_SUPERBLOCK_MAGIC&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;8&lt;/span&gt;] &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;b&amp;quot;_BHRfS_M&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Most superblocks have a “magic” value embedded inside so that a
filesystem implementation has a way to easily identify that the image
it’s been told to process is a format it can understand.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; parse_superblock(file&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;File) &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsSuperblock&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; superblock&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsSuperblock &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;std::mem::&lt;/span&gt;zeroed() &lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; superblock_size &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;std::mem::size_of::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsSuperblock&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;()&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; slice&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        slice &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;slice::&lt;/span&gt;from_raw_parts_mut(&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; superblock &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; _ &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; superblock_size)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    file&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;read_exact_at(slice&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; BTRFS_SUPERBLOCK_OFFSET)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; superblock&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;magic &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; BTRFS_SUPERBLOCK_MAGIC &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;pp&quot;&gt;bail!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;superblock magic is wrong&amp;quot;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cn&quot;&gt;Ok&lt;/span&gt;(superblock)&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function takes our &lt;code&gt;image&lt;/code&gt; file as a borrowed &lt;a
href=&quot;https://doc.rust-lang.org/std/fs/struct.File.html&quot;&gt;&lt;code&gt;File&lt;/code&gt;&lt;/a&gt;
and returns a &lt;code&gt;BtrfsSuperblock&lt;/code&gt;. Then we do a bit of unsafe
rust to read from the right offset &lt;code&gt;sizeof(BtrfsSuperblock)&lt;/code&gt;
bytes. If, after reading, the magic doesn’t match, we bail with an
error. The superblock technically contains a &lt;code&gt;csum&lt;/code&gt; (short
for checksum) value and we could (and probably should) check that the
checksum for the superblock matches, but we’re lazy and verifying the
magic value is probably good enough.&lt;/p&gt;
&lt;h3 id=&quot;next&quot;&gt;Next&lt;/h3&gt;
&lt;p&gt;Now that we have the superblock, we can start bootstrapping the rest
of the data structures. More in the next post.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Setting up a barebones website</title><id>https://dxuuu.xyz/barebones-website.html</id><updated>2020-09-12T18:06:13-07:00</updated><link href="https://dxuuu.xyz/barebones-website.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Setting up a barebones website&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Setting up a barebones website&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;I had a very specific workflow in mind when I set out to host a
website. First, I had no desire to be locked into a specific platform.
I’ve experimented with Github pages but it’s pretty locked into Github’s
ecosystem.&lt;/p&gt;
&lt;p&gt;Second, publication and hosting had to be as cross platform as
possible. I wanted to be able to write and publish from anywhere.&lt;/p&gt;
&lt;p&gt;Lastly, I wanted writing to be as hassle-free and minimally invasive
as possible. This meant I did not want to figure out how &lt;a
href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; or &lt;a
href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt; or whatever- have-you works. I
understand that those tools exist for specific reasons, but all I wanted
was a simple setup.&lt;/p&gt;
&lt;p&gt;In other words, I wanted something that would be simple,
straightforward, and portable.&lt;/p&gt;
&lt;p&gt;I came up with the following workflow:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;I write a post or make a change to my website. I do this using
Pandoc flavored markdown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I push the commit to my site’s Github repo. Note: I could use any
git hosting service here, including my own.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then on my server a systemd timer eventually fires. It pulls down
the most recent commits and compiles all the Markdown files to HTML. It
then updates my webserver’s hosting directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some unfortunate soul visits my website and my webserver serves
them this junk.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Take a peek at all the &lt;a
href=&quot;https://github.com/danobi/dxuuu.xyz&quot;&gt;backend configuration
here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;notes&quot;&gt;Notes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Yes, I hard code links to other pages on my site. It might be a
bad idea.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lots of inspiration was drawn from &lt;a
href=&quot;https://danluu.com/&quot;&gt;Dan Luu&lt;/a&gt;‘s website’.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>On writing unmaintainable code</title><id>https://dxuuu.xyz/writing-unmaintainable-code.html</id><updated>2020-09-12T18:09:55-07:00</updated><link href="https://dxuuu.xyz/writing-unmaintainable-code.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;On writing unmaintainable code&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;On writing unmaintainable code&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;The internet’s beaten to death the concept of &lt;a
href=&quot;https://news.ycombinator.com/item?id=13911553&quot;&gt;legacy code&lt;/a&gt;, &lt;a
href=&quot;https://www.doc.ic.ac.uk/%7Esusan/475/unmain.html&quot;&gt;unmaintainable
code&lt;/a&gt;, &lt;a
href=&quot;http://higherorderlogic.com/2010/07/bad-code-isnt-technical-debt-its-an-unhedged-call-option/&quot;&gt;bad
code&lt;/a&gt;, and insert-word-here-code. It’s safe to say nobody really
likes dealing with code that doesn’t make much sense. But how about the
other side of the coin?&lt;/p&gt;
&lt;p&gt;Consider this: you’re tasked with writing inherently tricky code. You
know this code will be nigh unreadable next week, but you also know
someone has to write it. How do you manage the future pain of dealing
with this code?&lt;/p&gt;
&lt;p&gt;Last week I gave that question some thought and I now believe there
are two options in such a scenario.&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Write a lot of comments to help the next guy that comes along to
understand your genius (or lack thereof).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explain what this snippet of code does with clear
{pre,post}-conditions so it can simply be ripped out and replaced next
time someone needs it changed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Option 1 is generally good advice. Comments enhance readability after
all. But consider this snippet:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;/* Replace a subsection of a buffer with a replacement string */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Scrubber&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;scrub_buffer&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;buffer&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; Scrub &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;scrub&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;const&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;buffer_ptr&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; num_matched&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; match_len&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; replacement_len&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; buffer_len &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; strlen&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  buffer_ptr      &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; buffer&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  match_len       &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;ovector&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;ovector&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  replacement_len &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;replacement&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;replacement_len &lt;span class=&quot;op&quot;&gt;&amp;lt;=&lt;/span&gt; match_len&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    buffer_ptr &lt;span class=&quot;op&quot;&gt;+=&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;ovector&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    memcpy&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buffer_ptr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;replacement&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ptr&lt;span class=&quot;op&quot;&gt;(),&lt;/span&gt; replacement_len&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    buffer_ptr &lt;span class=&quot;op&quot;&gt;+=&lt;/span&gt; replacement_len&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    memmove&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buffer_ptr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; buffer &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;ovector&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;],&lt;/span&gt; buffer_len &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;ovector&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ink_assert&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buffer&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;buffer_len &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;match_len &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; replacement_len&lt;span class=&quot;op&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\0&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; n_slide &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; buffer_len &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;ovector&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; replacement_len&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;n_slide &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      replacement_len &lt;span class=&quot;op&quot;&gt;+=&lt;/span&gt; n_slide&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      buffer_ptr &lt;span class=&quot;op&quot;&gt;+=&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;ovector&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; replacement_len&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      memmove&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buffer_ptr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; buffer &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;ovector&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;],&lt;/span&gt; n_slide&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    buffer_ptr &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; buffer &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;ovector&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    memcpy&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buffer_ptr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; scrub&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;replacement&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ptr&lt;span class=&quot;op&quot;&gt;(),&lt;/span&gt; replacement_len&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    buffer&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;buffer_len&lt;span class=&quot;op&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\0&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-33&quot;&gt;&lt;a href=&quot;#function-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice all the C-style pointer fiddling. Reasoning through the code
itself would take less time than reading a sufficiently detailed enough
comment for each line to elucidate each statement. Thus, writing
sufficient comments would theoretically add complexity to the
codebase.&lt;/p&gt;
&lt;p&gt;Now consider option 2. To continue the previous code example, take a
look at this illustration:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;/*&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * When scrubbing the buffer in place, there are 2 scenarios we need to consider:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *   1) The replacement text length is shorter or equal to the text we want to scrub away&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *   2) The replacement text is longer than the text we want to scrub away&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * In case 1, we simply &amp;quot;slide&amp;quot; everything left a bit. Our final buffer should&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * look like this (where XXXX is the replacement text):&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *                                new_end  orig_end&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *                                    V      V&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *   -----------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *   |ORIGINAL TEXT|XXXX|ORIGINAL TEXT|      |&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *   -----------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * In case 2, since the final buffer would be longer than the original allocated buffer,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * we need to truncate everything that would have run over the original end of the buffer.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * The final buffer should look like this:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *                                         new_end&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *                                        orig_end&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *                                           V&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *   -----------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *   |ORIGINAL TEXT|XXXXXXXXXXXXXXXXXXX|ORIGI|NAL TEXT&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *   -----------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To quote an old english idiom, “A picture is worth a thousand words”.
In this case, our picture is actually some ASCII art. Now, the next
person who needs to change this function has two options of their
own:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Understand and modify the existing code with knowledge of the
scope of the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rip out all the old code and write something (hopefully)
better.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Waiting on process exit</title><id>https://dxuuu.xyz/wait-pid.html</id><updated>2020-09-12T18:25:06-07:00</updated><link href="https://dxuuu.xyz/wait-pid.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Waiting on process exit&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Waiting on process exit&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;How does a process wait for another process to exit? Simple question,
right?&lt;/p&gt;
&lt;p&gt;I’ve been recently working on bpftrace and I had to find an answer
for this problem. Ideally, the solution would not do any polling. First,
let’s try the most naive solution: &lt;code&gt;waitpid(2)&lt;/code&gt;:&lt;/p&gt;
&lt;h3 id=&quot;waitpid2&quot;&gt;waitpid(2)&lt;/h3&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;cstdlib&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;thread&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/epoll.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/eventfd.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/wait.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#define MAX_EVENTS &lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;10&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; waiter&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; pid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; efd&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; wstatus&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;waitpid&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;wstatus&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;    perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;waitpid&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; one &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;write&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;efd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;one&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;one&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;    perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;write&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; argv&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; pid&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-33&quot;&gt;&lt;a href=&quot;#function-33&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;argc &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-34&quot;&gt;&lt;a href=&quot;#function-34&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cerr&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;usage: ./waiter &amp;lt;pid&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-35&quot;&gt;&lt;a href=&quot;#function-35&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-36&quot;&gt;&lt;a href=&quot;#function-36&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-37&quot;&gt;&lt;a href=&quot;#function-37&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-38&quot;&gt;&lt;a href=&quot;#function-38&quot;&gt;&lt;/a&gt;  pid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;atoi&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;argv&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-39&quot;&gt;&lt;a href=&quot;#function-39&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-40&quot;&gt;&lt;a href=&quot;#function-40&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// create eventfd in semaphore mode&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-41&quot;&gt;&lt;a href=&quot;#function-41&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; efd &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; eventfd&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; EFD_CLOEXEC &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; EFD_SEMAPHORE&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-42&quot;&gt;&lt;a href=&quot;#function-42&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;efd &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-43&quot;&gt;&lt;a href=&quot;#function-43&quot;&gt;&lt;/a&gt;    perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;eventfd&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-44&quot;&gt;&lt;a href=&quot;#function-44&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-45&quot;&gt;&lt;a href=&quot;#function-45&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-46&quot;&gt;&lt;a href=&quot;#function-46&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-47&quot;&gt;&lt;a href=&quot;#function-47&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// set up epoll&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-48&quot;&gt;&lt;a href=&quot;#function-48&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; epoll_event ev&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; events&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;MAX_EVENTS&lt;span class=&quot;op&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-49&quot;&gt;&lt;a href=&quot;#function-49&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; epollfd &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; epoll_create1&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;EPOLL_CLOEXEC&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-50&quot;&gt;&lt;a href=&quot;#function-50&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epollfd &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-51&quot;&gt;&lt;a href=&quot;#function-51&quot;&gt;&lt;/a&gt;    perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;epoll_create1&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-52&quot;&gt;&lt;a href=&quot;#function-52&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-53&quot;&gt;&lt;a href=&quot;#function-53&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-54&quot;&gt;&lt;a href=&quot;#function-54&quot;&gt;&lt;/a&gt;  ev&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;events &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; EPOLLIN&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-55&quot;&gt;&lt;a href=&quot;#function-55&quot;&gt;&lt;/a&gt;  ev&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;fd &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; efd&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-56&quot;&gt;&lt;a href=&quot;#function-56&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epoll_ctl&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epollfd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; EPOLL_CTL_ADD&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; efd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;ev&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-57&quot;&gt;&lt;a href=&quot;#function-57&quot;&gt;&lt;/a&gt;    perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;epoll_ctl&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-58&quot;&gt;&lt;a href=&quot;#function-58&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-59&quot;&gt;&lt;a href=&quot;#function-59&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-60&quot;&gt;&lt;a href=&quot;#function-60&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-61&quot;&gt;&lt;a href=&quot;#function-61&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; t &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;thread&lt;span class=&quot;op&quot;&gt;([&amp;amp;]()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-62&quot;&gt;&lt;a href=&quot;#function-62&quot;&gt;&lt;/a&gt;    waiter&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; efd&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-63&quot;&gt;&lt;a href=&quot;#function-63&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-64&quot;&gt;&lt;a href=&quot;#function-64&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-65&quot;&gt;&lt;a href=&quot;#function-65&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-66&quot;&gt;&lt;a href=&quot;#function-66&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; nfds &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; epoll_wait&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epollfd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; events&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; MAX_EVENTS&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-67&quot;&gt;&lt;a href=&quot;#function-67&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;nfds &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-68&quot;&gt;&lt;a href=&quot;#function-68&quot;&gt;&lt;/a&gt;      perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;epoll_wait&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-69&quot;&gt;&lt;a href=&quot;#function-69&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-70&quot;&gt;&lt;a href=&quot;#function-70&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-71&quot;&gt;&lt;a href=&quot;#function-71&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-72&quot;&gt;&lt;a href=&quot;#function-72&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; nfds&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-73&quot;&gt;&lt;a href=&quot;#function-73&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;events&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;op&quot;&gt;].&lt;/span&gt;data&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;fd &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; efd&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-74&quot;&gt;&lt;a href=&quot;#function-74&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cerr&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; pid &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot; has exited&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-75&quot;&gt;&lt;a href=&quot;#function-75&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-76&quot;&gt;&lt;a href=&quot;#function-76&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-77&quot;&gt;&lt;a href=&quot;#function-77&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-78&quot;&gt;&lt;a href=&quot;#function-78&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-79&quot;&gt;&lt;a href=&quot;#function-79&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-80&quot;&gt;&lt;a href=&quot;#function-80&quot;&gt;&lt;/a&gt;  t&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-81&quot;&gt;&lt;a href=&quot;#function-81&quot;&gt;&lt;/a&gt;  close&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;efd&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-82&quot;&gt;&lt;a href=&quot;#function-82&quot;&gt;&lt;/a&gt;  close&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epollfd&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-83&quot;&gt;&lt;a href=&quot;#function-83&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In short, our first program creates a thread, passes an eventfd
handle to it, and writes to the eventfd handle once the thread exits
&lt;code&gt;waitpid(2)&lt;/code&gt;. What happens if we run it?&lt;/p&gt;
&lt;p&gt;In one window:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ python3
&amp;gt;&amp;gt;&amp;gt; import os
&amp;gt;&amp;gt;&amp;gt; os.getpid()
1573&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In another:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ g++ waitpid-waitpid.cpp -lpthread
$ ./a.out 1573
waitpid: No child processes
^C
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, &lt;code&gt;waitpid(2)&lt;/code&gt; only works on child
processes.&lt;/p&gt;
&lt;p&gt;Let’s try a different strategy.&lt;/p&gt;
&lt;h3 id=&quot;epoll2-on-procpid&quot;&gt;epoll(2) on /proc/pid&lt;/h3&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;cstdlib&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/epoll.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#define MAX_EVENTS &lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;10&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; argv&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; pid&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; buf&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;argc &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cerr&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;usage: ./waiter &amp;lt;pid&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;  pid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;atoi&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;argv&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;snprintf&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;buf&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;/proc/&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;/status&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; pid&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cerr&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;snprintf failed&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cerr&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;trying to open=&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; buf &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; pidfd &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; open&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;buf&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pidfd &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-33&quot;&gt;&lt;a href=&quot;#function-33&quot;&gt;&lt;/a&gt;    perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;open&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-34&quot;&gt;&lt;a href=&quot;#function-34&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-35&quot;&gt;&lt;a href=&quot;#function-35&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-36&quot;&gt;&lt;a href=&quot;#function-36&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-37&quot;&gt;&lt;a href=&quot;#function-37&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// set up epoll&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-38&quot;&gt;&lt;a href=&quot;#function-38&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; epoll_event ev&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; events&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;MAX_EVENTS&lt;span class=&quot;op&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-39&quot;&gt;&lt;a href=&quot;#function-39&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; epollfd &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; epoll_create1&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;EPOLL_CLOEXEC&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-40&quot;&gt;&lt;a href=&quot;#function-40&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epollfd &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-41&quot;&gt;&lt;a href=&quot;#function-41&quot;&gt;&lt;/a&gt;    perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;epoll_create1&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-42&quot;&gt;&lt;a href=&quot;#function-42&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-43&quot;&gt;&lt;a href=&quot;#function-43&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-44&quot;&gt;&lt;a href=&quot;#function-44&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-45&quot;&gt;&lt;a href=&quot;#function-45&quot;&gt;&lt;/a&gt;  ev&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;events &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; EPOLLERR &lt;span class=&quot;op&quot;&gt;|&lt;/span&gt; EPOLLHUP&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;co&quot;&gt;// wait for procfs entry to disappear&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-46&quot;&gt;&lt;a href=&quot;#function-46&quot;&gt;&lt;/a&gt;  ev&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;fd &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; pidfd&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-47&quot;&gt;&lt;a href=&quot;#function-47&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epoll_ctl&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epollfd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; EPOLL_CTL_ADD&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; pidfd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;ev&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-48&quot;&gt;&lt;a href=&quot;#function-48&quot;&gt;&lt;/a&gt;    perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;epoll_ctl&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-49&quot;&gt;&lt;a href=&quot;#function-49&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-50&quot;&gt;&lt;a href=&quot;#function-50&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-51&quot;&gt;&lt;a href=&quot;#function-51&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-52&quot;&gt;&lt;a href=&quot;#function-52&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-53&quot;&gt;&lt;a href=&quot;#function-53&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; nfds &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; epoll_wait&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epollfd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; events&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; MAX_EVENTS&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-54&quot;&gt;&lt;a href=&quot;#function-54&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;nfds &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-55&quot;&gt;&lt;a href=&quot;#function-55&quot;&gt;&lt;/a&gt;      perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;epoll_wait&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-56&quot;&gt;&lt;a href=&quot;#function-56&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-57&quot;&gt;&lt;a href=&quot;#function-57&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-58&quot;&gt;&lt;a href=&quot;#function-58&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-59&quot;&gt;&lt;a href=&quot;#function-59&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;bool&lt;/span&gt; exited &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-60&quot;&gt;&lt;a href=&quot;#function-60&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; nfds&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-61&quot;&gt;&lt;a href=&quot;#function-61&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;events&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;op&quot;&gt;].&lt;/span&gt;data&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;fd &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; pidfd&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-62&quot;&gt;&lt;a href=&quot;#function-62&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cerr&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; pid &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot; has exited&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-63&quot;&gt;&lt;a href=&quot;#function-63&quot;&gt;&lt;/a&gt;        exited &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-64&quot;&gt;&lt;a href=&quot;#function-64&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-65&quot;&gt;&lt;a href=&quot;#function-65&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-66&quot;&gt;&lt;a href=&quot;#function-66&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-67&quot;&gt;&lt;a href=&quot;#function-67&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;exited&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-68&quot;&gt;&lt;a href=&quot;#function-68&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-69&quot;&gt;&lt;a href=&quot;#function-69&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-70&quot;&gt;&lt;a href=&quot;#function-70&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-71&quot;&gt;&lt;a href=&quot;#function-71&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-72&quot;&gt;&lt;a href=&quot;#function-72&quot;&gt;&lt;/a&gt;  close&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pidfd&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-73&quot;&gt;&lt;a href=&quot;#function-73&quot;&gt;&lt;/a&gt;  close&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;epollfd&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-74&quot;&gt;&lt;a href=&quot;#function-74&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Hey, a clever idea! Let’s poll on &lt;code&gt;/proc/pid/status&lt;/code&gt; and
wait for an EPOLLHUP event. Let’s see if it works.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./a.out 1573
trying to open=/proc/1573/status
epoll_ctl: Operation not permitted
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It turns out that epoll does not support pseudo-fs kernel
interfaces.&lt;/p&gt;
&lt;p&gt;An interesting side note, according to &lt;code&gt;proc(5)&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/proc/[pid]/mounts (since Linux 2.4.19)
...
Since kernel version 2.6.15, this file is pollable: after
opening the file for reading, a change in this file (i.e., a
filesystem mount or unmount) causes select(2) to mark the file
descriptor as having an exceptional condition, and poll(2) and
epoll_wait(2) mark the file as having a priority event (POLL‐
PRI)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s make this change:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre
class=&quot;sourceCode diff&quot;&gt;&lt;code class=&quot;sourceCode diff&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;--- waitpid_epollhup.cpp        2019-01-16 20:16:29.078024749 -0800&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;+++ waitpid_epollhup2.cpp       2019-01-16 20:17:25.766842080 -0800&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;@@ -21,7 +21,7 @@&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   pid = std::atoi(argv[1]);&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;-  if (snprintf(&amp;amp;buf[0], sizeof(buf), &amp;quot;/proc/%d/status&amp;quot;, pid) &amp;lt; 0) {&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+  if (snprintf(&amp;amp;buf[0], sizeof(buf), &amp;quot;/proc/%d/mounts&amp;quot;, pid) &amp;lt; 0) {&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     std::cerr &amp;lt;&amp;lt; &amp;quot;snprintf failed&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     return 1;&lt;/span&gt;
&lt;span id=&quot;cb5-11&quot;&gt;&lt;a href=&quot;#cb5-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   }&lt;/span&gt;
&lt;span id=&quot;cb5-12&quot;&gt;&lt;a href=&quot;#cb5-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;@@ -42,7 +42,7 @@&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-13&quot;&gt;&lt;a href=&quot;#cb5-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     return 1;&lt;/span&gt;
&lt;span id=&quot;cb5-14&quot;&gt;&lt;a href=&quot;#cb5-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   }&lt;/span&gt;
&lt;span id=&quot;cb5-15&quot;&gt;&lt;a href=&quot;#cb5-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-16&quot;&gt;&lt;a href=&quot;#cb5-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;-  ev.events = EPOLLERR | EPOLLHUP;  // wait for procfs entry to disappear&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-17&quot;&gt;&lt;a href=&quot;#cb5-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+  ev.events = EPOLLERR | EPOLLHUP | EPOLLPRI;  // wait for procfs entry to disappear&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-18&quot;&gt;&lt;a href=&quot;#cb5-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   ev.data.fd = pidfd;&lt;/span&gt;
&lt;span id=&quot;cb5-19&quot;&gt;&lt;a href=&quot;#cb5-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   if (epoll_ctl(epollfd, EPOLL_CTL_ADD, pidfd, &amp;amp;ev) &amp;lt; 0) {&lt;/span&gt;
&lt;span id=&quot;cb5-20&quot;&gt;&lt;a href=&quot;#cb5-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     perror(&amp;quot;epoll_ctl&amp;quot;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and see if it works. Run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./a.out 9001
trying to open=/proc/9001/mounts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then kill the python process. Unfortunately (hard to show in
text), it does not work. &lt;code&gt;a.out&lt;/code&gt; hangs.&lt;/p&gt;
&lt;h3 id=&quot;final-attempt-polling-procfs&quot;&gt;Final attempt: polling procfs&lt;/h3&gt;
&lt;p&gt;Even though I said I didn’t want to poll, we might still be able to
get away with polling if we do it infrequently enough. Consider:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdexcept&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;bool&lt;/span&gt; is_pid_alive&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; pid&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; buf&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; ret &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; snprintf&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;buf&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;/proc/&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;/status&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; pid&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ret &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;runtime_error&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;failed to snprintf&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; fd &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; open&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;buf&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;fd &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; errno &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; ENOENT&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;  close&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;**&lt;/span&gt; argv&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;argc &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cerr&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;usage: ./poll &amp;lt;pid&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; pid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;atoi&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;argv&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-33&quot;&gt;&lt;a href=&quot;#function-33&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-34&quot;&gt;&lt;a href=&quot;#function-34&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-35&quot;&gt;&lt;a href=&quot;#function-35&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;is_pid_alive&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;pid&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-36&quot;&gt;&lt;a href=&quot;#function-36&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cerr&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; pid &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot; has died&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-37&quot;&gt;&lt;a href=&quot;#function-37&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-38&quot;&gt;&lt;a href=&quot;#function-38&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-39&quot;&gt;&lt;a href=&quot;#function-39&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-40&quot;&gt;&lt;a href=&quot;#function-40&quot;&gt;&lt;/a&gt;    sleep&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-41&quot;&gt;&lt;a href=&quot;#function-41&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-42&quot;&gt;&lt;a href=&quot;#function-42&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When run with the same python setup:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./a.out 11643
11643 has died
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I guess we’ll have to live with this.&lt;/p&gt;
&lt;h3 id=&quot;unattempted-solutions&quot;&gt;Unattempted solutions&lt;/h3&gt;
&lt;p&gt;There were a few ideas I knew about but didn’t try for various
reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;inotify
&lt;ul&gt;
&lt;li&gt;This doesn’t work for the same reason as &lt;code&gt;epoll&lt;/code&gt;ing on
procfs didn’t: inotify requires changes through a userspace
filesystem.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;netlink
&lt;ul&gt;
&lt;li&gt;There does exist a netlink interface for task stats. However,
creating a netlink socket and monitoring it takes quite a bit of
boilerplate. For bpftrace’s use case, it was far cleaner and less bug
prone to simply poll.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;bpf
&lt;ul&gt;
&lt;li&gt;We could have really nested the turtles here and created another bpf
program to watch for process exit. There’s no real reason I didn’t take
this route other than it was going to take a lot of code.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;ptrace with PTRACE_SEIZE
&lt;ul&gt;
&lt;li&gt;It wasn’t clear to me this would be overhead-free on the target
process. Perhaps in the future I can run some tests.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Understanding btrfs internals part 2</title><id>https://dxuuu.xyz/btrfs-internals-2.html</id><updated>2020-09-14T09:48:11-07:00</updated><link href="https://dxuuu.xyz/btrfs-internals-2.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Understanding btrfs internals part 2&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Understanding btrfs internals part 2&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This is the second of a multipart series that explains the basics of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Btrfs&quot;&gt;btrfs&lt;/a&gt;’s on-disk
format.&lt;/p&gt;
&lt;p&gt;At the end of this series, we’ll have a program that can print out
the absolute path of every regular file in an unmounted btrfs filesystem
image without external libraries or &lt;code&gt;ioctl(2)&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;Example code is available &lt;a
href=&quot;https://github.com/danobi/btrfs-walk&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;
&lt;p&gt;btrfs stores everything (with the exception of the superblocks) in &lt;a
href=&quot;https://en.wikipedia.org/wiki/B-tree&quot;&gt;B-trees&lt;/a&gt;. There’s a
number of different trees – each with their own purpose. All the trees
are linked together with a root of roots: a root node that contains
references to the roots of each tree. As a result, not much data needs
to be placed at fixed offsets. This property allows users to perform &lt;a
href=&quot;https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-convert&quot;&gt;in-place
converstions&lt;/a&gt; from ext2/3/4 or reiserfs to btrfs.&lt;/p&gt;
&lt;p&gt;btrfs also supports multiple devices, meaning data can be striped or
duplicated in various &lt;a
href=&quot;https://en.wikipedia.org/wiki/Standard_RAID_levels&quot;&gt;RAID&lt;/a&gt;
configurations. This information is stored in two central places: the
chunk tree and the device tree. The chunk tree maps logical offsets to
one or more physical offsets. The device tree does the inverse. The two
trees allow btrfs to grow and shrink without unmounting, as chunks can
be located and moved on the fly.&lt;/p&gt;
&lt;p&gt;Almost all of the on-disk structures work with logical offsets,
including the &lt;code&gt;BtrfsSuperblock::root&lt;/code&gt; field. In order to get
access to the root of roots, we must first bootstrap the chunk tree so
that we can translate the logical offset to a physical one. We can then
use the physical offset to read data from disk.&lt;/p&gt;
&lt;h3 id=&quot;bootstrapping-the-chunk-tree&quot;&gt;Bootstrapping the chunk tree&lt;/h3&gt;
&lt;p&gt;First, let’s define the necessary structures:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; BTRFS_CHUNK_ITEM_KEY&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;228&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsKey &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; objectid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; ty&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; offset&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;BtrfsKey&lt;/code&gt; is a fundamental type. All data items in the
on-disk b-trees are keyed by a &lt;code&gt;BtrfsKey&lt;/code&gt;. A node has one or
more data items. The data items in each node are ordered by their key in
ascending order. This allows the tree walking algorithms to do efficient
binary searches. I’ll go deeper into this in the next post. Note that
the all on-disk structures are stored little-endian. In a “real”
implementation, you’d see more little-endian to host-order helpers.
However, since your author is writing this on an x86 machine, we ignore
translating helpers to keep things simple.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsStripe &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; devid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; offset&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; dev_uuid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_UUID_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsChunk &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// size of this chunk in bytes&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; length&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// objectid of the root referencing this chunk&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; owner&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; stripe_len&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; ty&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// optimal io alignment for this chunk&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; io_align&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// optimal io width for this chunk&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; io_width&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// minimal io size for this chunk&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; sector_size&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; num_stripes&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// sub stripes only matter for raid10&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; sub_stripes&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; stripe&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsStripe&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// additional stripes go here&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;code&gt;BtrfsStripe&lt;/code&gt; describes a single stripe. One or more may
be present depending on the configured RAID level. If more than one is
present, the additional &lt;code&gt;BtrfsStripe&lt;/code&gt;s are laid out “after”
the associated &lt;code&gt;BtrfsChunk&lt;/code&gt; (see below).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;BtrfsChunk&lt;/code&gt; is simply the data stored on-disk to describe
a chunk. &lt;code&gt;BtrfsSuperblock::sys_chunk_array&lt;/code&gt; stores
&lt;code&gt;BtrfsKey&lt;/code&gt;s and &lt;code&gt;BtrfsChunk&lt;/code&gt;s “head to feet”. In
other words, with two stripes per chunk:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/btrfs-internals-2/superblock_chunks.png&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;writing-the-code&quot;&gt;Writing the code&lt;/h3&gt;
&lt;p&gt;To bootstrap the chunk tree, we write the following code:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; bootstrap_chunk_tree(superblock&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;BtrfsSuperblock) &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;ChunkTreeCache&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; array_size &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; superblock&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;sys_chunk_array_size &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; offset&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We’ll be walking the length of &lt;code&gt;sys_chunk_array&lt;/code&gt;, so we’ll
need to know where in the array we’re at and when to stop.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; chunk_tree_cache &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;ChunkTreeCache::&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;default&lt;/span&gt;()&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;ChunkTreeCache&lt;/code&gt; is a brain-dead implementation of a
non-overlapping &lt;a
href=&quot;https://en.wikipedia.org/wiki/Interval_tree&quot;&gt;interval tree&lt;/a&gt;.
We’ll omit the implementation here for brevity but you can view it in
full at the link at the top of this page. Suffice to say, the
&lt;code&gt;ChunkTreeCache&lt;/code&gt; stores
&lt;code&gt;(logical offset start, length) -&amp;gt; physical offset start&lt;/code&gt;
mappings and does a little math to help us translate a logical offset to
physical offset, especially if the logical offset is in the middle of a
chunk.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;while&lt;/span&gt; offset &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; array_size &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; key_size &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;std::mem::size_of::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsKey&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;()&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; offset &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; key_size &lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; array_size &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;pp&quot;&gt;bail!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;short key read&amp;quot;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; key_slice &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;superblock&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;sys_chunk_array[offset&lt;span class=&quot;op&quot;&gt;..&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; key &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;*&lt;/span&gt;(key_slice&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;as_ptr() &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; BtrfsKey) &lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ty &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; BTRFS_CHUNK_ITEM_KEY &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;pp&quot;&gt;bail!&lt;/span&gt;(&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;st&quot;&gt;&amp;quot;unknown item type={} in sys_array at offset={}&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ty&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                offset&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            )&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        offset &lt;span class=&quot;op&quot;&gt;+=&lt;/span&gt; key_size&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;First, we start a loop that continues until the entire array is
processed.&lt;/p&gt;
&lt;p&gt;Next, we look for the current &lt;code&gt;BtrfsKey&lt;/code&gt; to process. We do
a little unsafe rust to get a &lt;code&gt;&amp;amp;BtrfsKey&lt;/code&gt; from the raw
&lt;code&gt;sys_chunk_array&lt;/code&gt; buffer. There should only be
&lt;code&gt;BTRFS_CHUNK_ITEM_KEY&lt;/code&gt;s in &lt;code&gt;sys_chunk_array&lt;/code&gt; so
report an error if we see something unexpected.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; offset &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;std::mem::size_of::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsChunk&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;() &lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; array_size &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;pp&quot;&gt;bail!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;short chunk item read&amp;quot;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; chunk_slice &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;superblock&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;sys_chunk_array[offset&lt;span class=&quot;op&quot;&gt;..&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; chunk &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;*&lt;/span&gt;(chunk_slice&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;as_ptr() &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; BtrfsChunk) &lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; chunk&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;num_stripes &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;pp&quot;&gt;bail!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;num_stripes cannot be 0&amp;quot;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that we’ve pulled out a &lt;code&gt;BtrfsKey&lt;/code&gt;, we try and pull
out the associated &lt;code&gt;BtrfsChunk&lt;/code&gt; as well. Each
&lt;code&gt;BtrfsChunk&lt;/code&gt; stores information about one or more stripes,
depending on the RAID level. We &lt;em&gt;have&lt;/em&gt; to have at least one
stripe otherwise it means there’s no backing device. We do this check
just for sanity.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; num_stripes &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; chunk&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;num_stripes&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;// copy to prevent unaligned access&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; num_stripes &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;pp&quot;&gt;println!&lt;/span&gt;(&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;st&quot;&gt;&amp;quot;warning: {} stripes detected but only processing 1&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                num_stripes&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            )&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To keep things simple, we’ll only process 1 stripe, as stripes should
have identical content. Warn the user just to be nice.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; logical &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; chunk_tree_cache&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset(logical)&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;is_none() &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            chunk_tree_cache&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;insert(&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                ChunkTreeKey &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    start&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; logical&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    size&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; chunk&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                ChunkTreeValue &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    offset&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; chunk&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;stripe&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            )&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we add an entry into the &lt;code&gt;ChunkTreeCache&lt;/code&gt; if the
interval is not already present. Note that &lt;code&gt;BtrfsKey::offset&lt;/code&gt;
contains the logical start of the chunk. You’ll see this pattern
repeated often throughout the btrfs codebase. The only field that has a
fixed meaning between different trees and data items is
&lt;code&gt;BtrfsKey::ty&lt;/code&gt;. &lt;code&gt;BtrfsKey::objectid&lt;/code&gt; and
&lt;code&gt;BtrfsOffset::offset&lt;/code&gt; are opaque and may represent different
things from data item to data item.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; chunk_item_size &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;std::mem::size_of::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsChunk&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;()&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; (&lt;span class=&quot;pp&quot;&gt;std::mem::size_of::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsStripe&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;() &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; (chunk&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;num_stripes &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; offset &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; chunk_item_size &lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; array_size &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;pp&quot;&gt;bail!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;short chunk item + stripe read&amp;quot;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        offset &lt;span class=&quot;op&quot;&gt;+=&lt;/span&gt; chunk_item_size&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cn&quot;&gt;Ok&lt;/span&gt;(chunk_tree_cache)&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Despite only processing one stripe, we need to be careful to skip
over the entire chunk item. As mentioned earlier, this is because each
additional stripe (beyond the first) is appended to the end of
&lt;code&gt;BtrfsChunk&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;And finally, we return.&lt;/p&gt;
&lt;h3 id=&quot;next&quot;&gt;Next&lt;/h3&gt;
&lt;p&gt;Having bootstrapped the chunk tree, the next thing we need to do is
process the rest of the chunk tree. More in the next post.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Understanding btrfs internals part 3</title><id>https://dxuuu.xyz/btrfs-internals-3.html</id><updated>2020-09-27T16:23:36-07:00</updated><link href="https://dxuuu.xyz/btrfs-internals-3.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Understanding btrfs internals part 3&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Understanding btrfs internals part 3&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This is the third of a multipart series that explains the basics of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Btrfs&quot;&gt;btrfs&lt;/a&gt;’s on-disk
format.&lt;/p&gt;
&lt;p&gt;At the end of this series, we’ll have a program that can print out
the absolute path of every regular file in an unmounted btrfs filesystem
image without external libraries or &lt;code&gt;ioctl(2)&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;Example code is available &lt;a
href=&quot;https://github.com/danobi/btrfs-walk&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;
&lt;p&gt;As explained in &lt;a href=&quot;btrfs-internals-2.html&quot;&gt;part 2&lt;/a&gt;, btrfs
stores nearly everything on-disk in B-trees. And as promised, I’ll now
describe the B-tree data format. First, an example tree:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/btrfs-internals-3/tree.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Each node in a btrfs B-tree is prefixed with a header. The header
records the node’s “level”. Level 0 means the node is a leaf node and
stores a payload. Level &amp;gt; 0 means the node is an internal node and
stores pointers to children nodes. The header also stores the number of
“items” the node contains where an “item” is either a pointer to child
node if &lt;code&gt;level &amp;gt; 0&lt;/code&gt;, else, information on where to find
the payload in the node. Recall that each item in a node is sorted by
the associated &lt;code&gt;BtrfsKey&lt;/code&gt; which allows for efficient binary
searches. There’s also some other data but it’s not too important to
us.&lt;/p&gt;
&lt;p&gt;In our example, &lt;code&gt;root&lt;/code&gt; and &lt;code&gt;node 0&lt;/code&gt; contain
&lt;code&gt;BtrfsKeyPtr&lt;/code&gt;s because they’re not leaf nodes.
&lt;code&gt;leaf 0&lt;/code&gt; and &lt;code&gt;leaf 1&lt;/code&gt; contain
&lt;code&gt;BtrfsItem&lt;/code&gt;s because they &lt;em&gt;are&lt;/em&gt; leaf nodes.&lt;/p&gt;
&lt;h3 id=&quot;reading-the-chunk-tree&quot;&gt;Reading the chunk tree&lt;/h3&gt;
&lt;p&gt;Now that we understand how trees are laid out on disk, let’s process
the rest of the chunk tree.&lt;/p&gt;
&lt;p&gt;First, let’s define the necessary structures:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsHeader &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; csum&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_CSUM_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; fsid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_FSID_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; bytenr&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; flags&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; chunk_tree_uuid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_UUID_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; generation&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; owner&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; nritems&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; level&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsKeyPtr &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; key&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsKey&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; blockptr&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; generation&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsItem &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; key&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsKey&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; offset&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; size&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that &lt;code&gt;BtrfsItem::offset&lt;/code&gt; is the offset from the
&lt;em&gt;end&lt;/em&gt; of the associated &lt;code&gt;BtrfsHeader&lt;/code&gt; that we can find
the payload for the &lt;code&gt;BtrfsItem&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Although not strictly necessary, we also define
&lt;code&gt;BtrfsNode&lt;/code&gt; and &lt;code&gt;BtrfsLeaf&lt;/code&gt; as the following:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsNode &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; header&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsHeader&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// `BtrfsKeyPtr`s begin here&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsLeaf &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; header&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsHeader&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// `BtrfsItem`s begin here&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We don’t need these structure definitions because all it tells us is
that every node in the on-disk B-tree starts with
&lt;code&gt;BtrfsHeader&lt;/code&gt;. After parsing the header and reading
&lt;code&gt;BtrfsHeader::level&lt;/code&gt;, we can infer what follows the
header.&lt;/p&gt;
&lt;h3 id=&quot;writing-the-code&quot;&gt;Writing the code&lt;/h3&gt;
&lt;p&gt;To walk any tree, we need to start at the root node. The superblock
contains the logical offset the chunk tree root lives at. To read
it:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; read_chunk_tree_root(&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    file&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;File&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    chunk_root_logical&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cache&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;ChunkTreeCache&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;) &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; size &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; cache&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;mapping_kv(chunk_root_logical)&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ok_or_else(&lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;anyhow!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;Chunk tree root not bootstrapped&amp;quot;&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;?&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; physical &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; cache&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset(chunk_root_logical)&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ok_or_else(&lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;anyhow!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;Chunk tree root not bootstrapped&amp;quot;&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; root &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;vec!&lt;/span&gt;[&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; size &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    file&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;read_exact_at(&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; root&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; physical)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cn&quot;&gt;Ok&lt;/span&gt;(root)&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;where &lt;code&gt;chunk_root_logical&lt;/code&gt; is
&lt;code&gt;BtrfsSuperblock::chunk_root&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Walking the actual tree looks like a traditional recursive
tree-walking algorithm:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; read_chunk_tree(&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    file&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;File&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    root&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;[&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    chunk_tree_cache&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; ChunkTreeCache&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    superblock&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;BtrfsSuperblock&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;) &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;()&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; header &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;tree::&lt;/span&gt;parse_btrfs_header(root)&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;expect(&lt;span class=&quot;st&quot;&gt;&amp;quot;failed to parse chunk root header&amp;quot;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;tree::parse_btrfs_header&lt;/code&gt; is a simple helper function
that extracts the &lt;code&gt;BtrfsHeader&lt;/code&gt; out of &lt;code&gt;root&lt;/code&gt; and
returns a reference to the header.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// Level 0 is leaf node, !0 is internal node&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; header&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;level &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; items &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;tree::&lt;/span&gt;parse_btrfs_leaf(root)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we’re at level 0, we know we’re looking at a leaf node. So we use
&lt;code&gt;tree::parse_btrfs_leaf&lt;/code&gt; to extract the
&lt;code&gt;BtrfsItem&lt;/code&gt;s.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; items &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ty &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; BTRFS_CHUNK_ITEM_KEY &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We skip anything that isn’t a chunk item. The chunk tree also
contains &lt;code&gt;BTRFS_DEV_ITEM_KEY&lt;/code&gt;s which help map physical
offsets to logical offsets. However, we only need chunk items for our
purpose so we skip everything else.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; chunk &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;// `item.offset` is offset from data portion of `BtrfsLeaf` where&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;// associated `BtrfsChunk` starts&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;&amp;amp;*&lt;/span&gt;(root&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;as_ptr()&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;add(&lt;span class=&quot;pp&quot;&gt;std::mem::size_of::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsHeader&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;() &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; BtrfsChunk)&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As mentioned earlier, &lt;code&gt;BtrfsItem::offset&lt;/code&gt; is the offset
from the &lt;em&gt;end&lt;/em&gt; of the &lt;code&gt;BtrfsHeader&lt;/code&gt;. The above code
does the proper math to pull out the &lt;code&gt;BtrfsChunk&lt;/code&gt; associated
with the current &lt;code&gt;item&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            chunk_tree_cache&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;insert(&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                ChunkTreeKey &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    start&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    size&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; chunk&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                ChunkTreeValue &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    offset&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; chunk&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;stripe&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            )&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, we add the chunk entry into our chunk tree cache.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; ptrs &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;tree::&lt;/span&gt;parse_btrfs_node(root)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; ptr &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; ptrs &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; physical &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; chunk_tree_cache&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset(ptr&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;blockptr)&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ok_or_else(&lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;anyhow!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;Chunk tree node not mapped&amp;quot;&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; node &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;vec!&lt;/span&gt;[&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; superblock&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;node_size &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            file&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;read_exact_at(&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; node&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; physical)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            read_chunk_tree(file&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;node&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; chunk_tree_cache&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; superblock)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we see &lt;code&gt;level != 0&lt;/code&gt;, we know we’re looking at an
internal node. So we use the &lt;code&gt;tree::parse_btrfs_node&lt;/code&gt; helper
to parse an internal node. Once we have the &lt;code&gt;BtrfsKeyPtr&lt;/code&gt;s,
we read the node the key points to and recursively call
&lt;code&gt;read_chunk_tree&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cn&quot;&gt;Ok&lt;/span&gt;(())&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we haven’t errored out by the end, it means we successfully walked
the chunk tree.&lt;/p&gt;
&lt;h3 id=&quot;next&quot;&gt;Next&lt;/h3&gt;
&lt;p&gt;Now that we’ve loaded the entire chunk tree into our cache, we can
move onto walking the trees that contain the information we actually
care about. In the next post, we’ll extract the filesystem tree root
from the root tree root.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Understanding btrfs internals part 5</title><id>https://dxuuu.xyz/btrfs-internals-5.html</id><updated>2020-11-15T18:21:50-08:00</updated><link href="https://dxuuu.xyz/btrfs-internals-5.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Understanding btrfs internals part 5&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Understanding btrfs internals part 5&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This is the fifth and final part of a multipart series that explains
the basics of &lt;a href=&quot;https://en.wikipedia.org/wiki/Btrfs&quot;&gt;btrfs&lt;/a&gt;’s
on-disk format.&lt;/p&gt;
&lt;p&gt;At the end of this series, we’ll have a program that can print out
the absolute path of every regular file in an unmounted btrfs filesystem
image without external libraries or &lt;code&gt;ioctl(2)&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;Example code is available &lt;a
href=&quot;https://github.com/danobi/btrfs-walk&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;
&lt;p&gt;At the end of &lt;a href=&quot;btrfs-internals-4.html&quot;&gt;Part 4&lt;/a&gt;, we had
access to the filesystem tree root. All that’s left for us to do now is
walk the filesystem tree and make sense of the data it contains.&lt;/p&gt;
&lt;p&gt;By now, you should be fairly familiar with the high level B-tree
algorithms we’re using. You should also be familiar with how btrfs
structures its metadata. The hard part is over! This final part is not
very complicated – at this point it’s an exercise in reading &lt;a
href=&quot;https://btrfs.wiki.kernel.org/index.php/On-disk_Format#FS_TREE_.285.29&quot;&gt;the
documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;filesystem-tree-item-types&quot;&gt;Filesystem tree item types&lt;/h3&gt;
&lt;p&gt;There are quite a few item types stored in the FS tree. However, we
only care about two:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;a
href=&quot;https://btrfs.wiki.kernel.org/index.php/Data_Structures#btrfs_dir_item&quot;&gt;&lt;code&gt;BtrfsDirItem&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://btrfs.wiki.kernel.org/index.php/Data_Structures#btrfs_inode_ref&quot;&gt;&lt;code&gt;BtrfsInodeRef&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;BtrfsDirItem&lt;/code&gt; represents an entry in a directory. The
name of the directory entry directly follows the structure. We’ll
enumerate all the &lt;code&gt;BtrfsDirItem&lt;/code&gt;s in the filesystem, grab
their names, and the compute the absolute path leading up to the
directory entry.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;BtrfsInodeRef&lt;/code&gt; is a helper structure that helps link
inode numbers to &lt;code&gt;BtrfsDirItem&lt;/code&gt;s. It also contains
information on the parent of the inode. We’ll use this information to
locate the parents for every regular file we find. The name of the inode
&lt;code&gt;BtrfsInodeRef&lt;/code&gt; refers to directly follows the structure.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;BtrfsDirItem&lt;/code&gt; and &lt;code&gt;BtrfsInodeRef&lt;/code&gt; are defined
as follows:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsDirItem &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; location&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsKey&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; transid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; data_len&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; name_len&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; ty&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsInodeRef &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; index&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; name_len&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u16&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;writing-the-code&quot;&gt;Writing the code&lt;/h3&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; walk_fs_tree(&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    file&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;File&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    superblock&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;BtrfsSuperblock&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    node&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;[&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    root_fs_node&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;[&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cache&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;ChunkTreeCache&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;) &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;()&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; header &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;tree::&lt;/span&gt;parse_btrfs_header(node)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This should be fairly familiar to you by now. Always parse the header
of a node first.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// Leaf node&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; header&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;level &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; items &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;tree::&lt;/span&gt;parse_btrfs_leaf(node)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; items &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ty &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; BTRFS_DIR_ITEM_KEY &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; dir_item &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;&amp;amp;*&lt;/span&gt;(node&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;as_ptr()&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;add(&lt;span class=&quot;pp&quot;&gt;std::mem::size_of::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsHeader&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;() &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; BtrfsDirItem)&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; dir_item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ty &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; BTRFS_FT_REG_FILE &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This too should be familiar. If we’re at a leaf node, start
processing the items in the node.&lt;/p&gt;
&lt;p&gt;For our use case, we only want &lt;code&gt;BtrfsDirItem&lt;/code&gt;s that
represent regular files. Skip everything else.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; name_slice &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;pp&quot;&gt;std::slice::&lt;/span&gt;from_raw_parts(&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    (dir_item &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; BtrfsDirItem &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;add(&lt;span class=&quot;pp&quot;&gt;std::mem::size_of::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsDirItem&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;())&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    dir_item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;name_len&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;into()&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                )&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; name &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;std::&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;::&lt;/span&gt;from_utf8(name_slice)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Extract the name of the directory entry. For example, if this
&lt;code&gt;BtrfsDirItem&lt;/code&gt; represented
&lt;code&gt;/home/daniel/dev/readme.txt&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt; would
contain &lt;code&gt;readme.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now that we have the filename, we must compute the absolute path
leading up to it.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;co&quot;&gt;// Capacity 1 so we don&amp;#39;t panic the first `String::insert`&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; path_prefix &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;::&lt;/span&gt;with_capacity(&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;co&quot;&gt;// `item.key.objectid` is parent inode number&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; current_inode_nr &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;objectid&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here’s where things get a little trickier. If you haven’t already
noticed, btrfs tends to store whatever it wants inside a
&lt;code&gt;BtrfsKey&lt;/code&gt;. The only thing that’s really nailed down is
&lt;code&gt;BtrfsKey::ty&lt;/code&gt;. Aside from the type field, the meaning of the
&lt;code&gt;BtrfsKey::objectid&lt;/code&gt; and &lt;code&gt;BtrfsKey::offset&lt;/code&gt; fields
completely depend on the item type. In other words, just because the
name is &lt;code&gt;offset&lt;/code&gt; doesn’t necessarily mean it’s actually the
offset to anything.&lt;/p&gt;
&lt;p&gt;Here, &lt;code&gt;item.key.objectid&lt;/code&gt; actually means the inode number
of the current directory item’s parent.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;cf&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Start a loop that’ll end when we’re done looking up the absolute path
of this current directory entry.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; (current_key&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; _current_inode&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; current_inode_payload) &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    get_inode_ref(current_inode_nr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; file&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; superblock&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; root_fs_node&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; cache)&lt;span class=&quot;op&quot;&gt;?&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ok_or_else(&lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                            &lt;span class=&quot;pp&quot;&gt;anyhow!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;Failed to find inode_ref for inode={}&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                                current_inode_nr)&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;kw&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;assert_eq!&lt;/span&gt;(current_key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;objectid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; current_inode_nr) &lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Look up the &lt;code&gt;BtrfsInodeRef&lt;/code&gt; for the
&lt;code&gt;current_inode_nr&lt;/code&gt;. When the loop beings, it holds the
immediate parent to the directory entry. As the loop iterates, it’ll go
to the parent’s parent, the parent’s parent’s parent, etc. until we
reach the root of the filesystem.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;get_inode_ref()&lt;/code&gt; returns a tuple of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BtrfsKey&lt;/code&gt; associated with the
&lt;code&gt;BtrfsInodeRef&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;BtrfsInodeRef&lt;/code&gt; struct itself&lt;/li&gt;
&lt;li&gt;the payload after the &lt;code&gt;BtrfsInodeRef&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We omit &lt;code&gt;get_inode_ref()&lt;/code&gt;s implementation for brevity.
It’s essentially the same code as this function except it searches for
&lt;code&gt;BtrfsInodeRef&lt;/code&gt;s.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; current_key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; current_inode_nr &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    path_prefix&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;insert(&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;cf&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Check if we’ve reached the root of the filesystem. For
&lt;code&gt;BtrfsInodeRef&lt;/code&gt;s, the &lt;code&gt;BtrfsKey::offset&lt;/code&gt; field
holds &lt;code&gt;_current_inode&lt;/code&gt;’s parent’s inode number. If the parent
inode # and the current inode # match, it means we’re at the root of the
filesyste.&lt;/p&gt;
&lt;p&gt;If we’re at the root, insert a &lt;code&gt;/&lt;/code&gt; to
&lt;code&gt;path_prefix&lt;/code&gt; to root the absolute path and exit the
loop.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                path_prefix&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;insert_str(&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                    &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;format!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;{}/&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;std::&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;::&lt;/span&gt;from_utf8(&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;current_inode_payload)&lt;span class=&quot;op&quot;&gt;?&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                )&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we’re not yet at the root, we interpret
&lt;code&gt;BtrfsInodeRef&lt;/code&gt;’s payload as a string containing the name of
the inode. We tack that onto the front of &lt;code&gt;path_prefix&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                current_inode_nr &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; current_key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The last thing we do in the loop is set &lt;code&gt;current_inode_nr&lt;/code&gt;
to its parent’s inode number. This ensure we keep moving closer to the
root of the filesystem.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;pp&quot;&gt;println!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;filename={}{}&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; path_prefix&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; name)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, after the loop exits, we combine &lt;code&gt;path_prefix&lt;/code&gt;
and &lt;code&gt;name&lt;/code&gt; to get the absolute path of the regular file we’re
processing. We print the result to the terminal.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; ptrs &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;tree::&lt;/span&gt;parse_btrfs_node(node)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; ptr &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; ptrs &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; physical &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; cache&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset(ptr&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;blockptr)&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ok_or_else(&lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;anyhow!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;fs tree node not mapped&amp;quot;&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; node &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;vec!&lt;/span&gt;[&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; superblock&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;node_size &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            file&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;read_exact_at(&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; node&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; physical)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            walk_fs_tree(file&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; superblock&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;node&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; root_fs_node&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; cache)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This really ought to bore you now. If we’re at an internal node,
recursively process each of the child nodes.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cn&quot;&gt;Ok&lt;/span&gt;(())&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And finally, if we’ve reached the end of the function, we’re
done.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Congrats on making it this far in the series! Creating and writing up
&lt;code&gt;btrfs-walk&lt;/code&gt; was extraordinarly educational for me and
hopefully for you as well.&lt;/p&gt;
&lt;p&gt;Note that we’ve just barely scratched the surface of all the
complexity btrfs contains. But with a solid understanding of the core
data structures, you should feel comfortable diving deeper into btrfs
internals on your own.&lt;/p&gt;
&lt;p&gt;If you’re still interested in btrfs, take a look at &lt;a
href=&quot;https://github.com/danobi/btrfs-fuzz&quot;&gt;&lt;code&gt;btrfs-fuzz&lt;/code&gt;&lt;/a&gt;.
It’s an unsupervised coverage-guided btrfs fuzzer that I’m creating
using what I’ve learned from btrfs-walk.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Understanding btrfs internals part 4</title><id>https://dxuuu.xyz/btrfs-internals-4.html</id><updated>2020-11-15T18:27:00-08:00</updated><link href="https://dxuuu.xyz/btrfs-internals-4.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Understanding btrfs internals part 4&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Understanding btrfs internals part 4&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This is the fourth of a multipart series that explains the basics of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Btrfs&quot;&gt;btrfs&lt;/a&gt;’s on-disk
format.&lt;/p&gt;
&lt;p&gt;At the end of this series, we’ll have a program that can print out
the absolute path of every regular file in an unmounted btrfs filesystem
image without external libraries or &lt;code&gt;ioctl(2)&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;Example code is available &lt;a
href=&quot;https://github.com/danobi/btrfs-walk&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;btrfs-internals-3.html&quot;&gt;Part 3&lt;/a&gt; went into detail on how
to walk an on-disk B-tree given the logical address of a root node.
However, not all tree roots are stored in the superblock. To access any
tree that isn’t the chunk tree or the log tree, we must locate the
relevant root using the root tree root.&lt;/p&gt;
&lt;p&gt;The root tree root contains references to all the other trees:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/btrfs-internals-4/tree.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The superblock contains the logical address for the root tree root
node. The root tree root is a leaf node that contains
&lt;code&gt;BtrfsRootItem&lt;/code&gt;s as payloads. The &lt;code&gt;BtrfsRootItem&lt;/code&gt;s
contain references to other tree roots. Note that the solid lines are
direct references insofar as the reference is a
&lt;code&gt;BtrfsKeyPtr&lt;/code&gt;. The dashed line is a reference through other
means.&lt;/p&gt;
&lt;p&gt;Note that the root tree may also contain other item types. They’re
not particularly interesting for our tool so we’ll ignore them.&lt;/p&gt;
&lt;h3 id=&quot;reading-the-root-tree-root&quot;&gt;Reading the root tree root&lt;/h3&gt;
&lt;p&gt;First, we read the root tree root. This should be fairly
straightforward by now:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; read_root_tree_root(&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    file&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;File&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    root_tree_root_logical&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cache&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;ChunkTreeCache&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;) &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; size &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; cache&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;mapping_kv(root_tree_root_logical)&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ok_or_else(&lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;anyhow!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;Root tree root logical addr not mapped&amp;quot;&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;?&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; physical &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; cache&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset(root_tree_root_logical)&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ok_or_else(&lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;anyhow!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;Root tree root logical addr not mapped&amp;quot;&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; root &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;vec!&lt;/span&gt;[&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; size &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    file&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;read_exact_at(&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; root&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; physical)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cn&quot;&gt;Ok&lt;/span&gt;(root)&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;where &lt;code&gt;root_tree_root_logical&lt;/code&gt; is available in
&lt;code&gt;BtrfsSuperblock::root&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now that we’ve got the root tree root, it’s time to extract the
filesystem tree root from it.&lt;/p&gt;
&lt;h3 id=&quot;reading-the-filesystem-tree-root&quot;&gt;Reading the filesystem tree
root&lt;/h3&gt;
&lt;p&gt;First, let’s define &lt;code&gt;BtrfsRootItem&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;repr&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; packed&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;#[&lt;/span&gt;derive&lt;span class=&quot;at&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;Clone&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; BtrfsRootItem &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; inode&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsInodeItem&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; generation&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; root_dirid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; bytenr&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; byte_limit&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; bytes_used&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; last_snapshot&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; flags&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; refs&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; drop_progress&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsKey&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; drop_level&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; level&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; generation_v2&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; uuid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_UUID_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; parent_uuid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_UUID_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; received_uuid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; BTRFS_UUID_SIZE]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// updated when an inode changes&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; ctransid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// trans when created&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; otransid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// trans when sent. non-zero for received subvol&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; stransid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// trans when received. non-zero for received subvol&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; rtransid&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; ctime&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsTimespec&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; otime&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsTimespec&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; stime&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsTimespec&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; rtime&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; BtrfsTimespec&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; reserved&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; [&lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;8&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-33&quot;&gt;&lt;a href=&quot;#function-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To walk the root tree root, we can use the same algorithm as we used
when we walked the chunk tree root. Note that this is the benefit of
using the same B-tree data structure to store all btrfs data and
metadata (reusable algorithms).&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; read_fs_tree_root(&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    file&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;File&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    superblock&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;BtrfsSuperblock&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    root_tree_root&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;[&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cache&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;ChunkTreeCache&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;) &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; header &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;pp&quot;&gt;tree::&lt;/span&gt;parse_btrfs_header(root_tree_root)&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;expect(&lt;span class=&quot;st&quot;&gt;&amp;quot;failed to parse root tree root header&amp;quot;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; header&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;level &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;pp&quot;&gt;bail!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;Root tree root is not a leaf node&amp;quot;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Extract the header and see if we’re at a leaf node. The root tree
root must be a leaf node so bail if it’s not.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; items &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;tree::&lt;/span&gt;parse_btrfs_leaf(root_tree_root)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; items&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;iter()&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;rev() &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;objectid &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; BTRFS_FS_TREE_OBJECTID&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;              &lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ty &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; BTRFS_ROOT_ITEM_KEY &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;cf&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, find the first (and only) &lt;code&gt;BtrfsItem&lt;/code&gt; in the node
that’s the filesystem tree root.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; root_item &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;unsafe&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;&amp;amp;*&lt;/span&gt;(root_tree_root&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;as_ptr()&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;add(&lt;span class=&quot;pp&quot;&gt;std::mem::size_of::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BtrfsHeader&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;() &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;const&lt;/span&gt; BtrfsRootItem)&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once we have the &lt;code&gt;&amp;amp;BtrfsItem&lt;/code&gt;, we want to extract the
payload. &lt;code&gt;BtrfsItem::offset&lt;/code&gt; is the offset from the
&lt;em&gt;end&lt;/em&gt; of the &lt;code&gt;BtrfsHeader&lt;/code&gt;. The above code does the
math to pull out the &lt;code&gt;BtrfsRootItem&lt;/code&gt; associated with the
current &lt;code&gt;BtrfsItem&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; physical &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; cache&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;offset(root_item&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;bytenr)&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;ok_or_else(&lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;anyhow!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;fs tree root not mapped&amp;quot;&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; node &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;vec!&lt;/span&gt;[&lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt; superblock&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;node_size &lt;span class=&quot;kw&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;usize&lt;/span&gt;]&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        file&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;read_exact_at(&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; node&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; physical)&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;cn&quot;&gt;Ok&lt;/span&gt;(node)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now read the filesystem tree root.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;pp&quot;&gt;bail!&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&amp;quot;Failed to find root tree item for fs tree root&amp;quot;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, if the loop has finished and we haven’t returned yet, we
return an error saying we couldn’t find the filesystem tree root. This
should never happen for a proper btrfs image.&lt;/p&gt;
&lt;h3 id=&quot;next&quot;&gt;Next&lt;/h3&gt;
&lt;p&gt;We’re almost done! We have the filesystem tree root. All that’s left
is to walk the filesystem tree and make sense of the data we care about.
In our case, we want the absolute path of every regular file. In the
next post, we’ll finish off our project.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>libbpf-rs: eBPF for the Rust ecosystem</title><id>https://dxuuu.xyz/libbpf-rs.html</id><updated>2021-01-04T17:24:15-08:00</updated><link href="https://dxuuu.xyz/libbpf-rs.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;libbpf-rs: eBPF for the Rust ecosystem&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;libbpf-rs: eBPF for the Rust ecosystem&lt;/h1&gt;
&lt;/header&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;libbpf-rs provides safe Rust bindings to libbpf as well as a cargo
plugin to help you develop “Compile Once - Run Everywhere” eBPF
applications. Use libbpf-rs over BCC to produce smaller, more efficient,
and more predictable applications.&lt;/p&gt;
&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;
&lt;p&gt;eBPF (BPF) programs have traditionally been written using &lt;a
href=&quot;https://github.com/iovisor/bcc&quot;&gt;BPF compiler collection&lt;/a&gt; (BCC).
The application would then call into BCC using the C++ or Python
bindings. BCC has an “on-the-fly” model, meaning BPF programs are
compiled during runtime on production hosts. While this works, there are
drawbacks:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;Every production machine needs kernel headers installed. These
can get out of sync and can be missing internal headers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LLVM/clang is heavyweight in both binary size and resource
consumption. This is because BCC needs to compile the BPF program
(written in C) down to BPF bytecode the kernel can understand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;End results can vary with kernel version and configuration. The
BPF program can and will change depending on the host it’s running
on.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This diagram illustrates BCC’s compilation and runtime model:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/libbpf-rs/bcc.svg&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;compile-once---run-everywhere&quot;&gt;Compile Once - Run
Everywhere&lt;/h3&gt;
&lt;p&gt;&lt;a
href=&quot;https://facebookmicrosites.github.io/bpf/blog/2020/02/19/bpf-portability-and-co-re.html&quot;&gt;Compile
Once - Run Everywhere&lt;/a&gt; (CO-RE) is a development effort solves the
above issues by enabling ahead of time BPF program compilation. A
summary of developments include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.kernel.org/doc/html/latest/bpf/btf.html&quot;&gt;BPF
type format&lt;/a&gt; (BTF). You can think of BTF as a very light weight
alternative to &lt;a href=&quot;https://en.wikipedia.org/wiki/DWARF&quot;&gt;DWARF&lt;/a&gt;;
light enough that you can write a parser in an afternoon. When the
kernel is compiled with &lt;code&gt;CONFIG_DEBUG_INFO_BTF=y&lt;/code&gt;, the final
kernel image contains BTF entries for &lt;strong&gt;all&lt;/strong&gt; internal data
structures. Type definitions can then be extracted from BTF, obviating
the kernel header dependency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compiler (clang) support for relocatable field accesses. Consider
accessing field &lt;code&gt;bar&lt;/code&gt; from &lt;code&gt;struct Foo&lt;/code&gt;. In BCC’s
model, BCC doesn’t need to worry about &lt;code&gt;struct Foo&lt;/code&gt;’s
structure layout changing. That’s because BCC compiles the program
against the installed headers on every target host. This becomes an
issue for CO-RE BPF progs. CO-RE BPF progs must have their field
accesses relocated so that they reflect the target host’s structure
layouts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BPF loader (&lt;a
href=&quot;https://github.com/libbpf/libbpf&quot;&gt;libbpf&lt;/a&gt;) support for BPF
program fixups. libbpf must “custom-tailor” the BPF program for the
target host it’s running on.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More in-depth documentation as well as user facing APIs is available
&lt;a
href=&quot;https://facebookmicrosites.github.io/bpf/blog/2020/02/19/bpf-portability-and-co-re.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This diagram illustrates the CO-RE compilation and runtime model:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/libbpf-rs/core.svg&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;enter-rust&quot;&gt;Enter Rust&lt;/h3&gt;
&lt;p&gt;Why Rust? Rust’s appeal (to systems programmers like myself) is its
emphasis on safety without compromising performance or expressiveness.
As such, there are powerful facilities for library designers to build
abstractions that resist misuse. This, coupled with the kernel’s
guarantee that a verified BPF program (modulo bugs) can never crash,
hang or interfere with the kernel negatively makes Rust + BPF a very
attractive combination.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/libbpf/libbpf-rs&quot;&gt;libbpf-rs&lt;/a&gt; provides
safe (w.r.t. Rust’s &lt;code&gt;unsafe&lt;/code&gt; keyword) bindings to libbpf. On
top of that, libbpf-rs is designed such that if your code can compile,
you’re almost certainly using the library correctly. Much of that
guarantee comes from liberal use of newtype and builder APIs.&lt;/p&gt;
&lt;p&gt;libbpf-cargo is a &lt;a
href=&quot;https://doc.rust-lang.org/cargo/&quot;&gt;cargo&lt;/a&gt; plugin that integrates
with cargo workflows Rust programmers are already familiar with.&lt;/p&gt;
&lt;p&gt;Together, libbpf-rs and libbpf-cargo provide CO-RE support in the
Rust ecosystem.&lt;/p&gt;
&lt;h3 id=&quot;rust-skeleton&quot;&gt;Rust skeleton&lt;/h3&gt;
&lt;p&gt;If you want to skip ahead and browse the unabridged example, look &lt;a
href=&quot;https://github.com/libbpf/libbpf-rs/tree/master/examples/runqslower&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;BPF skeletons started out as an alternative interface to libbpf. Its
goal was to simplify and reduce boilerplate when developing BPF
applications. It ended up being so successful that it’s now the
recommended interface. Naturally, libbpf-rs supports Rust BPF
skeletons.&lt;/p&gt;
&lt;p&gt;Given BPF object files (eg &lt;code&gt;myobj.bpf.o&lt;/code&gt;),
&lt;code&gt;cargo libbpf gen&lt;/code&gt; can generate Rust skeletons for your
object files. Consider &lt;a
href=&quot;https://github.com/iovisor/bcc/blob/a55192b26d0a9294ed4e0bcd8170225dad62dd61/tools/runqslower_example.txt&quot;&gt;runqslower&lt;/a&gt;:
a prototypical BPF application. &lt;code&gt;runqslower&lt;/code&gt; shows high
latency scheduling times between tasks being ready to run and them
running on CPU after that. Below is an abridged copy of
&lt;code&gt;runqslower.bpf.c&lt;/code&gt; (the BPF program bits):&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;volatile&lt;/span&gt; __u64 min_us &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;volatile&lt;/span&gt; pid_t targ_pid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;volatile&lt;/span&gt; pid_t targ_tgid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    __uint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;type&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; BPF_MAP_TYPE_HASH&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    __uint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;max_entries&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;10240&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    __type&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; u32&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    __type&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; u64&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; start SEC&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;.maps&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    __uint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;type&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; BPF_MAP_TYPE_PERF_EVENT_ARRAY&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    __uint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;key_size&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;u32&lt;span class=&quot;op&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    __uint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;value_size&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;u32&lt;span class=&quot;op&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; events SEC&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;.maps&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;SEC&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;tp_btf/sched_wakeup&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; handle__sched_wakeup&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;u64 &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;ctx&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;SEC&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;tp_btf/sched_wakeup_new&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; handle__sched_wakeup_new&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;u64 &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;ctx&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;SEC&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;tp_btf/sched_switch&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; handle__sched_switch&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;u64 &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;ctx&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To compile the object:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cd $RUST_PROJECT_ROOT

$ # Program sources must be placed in `src/bpf`
$ find . -name runqslower.bpf.c
./src/bpf/runqslower.bpf.c

$ # If you haven&amp;#39;t already
$ cargo install libbpf-cargo

$ cargo libbpf build&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To generate the skeleton:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cargo libbpf gen

$ # Generated skeleton files are placed in `src/bpf`
$ find . -name runqslower.skel.rs
./src/bpf/runqslower.skel.rs
$ find . -name mod.rs
./src/bpf/mod.rs&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following is example code that drives the skeleton:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;mod&lt;/span&gt; bpf&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;bpf::&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;*;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; main() &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;()&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// Open skeleton&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; skel_builder &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;RunqslowerSkelBuilder::&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;default&lt;/span&gt;()&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; open_skel &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; skel_builder&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;open()&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// Write arguments into prog&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    open_skel&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;rodata()&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;min_us &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;co&quot;&gt;// The answer to everything&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    open_skel&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;rodata()&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;targ_pid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    open_skel&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;rodata()&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;targ_tgid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// Load skeleton into kernel&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; skel &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; open_skel&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;load()&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// Attach progs to attach points&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    skel&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;attach()&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// Set up ring buffer processing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;let&lt;/span&gt; perf &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;pp&quot;&gt;libbpf_rs::PerfBufferBuilder::&lt;/span&gt;new(skel&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;maps()&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;events())&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;sample_cb(handle_event)&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;lost_cb(handle_lost_events)&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;build()&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// Process entries from ring buffer&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        perf&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;poll(&lt;span class=&quot;pp&quot;&gt;core::time::Duration::&lt;/span&gt;from_millis(&lt;span class=&quot;dv&quot;&gt;100&lt;/span&gt;))&lt;span class=&quot;op&quot;&gt;?;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; handle_event(cpu&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; data&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;[&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;]) &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-33&quot;&gt;&lt;a href=&quot;#function-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;pp&quot;&gt;unimplemented!&lt;/span&gt;()&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-34&quot;&gt;&lt;a href=&quot;#function-34&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-35&quot;&gt;&lt;a href=&quot;#function-35&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-36&quot;&gt;&lt;a href=&quot;#function-36&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; handle_lost_events(cpu&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;i32&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;u64&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-37&quot;&gt;&lt;a href=&quot;#function-37&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;pp&quot;&gt;unimplemented!&lt;/span&gt;()&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-38&quot;&gt;&lt;a href=&quot;#function-38&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note there’s no mention of the &lt;code&gt;runqslower.bpf.o&lt;/code&gt; file
anywhere. That’s because the contents of the object file have been
embedded into the skeleton file (using &lt;code&gt;include_bytes!()&lt;/code&gt;
macro). As a result, you don’t have to worry about shipping BPF object
files along with your application binaries.&lt;/p&gt;
&lt;p&gt;Also note how &lt;code&gt;open_skel.rodata()&lt;/code&gt; and
&lt;code&gt;skel.maps()&lt;/code&gt; is infallible. Generated skeletons have
infallible accessors for all maps, programs, and global variables. This
reduces the number of errors your application can encounter at
runtime.&lt;/p&gt;
&lt;p&gt;Finally, note how we can set and get values for global data.
&lt;code&gt;cargo libbpf gen&lt;/code&gt; can read the BTF (that clang generates for
the object file) and generate appropriate Rust definitions. These
structures are then &lt;code&gt;mmap()&lt;/code&gt;ed to the kernel at runtime.
Global data is the most convenient way to communicate with BPF programs
from userspace. Simply read and write values like usual. Note that
&lt;code&gt;OpenRunqslowerSkel::rodata()&lt;/code&gt; returns a mutable reference to
the read-only data and &lt;code&gt;RunqslowerSkel::rodata()&lt;/code&gt; returns an
immutable reference. That’s because constant values can only be set
before the program is loaded into the kernel. Safety at work!&lt;/p&gt;
&lt;p&gt;To build the application:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cargo libbpf make
...
$ sudo ./target/debug/runqslower
...&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;If you have questions (you most likely do) about libbpf-rs, please
consult the official documentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.rs/libbpf-rs&quot;&gt;libbpf-rs docs.rs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.rs/libbpf-cargo&quot;&gt;libbpf-cargo docs.rs&lt;/a&gt; and
&lt;code&gt;cargo libbpf --help&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/libbpf/libbpf-rs/blob/master/examples/runqslower/README.md&quot;&gt;runqslower
docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have more questions / concerns after that, please reach out to
me in any way possible.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>C++ patterns: static registration</title><id>https://dxuuu.xyz/cpp-static-registration.html</id><updated>2021-02-19T11:42:43-08:00</updated><link href="https://dxuuu.xyz/cpp-static-registration.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;C++ patterns: static registration&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;C++ patterns: static registration&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Plugin architectures are useful: it’s hard to predict future needs in
the present. Thus, it’s often useful to punt as much business logic as
possible to the future. But how do we create a robust and scalable
plugin architecture?&lt;/p&gt;
&lt;p&gt;A naive approach is a large if-block. Suppose you have a
configuration file where the user specifies which plugin he or she wants
by name:&lt;/p&gt;
&lt;h4 id=&quot;config.toml&quot;&gt;config.toml&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;plugin=MyPlugin&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The easiest way to support selecting plugins could look something
like:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;plugin_name &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;default&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;make_unique&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;Default&lt;span class=&quot;op&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;plugin_name &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;myplugin&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;make_unique&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;MyPlugin&lt;span class=&quot;op&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You could imagine this code exists in the “core” codebase. However,
this is not scalable. Every time a developer authors a plugin (or
renames an existing) plugin, the core implementation needs to change. It
would be far better if we could make the addition, change, or removal of
plugins generic.&lt;/p&gt;
&lt;p&gt;The static registration pattern accomplishes this. We take advantage
of the fact that static variables are initialized &lt;em&gt;before&lt;/em&gt;
&lt;code&gt;main()&lt;/code&gt; is reached. Furthermore, static variables may call
other static methods. [citation?] Consider a plugin “registry”
implemented like so:&lt;/p&gt;
&lt;h4 id=&quot;registry.h&quot;&gt;Registry.h&lt;/h4&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#define REGISTER_PLUGIN&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;plugin_name&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt; &lt;/span&gt;create_func&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt; &lt;/span&gt;&lt;span class=&quot;op&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt; &lt;/span&gt;plugin_name&lt;span class=&quot;pp&quot;&gt; &lt;/span&gt;&lt;span class=&quot;op&quot;&gt;##&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt; &lt;/span&gt;_entry&lt;span class=&quot;pp&quot;&gt; &lt;/span&gt;&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt; &lt;/span&gt;PluginRegistry&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;Plugin&lt;span class=&quot;op&quot;&gt;&amp;gt;::&lt;/span&gt;add&lt;span class=&quot;op&quot;&gt;(#&lt;/span&gt;plugin_name&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt; &lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;create_func&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;typename&lt;/span&gt; T&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;class&lt;/span&gt; PluginRegistry &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;function&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;op&quot;&gt;*()&amp;gt;&lt;/span&gt; FactoryFunction&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;unordered_map&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;string&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; FactoryFunction&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; FactoryMap&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;at&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;bool&lt;/span&gt; add&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;string&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt; name&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; FactoryFunction fac&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; map &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; getFactoryMap&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;map&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;find&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; map&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;op&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;      getFactoryMap&lt;span class=&quot;op&quot;&gt;()[&lt;/span&gt;name&lt;span class=&quot;op&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; fac&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;at&quot;&gt;static&lt;/span&gt; T&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; create&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;at&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;string&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt; name&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; map &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; getFactoryMap&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;map&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;find&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; map&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;op&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; map&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;name&lt;span class=&quot;op&quot;&gt;]();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;// Use Meyer&amp;#39;s singleton to prevent SIOF&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;at&quot;&gt;static&lt;/span&gt; FactoryMap&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt; getFactoryMap&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;at&quot;&gt;static&lt;/span&gt; FactoryMap map&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-33&quot;&gt;&lt;a href=&quot;#function-33&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; map&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-34&quot;&gt;&lt;a href=&quot;#function-34&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-35&quot;&gt;&lt;a href=&quot;#function-35&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice how &lt;code&gt;PluginRegistry&lt;/code&gt; is completely generic. It can
hold factory methods for any type. On line 1, we define a macro that
specializes &lt;code&gt;PluginRegistry&lt;/code&gt; for a class &lt;code&gt;Plugin&lt;/code&gt;,
which we’ll pretend is trivial.&lt;/p&gt;
&lt;p&gt;In this manner, when a developer authors a plugin, registration is
trivial.&lt;/p&gt;
&lt;h4 id=&quot;realplugin.h&quot;&gt;RealPlugin.h&lt;/h4&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;class&lt;/span&gt; RealPlugin &lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;public&lt;/span&gt; Plugin &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; doWork&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;I&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\&amp;#39;&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;m doing real work!&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;at&quot;&gt;static&lt;/span&gt; Plugin&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; create&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;new&lt;/span&gt; RealPlugin&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;REGISTER_PLUGIN&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;RealPlugin&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; RealPlugin&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;create&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And in &lt;code&gt;Main.cpp&lt;/code&gt;, we can instantiate
&lt;code&gt;RealPlugin&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;p &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; PluginRegistry&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;Plugin&lt;span class=&quot;op&quot;&gt;&amp;gt;::&lt;/span&gt;create&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;RealPlugin&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;p&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;doWork&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And so, our nasty if block turns into:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource cpp numberLines&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;unique_ptr&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;Plugin&lt;span class=&quot;op&quot;&gt;&amp;gt;(&lt;/span&gt;PluginRegistry&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;Plugin&lt;span class=&quot;op&quot;&gt;&amp;gt;::&lt;/span&gt;create&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;plugin_name&lt;span class=&quot;op&quot;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;note-on-linking&quot;&gt;Note on linking&lt;/h2&gt;
&lt;p&gt;Particularly astute readers might wonder: will the linker garbage
collect my static plugin variables (ie &lt;code&gt;bool *_entry = ...&lt;/code&gt;)?
The answer is maybe, depending on how you’re building your program.
Because the “core” program does not “touch” any symbols in plugin
translation units, some linkers assume that it is safe to garbage
collect the plugin TU. In most cases, this is safe and ok and a worthy
optimization. However in our case, this is unwanted.&lt;/p&gt;
&lt;p&gt;The solution is to pass to the linker a “-lwhole-achive” [citation?]
flag.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Switching to Caddy</title><id>https://dxuuu.xyz/caddy.html</id><updated>2021-03-20T15:10:49-07:00</updated><link href="https://dxuuu.xyz/caddy.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Switching to Caddy&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Switching to Caddy&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;I decided to upgrade my ancient Fedora 25 VPS to Fedora 33 this
weekend. I couldn’t get the in-place upgrade to work across so many
releases so I just blew away the entire server and started fresh. While
typing away, I remembered I had heard some good stuff about &lt;a
href=&quot;https://caddyserver.com/&quot;&gt;Caddy&lt;/a&gt;. I was also getting annoyed
manually refreshing my &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;Let’s
Encrypt&lt;/a&gt; certs every three months for &lt;a
href=&quot;https://www.lighttpd.net/&quot;&gt;lighttpd&lt;/a&gt;. I figured why not give
Caddy a try?&lt;/p&gt;
&lt;p&gt;Turns out caddy is a joy compared to lighttpd. Compare my old
lighttpd notes to the new caddy config:&lt;/p&gt;
&lt;p&gt;lighttpd:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/caddy/lighttpd.png&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Caddyfile:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dxuuu.xyz

root * /var/www/dxuuu.xyz
file_server&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And caddy automatically renews https certs!&lt;/p&gt;
&lt;p&gt;One final note: I originally chose lighttpd out of resource concerns
b/c I’m running this site on a $5/mo DigitalOcean droplet. A brief
inspection reveals caddy is doing just fine:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[dxu@shiva ~]$ systemctl status caddy
● caddy.service - Caddy web server
     Loaded: loaded (/usr/lib/systemd/system/caddy.service; enabled; vendor preset: disabled)
     Active: active (running) since Sat 2021-03-20 21:53:36 UTC; 12min ago
       Docs: https://caddyserver.com/docs/
    Process: 6395 ExecStartPre=/usr/bin/caddy validate --config /etc/caddy/Caddyfile (code=exited, status=&amp;gt;
   Main PID: 6401 (caddy)
      Tasks: 7 (limit: 1125)
     Memory: 29.1M
        CPU: 227ms
     CGroup: /system.slice/caddy.service
             └─6401 /usr/bin/caddy run --environ --config /etc/caddy/Caddyfile&lt;/code&gt;&lt;/pre&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Debug</title><id>https://dxuuu.xyz/debug.html</id><updated>2021-05-19T21:25:18-07:00</updated><link href="https://dxuuu.xyz/debug.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Debug&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Debug&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This page is used for debugging.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>DWARF stack walks and fast symbolization for BPF</title><id>https://dxuuu.xyz/stack-symbolize.html</id><updated>2021-10-12T18:05:57-07:00</updated><link href="https://dxuuu.xyz/stack-symbolize.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;DWARF stack walks and fast symbolization for BPF&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;DWARF stack walks and fast symbolization for BPF&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;&lt;strong&gt;10/12/21 update: I have no immediate plans to work on this
b/c I’ve recently switched jobs. If you’re really dying to see this
implemented maybe we can work something out. Just email me.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;In this document we are proposing solutions for two separate but
related problems: stack walking and symbolization. We’ll first go over
stack walking and then symbolization.&lt;/p&gt;
&lt;h3 id=&quot;stack-walking&quot;&gt;Stack walking&lt;/h3&gt;
&lt;p&gt;A call stack is a &lt;a
href=&quot;https://en.wikipedia.org/wiki/Stack_(abstract_data_type)&quot;&gt;stack&lt;/a&gt;
function names. Whenever a function is called, that function name is
(conceptually) pushed onto the stack. When that function returns, that
function name is popped. Stalk walking is the act of retrieving a
program call stack at a certain point of execution. This is a fairly
complicated topic and heavily depends on the programming language and
runtime (if applicable). For the purpose of this document, we’ll stick
to native languages like C/C++/Rust.&lt;/p&gt;
&lt;p&gt;There are a number of ways to walk stacks. For a long time, &lt;a
href=&quot;https://en.wikipedia.org/wiki/Call_stack#FRAME-POINTER&quot;&gt;frame
pointer&lt;/a&gt; based stack walks were the best way to do it. We won’t go
into detail here, but frame pointers basically form a chain on the stack
such that you can always find the caller’s frame given the current
frame. Unfortunately, for &lt;a
href=&quot;https://gnu.wildebeest.org/blog/mjw/2007/08/23/stack-unwinding/&quot;&gt;various
reasons&lt;/a&gt;, frame pointers started to fall out of favor as compilers
started performing more complex codegen optimizations.&lt;/p&gt;
&lt;p&gt;Thus, DWARF-based stack walks were born. Compilers will now
(sometimes) generate unwind information in &lt;code&gt;.eh_frame&lt;/code&gt; or
&lt;code&gt;.debug_frame&lt;/code&gt; ELF sections. By parsing this information, you
can walk the stack.&lt;/p&gt;
&lt;p&gt;Unfortunately, Linus &lt;a href=&quot;https://lkml.org/lkml/2012/2/10/356&quot;&gt;is
not a great lover of DWARF&lt;/a&gt;, so there is not and probably will not be
in-kernel DWARF support. This is why &lt;a
href=&quot;https://github.com/torvalds/linux/blob/0d18c12b288a177906e31fecfab58ca2243ffc02/include/uapi/linux/bpf.h#L2064&quot;&gt;&lt;code&gt;bpf_get_stackid()&lt;/code&gt;&lt;/a&gt;
and &lt;a
href=&quot;https://github.com/torvalds/linux/blob/0d18c12b288a177906e31fecfab58ca2243ffc02/include/uapi/linux/bpf.h#L2932&quot;&gt;&lt;code&gt;bpf_get_stack()&lt;/code&gt;&lt;/a&gt;
will often return gibberish if frame pointers are not built into the
userspace application. Thus, a different solution is needed.&lt;/p&gt;
&lt;h3 id=&quot;symbolization&quot;&gt;Symbolization&lt;/h3&gt;
&lt;p&gt;Before we move onto solutions, we still need to discuss
symbolization. Conceptually, symbolization is very simple. Computers
deal with addresses when calling functions. Assuming we sucessfully
obtained a call stack as outlined in the previous section, we still need
to convert the list of addresses into human readable function names.
This process is called symbolization.&lt;/p&gt;
&lt;p&gt;A symbolizer takes as input an address along with a process ID or
executable and returns the function name (and maybe line number) as
output. There are plenty of symbolizers to choose from includig &lt;a
href=&quot;https://www.llvm.org/docs/CommandGuide/llvm-symbolizer.html&quot;&gt;llvm-symbolizer&lt;/a&gt;
and &lt;a href=&quot;https://linux.die.net/man/1/addr2line&quot;&gt;addr2line&lt;/a&gt;.
llvm-symbolizer suffers from huge memory consumption issues and
addr2line is fairly slow. With modern tools and libraries (e.g. Rust),
it should be possible to construct a fast, efficient, and portable
symbolizing library that covers all known edge cases. Whether we can
execute on this remains to be seen.&lt;/p&gt;
&lt;p&gt;In practice, this is a tricky problem. You must deal with inlined
functions, VDSO symbols, deleted-but-still-running binaries, debug
links, split debug info, and more.&lt;/p&gt;
&lt;h2 id=&quot;proposed-design&quot;&gt;Proposed design&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;../examples/stack-symbolize/stack_and_symbolize.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The proposed design for the BPF ecosystem is two-fold:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;A &lt;code&gt;libstackwalker&lt;/code&gt; library that can DWARF-walk a chunk of
stack&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;libsymbolize&lt;/code&gt; library that can symbolize
addresses&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For (1), given that we can’t perform the DWARF walk in kernelspace,
we must perform it in userspace. BPF programs will copy out a chunk of
the stack (the exact size can be adaptively sized, as we should be able
to know in userspace if more stack is required).
&lt;code&gt;libstackwalker&lt;/code&gt; will then perform the stack walk on that
buffer of memory. There will need to be some level of coordination as to
whether an executable has frame pointers and can have its stack walked
in kernelspace or does not have frame pointers and must be
&lt;code&gt;libstackwalker&lt;/code&gt;ed.&lt;/p&gt;
&lt;p&gt;For (2), we will implement &lt;code&gt;libsymbolize&lt;/code&gt; (which is
another conceptually simple task). On top of that, we will add to
bpftrace a &lt;code&gt;dlopen()&lt;/code&gt;-based symbolization framework where
users can plug and play different symbolizers. This is important because
it decouples bpftrace from language/runtime changes. For example, if you
were to implement a python symbolizer today, you’d need to reach into
the guts of the python runtime (b/c there’s no standard interface) that
can change at any time. By decoupling bpftrace from the symbolizer, we
can allow python symbolization matched to the python runtime. The
decoupling also enables remote symbolization for more controlled
environments.&lt;/p&gt;
&lt;h2 id=&quot;status&quot;&gt;Status&lt;/h2&gt;
&lt;p&gt;This project is currently in the planning phase. Status updates will
be available here as progress is made.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Ahead-Of-Time compiled bpftrace programs</title><id>https://dxuuu.xyz/aot-bpftrace.html</id><updated>2021-10-17T15:14:42-07:00</updated><link href="https://dxuuu.xyz/aot-bpftrace.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Ahead-Of-Time compiled bpftrace programs&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Ahead-Of-Time compiled bpftrace programs&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This page serves as a design document for bpftrace AOT compilation
support. Design is currently a work-in-progress and will be (somewhat)
regularly updated.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AOT is motivated by the following technical concerns:
&lt;ul&gt;
&lt;li&gt;Shipping/running LLVM onto prod hosts is resource-heavy (binary
size, memory consumption)&lt;/li&gt;
&lt;li&gt;Time to first trace is slow for dynamic bpftrace b/c we have to do
all the AST passes AND setup runtime resources, where for AOT bpftrace
we can just do runtime resource setup&lt;/li&gt;
&lt;li&gt;Dynamically compiled bpftrace scripts cannot be easily signed&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;overall-design&quot;&gt;Overall design&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ship a fully executable runtime shim with bpftrace&lt;/li&gt;
&lt;li&gt;When compiling a AOT bpftrace program:
&lt;ul&gt;
&lt;li&gt;Build the metadata&lt;/li&gt;
&lt;li&gt;Build the bytecode&lt;/li&gt;
&lt;li&gt;Make a copy of runtime shim and store metadata + bytecode into a
special ELF section (this is the final executable)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;When the shim runs, it knows to look inside itself for the metadata
+ bytecode and start execution&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;current-architecture&quot;&gt;Current architecture&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;../examples/aot-bpftrace/old-architecture.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;proposed-architecture&quot;&gt;Proposed architecture&lt;/h2&gt;
&lt;p&gt;AST passes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/aot-bpftrace/old-passes.png&quot; /&gt; =&amp;gt; &lt;img
src=&quot;../examples/aot-bpftrace/new-passes.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Simplified architecture (some unchanged parts omitted):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/aot-bpftrace/new-architecture.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Key:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Green -&amp;gt; added to all codepaths&lt;/li&gt;
&lt;li&gt;Orange -&amp;gt; added to AOT compile codepath&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;AOT execution:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/aot-bpftrace/aot-execution.png&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;unsolved-problems&quot;&gt;Unsolved problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Create fully static aot-rt binary&lt;/li&gt;
&lt;li&gt;Generate CO-RE field access instructions
&lt;ul&gt;
&lt;li&gt;Will need to generate some kind of access identifier (eg.
&lt;code&gt;1:0:3:4&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Runtime still use bcc (eg. symbolization) and bcc links LLVM&lt;/li&gt;
&lt;li&gt;Punt all loading to libbpf to gain access to CO-RE features?
&lt;ul&gt;
&lt;li&gt;Map creation, map FD fixup, extern symbol resolution&lt;/li&gt;
&lt;li&gt;Reason is that some new bpf helpers (bpf_per_cpu_ptr()) require BTF
ID to be in immediate operand of certain instructions, and we may not
want to redo/maintain that stuff in bpftrace&lt;/li&gt;
&lt;li&gt;Another reason is that in the future we may want to link other BPF
programs in (like DWARF-based stack walker)&lt;/li&gt;
&lt;li&gt;Reasons not to completely switch over to libbpf include:
&lt;ul&gt;
&lt;li&gt;Large amount of bpftrace code modifications&lt;/li&gt;
&lt;li&gt;Loss of ability to mock out maps / unit testing&lt;/li&gt;
&lt;li&gt;Extra overhead constructing ELF files for libbpf to work with&lt;/li&gt;
&lt;li&gt;If there’s ever a bug in libbpf or we need a new feature, we are
beholden to distros shipping an updated libbpf. We cannot vendor either
as it’s not going to fly with the distros.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Can save metadata into special ELF section; fortunately we don’t
need to worry about compatability as an AOT executable is hermetic&lt;/li&gt;
&lt;li&gt;Must ship a stubbed (no bytecode) AOT executable that knows to look
inside itself for bytecode
&lt;ul&gt;
&lt;li&gt;Should be simple enough with cmake&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Will need to relocate pseudo-map-FDs at runtime to FDs of created
maps (see BPF_PSEUDO_MAP_FD in libbpf)&lt;/li&gt;
&lt;li&gt;Create &lt;code&gt;RequiredResources&lt;/code&gt; abstraction
&lt;ul&gt;
&lt;li&gt;That:
&lt;ul&gt;
&lt;li&gt;Describes all the runtime resources that need to be setup before a
script is run&lt;/li&gt;
&lt;li&gt;Can initialize all the resources given a &lt;code&gt;BPFtrace &amp;amp;&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Or should &lt;code&gt;RequiredResources&lt;/code&gt; contain live map FDs
too?&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Can be serialized/deserialized&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Can just be a public field: &lt;code&gt;BPFtrace::resources&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;So it can be easily mocked out for tests&lt;/li&gt;
&lt;li&gt;So semantic analyser can add resources&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;future-goals&quot;&gt;Future goals&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Re-enable all features block by portability analyser&lt;/li&gt;
&lt;li&gt;User can select features to enable in codegen
&lt;ul&gt;
&lt;li&gt;eg. “tell codegen that the target host has XXX feature”&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Emitted bytecode takes advantage of CO-RE to be more compatible on
other hosts&lt;/li&gt;
&lt;li&gt;Support &lt;code&gt;-k[k]&lt;/code&gt; error helper flags (runtime state
currently constructed in codegen)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;towards-a-functional-prototype&quot;&gt;Towards a functional
prototype&lt;/h2&gt;
&lt;ul class=&quot;task-list&quot;&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; checked=&quot;&quot; /&gt;Eliminate hard-coded map FDs in
bytecode
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iovisor/bpftrace/pull/1861&quot;&gt;PR
#1861&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; checked=&quot;&quot; /&gt;Add AST pass to check for
non-portable features
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iovisor/bpftrace/pull/1871&quot;&gt;PR
#1871&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; checked=&quot;&quot; /&gt;Encapsulate runtime resource
requirements
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iovisor/bpftrace/pull/1883&quot;&gt;PR
#1883&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; checked=&quot;&quot; /&gt;Create
serialization/deserialization routines for
&lt;code&gt;RequiredResources&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iovisor/bpftrace/pull/1893&quot;&gt;PR
#1893&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; checked=&quot;&quot; /&gt;Create runtime shim
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iovisor/bpftrace/pull/1950&quot;&gt;PR
#1950&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;slow-march-to-feature-completeness&quot;&gt;Slow march to feature
completeness&lt;/h2&gt;
&lt;h3 id=&quot;big-ticket&quot;&gt;Big ticket&lt;/h3&gt;
&lt;ul class=&quot;task-list&quot;&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; /&gt;Shim injection / shim extraction&lt;/li&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; /&gt;Fully static shim&lt;/li&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; /&gt;Re-enable portability analyser disabled
features&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;test-suite&quot;&gt;Test suite&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;../examples/aot-bpftrace/tests_plot.png&quot;
style=&quot;width:70.0%&quot; /&gt;&lt;/p&gt;
&lt;ul class=&quot;task-list&quot;&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; checked=&quot;&quot; /&gt;Fix AOT build/tests with older
BCC versions
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iovisor/bpftrace/pull/2010&quot;&gt;PR
#2010&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; checked=&quot;&quot; /&gt;Completely remove dependency on
LLVM
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iovisor/bpftrace/pull/2031&quot;&gt;PR
#2031&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; /&gt;Reuse as much of existing runtime tests as
possible for AOT
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iovisor/bpftrace/pull/2035&quot;&gt;PR
#2035&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type=&quot;checkbox&quot; checked=&quot;&quot; /&gt;Print out attached_probes
message
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/iovisor/bpftrace/pull/2037&quot;&gt;PR
#2037&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Rewriting clipd</title><id>https://dxuuu.xyz/clipd.html</id><updated>2021-11-28T20:40:50-08:00</updated><link href="https://dxuuu.xyz/clipd.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Rewriting clipd&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Rewriting clipd&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;&lt;code&gt;clipd&lt;/code&gt; is a distributed clipboard I wrote back in 2017.
Distributed in this context means that a server somewhere runs the clipd
server and accepts requests from clients to either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Store new data into the clipboard, or&lt;/li&gt;
&lt;li&gt;Grab the current data in the clipboard&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This solved an annoying problem I had back then where I had too many
computers (still do, actually) and had difficulty sharing links between
them. This was not a very complicated piece of software (I think it took
maybe two weekends). Nonetheless, it still bitrot over the years and
recently stopped working for reasons I was too lazy to debug. I did,
however, take it as a chance to rewrite the code from Python to Rust,
along with a bunch of other improvements along the way.&lt;/p&gt;
&lt;p&gt;It took about 6-8 hours to do the full rewrite and after having done
so, I thought it would be interesting to document the different design
choices I’ve made. Put differently, why current-me is better at
programming than old-me four years ago.&lt;/p&gt;
&lt;h2 id=&quot;language-and-framework&quot;&gt;Language and framework&lt;/h2&gt;
&lt;p&gt;We’ll ignore the client in this section because the client is very
simple in both implementations: open a connection, write some bytes,
read some bytes, print. The server is more interesting to discuss.&lt;/p&gt;
&lt;h4 id=&quot;old-server&quot;&gt;Old server&lt;/h4&gt;
&lt;p&gt;The old server was written in Python and used &lt;a
href=&quot;https://docs.python.org/3/library/socketserver.html&quot;&gt;&lt;code&gt;socketserver.TCPServer&lt;/code&gt;&lt;/a&gt;
with &lt;code&gt;socketserver.ThreadingMixIn&lt;/code&gt;, meaning each connection
was handled in a separate thread.&lt;/p&gt;
&lt;h4 id=&quot;new-server&quot;&gt;New server&lt;/h4&gt;
&lt;p&gt;For the new server, I used async Rust with &lt;a
href=&quot;https://tokio.rs/&quot;&gt;tokio&lt;/a&gt; and &lt;a
href=&quot;https://docs.rs/tokio/1.13.0/tokio/net/struct.TcpListener.html&quot;&gt;&lt;code&gt;tokio::TcpListener&lt;/code&gt;&lt;/a&gt;
on a single thread to drive the event loop.&lt;/p&gt;
&lt;h4 id=&quot;commentary&quot;&gt;Commentary&lt;/h4&gt;
&lt;p&gt;Python as a language was an OK choice. Using
&lt;code&gt;socketserver&lt;/code&gt; is fine as well, thought I might have chosen
&lt;code&gt;asyncio&lt;/code&gt; if I had to do things over in Python. I’m not sure
what the state of asyncio was back then.&lt;/p&gt;
&lt;p&gt;I quite like Rust these days. Rust is pretty easy to write and reason
about, plus the memory and type safety is extremely appealing for a
project I have no intention of ever writing tests for. The extra
efficiency from being a compiled language is nice as well. Using an
async framework seems like a good choice since clipd is entire I/O
bound.&lt;/p&gt;
&lt;h2 id=&quot;protocol&quot;&gt;Protocol&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;clipd&lt;/code&gt; was and still is TCP-based protocol. TCP remains
an excellent choice because I really don’t want to deal with an
unreliable connection. On top of TCP, we have our own framed protocol.
Framing is obviously necessary because TCP is a streaming protocol, not
a message based one. And delimiters seems troublesome given we support
arbitrary payloads.&lt;/p&gt;
&lt;h4 id=&quot;old-protocol&quot;&gt;Old protocol&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;`clipd` communicates over TCP using ASCII encoded data (please don&amp;#39;t hate me,
utf-8 people). The wire format is as follows:

+---+------+-------+
|LEN|HEADER|PAYLOAD|
+---+------+-------+&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LEN&lt;/code&gt; is the total number of characters in the message
(&lt;code&gt;LEN&lt;/code&gt; excluded).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HEADER&lt;/code&gt; can be either &lt;code&gt;&quot;PUSH&quot;&lt;/code&gt; or
&lt;code&gt;&quot;PULL&quot;&lt;/code&gt; for requests and &lt;code&gt;&quot;OK&quot;&lt;/code&gt; or
&lt;code&gt;&quot;ERR&quot;&lt;/code&gt; for responses&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PAYLOAD&lt;/code&gt; is either empty, contains the clipboard
payload, or the error message&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;new-protocol&quot;&gt;New protocol&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;clipd protocol (request and response):

0       8      16
+-------+-------------------------+
| magic | type | optional payload |
+-------+-------------------------+

The payload, if present:

0     64
+-----+---------+
| len | payload |
+-----+---------+&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;magic&lt;/code&gt; is a clipd-specific magic value (integer)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt; is the type of request (integer)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;len&lt;/code&gt; is length of payload&lt;/li&gt;
&lt;li&gt;&lt;code&gt;payload&lt;/code&gt; is opaque series of bytes&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;commentary-1&quot;&gt;Commentary&lt;/h4&gt;
&lt;p&gt;Thinking about the old protocol now, I have a couple immediate
thoughts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using ASCII is plain bad because UTF-8 is clearly superior&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LEN&lt;/code&gt; is a strange field because any wire protocol
usually has a fixed set of fields in the front and length is only needed
if there is a variable sized field. Although not wrong, the placement is
strange&lt;/li&gt;
&lt;li&gt;The text-based &lt;code&gt;HEADER&lt;/code&gt; field is extremely strange, as
it’s extra bytes and could be replaced by an integer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One thing I learned from staring at the output from the old clipd
server is that there are a lot of scanners on the internet that will try
probing (sending bytes to) any open port on your server. The magic in
the new protocol is there to quickly drop invalid requests. The type in
the new protocol is now an integer to be more efficient. Similarly, the
length field is now only included when necessary.&lt;/p&gt;
&lt;h2 id=&quot;protocol-parsing&quot;&gt;Protocol parsing&lt;/h2&gt;
&lt;p&gt;Protocol parsing is, well, parsing the bytes that come over the wire
into the protocol we have designed in the previous section. Although
this needs to happen in both the server and the client, the process is
similar enough in both binaries to describe together.&lt;/p&gt;
&lt;h4 id=&quot;old-process&quot;&gt;Old process&lt;/h4&gt;
&lt;p&gt;The raw bytes are both constructed and processed inline with the
application level logic. Meaning something like the following:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre
class=&quot;sourceCode python&quot;&gt;&lt;code class=&quot;sourceCode python&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;req &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;str&lt;/span&gt;(&lt;span class=&quot;bu&quot;&gt;len&lt;/span&gt;(HDR_PULL)) &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; HDR_PULL&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;req &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;bytes&lt;/span&gt;(req, &lt;span class=&quot;st&quot;&gt;&amp;#39;ascii&amp;#39;&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;resp &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; _sock_send_recv(...)&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;hdr, payload &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; _parse_resp(resp)&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; (hdr &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; HDR_OK):&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;raise&lt;/span&gt; ClipdException(payload)&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; payload&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;new-process&quot;&gt;New process&lt;/h4&gt;
&lt;p&gt;The new code is structured to have a protocol “library” that hides
the details of how the requests and responses are sent over the wire.
This “library” is used in both the client and server. The library more
or less looks like:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre
class=&quot;sourceCode rust&quot;&gt;&lt;code class=&quot;sourceCode rust&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;enum&lt;/span&gt; RequestFrame &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// A request to push bytes to the server&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    Push(&lt;span class=&quot;dt&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt;)&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/// A request to pull the currently stored bytes on the server&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    Pull&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-6&quot;&gt;&lt;a href=&quot;#cb4-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-7&quot;&gt;&lt;a href=&quot;#cb4-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-8&quot;&gt;&lt;a href=&quot;#cb4-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;impl&lt;/span&gt; RequestFrame &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-9&quot;&gt;&lt;a href=&quot;#cb4-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; from_socket(socket&lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;mut&lt;/span&gt; TcpStream) &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;RequestFrame&lt;span class=&quot;op&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-10&quot;&gt;&lt;a href=&quot;#cb4-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;fn&lt;/span&gt; to_bytes(&lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;self&lt;/span&gt;) &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;u8&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb4-11&quot;&gt;&lt;a href=&quot;#cb4-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;ResponseFrame&lt;/code&gt; has an symmetric API except with different
enum variants.&lt;/p&gt;
&lt;h4 id=&quot;commentary-2&quot;&gt;Commentary&lt;/h4&gt;
&lt;p&gt;The new way is obviously superior looking back after the fact. Mixing
protocol level details with the application logic leads to more
complexity (not necessarily in this simple application, but the
principle still applies) as well as duplicated logic in both client and
server. It’s a clear win to separate concerns and share code between the
client and server.&lt;/p&gt;
&lt;h2 id=&quot;operation-in-production&quot;&gt;Operation in production&lt;/h2&gt;
&lt;p&gt;“Operation” and “production” in this context means “how it’s run” and
“on my server”, respectively.&lt;/p&gt;
&lt;h4 id=&quot;old-way&quot;&gt;Old way&lt;/h4&gt;
&lt;p&gt;I ran the clipd server binary inside a session of tmux.&lt;/p&gt;
&lt;h4 id=&quot;new-way&quot;&gt;New way&lt;/h4&gt;
&lt;p&gt;I run clipd as a systemd system service.&lt;/p&gt;
&lt;h4 id=&quot;commentary-3&quot;&gt;Commentary&lt;/h4&gt;
&lt;p&gt;The old way was simpler (not by much) but easier to mess up. For
example if the server was restarted I would have to remember to run
clipd again.&lt;/p&gt;
&lt;p&gt;The new way is clearly better b/c systemd is designed to manage
system daemons (among other things). I suspect I didn’t know systemd
well enough back then to know to make a systemd service.&lt;/p&gt;
&lt;h2 id=&quot;final-commentary&quot;&gt;Final commentary&lt;/h2&gt;
&lt;p&gt;After the rewrite clipd feels much snappier and seems to work well
again. I found the process of exploring my old code interesting enough
that I spent even more time to write a post. So in a way I suppose I’m
doubly glad I finally got around to it.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Pull request review (prr)</title><id>https://dxuuu.xyz/prr.html</id><updated>2022-05-08T18:15:25-07:00</updated><link href="https://dxuuu.xyz/prr.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Pull request review (prr)&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Pull request review (prr)&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Last month I developed a new tool that brings mailing-list style code
reviews to github. The tool was born out of frustration with github’s
point and click web UI. Since I do a lot of code review, the tabbing
between my text editor and my browser became a constant source of
friction.&lt;/p&gt;
&lt;p&gt;Ideally, I wanted to stay in my text editor so that my code writing
and code reviewing workflows could be unified. I didn’t find any such
tool on the internet so I built my own.&lt;/p&gt;
&lt;h3 id=&quot;demo&quot;&gt;Demo&lt;/h3&gt;
&lt;p&gt;Consider the following pull request:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/prr/pr.png&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;To download the PR for review:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ prr get danobi/prr-test-repo/2
/home/dxu/dev/review/danobi/prr-test-repo/2.prr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you open the review file, you’ll see:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre
class=&quot;sourceCode diff&quot;&gt;&lt;code class=&quot;sourceCode diff&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; diff --git a/ch4.txt b/ch4.txt&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; index 41e1932..8741175 100644&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; --- a/ch4.txt&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +++ b/ch4.txt&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; @@ -16,6 +16,10 @@ CHAPTER 4. TACTICAL DISPOSITIONS&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;  8. To see victory only when it is within the ken of the common herd is not the acme of excellence.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +HERE IS SOME CONTENT I&amp;#39;M TRYING TO ADD&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +LALALALLALALALALAL&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +LALAL&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;  9. Neither is it the acme of excellence if you fight and conquer and the whole Empire says, &amp;quot;Well done!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;  10. To lift an autumn hair is no sign of great strength; to see the sun and moon is no sign of sharp sight; to hear the noise of thunder is no sign of a quick ear.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now suppose you want to have the author remove the extraneous edits
and reject the PR because of it. Simply mark up the review file as
follows:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre
class=&quot;sourceCode diff&quot;&gt;&lt;code class=&quot;sourceCode diff&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;@prr reject&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; diff --git a/ch4.txt b/ch4.txt&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; index 41e1932..8741175 100644&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; --- a/ch4.txt&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +++ b/ch4.txt&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; @@ -16,6 +16,10 @@ CHAPTER 4. TACTICAL DISPOSITIONS&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;  8. To see victory only when it is within the ken of the common herd is not the acme of excellence.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-11&quot;&gt;&lt;a href=&quot;#cb3-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-12&quot;&gt;&lt;a href=&quot;#cb3-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +HERE IS SOME CONTENT I&amp;#39;M TRYING TO ADD&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-13&quot;&gt;&lt;a href=&quot;#cb3-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +LALALALLALALALALAL&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-14&quot;&gt;&lt;a href=&quot;#cb3-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +LALAL&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-15&quot;&gt;&lt;a href=&quot;#cb3-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-16&quot;&gt;&lt;a href=&quot;#cb3-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-17&quot;&gt;&lt;a href=&quot;#cb3-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Remove this junk&lt;/span&gt;
&lt;span id=&quot;cb3-18&quot;&gt;&lt;a href=&quot;#cb3-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-19&quot;&gt;&lt;a href=&quot;#cb3-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;  9. Neither is it the acme of excellence if you fight and conquer and the whole Empire says, &amp;quot;Well done!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-20&quot;&gt;&lt;a href=&quot;#cb3-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-21&quot;&gt;&lt;a href=&quot;#cb3-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;&amp;gt;  10. To lift an autumn hair is no sign of great strength; to see the sun and moon is no sign of sharp sight; to hear the noise of thunder is no sign of a quick ear.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Two things to note:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;We can use &lt;code&gt;prr&lt;/code&gt; directives by “tagging”
&lt;code&gt;@prr&lt;/code&gt;. Just like how you might use a github bot.&lt;/li&gt;
&lt;li&gt;We added a “spanned” comment on the hunk by adding a newline before
the start of the span.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To submit the review back to github, run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ prr submit danobi/prr-test-repo/2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll now see something like this on github:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/prr/comment.png&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;(Note that you don’t see the “Changes requested” in this example
because github doesn’t let you request changes on your own PR. It should
work on a real PR.)&lt;/p&gt;
&lt;h3 id=&quot;looking-forward&quot;&gt;Looking forward&lt;/h3&gt;
&lt;p&gt;The above demo shows off most of the features I’ve currently
implemented. There’s still a few things I want to add but they’re not
too pressing as I’m currently using &lt;code&gt;prr&lt;/code&gt; every day just
fine.&lt;/p&gt;
&lt;p&gt;If you wanna try out &lt;code&gt;prr&lt;/code&gt; or request new features, feel
free to file an issue or open a PR at https://github.com/danobi/prr
.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>BPF and go pprof</title><id>https://dxuuu.xyz/bpf-go-pprof.html</id><updated>2022-09-10T14:49:39-07:00</updated><link href="https://dxuuu.xyz/bpf-go-pprof.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;BPF and go pprof&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;BPF and go pprof&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Earlier this week I was made aware of what appeared to be an infinite
loop in the in-kernel BPF verifier. Golang stacks were pulled,
flamegraphs were captured (shoutout to &lt;a
href=&quot;https://profiler.firefox.com/&quot;&gt;profiler.firefox.com&lt;/a&gt;), and by
all appearances it seemed like there was indeed an infinite loop.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/bpf-go-pprof/flamegraph.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I spent some time studying the verifier source and nothing really
stood out to me as infinite loopable. Plus, the flamegraph showed a
rather equal distribution of callees so the verifier being stuck in a
single place seemed unlikely.&lt;/p&gt;
&lt;p&gt;By some random chance I thought it would be useful to see how often
the verifier was being called. I answered that question by running the
following bpftrace script for a few seconds:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo ./bpftrace -e &amp;#39;t:syscalls:sys_enter_bpf { @ = count(); }&amp;#39;
Attaching 1 probe...
^C

@: 932&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So clearly this was not an infinite loop but rather
&lt;code&gt;bpf(BPF_PROG_LOAD, ...)&lt;/code&gt; being called in a tight loop. That
by itself seemed rather odd so I took to the &lt;code&gt;cilium/ebpf&lt;/code&gt;
source. A quick dig turned up:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;16&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource go numberLines&quot;&gt;&lt;code class=&quot;sourceCode go&quot; style=&quot;counter-reset: source-line 15;&quot;&gt;&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;// BPF wraps SYS_BPF.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;// Any pointers contained in attr must use the Pointer type from this package.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;func&lt;/span&gt; BPF&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;cmd Cmd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; attr unsafe&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Pointer&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; size &lt;span class=&quot;dt&quot;&gt;uintptr&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;uintptr&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;        r1&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; _&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; errNo &lt;span class=&quot;op&quot;&gt;:=&lt;/span&gt; unix&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Syscall&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;unix&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;SYS_BPF&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;uintptr&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;cmd&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;uintptr&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;attr&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; size&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;        runtime&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;KeepAlive&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;attr&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;// As of ~4.20 the verifier can be interrupted by a signal,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;// and returns EAGAIN in that case.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; errNo &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; unix&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;EAGAIN &lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; cmd &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; BPF_PROG_LOAD &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;cf&quot;&gt;continue&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; err &lt;span class=&quot;dt&quot;&gt;error&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; errNo &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot;&gt;&lt;/a&gt;            err &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; wrappedErrno&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;errNo&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-33&quot;&gt;&lt;a href=&quot;#function-33&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-34&quot;&gt;&lt;a href=&quot;#function-34&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-35&quot;&gt;&lt;a href=&quot;#function-35&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; r1&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; err&lt;/span&gt;
&lt;span id=&quot;function-36&quot;&gt;&lt;a href=&quot;#function-36&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-37&quot;&gt;&lt;a href=&quot;#function-37&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ah ha, so the looping condition is &lt;code&gt;-EAGAIN&lt;/code&gt;. I quickly
verified that by running:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo ./bpftrace -e &amp;#39;t:syscalls:sys_exit_bpf { @[args-&amp;gt;ret] = count(); }&amp;#39;
Attaching 1 probe...
^C

@[-11]: 543&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;-EAGAIN&lt;/code&gt; is &lt;code&gt;-11&lt;/code&gt;, so great. That’s
confirmation.&lt;/p&gt;
&lt;p&gt;To answer why the verifier would ever return &lt;code&gt;-EAGAIN&lt;/code&gt;, I
grepped through &lt;code&gt;kernel/bpf/verifier.c&lt;/code&gt;. It turns out there’s
precisely one occurence of &lt;code&gt;-EAGAIN&lt;/code&gt; in the file (which
contains all verifier logic):&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;12089&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 12088;&quot;&gt;&lt;span id=&quot;function-12089&quot;&gt;&lt;a href=&quot;#function-12089&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; do_check&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; bpf_verifier_env &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;env&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12090&quot;&gt;&lt;a href=&quot;#function-12090&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12091&quot;&gt;&lt;a href=&quot;#function-12091&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;/* [...] */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12092&quot;&gt;&lt;a href=&quot;#function-12092&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(;;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12093&quot;&gt;&lt;a href=&quot;#function-12093&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; bpf_insn &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;insn&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12094&quot;&gt;&lt;a href=&quot;#function-12094&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-12095&quot;&gt;&lt;a href=&quot;#function-12095&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;/* [...] */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12096&quot;&gt;&lt;a href=&quot;#function-12096&quot;&gt;&lt;/a&gt;                insn &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;insns&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;env&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;insn_idx&lt;span class=&quot;op&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12097&quot;&gt;&lt;a href=&quot;#function-12097&quot;&gt;&lt;/a&gt;                class &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; BPF_CLASS&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;insn&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;code&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12098&quot;&gt;&lt;a href=&quot;#function-12098&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-12099&quot;&gt;&lt;a href=&quot;#function-12099&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;/* [...] */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12100&quot;&gt;&lt;a href=&quot;#function-12100&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;signal_pending&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;current&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12101&quot;&gt;&lt;a href=&quot;#function-12101&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;EAGAIN&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-12102&quot;&gt;&lt;a href=&quot;#function-12102&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-12103&quot;&gt;&lt;a href=&quot;#function-12103&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;/* Main logic follows */&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So the only reason the verifier would return &lt;code&gt;-EAGAIN&lt;/code&gt; is
if there is a pending signal waiting for the caller.&lt;/p&gt;
&lt;p&gt;In general this would be pretty difficult to debug b/c any code
modification could potentially disturb the bad state. Fortunately, we
can turn to bpftrace:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo ./bpftrace -e &amp;#39;t:syscalls:sys_exit_bpf { @[args-&amp;gt;ret] = count(); } t:signal:signal_deliver / pid == $1 / { @sigs[args-&amp;gt;sig] = count() }&amp;#39; $(pidof binary-under-investigation)
Attaching 2 probes...
^C

@[-11]: 876
@sigs[27]: 1136&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here lies the smoking gun: signal 27 is &lt;code&gt;SIGPROF&lt;/code&gt;. From
here, two things were realized:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Go’s built in CPU profiling &lt;a
href=&quot;https://cs.opensource.google/go/go/+/refs/tags/go1.19.1:src/runtime/pprof/pprof.go;l=755&quot;&gt;uses
&lt;code&gt;SIGPROF&lt;/code&gt; to sample&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;We recently turned on continuous &lt;code&gt;pprof&lt;/code&gt; based
profiling&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In other words, what was happening was:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;The verifier was taking time for verification to complete&lt;/li&gt;
&lt;li&gt;While the verifier was working, &lt;code&gt;pprof&lt;/code&gt; was sending
&lt;code&gt;SIGPROF&lt;/code&gt; at high enough frequency to prevent verifier from
completing its work&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cilium/ebpf&lt;/code&gt; kept retrying
&lt;code&gt;bpf(BPF_PROG_LOAD, ..)&lt;/code&gt; because it received
&lt;code&gt;-EAGAIN&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;All the above caused our process to spin on prog verification&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This was a really nice bug b/c it’s simple to grok and totally
non-obvious.&lt;/p&gt;
&lt;p&gt;My only takeaway is that I’m not sure I like go’s signal based
profiling mechanism. It intereres quite heavily with long-running
syscalls like &lt;code&gt;bpf(BPF_PROG_LOAD, ...)&lt;/code&gt;. I would much rather
prefer using &lt;a
href=&quot;https://easyperf.net/blog/2018/06/01/PMU-counters-and-profiling-basics&quot;&gt;PMU-based&lt;/a&gt;
profilers like &lt;code&gt;perf&lt;/code&gt;.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>File capabilities and /proc/&amp;lt;pid&amp;gt;</title><id>https://dxuuu.xyz/filecaps.html</id><updated>2022-10-21T07:43:11-07:00</updated><link href="https://dxuuu.xyz/filecaps.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;File capabilities and /proc/&amp;lt;pid&amp;gt;&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;File capabilities and /proc/&amp;lt;pid&amp;gt;&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;I’ve spent the past few evenings staring at a rather interesting
kernel “bug”. I put “bug” in quotes b/c, spoiler alert, it’s not a
bug.&lt;/p&gt;
&lt;p&gt;It all started with an integration test failing due to a
&lt;code&gt;-EACCES&lt;/code&gt; return code. Normally I’d assume it’s a bug with
the code under test, but we also happen to cover the same codepath in
unit tests. So a failure when the code was run in a separate binary was
something worth investigating.&lt;/p&gt;
&lt;p&gt;The details of the test and test infrastructure aren’t important b/c
I was able to come up with a short reproducer:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;function-1&quot;&gt;&lt;a href=&quot;#function-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-2&quot;&gt;&lt;a href=&quot;#function-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-3&quot;&gt;&lt;a href=&quot;#function-3&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-4&quot;&gt;&lt;a href=&quot;#function-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-5&quot;&gt;&lt;a href=&quot;#function-5&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; fd &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; open&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;/proc/self/auxv&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; O_RDONLY&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-6&quot;&gt;&lt;a href=&quot;#function-6&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-7&quot;&gt;&lt;a href=&quot;#function-7&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;fd &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-8&quot;&gt;&lt;a href=&quot;#function-8&quot;&gt;&lt;/a&gt;    perror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;open&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-9&quot;&gt;&lt;a href=&quot;#function-9&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-10&quot;&gt;&lt;a href=&quot;#function-10&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-11&quot;&gt;&lt;a href=&quot;#function-11&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-12&quot;&gt;&lt;a href=&quot;#function-12&quot;&gt;&lt;/a&gt;  printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;ok&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-13&quot;&gt;&lt;a href=&quot;#function-13&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-14&quot;&gt;&lt;a href=&quot;#function-14&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;$ gcc main.c
$ ./a.out                                             # (1)
ok
$ sudo setcap &amp;quot;cap_net_admin,cap_sys_admin+p&amp;quot; a.out   # (2)
$ ./a.out                                             # (3)
open: Permission denied&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Basically the above program tries to open
&lt;code&gt;/proc/self/auxv&lt;/code&gt; and reports on whether it was successful.
Pretty simple, and that’s all we do in step (1).&lt;/p&gt;
&lt;p&gt;Things get more interesting when we get to step (2). For the
unititiated, in step (2) we set a couple file capabilities on the
executable. File capabilities (filecaps) are basically the same thing as
&lt;a href=&quot;https://en.wikipedia.org/wiki/Setuid&quot;&gt;setuid&lt;/a&gt;, except
filecaps operate on capabilities which are much more granular than
setuid’s “root or not”.&lt;/p&gt;
&lt;p&gt;More specifically, we add the capabilities to the
&lt;strong&gt;permitted&lt;/strong&gt; set. This is an important distinction b/c it
means the executable, when run as an unprivileged process, starts out
with no extra capabilities. However, the process may grant itself any of
the permitted capabilities (ie. “elevate”). Note how the reproducer does
not elevate to any capabilities. In other words, our reproducer is
capability-dumb.&lt;/p&gt;
&lt;p&gt;Finally, in step (3) we run the reproducer just like in step (1).
However unlike in step (1), we get &lt;code&gt;-EACCES&lt;/code&gt;. And to be
explicit, this is really strange b/c usually programs have
&lt;em&gt;extra&lt;/em&gt; powers with more capabilities, not &lt;em&gt;less&lt;/em&gt;.
Furthermore, the process doesn’t even use extra capabilities at
runtime.&lt;/p&gt;
&lt;p&gt;The stage is set for an interesting investigation: a trivial
reproducer and a wildly unexpected result.&lt;/p&gt;
&lt;h2 id=&quot;odd-ownership&quot;&gt;Odd ownership&lt;/h2&gt;
&lt;p&gt;I spent some time trying to trace kernel execution with everyone’s
favorite tracer (bpftrace!). Unfortunately, a lot of the interesting
logic was either in the body of a long function or in an inlined
function call so I had to fall back to &lt;code&gt;printk()&lt;/code&gt;
debugging.&lt;/p&gt;
&lt;p&gt;What followed was a lot of edit-compile-run loops (shoutout to &lt;a
href=&quot;https://github.com/amluto/virtme&quot;&gt;virtme&lt;/a&gt; for making testing
kernels so easy). I won’t bore you with the details, so suffice to say
after a few hours I discovered that &lt;code&gt;/proc/self/auxv&lt;/code&gt; was
owned by &lt;code&gt;root:root&lt;/code&gt;. And since &lt;code&gt;/proc/self/auxv&lt;/code&gt;
has &lt;code&gt;0400&lt;/code&gt; permissions, our process running under
&lt;code&gt;daniel:daniel&lt;/code&gt; fails the UNIX permission check in
&lt;code&gt;acl_permission_check()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Christian Brauner &lt;a
href=&quot;https://lore.kernel.org/linux-fsdevel/20221019132201.kd35firo6ks6ph4j@wittgenstein/&quot;&gt;later
confirms&lt;/a&gt; this discovery on the lists.&lt;/p&gt;
&lt;p&gt;So &lt;code&gt;-EACCES&lt;/code&gt; is explained. But this begs a new question:
why is &lt;code&gt;/proc/self/auxv&lt;/code&gt; owned by root?&lt;/p&gt;
&lt;h2 id=&quot;process-dumpability&quot;&gt;Process dumpability&lt;/h2&gt;
&lt;p&gt;I’ve looked at procfs internals &lt;a
href=&quot;https://dxuuu.xyz/proc-threads.html&quot;&gt;before&lt;/a&gt; so I had an idea
where to start looking. It took another few hours and a mixture of
&lt;code&gt;printk()&lt;/code&gt; and tracing, but I discovered where the procfs
inodes get their owners calculated: &lt;code&gt;task_dump_owner()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Around the same time (within minutes actually), Omar Sandoval kindly
&lt;a
href=&quot;https://twitter.com/omsandov/status/1582941637705359360&quot;&gt;pointed
out&lt;/a&gt; on twitter to look at process dumpability.&lt;/p&gt;
&lt;p&gt;Process dumpability appears to govern whether or not processes can
have their cores dumped. This seems reasonable – you may not want a
privileged process’s memory to be dumped to disk if it contains
sensitive information.&lt;/p&gt;
&lt;p&gt;With the above hint, the search is narrowed down to the following
block:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1848&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 1847;&quot;&gt;&lt;span id=&quot;function-1848&quot;&gt;&lt;a href=&quot;#function-1848&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; task_dump_owner&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; task_struct &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; umode_t mode&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1849&quot;&gt;&lt;a href=&quot;#function-1849&quot;&gt;&lt;/a&gt;                     kuid_t &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;ruid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; kgid_t &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;rgid&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1850&quot;&gt;&lt;a href=&quot;#function-1850&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1851&quot;&gt;&lt;a href=&quot;#function-1851&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1852&quot;&gt;&lt;a href=&quot;#function-1852&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-1853&quot;&gt;&lt;a href=&quot;#function-1853&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;mode &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;S_IFDIR&lt;span class=&quot;op&quot;&gt;|&lt;/span&gt;S_IRUGO&lt;span class=&quot;op&quot;&gt;|&lt;/span&gt;S_IXUGO&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1854&quot;&gt;&lt;a href=&quot;#function-1854&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; mm_struct &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;mm&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1855&quot;&gt;&lt;a href=&quot;#function-1855&quot;&gt;&lt;/a&gt;                task_lock&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1856&quot;&gt;&lt;a href=&quot;#function-1856&quot;&gt;&lt;/a&gt;                mm &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; task&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;mm&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1857&quot;&gt;&lt;a href=&quot;#function-1857&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;/* Make non-dumpable tasks owned by some root */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1858&quot;&gt;&lt;a href=&quot;#function-1858&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;mm&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1859&quot;&gt;&lt;a href=&quot;#function-1859&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;get_dumpable&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;mm&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; SUID_DUMP_USER&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1860&quot;&gt;&lt;a href=&quot;#function-1860&quot;&gt;&lt;/a&gt;                                &lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; user_namespace &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;user_ns &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; mm&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;user_ns&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1861&quot;&gt;&lt;a href=&quot;#function-1861&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-1862&quot;&gt;&lt;a href=&quot;#function-1862&quot;&gt;&lt;/a&gt;                                uid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; make_kuid&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;user_ns&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1863&quot;&gt;&lt;a href=&quot;#function-1863&quot;&gt;&lt;/a&gt;                                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;uid_valid&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;uid&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1864&quot;&gt;&lt;a href=&quot;#function-1864&quot;&gt;&lt;/a&gt;                                        uid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; GLOBAL_ROOT_UID&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1865&quot;&gt;&lt;a href=&quot;#function-1865&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-1866&quot;&gt;&lt;a href=&quot;#function-1866&quot;&gt;&lt;/a&gt;                                gid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; make_kgid&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;user_ns&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1867&quot;&gt;&lt;a href=&quot;#function-1867&quot;&gt;&lt;/a&gt;                                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;gid_valid&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;gid&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1868&quot;&gt;&lt;a href=&quot;#function-1868&quot;&gt;&lt;/a&gt;                                        gid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; GLOBAL_ROOT_GID&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1869&quot;&gt;&lt;a href=&quot;#function-1869&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1870&quot;&gt;&lt;a href=&quot;#function-1870&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1871&quot;&gt;&lt;a href=&quot;#function-1871&quot;&gt;&lt;/a&gt;                        uid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; GLOBAL_ROOT_UID&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1872&quot;&gt;&lt;a href=&quot;#function-1872&quot;&gt;&lt;/a&gt;                        gid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; GLOBAL_ROOT_GID&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1873&quot;&gt;&lt;a href=&quot;#function-1873&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1874&quot;&gt;&lt;a href=&quot;#function-1874&quot;&gt;&lt;/a&gt;                task_unlock&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1875&quot;&gt;&lt;a href=&quot;#function-1875&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1876&quot;&gt;&lt;a href=&quot;#function-1876&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;ruid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; uid&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1877&quot;&gt;&lt;a href=&quot;#function-1877&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;rgid &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; gid&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1878&quot;&gt;&lt;a href=&quot;#function-1878&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Line 1853 checks if the inode is a globally accessible directory.
&lt;code&gt;/proc/pid/auxv&lt;/code&gt; is a regular file so we enter the body.&lt;/p&gt;
&lt;p&gt;Line 1859 then checks for process dumpability. If it’s not globally
dumpable (globally dumpable meaning anyone can read the process’s core
dumps), the procfs inode is set to be owned by &lt;code&gt;root:root&lt;/code&gt;.
This decision is returned via &lt;code&gt;ruid&lt;/code&gt; and &lt;code&gt;rgid&lt;/code&gt;
out-params on lines 1876-1877.&lt;/p&gt;
&lt;h2 id=&quot;file-capabilities&quot;&gt;File capabilities&lt;/h2&gt;
&lt;p&gt;Now that we suspect process dumpability is involved, all that’s left
to do is figure out who or what is setting process dumpability. To that
end, we run the following bpftrace script against the reproducer:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat b.bt
kfunc:set_dumpable
/ comm == &amp;quot;a.out&amp;quot; /
{
  printf(&amp;quot;value=%d\n&amp;quot;, args-&amp;gt;value);
  print(kstack);
}

$ sudo bpftrace ./b.bt
Attaching 1 probe...
value=2

        bpf_prog_f61e3e4e5dc2ac1c_set_dumpable+306
        bpf_get_stackid_raw_tp+119
        bpf_prog_f61e3e4e5dc2ac1c_set_dumpable+306
        bpf_trampoline_6442491445_0+71
        set_dumpable+9
        commit_creds+111
        begin_new_exec+1653
        load_elf_binary+1665
        bprm_execve+639
        do_execveat_common.isra.0+429
        __x64_sys_execve+54
        do_syscall_64+92
        entry_SYSCALL_64_after_hwframe+99

^C&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we see the smoking gun: &lt;code&gt;__x64_sys_execve+54&lt;/code&gt;. This
means that dumpability is being set at process creation time. This
smells badly of file capability shenanigans. However for completeness,
we’ll look at &lt;code&gt;commit_creds()&lt;/code&gt; which directly calls
&lt;code&gt;set_dumpable()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;466&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 465;&quot;&gt;&lt;span id=&quot;function-466&quot;&gt;&lt;a href=&quot;#function-466&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; commit_creds&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; cred &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;new&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-467&quot;&gt;&lt;a href=&quot;#function-467&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-468&quot;&gt;&lt;a href=&quot;#function-468&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-469&quot;&gt;&lt;a href=&quot;#function-469&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-470&quot;&gt;&lt;a href=&quot;#function-470&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;/* dumpability changes */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-471&quot;&gt;&lt;a href=&quot;#function-471&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;uid_eq&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;euid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; new&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;euid&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;||&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-472&quot;&gt;&lt;a href=&quot;#function-472&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;gid_eq&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;egid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; new&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;egid&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;||&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-473&quot;&gt;&lt;a href=&quot;#function-473&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;uid_eq&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;fsuid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; new&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;fsuid&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;||&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-474&quot;&gt;&lt;a href=&quot;#function-474&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;gid_eq&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;fsgid&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; new&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;fsgid&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;||&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-475&quot;&gt;&lt;a href=&quot;#function-475&quot;&gt;&lt;/a&gt;            &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;cred_cap_issubset&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;old&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; new&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-476&quot;&gt;&lt;a href=&quot;#function-476&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;mm&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-477&quot;&gt;&lt;a href=&quot;#function-477&quot;&gt;&lt;/a&gt;                        set_dumpable&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;mm&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; suid_dumpable&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-478&quot;&gt;&lt;a href=&quot;#function-478&quot;&gt;&lt;/a&gt;                task&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;pdeath_signal &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-479&quot;&gt;&lt;a href=&quot;#function-479&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;co&quot;&gt;/*&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-480&quot;&gt;&lt;a href=&quot;#function-480&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;                 * If a task drops privileges and becomes nondumpable,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-481&quot;&gt;&lt;a href=&quot;#function-481&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;                 * the dumpability change must become visible before&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-482&quot;&gt;&lt;a href=&quot;#function-482&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;                 * the credential change; otherwise, a __ptrace_may_access()&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-483&quot;&gt;&lt;a href=&quot;#function-483&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;                 * racing with this change may be able to attach to a task it&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-484&quot;&gt;&lt;a href=&quot;#function-484&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;                 * shouldn&amp;#39;t be able to attach to (as if the task had dropped&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-485&quot;&gt;&lt;a href=&quot;#function-485&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;                 * privileges without becoming nondumpable).&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-486&quot;&gt;&lt;a href=&quot;#function-486&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;                 * Pairs with a read barrier in __ptrace_may_access().&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-487&quot;&gt;&lt;a href=&quot;#function-487&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;                 */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-488&quot;&gt;&lt;a href=&quot;#function-488&quot;&gt;&lt;/a&gt;                smp_wmb&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-489&quot;&gt;&lt;a href=&quot;#function-489&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-490&quot;&gt;&lt;a href=&quot;#function-490&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-491&quot;&gt;&lt;a href=&quot;#function-491&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-492&quot;&gt;&lt;a href=&quot;#function-492&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Line 475 is what we’ve been after. &lt;code&gt;cred_cap_issubset()&lt;/code&gt;
is checking is if the old capabilities are a subset of the new
capabilities. If so, it means the process has gained capabilities during
an &lt;code&gt;execve(2)&lt;/code&gt; and process dumpability is adjusted. Again,
this checks out b/c the new process may (or already) have elevated
capabilities and could contain sensitive information going forward.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So we have our answer: our unprivileged cannot read
&lt;code&gt;/proc/self/auxv&lt;/code&gt; because it has filecaps assigned. And b/c
filecaps can potentially make a process contain sensitive information,
the kernel makes its &lt;code&gt;/proc/&amp;lt;pid&amp;gt;&lt;/code&gt; inodes owned by
&lt;code&gt;root:root&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Although nothing terribly actionable resulted from this
investivation, I nonetheless found this to be an interesting case study
in emergent properties. Each new discovery made sense in isolation. But
despite each step making sense, the final result remains unexpected. And
b/c each step makes sense in isolation, I cannot think of a good way to
change the final result without making some piece of the puzzle
&lt;em&gt;not&lt;/em&gt; make sense.&lt;/p&gt;
&lt;p&gt;I suppose that’s why documentation is a thing.&lt;/p&gt;
&lt;p&gt;And by the way, this behavior is actually documented in
&lt;code&gt;proc(2)&lt;/code&gt; man page under &lt;code&gt;PR_SET_DUMPABLE&lt;/code&gt;.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>3D modeling with OpenSCAD</title><id>https://dxuuu.xyz/openscad.html</id><updated>2023-02-13T08:51:39-08:00</updated><link href="https://dxuuu.xyz/openscad.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;3D modeling with OpenSCAD&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;3D modeling with OpenSCAD&lt;/h1&gt;
&lt;/header&gt;
&lt;h3 id=&quot;the-boring-background&quot;&gt;The Boring Background&lt;/h3&gt;
&lt;p&gt;A few months ago I got tired of commuting to the local hacker space
so I bought a &lt;a
href=&quot;https://www.creality.com/products/ender-3-v2-3d-printer-csco&quot;&gt;cheap
3D printer&lt;/a&gt; to use at home. Like any good neophyte, I printed quite a
few precooked models before getting the itch to design some of my
own.&lt;/p&gt;
&lt;p&gt;The biggest hurdle was that I couldn’t find good modeling software to
run on Linux. I tried &lt;a href=&quot;https://www.freecad.org/&quot;&gt;FreeCAD&lt;/a&gt; and
&lt;a href=&quot;https://www.blender.org/&quot;&gt;Blender&lt;/a&gt; but found them hard to
approach. I eventually stumbled upon &lt;a
href=&quot;https://openscad.org/&quot;&gt;OpenSCAD&lt;/a&gt; which I ended up absolutely
loving. So hopefully this is the first of at least a few posts where I
dive into some of the techniques I’ve learned.&lt;/p&gt;
&lt;h3 id=&quot;spice-rack&quot;&gt;Spice rack&lt;/h3&gt;
&lt;p&gt;There’s obviously a lot of useful things you can make with a 3D
printer. For my first project, I decided on a spice rack for two
reasons:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;My spice cabinet is a total mess and it take forever to find
anything.&lt;/li&gt;
&lt;li&gt;It’s a simple geometry, meaning I could focus most of my attention
on learning the tooling.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s the final design for reference:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/openscad/final_render.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-quick-primer&quot;&gt;A quick primer&lt;/h3&gt;
&lt;p&gt;I’m not really an expert at 3D modeling so I won’t say much about the
theory. But based on my limited research, I found OpenSCAD’s marriage
between declarative scripting and constructive solid geometry (CSG) to
be a wonderfully elegant combination.&lt;/p&gt;
&lt;p&gt;The premise behind CSG is that there are a limited set of 2D and 3D
primitives such as squares, circles, spheres, cylinders, cubes, etc.
which can be combined with with boolean operators to yield complex
geometries. For example, with the following code, you can take the union
of a cube and a sphere to yield a cube-sphere fusion:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;union() {
    cube([5, 5, 5], center=true);
    translate([5, 0, 0])
        sphere(r=3);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;../examples/openscad/cube_sphere.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Expressions are not limited to the top level – they can be
arbitrarily nested. Consider this following example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module ring() {
    difference() {
        circle(r=10);
        circle(r=5);
    }
}

linear_extrude(15) {
    union() {
        translate([15, 0, 0]) ring();
        ring();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;../examples/openscad/before_extrude.png&quot;
style=&quot;width:49.0%&quot; /&gt; &lt;img src=&quot;../examples/openscad/after_extrude.png&quot;
style=&quot;width:50.0%&quot; /&gt;&lt;/p&gt;
&lt;center&gt;
Before (left) and after (right) extrusion
&lt;/center&gt;
&lt;p&gt;The basic idea is we first create two rings, one next to the other.
We then take the two rings and join them with a union. Finally, take the
union and extrude along Z axis to create the binocular shape on the
right above.&lt;/p&gt;
&lt;p&gt;The other new technique here is a &lt;code&gt;module&lt;/code&gt;. A module,
taken in the context of C/C++ like languages, is essentially a macro. We
don’t use any parameters in the module here, but we could have.&lt;/p&gt;
&lt;p&gt;Knowing these basics, we move onto the rack design.&lt;/p&gt;
&lt;h3 id=&quot;rack-design&quot;&gt;Rack design&lt;/h3&gt;
&lt;p&gt;To start, we create the backboard:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;translate([(225/2), 25, 0])
    cube([225, 5, 15], center=true);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;../examples/openscad/backboard.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We translate the backboard a bit so that it’s length is easier to
eyeball on the X axis and so it’s arms are more easily positioned on the
Y axis. Note that OpenSCAD is unitless but my slicer (&lt;a
href=&quot;https://en.wikipedia.org/wiki/Cura_(software)&quot;&gt;Cura&lt;/a&gt;)
interprets the units by default as millimeters.&lt;/p&gt;
&lt;p&gt;Next we create the arms:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;inner_radius = 20;
outer_radius = inner_radius + 3;

module arm() {
    difference() {
        intersection() {
            circle(outer_radius);
            translate([0, 7.8, 0])
                square([500, 41], center=true);
        }
        circle(inner_radius);
    }
}

for (i=[0:3]) {
    translate([i*56.5 + 28, 2, 0])
        #arm();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;../examples/openscad/arms_before.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The arms follow a similar design to the examples above. We make each
arm by intersecting two circles and slicing off the end so the spices
can fit. And instead of making one, we make four by using a
&lt;code&gt;for&lt;/code&gt; loop.&lt;/p&gt;
&lt;p&gt;One practical tidbit here is we lexically prefix each arm with
&lt;code&gt;#&lt;/code&gt; to give it a different render color. This is useful for
quickly eyeballing changes to your model. In this case, we’ll be using
it to illustrate the changes from the previous code snippet.&lt;/p&gt;
&lt;p&gt;Once we have the 2D arms, all that’s left is to extrude them to the
appropriate height:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module arm() {
    #linear_extrude(15, center=true) {
        // Previous contents of `arm()`
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;../examples/openscad/arms_after.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;At this point we have a functional model. In fact, this is what I
have printed and installed in my cabinets. However, there’s still one
small improvement we can make: the tips of the arms. The tips are
slightly sharp and could use some rounding out. To achieve this, we’ll
use a &lt;a href=&quot;https://www.youtube.com/watch?v=hKVBJMHivA4&quot;&gt;Minkowski
Sum&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Minkowski sums are hard to explain through text but surprisingly easy
to understand with a visualization. In the previously link, the
animation demonstrates that the sum of two nodes involves running the
child node around the edges of the parent node and adding the shape that
the child node’s motion creates to the parent node.&lt;/p&gt;
&lt;p&gt;In our case, we’ll run a small circle around the edges of the arm
while also subtracting an additional unit off the inside and outside to
keep the final dimensions roughly the same. The end result is the sharp
edges are rounded out but the smooth parts remain unchanged.&lt;/p&gt;
&lt;p&gt;In code, this looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;minkowski_radius = 1;

module arm() {
    linear_extrude(15, center=true) {
        minkowski() {
            difference() {
                intersection() {
                    circle(outer_radius-minkowski_radius);
                    translate([0, 7.8, 0])
                        square([500, 41-minkowski_radius], center=true);
                }
                circle(inner_radius+minkowski_radius);
            }
            circle(minkowski_radius);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this we arrive at the model displayed in the beginning of this
post.&lt;/p&gt;
&lt;p&gt;For completeness, the following is the physical result. As I
mentioned earlier, the physical model doesn’t yet have the rounded edges
(the 3M adhesive strips are surprisingly expensive!). So you’ll have to
use your imagination a little here.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/openscad/final.png&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Obviously this is not a complicated geometry. In fact, a (real)
engineer friend of mine was timed creating a similar model using
professional tooling and it took him about 90 seconds. Despite that, I
still think this was a really enjoyable process. I particularly love how
the entire language fits on a &lt;a
href=&quot;https://openscad.org/cheatsheet/&quot;&gt;small cheat sheet&lt;/a&gt; –
something unimaginable for industrial grade tools. So I suppose my
preference for elegance over practicality is why he’s a real engineer
and I’m not.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Generating kernel patchsets</title><id>https://dxuuu.xyz/patchsets.html</id><updated>2023-02-27T13:29:18-08:00</updated><link href="https://dxuuu.xyz/patchsets.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Generating kernel patchsets&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Generating kernel patchsets&lt;/h1&gt;
&lt;/header&gt;
&lt;h3 id=&quot;background&quot;&gt;Background&lt;/h3&gt;
&lt;p&gt;The Linux kernel famously has an &lt;a
href=&quot;https://www.kernel.org/doc/html/latest/process/submitting-patches.html&quot;&gt;email
workflow&lt;/a&gt;. Ignoring whether or not it’s a good thing, it is still a
fact that it can be tricky to follow the process.&lt;/p&gt;
&lt;p&gt;One problem I’ve had for years is wrangling
&lt;code&gt;git-format-patch&lt;/code&gt; and &lt;code&gt;git-send-email&lt;/code&gt; to do the
right thing. Any time I’ve wanted to send a patchset, I’ve had to search
through my shell history to help remember the right incantations.&lt;/p&gt;
&lt;p&gt;Obviously this gets old fast and becomes a constant source of
friction.&lt;/p&gt;
&lt;h3 id=&quot;problem&quot;&gt;Problem&lt;/h3&gt;
&lt;p&gt;Automation is clearly the answer. A wrapper script over
&lt;code&gt;git&lt;/code&gt; is always an option but can become overcomplicated over
time. I’d rather try to integrate with &lt;code&gt;git&lt;/code&gt; than hide
it.&lt;/p&gt;
&lt;p&gt;The above is &lt;a
href=&quot;https://mudongliang.github.io/2021/06/21/git-send-email-with-cc-cmd-and-to-cmd.html&quot;&gt;not
a new idea&lt;/a&gt;; there’ve been plenty of &lt;a
href=&quot;https://www.marcusfolkesson.se/blog/get_maintainers-and-git-send-email/&quot;&gt;previous
writing&lt;/a&gt; on this. Basically what the two linked approaches suggest is
to hook git-send-email to automatically generate &lt;code&gt;To&lt;/code&gt; and
&lt;code&gt;Cc&lt;/code&gt; headers using
&lt;code&gt;scripts/get_maintainer.pl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately there are multiple drawbacks of the above
approaches:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;They do not correctly generate To and Cc headers for cover
letters&lt;/li&gt;
&lt;li&gt;It is painful to realize the generation is incorrect halfway through
sending a large patchset. Half the emails are already sent – you cannot
take them back.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After some experimenting, I offer a slightly improved solution.&lt;/p&gt;
&lt;h3 id=&quot;solution&quot;&gt;Solution&lt;/h3&gt;
&lt;p&gt;The first improvement I’m offering is to generate the headers during
git-format-patch time. This allows you to eyeball the results before
sending. This also gives you a way to incrementally add more emails.&lt;/p&gt;
&lt;p&gt;To that end, I ended up using &lt;a
href=&quot;https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases&quot;&gt;Git
aliases&lt;/a&gt; to “create” my own git command: &lt;code&gt;git patchset&lt;/code&gt;.
The alias is defined as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[alias]
        patchset = &amp;quot;!linux-patchset.sh&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, all it does is run a script. Note that all arguments
after &lt;code&gt;git patchset&lt;/code&gt; are forwarded to the script as
positional arguments.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;linux-patchset.sh&lt;/code&gt; is more or less the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ROOT=$(git rev-parse --show-toplevel)
OUTDIR=&amp;quot;${ROOT}/outgoing/$(git rev-parse --abbrev-ref HEAD)&amp;quot;

git format-patch -o &amp;quot;$OUTDIR&amp;quot; -s --to &amp;quot;&amp;quot; --cc &amp;quot;&amp;quot; &amp;quot;$@&amp;quot;
LINUX_ROOT=&amp;quot;$ROOT&amp;quot; linux-address-patchset.py &amp;quot;$OUTDIR&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Basically what this script does is first git-format-patch the
patchset and place the output into &lt;code&gt;linux/outgoing&lt;/code&gt;. The
output location is not that important – I just prefer it there.&lt;/p&gt;
&lt;p&gt;Then it runs &lt;code&gt;linux-address-patchset.py&lt;/code&gt; over the
formatted patches. The logic in linux-address-patchset.py is fairly
mechanical and might be subject to change over time. But the basic idea
is for each patch file:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the patch file is a cover letter, iterate through the rest of the
series and collect all the &lt;em&gt;mailing list&lt;/em&gt; addresses for the To
and Cc headers&lt;/li&gt;
&lt;li&gt;For non-cover letter patches, collect maintainer addresses for the
To header&lt;/li&gt;
&lt;li&gt;Similarly for Cc, collect reviewer and mailing list addresses&lt;/li&gt;
&lt;li&gt;Once all the addresses are collected and deduped, append addresses
to the appropriate header&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The full scripts are available &lt;a
href=&quot;https://github.com/danobi/bin&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;All together, this how my latest patchset was generated:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ git patchset -v2 --subject-prefix &amp;quot;PATCH bpf-next&amp;quot; bpf-next/master
~/linux/outgoing/ip_check_defrag-v2/v2-0000-cover-letter.patch
~/linux/outgoing/ip_check_defrag-v2/v2-0001-ip-frags-Return-actual-error-codes-from-ip_check_.patch
~/linux/outgoing/ip_check_defrag-v2/v2-0002-bpf-verifier-Support-KF_CHANGES_PKT-flag.patch
~/linux/outgoing/ip_check_defrag-v2/v2-0003-bpf-net-frags-Add-bpf_ip_check_defrag-kfunc.patch
~/linux/outgoing/ip_check_defrag-v2/v2-0004-net-ipv6-Factor-ipv6_frag_rcv-to-take-netns-and-u.patch
~/linux/outgoing/ip_check_defrag-v2/v2-0005-bpf-net-ipv6-Add-bpf_ipv6_frag_rcv-kfunc.patch
~/linux/outgoing/ip_check_defrag-v2/v2-0006-bpf-selftests-Support-not-connecting-client-socke.patch
~/linux/outgoing/ip_check_defrag-v2/v2-0007-bpf-selftests-Support-custom-type-and-proto-for-c.patch
~/linux/outgoing/ip_check_defrag-v2/v2-0008-bpf-selftests-Add-defrag-selftests.patch&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if you take a peek at the first two patches:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ head -n7 outgoing/ip_check_defrag-v2/v2-0000-cover-letter.patch
From 99ddd1e2b35f6133c1f49a0245340e1a8aaaf32f Mon Sep 17 00:00:00 2001
Message-Id: &amp;lt;cover.1677526810.git.dxu@dxuuu.xyz&amp;gt;
From: Daniel Xu &amp;lt;dxu@dxuuu.xyz&amp;gt;
Date: Mon, 27 Feb 2023 12:40:10 -0700
Subject: [PATCH bpf-next v2 0/8] Support defragmenting IPv(4|6) packets in BPF
To: bpf@vger.kernel.org,linux-kselftest@vger.kernel.org,netdev@vger.kernel.org,linux-doc@vger.kernel.org,linux-kernel@vger.kernel.org
Cc: bpf@vger.kernel.org

$ head -n11 outgoing/ip_check_defrag-v2/v2-0001-ip-frags-Return-actual-error-codes-from-ip_check_.patch
From bf4afe3484836972f94c1b7738845ba69d7008f5 Mon Sep 17 00:00:00 2001
Message-Id: &amp;lt;bf4afe3484836972f94c1b7738845ba69d7008f5.1677526810.git.dxu@dxuuu.xyz&amp;gt;
In-Reply-To: &amp;lt;cover.1677526810.git.dxu@dxuuu.xyz&amp;gt;
References: &amp;lt;cover.1677526810.git.dxu@dxuuu.xyz&amp;gt;
From: Daniel Xu &amp;lt;dxu@dxuuu.xyz&amp;gt;
Date: Tue, 6 Dec 2022 17:47:16 -0700
Subject: [PATCH bpf-next v2 1/8] ip: frags: Return actual error codes from
 ip_check_defrag()
To: kuba@kernel.org,edumazet@google.com,willemdebruijn.kernel@gmail.com,davem@davemloft.net,pabeni@redhat.com,dsahern@kernel.org
Cc: netdev@vger.kernel.org,linux-kernel@vger.kernel.org,bpf@vger.kernel.org&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Happy hacking!&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Visualizing below using Grafana</title><id>https://dxuuu.xyz/below-grafana.html</id><updated>2023-03-04T10:35:11-08:00</updated><link href="https://dxuuu.xyz/below-grafana.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Visualizing below using Grafana&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Visualizing below using Grafana&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;&lt;img src=&quot;../examples/below-grafana/example.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The fancy way to describe &lt;a
href=&quot;https://github.com/facebookincubator/below&quot;&gt;&lt;code&gt;below&lt;/code&gt;&lt;/a&gt;
is “a time traveling resource monitor for modern Linux systems”. The
less fancy description is that &lt;code&gt;below&lt;/code&gt; is pretty much like
&lt;code&gt;top&lt;/code&gt; or &lt;code&gt;htop&lt;/code&gt; but can persist historical data to
disk. It comes with quite a few more neat features but I’ll defer the
full explanation and demo to the previous link.&lt;/p&gt;
&lt;p&gt;Despite having a nice TUI client to replay data, it is sometimes
useful to be able to plot a graph to identify patterns. This is the main
weakness (open source) below has today. Since the current $DAYJOB now
has a vested interest in making below work for our production use cases,
I decided to tackle the visualization weakness.&lt;/p&gt;
&lt;h3 id=&quot;design&quot;&gt;Design&lt;/h3&gt;
&lt;p&gt;I considered a few design ideas:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Build custom visualization into a web page below would serve&lt;/li&gt;
&lt;li&gt;Have below serve Grafana’s UI&lt;/li&gt;
&lt;li&gt;Teach Grafana to talk to below using a &lt;a
href=&quot;https://grafana.com/tutorials/build-a-data-source-plugin/&quot;&gt;data
source plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ingest below’s data into Prometheus and have Grafana talk to
Prometheus&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Options (1) and (2) were invalidated after a day of research. They
were too much work and don’t fully leverage all the amazing work that
went into Grafana. Option (3) is valid, but seemed like more of a hassle
to maintain than (4). Option (4) is ultimately what I ended up going
with b/c it fully leverages Grafana’s power without getting off the
beaten path.&lt;/p&gt;
&lt;h3 id=&quot;openmetrics&quot;&gt;OpenMetrics&lt;/h3&gt;
&lt;p&gt;Luckily for us Prometheus has fairly good &lt;a
href=&quot;https://prometheus.io/docs/prometheus/latest/storage/#backfilling-from-openmetrics-format&quot;&gt;backfill
support&lt;/a&gt;. However the only format it understands is
&lt;code&gt;OpenMetrics&lt;/code&gt;. OpenMetrics has a fairly straightforward &lt;a
href=&quot;https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md&quot;&gt;schema&lt;/a&gt;
(the overly rigorous spec notwithstanding). For example consider the
following “exposition”:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# TYPE my_gauge gauge
# HELP my_gauge Current value of the gauge
my_gauge 123 1677953705
# TYPE my_counter counter
# HELP my_counter Monotonically increasing counter
my_counter 1677953705
# EOF&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above exposition describes two metrics: &lt;code&gt;my_gauge&lt;/code&gt; and
&lt;code&gt;my_counter&lt;/code&gt;, where a gauge provides a point-in-time value
that can go up and down and a counter is a monotonically increasing
counter.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;# TYPE&lt;/code&gt; line describes the name and type of the
metric.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;# HELP&lt;/code&gt; line provides a human readable description of
the metric.&lt;/p&gt;
&lt;p&gt;The sample has three parts: the name of the metric, the value, and
the unix timestamp. The timestamp is optional. For backfilling we will
need to always provide a timestamp.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;# EOF&lt;/code&gt; line terminates the exposition.&lt;/p&gt;
&lt;h3 id=&quot;ingestion&quot;&gt;Ingestion&lt;/h3&gt;
&lt;p&gt;From here it’s clear that below, Prometheus, and Grafana all think
about data in the same way. All that’s left is data conversion. Since
below has good structured output support, it’s a fairly straightforwad
but somewhat tedious exercise to munge below’s data into a text
file.&lt;/p&gt;
&lt;p&gt;I won’t bore you with the details so here’s the &lt;a
href=&quot;https://github.com/danobi/below-grafana/blob/master/import.py&quot;&gt;link
to the code&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;Once the OpenMetrics text file is generated, we can ingest the data
into Prometheus using the following Prometheus CLI subcommand:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ promtool tsdb create-blocks-from openmetrics ./path/to/input ./path/to/prom/data&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;putting-it-all-together&quot;&gt;Putting it all together&lt;/h3&gt;
&lt;p&gt;Here’s what the final user workflow looks like given some
&lt;code&gt;below-snapshot&lt;/code&gt; data at &lt;code&gt;/tmp/snapshot-data&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ git clone https://github.com/danobi/below-grafana; cd below-grafana
$ docker compose up -d
$ ./import.py /tmp/snapshot-data --begin &amp;quot;4h ago&amp;quot; --end &amp;quot;2h ago&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The user then visits &lt;code&gt;http://localhost:3000&lt;/code&gt; and can start
Grafana.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Hopefully this is useful to people. I know I’ll be using it heavily
in the future.&lt;/p&gt;
&lt;p&gt;Full code is &lt;a
href=&quot;https://github.com/danobi/below-grafana&quot;&gt;available here&lt;/a&gt;.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Not so perfect forwarding</title><id>https://dxuuu.xyz/perfect-forwarding.html</id><updated>2023-04-20T08:14:14-07:00</updated><link href="https://dxuuu.xyz/perfect-forwarding.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Not so perfect forwarding&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Not so perfect forwarding&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Consider the following C++ structs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;struct Foo {
  char b;
  int a;
} __attribute__((packed));

struct Bar {
  Bar(int a) {}
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now consider the following code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;memory&amp;gt;

int main() {
  Foo f;
  auto p = std::make_unique&amp;lt;Bar&amp;gt;(f.a);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It should compile right? Wrong:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/tmp/cppsh-NLnGU.cpp: In function ‘int main()’:
/tmp/cppsh-NLnGU.cpp:14:36: error: cannot bind packed field ‘f.Foo::a’ to ‘int&amp;amp;’
   14 |   auto p = std::make_unique&amp;lt;Bar&amp;gt;(f.a);
      |&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What gives? I can take it on faith that references to packed fields
are banned – in general unaligned memory access is bad. But
&lt;code&gt;Bar::Bar&lt;/code&gt; takes an &lt;code&gt;int&lt;/code&gt; by value, not by
reference.&lt;/p&gt;
&lt;p&gt;The answer lies in &lt;code&gt;std::make_unique&lt;/code&gt;.
&lt;code&gt;std::make_unique&lt;/code&gt; uses perfect forwarding, a way to forward
function arguments “without changing its lvalue or rvalue
characteristics” such as &lt;code&gt;const&lt;/code&gt;-ness and rvalue-ness. Its
function signature looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;template&amp;lt; class T, class... Args &amp;gt;
unique_ptr&amp;lt;T&amp;gt; make_unique( Args&amp;amp;&amp;amp;... args );&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In order to forward the perfectly forward the arguments without extra
copies, it tries to take a reference, leaving the final (and required)
copy to &lt;code&gt;Bar::Bar&lt;/code&gt;. Usually this is good, but in this
specific case it breaks our code.&lt;/p&gt;
&lt;p&gt;To workaround this issue, we could do:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int main() {
  Foo f;
  int a = f.a;
  auto p = std::make_unique&amp;lt;Bar&amp;gt;(a);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;addendum&quot;&gt;Addendum&lt;/h3&gt;
&lt;p&gt;Scott Meyers actually lays out a &lt;a
href=&quot;https://github.com/peter-can-write/cpp-notes/blob/master/perfect-forwarding-failure-cases.md&quot;&gt;few
more&lt;/a&gt; perfect forwarding failure cases. Packed members are not
covered, but bitfields are probably close enough semantically.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>vmtest: Run your tests in virtual machines</title><id>https://dxuuu.xyz/vmtest.html</id><updated>2023-05-16T16:38:45-07:00</updated><link href="https://dxuuu.xyz/vmtest.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;vmtest: Run your tests in virtual machines&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;vmtest: Run your tests in virtual machines&lt;/h1&gt;
&lt;/header&gt;
&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Systems software that depend on specific kernel or host properties
often contains logic to gate functionality based on what features are
available at runtime. This necessarily begs the question: how do you
test platform specific logic? Mocks can help, but they come with their
own set of tradeoffs. At the end of the day, there is no substitute for
actually running your code.&lt;/p&gt;
&lt;p&gt;eBPF (BPF) is somewhat of an extreme example because of how fast
development occurs in that ecosystem. Most, if not all, BPF features are
baked into the kernel, meaning that any non-trivial BPF-powered
application heavily depends on kernel version. Since I do quite a bit of
BPF development, the rest of this post is as a result, BPF focused.
Despite that, keep in mind that all proposed techniques/solutions are
quite general and can be applied to other domains.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;Paradoxicaly enough, despite BPF being my motivation for
&lt;code&gt;vmtest&lt;/code&gt;, BPF has excellent support for testing through &lt;a
href=&quot;https://github.com/torvalds/linux/blob/16a8829130ca22666ac6236178a6233208d425c3/include/uapi/linux/bpf.h#L332-L368&quot;&gt;&lt;code&gt;BPF_PROG_RUN&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;BPF programs are normally attached to a hook and only executed when
when the hook is reached by the kernel. &lt;code&gt;BPF_PROG_RUN&lt;/code&gt;, on
the other hand, allows userspace to run BPF programs in “freestanding”
mode. More precisely, it allows userspace to both provide the input
context, run the program on demand, and collect the program’s return
value (among a few other things).&lt;/p&gt;
&lt;p&gt;Contrast this with something like &lt;code&gt;iptables&lt;/code&gt; where it
takes considerably more setup (network namespaces, fake network devices,
traffic generators, etc.) to get automated tests. And even after all of
that, it’s more of an integration test than a true unit test.&lt;/p&gt;
&lt;p&gt;Basically given &lt;code&gt;BPF_PROG_RUN&lt;/code&gt;, all that’s left to solve
is how to control the kernel your tests run on top of.&lt;/p&gt;
&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;/h2&gt;
&lt;p&gt;The primary goal is to &lt;strong&gt;create infrastructure that runs code
on target kernels&lt;/strong&gt;. Along the way we may solve other problems or
enable other use cases, but our primary goal will help inform our design
decisions.&lt;/p&gt;
&lt;p&gt;In addition, the following are design ideas (in decreasing order of
importance) that will help inform our decisions:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Make it reusable: &lt;code&gt;vmtest&lt;/code&gt; should be as generic as
possible and adoptable across projects in different domains.&lt;/li&gt;
&lt;li&gt;Make it work in CI: &lt;code&gt;vmtest&lt;/code&gt; should be able to run in
Github Actions. Supporting other providers would be even better.&lt;/li&gt;
&lt;li&gt;Make it simple: defaults should “just work”. Any configurables
should be unavoidable to expose.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;solution&quot;&gt;Solution&lt;/h2&gt;
&lt;p&gt;Our solution is two-fold: &lt;a
href=&quot;https://github.com/danobi/vmtest&quot;&gt;&lt;code&gt;vmtest&lt;/code&gt;&lt;/a&gt; and &lt;a
href=&quot;https://github.com/danobi/vmtest-action&quot;&gt;&lt;code&gt;vmtest-action&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vmtest&lt;/code&gt; is the workhorse binary and contains all the
logic to orchestrate &lt;code&gt;qemu&lt;/code&gt; on the root host and
&lt;code&gt;qemu-guest-agent&lt;/code&gt; inside the guest VM. Among other things,
it maps the running userspace into the guest VM as its rootfs. The end
result is that your host’s userspace “just runs”, except the kernel it’s
running under is different. The binary also supports a handful of
nice-to-have things such as a standard unix interface, a terminal user
interface, and support for multiple targets through a configuration
file.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vmtest-action&lt;/code&gt; is a Github Actions wrapper (ie. a
singular &lt;a
href=&quot;https://docs.github.com/en/actions/creating-actions/about-custom-actions&quot;&gt;Github
Action&lt;/a&gt;) that downloads/installs &lt;code&gt;vmtest&lt;/code&gt; as well as its
runtime dependencies. The action exposes a subset of the features
&lt;code&gt;vmtest&lt;/code&gt; supports but at the same time adds a few
conveniences (such as URL asset downloads) – effectively tailoring
&lt;code&gt;vmtest&lt;/code&gt; to CI usage.&lt;/p&gt;
&lt;p&gt;The two part solution helps separate concerns but also allows for
novel uses cases such iterating on kernel changes using the
&lt;code&gt;vmtest&lt;/code&gt; binary.&lt;/p&gt;
&lt;h2 id=&quot;multi-target-example&quot;&gt;Multi-target example&lt;/h2&gt;
&lt;p&gt;Consider the following &lt;code&gt;vmtest.toml&lt;/code&gt; configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[[target]]
name = &amp;quot;check if kernel is 6.2&amp;quot;
kernel = &amp;quot;./bzImage-v6.2&amp;quot;
command = &amp;quot;/bin/bash -c &amp;#39;uname -r | grep -e ^6.2.0$&amp;#39;&amp;quot;

[[target]]
name = &amp;quot;check if kernel is 6.1&amp;quot;
kernel = &amp;quot;./bzImage-v6.2&amp;quot;
command = &amp;quot;/bin/bash -c &amp;#39;uname -r; uname -r | grep -e ^6.1.0$&amp;#39;&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above has two targets: the first target checks if the running
kernel is v6.2 and the second checks if the running kernel is v6.1.
Since they’re both going to run under a v6.2 kernel, only the first
target should succeed. Carefully note here that we do not define a
rootfs or run install scripts to get access to &lt;code&gt;bash&lt;/code&gt; and
&lt;code&gt;coreutils&lt;/code&gt; – the entire running userspace on your host is
shared into the VM.&lt;/p&gt;
&lt;p&gt;This is what a run looks like:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/vmtest/demo.gif&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Note that our second target fails as expected.&lt;/p&gt;
&lt;h2 id=&quot;ci-example&quot;&gt;CI example&lt;/h2&gt;
&lt;p&gt;Now pretend you have a bog standard Github Actions (GHA) workflow. It
has fairly standard steps – for example installing dependencies, build
configuration, and executing a test runner. This workflow implicitly
uses the kernel the GHA runner’s kernel. Perhaps it was new enough for a
while but now it’s too old and you need to find a way to run your tests
against a matrix of newer kernels.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vmtest-action&lt;/code&gt; would satisfy your needs with the
following diff:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre
class=&quot;sourceCode diff&quot;&gt;&lt;code class=&quot;sourceCode diff&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;index 4b1d68f..d62fed9 100644&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;--- a/.github/workflows/ci.yml&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;+++ b/.github/workflows/ci.yml&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;@@ -7,6 +7,16 @@ on:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; &lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; jobs:&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;   build:&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+    strategy:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+      matrix:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+        kernel:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+          - name: v6.0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+            url: https://github.com/danobi/vmtest/releases/download/test_assets/bzImage-v6.0-empty&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+          - name: v6.1&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+            url: https://github.com/danobi/vmtest/releases/download/test_assets/bzImage-v6.1-empty&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-16&quot;&gt;&lt;a href=&quot;#cb2-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+          - name: v6.2&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-17&quot;&gt;&lt;a href=&quot;#cb2-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+            url: https://github.com/danobi/vmtest/releases/download/test_assets/bzImage-v6.2-empty&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-18&quot;&gt;&lt;a href=&quot;#cb2-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-19&quot;&gt;&lt;a href=&quot;#cb2-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     runs-on: ubuntu-latest&lt;/span&gt;
&lt;span id=&quot;cb2-20&quot;&gt;&lt;a href=&quot;#cb2-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     steps:&lt;/span&gt;
&lt;span id=&quot;cb2-21&quot;&gt;&lt;a href=&quot;#cb2-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     - uses: actions/checkout@v3&lt;/span&gt;
&lt;span id=&quot;cb2-22&quot;&gt;&lt;a href=&quot;#cb2-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;@@ -21,5 +31,8 @@ jobs:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-23&quot;&gt;&lt;a href=&quot;#cb2-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;         ninja -C build&lt;/span&gt;
&lt;span id=&quot;cb2-24&quot;&gt;&lt;a href=&quot;#cb2-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; &lt;/span&gt;
&lt;span id=&quot;cb2-25&quot;&gt;&lt;a href=&quot;#cb2-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     - name: Run&lt;/span&gt;
&lt;span id=&quot;cb2-26&quot;&gt;&lt;a href=&quot;#cb2-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;-      run: |&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-27&quot;&gt;&lt;a href=&quot;#cb2-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;-        ./build/vmtest-action-demo&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-28&quot;&gt;&lt;a href=&quot;#cb2-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+      uses: danobi/vmtest-action@master&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-29&quot;&gt;&lt;a href=&quot;#cb2-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+      with:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-30&quot;&gt;&lt;a href=&quot;#cb2-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+        name: ${{ matrix.kernel.name }}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-31&quot;&gt;&lt;a href=&quot;#cb2-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+        kernel_url: ${{ matrix.kernel.url }}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-32&quot;&gt;&lt;a href=&quot;#cb2-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+        command: ${{ github.workspace}}/build/vmtest-action-demo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note how the dependency install, configure, and build steps are being
run &lt;em&gt;outside&lt;/em&gt; the VM. This is desirable b/c anything running
inside the VM is liable to be slower in the event emulation is
necessary.&lt;/p&gt;
&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;../examples/vmtest/architecture.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The first big idea is that vmtest tries to orchestrate everything
through QEMU’s programmable interfaces, namely the QEMU machine protocol
(QMP) for orchestrating QEMU and qemu-guest-agent (which also uses QMP
under the hood) for running things inside the guest VM. Both interfaces
use a unix domain socket for transport.&lt;/p&gt;
&lt;p&gt;Using QEMU’s programmable interfaces is probably the only novel
contribution we make to this problem space. The other ideas (even the
name) are shamelessly borrowed from other folk’s earlier explorations.
This contribution, however, makes developing and extending
&lt;code&gt;vmtest&lt;/code&gt; a much saner and pleasant experience over things
like triple-escaping shell commands. qemu-guest-agent alone gives us a
clean out-of-band mechanism (so not requiring networking or SSH) to run
commands inside the guest.&lt;/p&gt;
&lt;p&gt;The second big idea is that we use 9p filesystems to share the host
filesystem inside the guest. This is useful so that vmtest targets can
import/export data in bulk without having to specify what to copy. In a
kernel target, vmtest exports two volumes: &lt;code&gt;/mnt/vmtest&lt;/code&gt; and
the root filesystem. The first volume is the directory rooted by
&lt;code&gt;vmtest.toml&lt;/code&gt; mounted read/write. The latter export
effectively gives the guest VM the same userspace environment as the
host, except we mount it read-only so the guest cannot do too much
damage to the host.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;vmtest&lt;/code&gt; is only just getting started. By the time it goes
into maintenance mode, there should be no excuse to be missing VM-based
testing from your development workflows.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>The case for a community maintained BPF book</title><id>https://dxuuu.xyz/bpf-book.html</id><updated>2023-05-22T11:50:28-07:00</updated><link href="https://dxuuu.xyz/bpf-book.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;The case for a community maintained BPF book&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;The case for a community maintained BPF book&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;It’s widely accepted that it’s hard to get started with eBPF (BPF).
It’s an extremely fast moving ecosystem and the state-of-the-art today
is not the same as it was the last year. For new and perhaps more casual
developers who cannot afford to follow along closely, this is a problem.
How do we expect them to become productive while also avoiding potential
stumbling blocks?&lt;/p&gt;
&lt;p&gt;You have to understand C. You have to understand the kernel. You have
to understand the verifier and what it tries to tell you. There is a lot
to understand and no one good place to learn it all. Reading the kernel
selftests is not a good answer for someone who is not involved with
kernel development (consider how you’d explain making and running a
change). Sure, there are some BPF books these days. But they’re out of
date as soon as the ink is dry.&lt;/p&gt;
&lt;p&gt;There is, however, precedence for solving this problem. Take a look
at the Rust &lt;a href=&quot;https://doc.rust-lang.org/book/&quot;&gt;ecosystem&lt;/a&gt; of
&lt;a href=&quot;https://doc.rust-lang.org/cargo/&quot;&gt;community&lt;/a&gt; maintained &lt;a
href=&quot;https://doc.rust-lang.org/rustc/what-is-rustc.html&quot;&gt;books&lt;/a&gt;.
They’re all version controlled and contributions are made through pull
requests. A large, gaping hole exists in the BPF ecosystem for such a
community maintained book. Having an open book allows us all to share
best practices as well as learned experience and keep it up to date over
time. It’d be in a digestible format – something someone new can read
cover to cover and feel up to speed.&lt;/p&gt;
&lt;p&gt;Yeah, it’s a lot of work. But I’m pretty sure it’d be worth it.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Sudo and signal propagation</title><id>https://dxuuu.xyz/sudo.html</id><updated>2023-05-27T10:11:23-07:00</updated><link href="https://dxuuu.xyz/sudo.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Sudo and signal propagation&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Sudo and signal propagation&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This week I spent some time debugging a curious case where signals
were not being delivered to a &lt;code&gt;sudo&lt;/code&gt;’ed process.&lt;/p&gt;
&lt;p&gt;Consider this shell script:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/bash

sudo timeout 5 dd if=/dev/urandom of=/dev/null &amp;amp;
sudo_pid=$!
sudo kill $sudo_pid

if ps -p $sudo_pid &amp;amp;&amp;gt;/dev/null; then
  echo Still running
else
  echo Dead
fi&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What should be printed? If you guessed “Dead”, then you would be
correct:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./sudo_kill.sh
Dead&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, when run in CI, I was seeing the opposite. The following is
run from a recreated CI environment (through docker):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker@cd71223430f4$ ./sudo_kill.sh
Still running&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;signal-propagation&quot;&gt;Signal propagation&lt;/h2&gt;
&lt;p&gt;Before going deeper, we need a little background on how
&lt;code&gt;sudo&lt;/code&gt; handles signals.&lt;/p&gt;
&lt;p&gt;According to the man page:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When the command is run as a child of the sudo process, sudo will
relay signals it receives to the command. The SIGINT and SIGQUIT signals
are only relayed when the command is being run in a new pty or when the
signal was sent by a user process, not the kernel. This prevents the
command from receiving SIGINT twice each time the user enters control-C.
Some signals, such as SIGSTOP and SIGKILL, cannot be caught and thus
will not be relayed to the command.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This makes sense. Signals need to be relayed by &lt;code&gt;sudo&lt;/code&gt; to
the process it’s managing. Otherwise, scripts would need to calculate
the child PID or send signals to the appropriate process group (a rather
arcane concept). It is much simpler to run a backgrounded
&lt;code&gt;sudo&lt;/code&gt; instance and send signals to &lt;code&gt;$!&lt;/code&gt; (as we
did in the test script).&lt;/p&gt;
&lt;p&gt;However, there are some drawbacks to this approach. The documentation
goes on to say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As a special case, sudo will not relay signals that were sent by the
command it is running. This prevents the command from accidentally
killing itself. On some systems, the reboot(8) utility sends SIGTERM to
all non-system processes other than itself before rebooting the system.
This prevents sudo from relaying the SIGTERM signal it received back to
reboot(8), which might then exit before the system was actually
rebooted, leaving it in a half-dead state similar to single user
mode.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;While this note is not directly related to our curious issue (b/c we
are not getting &lt;code&gt;dd&lt;/code&gt; to send signals), it is important to
note there are special cases carved out.&lt;/p&gt;
&lt;h2 id=&quot;changes-in-sudo&quot;&gt;Changes in sudo&lt;/h2&gt;
&lt;p&gt;Keeping in mind the aforementioned signal propagation corner cases,
the obvious suspect is a change in &lt;code&gt;sudo&lt;/code&gt;. From comparing the
local version to the CI version (&lt;code&gt;1.9.13p2&lt;/code&gt; vs
&lt;code&gt;1.8.21p2&lt;/code&gt;), we discover &lt;a
href=&quot;https://www.sudo.ws/repos/sudo/rev/d1bf60eac57f&quot;&gt;this commit&lt;/a&gt;
which landed in &lt;code&gt;1.9.13p1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The old behavior (before the change) was to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Only forward user-generated signals not sent by a process in the
command’s own process group. […]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This explains the discrepancy we saw earlier. &lt;code&gt;bash&lt;/code&gt; runs
all the commands in the script in the same process group, so
&lt;code&gt;kill&lt;/code&gt;’s signals were being ignored by &lt;code&gt;sudo&lt;/code&gt; b/c
&lt;code&gt;kill&lt;/code&gt; is in the same process group as &lt;code&gt;dd&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In my opinion this is surprising and unexpected, if only because this
behavior is undocumented. That being said, I did manage to find a zero
upvote &lt;a href=&quot;https://stackoverflow.com/a/68879134&quot;&gt;stack overflow&lt;/a&gt;
answer for a &lt;code&gt;setsid&lt;/code&gt; workaround. But I think that just
proves my point.&lt;/p&gt;
&lt;p&gt;Fortunately, as of November 2022, the new behavior is to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[…] forward signals from a process in the same pgrp if the pgrp
leader is not either sudo or the command itself. […]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;which fixes the script use case and obviates the need for a
&lt;code&gt;setsid&lt;/code&gt; workaround.&lt;/p&gt;
&lt;h2 id=&quot;complexity&quot;&gt;Complexity&lt;/h2&gt;
&lt;p&gt;I had remarked a few months ago I was surprised &lt;a
href=&quot;https://github.com/sudo-project/sudo&quot;&gt;the sudo project&lt;/a&gt; has
over 12,000 commits. Now I am no longer surprised. Behind a rather
simple interface (from the common use case perspective) lies a mountain
of complexity. That being said, I’m still quite surprised it took &lt;a
href=&quot;https://www.sudo.ws/about/history/&quot;&gt;over 40 years&lt;/a&gt; for this
surprising and undocumented behavior to be fixed.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Kernel string overcopying</title><id>https://dxuuu.xyz/string-overcopy.html</id><updated>2023-06-09T19:45:52-07:00</updated><link href="https://dxuuu.xyz/string-overcopy.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Kernel string overcopying&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Kernel string overcopying&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;While on a long roadtrip the past weekend, I somehow remembered one
of the fun bugs I fixed in the kernel a couple years ago.&lt;/p&gt;
&lt;p&gt;A bug was reported to me about bpftrace: somehow there were duplicate
map entries for the same string key. So something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# bpftrace -e &amp;#39;...  END { print(@) }&amp;#39;
^C

@[asdf]: 1
@[asdf]: 2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At first glance, this seemed like a bpftrace bug. I remember being
confused for a few hours until finally narrowing down the issue to the
kernel. It turns out the kernel had an optimized &lt;code&gt;strncpy()&lt;/code&gt;
routine where instead of copying a single byte at a time and stopping
when it saw a zero (NUL), it was doing word-sized strides and stopping
whenever the word contained a NUL. This also meant that there could be
extra bytes copied &lt;em&gt;after&lt;/em&gt; the NUL. This actually works perfectly
fine for C use cases, but BPF is a slightly different environment and it
turns out it &lt;em&gt;does&lt;/em&gt; matter.&lt;/p&gt;
&lt;h3 id=&quot;bpf-maps&quot;&gt;BPF maps&lt;/h3&gt;
&lt;p&gt;BPF hash maps store arbitrarily sized keys and values. In other
words, they’re completely string agnostic. To simulate a string keyed
map, bpftrace creates the map with key size 64 bytes (configurable with
&lt;code&gt;BPFTRACE_STRLEN&lt;/code&gt; environment variable) and just shoves bytes
inside. Since the kernel map implementation is string-oblivious, any
hashing or comparison doesn’t stop at a NUL byte – it keeps going for
all 64 bytes.&lt;/p&gt;
&lt;p&gt;Herein lies the issue. The BPF map implementation calls into
&lt;code&gt;strncpy_from_user()&lt;/code&gt; which can overcopy. To C string
functions (eg. &lt;code&gt;strncmp()&lt;/code&gt;, &lt;code&gt;strnlen()&lt;/code&gt;), this is
all kosher. However for a string-oblivious hash table, semantically
equivalent strings can occupy different hash table entries.&lt;/p&gt;
&lt;h3 id=&quot;the-fix&quot;&gt;The fix&lt;/h3&gt;
&lt;p&gt;The fix was rather simple conceptually but took several iterations to
reach. Starting from &lt;a
href=&quot;https://github.com/torvalds/linux/commit/6fa6d28051e9&quot;&gt;&lt;code&gt;6fa6d28051e9 (&quot;lib/strncpy_from_user.c: Mask out bytes after NUL terminator.&quot;&lt;/code&gt;)&lt;/a&gt;,
the kernel’s &lt;code&gt;strncpy_from_user()&lt;/code&gt; masks out trailing bytes
after the NUL terminator.&lt;/p&gt;
&lt;p&gt;And since map keys should always start out zeroed, the above fix
solves the issue.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>bpfilter is forever</title><id>https://dxuuu.xyz/bpfilter.html</id><updated>2023-07-29T19:19:19-07:00</updated><link href="https://dxuuu.xyz/bpfilter.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;bpfilter is forever&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;bpfilter is forever&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This week it was brought to my attention that &lt;code&gt;bpfilter&lt;/code&gt;
might be delaying our kernel boot sequence. The initial thought was that
bpfilter’s usermode upcalls were stalled for some reason and caused boot
time stalls.&lt;/p&gt;
&lt;p&gt;While it is true that module initialization for built-in modules (ie.
&lt;code&gt;CONFIG_FOO=y&lt;/code&gt;) is serialized and that in theory it is
possible for the boot to be stalled if a module was slow, it turned out
not to be the case for bpfilter, as we had
&lt;code&gt;CONFIG_BPFILTER_UMH=m&lt;/code&gt; which actually causes
&lt;code&gt;bpfilter.ko&lt;/code&gt; to be built and loaded separately.&lt;/p&gt;
&lt;p&gt;So end of story, at least for the important side of the
investigation.&lt;/p&gt;
&lt;h3 id=&quot;mystery-reloads&quot;&gt;Mystery reloads&lt;/h3&gt;
&lt;p&gt;While debugging the above, I unloaded and loaded
&lt;code&gt;bpfilter.ko&lt;/code&gt; a lot. After one &lt;code&gt;modprobe -r&lt;/code&gt;, I
noticed that bpfilter was reloaded without my involvement. It looked
like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo modprobe -r bpfilter
$ lsmod | grep bpf
$ lsmod | grep bpf
$ lsmod | grep bpf
$ lsmod | grep bpf
$ lsmod | grep bpf
$ lsmod | grep bpf
$ lsmod | grep bpf
lsmod | grep bpf
bpfilter               24576  0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No good investigation is without a rabbit hole, so naturally I
fixated on this.&lt;/p&gt;
&lt;p&gt;The first thing I checked was &lt;a
href=&quot;https://www.freedesktop.org/software/systemd/man/modules-load.d.html&quot;&gt;&lt;code&gt;modules-load.d&lt;/code&gt;&lt;/a&gt;
and &lt;a
href=&quot;https://man7.org/linux/man-pages/man5/modprobe.d.5.html&quot;&gt;&lt;code&gt;modprobe.d&lt;/code&gt;&lt;/a&gt;.
A thorough &lt;code&gt;grep&lt;/code&gt; of the relevant directories for choice
keywords like “bpf” or “bpfilter” turned up nothing. That was all I had
for top-down approaches so I moved to bottom-up.&lt;/p&gt;
&lt;h3 id=&quot;luckily-we-have-bpftrace&quot;&gt;Luckily we have bpftrace&lt;/h3&gt;
&lt;p&gt;I had poked around the kernel module subsystem a few weeks back for
an unrelated task so I knew about the entry and exit points:
&lt;code&gt;init_module(2)&lt;/code&gt;, &lt;code&gt;finit_module(2)&lt;/code&gt;, and
&lt;code&gt;delete_module(2)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Knowing that, it’s a simple matter of writing a one-liner to monitor
those system calls:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -e &amp;#39;t:syscalls:sys_enter_*module { printf(&amp;quot;%s: comm=%s\n&amp;quot;, probe, comm) }&amp;#39; &amp;amp;
$ sudo modprobe -r bpfilter
tracepoint:syscalls:sys_enter_delete_module: comm=modprobe
tracepoint:syscalls:sys_enter_finit_module: comm=modprobe&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So something is calling &lt;code&gt;modprobe&lt;/code&gt;. I was halfway through
writing a wrapper script to stash the parent’s &lt;code&gt;comm&lt;/code&gt; in a
file when I remembered that bpfilter will call
&lt;code&gt;request_module()&lt;/code&gt; in certain cases.&lt;/p&gt;
&lt;p&gt;For the uninitiated, &lt;code&gt;request_module()&lt;/code&gt; is a kernel
function that requests userspace load a particular kernel module.
Internally, it performs an upcall to userspace’s
&lt;code&gt;modprobe(8)&lt;/code&gt; – exactly the sort of thing we might have seen
above.&lt;/p&gt;
&lt;p&gt;Indeed, &lt;code&gt;net/ipv4/bpfilter/sockopt.c&lt;/code&gt; confirms this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;15&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 14;&quot;&gt;&lt;span id=&quot;function-15&quot;&gt;&lt;a href=&quot;#function-15&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; bpfilter_mbox_request&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; sock &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;sk&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; optname&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; sockptr_t optval&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-16&quot;&gt;&lt;a href=&quot;#function-16&quot;&gt;&lt;/a&gt;                                 &lt;span class=&quot;dt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; optlen&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;bool&lt;/span&gt; is_set&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-17&quot;&gt;&lt;a href=&quot;#function-17&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-18&quot;&gt;&lt;a href=&quot;#function-18&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; err&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-19&quot;&gt;&lt;a href=&quot;#function-19&quot;&gt;&lt;/a&gt;        mutex_lock&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;bpfilter_ops&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;lock&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-20&quot;&gt;&lt;a href=&quot;#function-20&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;bpfilter_ops&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;sockopt&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-21&quot;&gt;&lt;a href=&quot;#function-21&quot;&gt;&lt;/a&gt;                mutex_unlock&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;bpfilter_ops&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;lock&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-22&quot;&gt;&lt;a href=&quot;#function-22&quot;&gt;&lt;/a&gt;                request_module&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;bpfilter&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-23&quot;&gt;&lt;a href=&quot;#function-23&quot;&gt;&lt;/a&gt;                mutex_lock&lt;span class=&quot;op&quot;&gt;(&amp;amp;&lt;/span&gt;bpfilter_ops&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;lock&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-24&quot;&gt;&lt;a href=&quot;#function-24&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-25&quot;&gt;&lt;a href=&quot;#function-25&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(!&lt;/span&gt;bpfilter_ops&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;sockopt&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-26&quot;&gt;&lt;a href=&quot;#function-26&quot;&gt;&lt;/a&gt;                        err &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;ENOPROTOOPT&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-27&quot;&gt;&lt;a href=&quot;#function-27&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;cf&quot;&gt;goto&lt;/span&gt; out&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-28&quot;&gt;&lt;a href=&quot;#function-28&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-29&quot;&gt;&lt;a href=&quot;#function-29&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-30&quot;&gt;&lt;a href=&quot;#function-30&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-31&quot;&gt;&lt;a href=&quot;#function-31&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-32&quot;&gt;&lt;a href=&quot;#function-32&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;bpfilter_mbox_request()&lt;/code&gt; is called from both the
&lt;code&gt;getsockopt(2)&lt;/code&gt; and &lt;code&gt;setsockopt(2)&lt;/code&gt; codepaths.
Since &lt;code&gt;getsockopt()&lt;/code&gt; seemed like a more common codepath, I
further traced there:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -e &amp;#39;k:bpfilter_ip_get_sockopt { printf(&amp;quot;comm=%s\n kstack=\n%s\n&amp;quot;, comm, kstack) }&amp;#39;
Attaching 1 probe...
comm=iptables
kstack=

        bpfilter_ip_get_sockopt+1
        raw_getsockopt+52
        sock_common_getsockopt+26
        __sys_getsockopt+181
        __x64_sys_getsockopt+36
        do_syscall_64+87
        entry_SYSCALL_64_after_hwframe+6
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, I didn’t even have to unload the module! It turns out
&lt;code&gt;iptables&lt;/code&gt; was regularly calling
&lt;code&gt;getsockopt(2)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now the question is why iptables is talking to bpfilter. bpfilter
literally has no functionality, so it does not make sense for iptables
to use it. To answer this, we must look further up the call stack to
where &lt;code&gt;getsockopt()&lt;/code&gt; is dispatched to
&lt;code&gt;bpfilter_ip_get_sockopt()&lt;/code&gt; – in
&lt;code&gt;net/ipv4/ip_sockglue.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;function&quot; data-startFrom=&quot;1803&quot;&gt;&lt;pre
class=&quot;sourceCode numberSource c numberLines&quot;&gt;&lt;code class=&quot;sourceCode c&quot; style=&quot;counter-reset: source-line 1802;&quot;&gt;&lt;span id=&quot;function-1803&quot;&gt;&lt;a href=&quot;#function-1803&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; ip_getsockopt&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;struct&lt;/span&gt; sock &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;sk&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; level&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1804&quot;&gt;&lt;a href=&quot;#function-1804&quot;&gt;&lt;/a&gt;                  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; optname&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; __user &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;optval&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; __user &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;optlen&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1805&quot;&gt;&lt;a href=&quot;#function-1805&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1806&quot;&gt;&lt;a href=&quot;#function-1806&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; err&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1807&quot;&gt;&lt;a href=&quot;#function-1807&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-1808&quot;&gt;&lt;a href=&quot;#function-1808&quot;&gt;&lt;/a&gt;        err &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; do_ip_getsockopt&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;sk&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; level&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; optname&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1809&quot;&gt;&lt;a href=&quot;#function-1809&quot;&gt;&lt;/a&gt;                               USER_SOCKPTR&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;optval&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; USER_SOCKPTR&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;optlen&lt;span class=&quot;op&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1810&quot;&gt;&lt;a href=&quot;#function-1810&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-1811&quot;&gt;&lt;a href=&quot;#function-1811&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#if IS_ENABLED(CONFIG_BPFILTER_UMH)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1812&quot;&gt;&lt;a href=&quot;#function-1812&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;optname &lt;span class=&quot;op&quot;&gt;&amp;gt;=&lt;/span&gt; BPFILTER_IPT_SO_GET_INFO &lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1813&quot;&gt;&lt;a href=&quot;#function-1813&quot;&gt;&lt;/a&gt;            optname &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; BPFILTER_IPT_GET_MAX&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1814&quot;&gt;&lt;a href=&quot;#function-1814&quot;&gt;&lt;/a&gt;                err &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; bpfilter_ip_get_sockopt&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;sk&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; optname&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; optval&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; optlen&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1815&quot;&gt;&lt;a href=&quot;#function-1815&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#endif&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1816&quot;&gt;&lt;a href=&quot;#function-1816&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#ifdef CONFIG_NETFILTER&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1817&quot;&gt;&lt;a href=&quot;#function-1817&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;/* we need to exclude all possible ENOPROTOOPTs except default case */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1818&quot;&gt;&lt;a href=&quot;#function-1818&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;err &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;ENOPROTOOPT &lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; optname &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; IP_PKTOPTIONS &lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1819&quot;&gt;&lt;a href=&quot;#function-1819&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;op&quot;&gt;!&lt;/span&gt;ip_mroute_opt&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;optname&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1820&quot;&gt;&lt;a href=&quot;#function-1820&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; len&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1821&quot;&gt;&lt;a href=&quot;#function-1821&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-1822&quot;&gt;&lt;a href=&quot;#function-1822&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;get_user&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;len&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; optlen&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1823&quot;&gt;&lt;a href=&quot;#function-1823&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;EFAULT&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1824&quot;&gt;&lt;a href=&quot;#function-1824&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;function-1825&quot;&gt;&lt;a href=&quot;#function-1825&quot;&gt;&lt;/a&gt;                err &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; nf_getsockopt&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;sk&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; PF_INET&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; optname&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; optval&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;len&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1826&quot;&gt;&lt;a href=&quot;#function-1826&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;err &lt;span class=&quot;op&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1827&quot;&gt;&lt;a href=&quot;#function-1827&quot;&gt;&lt;/a&gt;                        err &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; put_user&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;len&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; optlen&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1828&quot;&gt;&lt;a href=&quot;#function-1828&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; err&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1829&quot;&gt;&lt;a href=&quot;#function-1829&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1830&quot;&gt;&lt;a href=&quot;#function-1830&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#endif&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1831&quot;&gt;&lt;a href=&quot;#function-1831&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; err&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;function-1832&quot;&gt;&lt;a href=&quot;#function-1832&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Fortunately the code here is pretty simple: &lt;code&gt;optname&lt;/code&gt; must
be in the range
&lt;code&gt;[BPFFILTER_IPT_SO_GET_INFO, BPFILTER_IPT_GET_MAX)&lt;/code&gt; for our
fateful function to be called. Another quick trace gives us there raw
values:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -e &amp;#39;k:bpfilter_ip_get_sockopt { printf(&amp;quot;comm=%s\n optname=%d\n ustack=%s\n kstack=%s\n&amp;quot;, comm, arg1, ustack, kstack) }&amp;#39;
Attaching 1 probe...
comm=iptables
 optname=64
 ustack=
        0x7fa0acd7783a

 kstack=
        bpfilter_ip_get_sockopt+1
        raw_getsockopt+52
        sock_common_getsockopt+26
        __sys_getsockopt+181
        __x64_sys_getsockopt+36
        do_syscall_64+87
        entry_SYSCALL_64_after_hwframe+68&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From here, it was basic due dilligence to check the values of
&lt;code&gt;BPFFILTER_IPT_SO_GET_INFO&lt;/code&gt; and
&lt;code&gt;BPFILTER_IPT_GET_MAX&lt;/code&gt; to see if:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;The range contains 64&lt;/li&gt;
&lt;li&gt;If the range is shared with any iptables sockopts&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Some quick grepping gives us the (abbreviated) definitions:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#define IPT_BASE_CTL            &lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;64&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#define IPT_SO_GET_INFO         &lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;IPT_BASE_CTL&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        BPFILTER_IPT_SO_GET_INFO &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        BPFILTER_IPT_GET_MAX&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So there you have it. bpfilter deliberately overlaps the iptables
sockopt optname ranges. Probably so &lt;code&gt;iptables(8)&lt;/code&gt; (the CLI)
can be transparently used with the bpfilter backend. Unfortunately as a
result of this design, if &lt;code&gt;CONFIG_BPFILTER=y&lt;/code&gt;, then
&lt;code&gt;bpfilter_ip_get_sockopt()&lt;/code&gt; is unconditionally called when
iptables &lt;code&gt;getsockopt(2)&lt;/code&gt;/&lt;code&gt;setsockopt(2)&lt;/code&gt; is used.
And this triggers our module reloads. Unfortunate, understandable, and
relatively harmless.&lt;/p&gt;
&lt;h3 id=&quot;the-obvious-question&quot;&gt;The obvious question&lt;/h3&gt;
&lt;p&gt;Astute readers will have already wondered: why do you build kernels
with &lt;code&gt;CONFIG_BPFILTER=y&lt;/code&gt; if bpfilter does not currently
contain any functionality?&lt;/p&gt;
&lt;p&gt;Well, that’s a question for Ubuntu:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ vagrant init ubuntu/jammy64
$ vagrant up
[...]
$ vagrant ssh
vagrant@ubuntu-jammy:~$ uname -r
5.15.0-76-generic
vagrant@ubuntu-jammy:~$ grep CONFIG_BPFILTER /boot/config-$(uname -r)
CONFIG_BPFILTER=y
CONFIG_BPFILTER_UMH=m&lt;/code&gt;&lt;/pre&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Revamping bpftrace’s CI with Nix</title><id>https://dxuuu.xyz/bpftrace-nix.html</id><updated>2023-09-04T22:07:59-07:00</updated><link href="https://dxuuu.xyz/bpftrace-nix.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Revamping bpftrace’s CI with Nix&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Revamping bpftrace’s CI with Nix&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;I’ve been rewriting the bpftrace CI on-and-off the past few months.
Now that it’s nearly done, I thought it would be nice to sum up some of
the changes.&lt;/p&gt;
&lt;h3 id=&quot;previous-state&quot;&gt;Previous state&lt;/h3&gt;
&lt;p&gt;The previous iteration of the bpftrace CI relied heavily on Github
Actions and docker. Specifically, we had three major workflows: CI,
embedded, and code scanning.&lt;/p&gt;
&lt;p&gt;The CI workflow was the main workhorse – it built and tested bpftrace
across various combinations of LLVM version, distro base, and compiler
suite (ie GCC and clang).&lt;/p&gt;
&lt;p&gt;The embedded workflow was fairly similar to the CI workflow except
that it built bpftrace in semi-static configurations. In other words,
the bpftrace binary under test would be statically linked with the
exception of dynamic linking against glibc and/or llvm/clang. If the
tests passed, it would then push the semi-static binary up to &lt;a
href=&quot;https://quay.io/repository/iovisor/bpftrace?tab=tags&amp;amp;tag=latest&quot;&gt;quay.io&lt;/a&gt;
for end user consumption.&lt;/p&gt;
&lt;p&gt;The code scanning job has seen various iterations over the years
(from LGTM to CodeQL) but the basic premise has been the same: to scan
for known code smells or bugs.&lt;/p&gt;
&lt;h3 id=&quot;musings&quot;&gt;Musings&lt;/h3&gt;
&lt;p&gt;I was very happy with Github Actions (GHA). The integration with
Github is obviously great and the free usage for open source projects is
killer. So I had very little desire to rip that out.&lt;/p&gt;
&lt;p&gt;The docker bits were a different story. Over time, we grew somewhat
of a &lt;a
href=&quot;https://github.com/iovisor/bpftrace/blob/f56caa0b655d4ae12965ece8da04987a24708162/docker/build.sh&quot;&gt;maze&lt;/a&gt;
of &lt;a
href=&quot;https://github.com/iovisor/bpftrace/blob/f56caa0b655d4ae12965ece8da04987a24708162/build-libs.sh&quot;&gt;build
scripts&lt;/a&gt; that our infra as well as our Dockerfiles would call into.
To make matters worse, almost all configuration was propagated through
environment variables, making adhoc analysis quite difficult. To top it
off, it was &lt;a
href=&quot;https://github.com/iovisor/bpftrace/blob/f56caa0b655d4ae12965ece8da04987a24708162/.github/workflows/ci.yml#L148-L191&quot;&gt;not
very user friendly&lt;/a&gt; to run the CI configuration locally.&lt;/p&gt;
&lt;p&gt;While I’ll grant it would’ve been possible to refactor the docker
setup so that it was more user friendly, it still had the unavoidable
drawback that binaries built inside the container could not be easily
run on the root host. This adds friction to the development
experience.&lt;/p&gt;
&lt;p&gt;The final pain point we had was the embedded builds. The embedded
builds were awesome for our users – a single binary that could run on
almost any linux system. That had nice properties like being able to
&lt;code&gt;curl&lt;/code&gt; it onto a host you’re debugging without worrying if
the distro had packaged the latest version of bpftrace yet. The drawback
was that it was nearly impossible to maintain. Dale Hamel did
tremendously valuable work years ago adding it, but unfortunately time
has shown it was nearly impossible for the maintainers to keep up.
Static C++ binaries are notoriously difficult to build. LLVM is
notoriously difficult to integrate and keep up with. Combine both
together and you have a serious problem. Since most of the maintainers
are volunteers, we simply could not do it.&lt;/p&gt;
&lt;h3 id=&quot;enter-nix&quot;&gt;Enter Nix&lt;/h3&gt;
&lt;p&gt;I had not planned on Nix fixing all these problems. Originally it was
an experiment for me to learn some new tech. But as I kept
experimenting, I realized Nix had a lot of awesome properties. I won’t
go into how I arrived at the solutions – it was an uninteresting
combination of curiosity and long walks. Rather, I’ll lay out how it all
fits together.&lt;/p&gt;
&lt;p&gt;At the center of it all is the &lt;a
href=&quot;https://github.com/iovisor/bpftrace/blob/e32fdb3af87ea9afc571e8df626e9172ef322c3c/flake.nix&quot;&gt;bpftrace
flake&lt;/a&gt;. A &lt;a href=&quot;https://nixos.wiki/wiki/Flakes&quot;&gt;flake&lt;/a&gt; is a Nix
feature that enables deterministic configuration and builds of software.
Inside our &lt;code&gt;flake.nix&lt;/code&gt;, we define various bpftrace
configurations. The main variable we change is the LLVM version, as it’s
the most component bpftrace needs to integrate with. We also define
pinned versions of &lt;code&gt;bcc&lt;/code&gt; and &lt;code&gt;libbpf&lt;/code&gt; as they are
the other core bpftrace dependencies.&lt;/p&gt;
&lt;p&gt;The flake immediately solves the developer experience problem. A new
bpftrace developer can simply install nix and run &lt;code&gt;nix build&lt;/code&gt;
to get a fully working bpftrace binary. There are also other &lt;a
href=&quot;https://github.com/iovisor/bpftrace/blob/e32fdb3af87ea9afc571e8df626e9172ef322c3c/docs/nix.md&quot;&gt;convenient
features&lt;/a&gt; like developer shells that allow for more incremental
builds and easy debugging. The nice thing is that all binaries built
under Nix can run on the root host (not that there was ever a non-root
host involved).&lt;/p&gt;
&lt;p&gt;Next is CI. To make running CI configurations easier locally, I wrote
a &lt;a
href=&quot;https://github.com/iovisor/bpftrace/blob/e32fdb3af87ea9afc571e8df626e9172ef322c3c/.github/include/ci.py&quot;&gt;dependency-free
python script&lt;/a&gt; that mirrored all the previously existing CI features.
The most salient bit of the python script (and the part that took the
longest to figure out) is &lt;a
href=&quot;https://github.com/iovisor/bpftrace/blob/e32fdb3af87ea9afc571e8df626e9172ef322c3c/.github/include/ci.py#L89-L142&quot;&gt;the
code&lt;/a&gt; that runs commands &lt;em&gt;inside&lt;/em&gt; the Nix “environment”:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre
class=&quot;sourceCode python&quot;&gt;&lt;code class=&quot;sourceCode python&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;def&lt;/span&gt; shell(&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cmd: List[&lt;span class=&quot;bu&quot;&gt;str&lt;/span&gt;],&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    as_root: &lt;span class=&quot;bu&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    cwd: Optional[Path] &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;None&lt;/span&gt;,&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    env: Optional[Dict[&lt;span class=&quot;bu&quot;&gt;str&lt;/span&gt;, &lt;span class=&quot;bu&quot;&gt;str&lt;/span&gt;]] &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;None&lt;/span&gt;,&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;):&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;    Runs the specified command in the proper nix development&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;    environment.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;    Note that output is sent to our inherited stderr/stdout and&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;    that any errors immediately raise an exception.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    [..]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With &lt;code&gt;ci.py&lt;/code&gt; in place, all the workflow does is:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre
class=&quot;sourceCode yaml&quot;&gt;&lt;code class=&quot;sourceCode yaml&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; &lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; actions/checkout@v2&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; &lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; DeterminateSystems/nix-installer-action@v4&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; &lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; DeterminateSystems/magic-nix-cache-action@v2&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; &lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; Load kernel modules&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;      # nf_tables and xfs are necessary for testing kernel modules BTF support&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;fu&quot;&gt;      run&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        sudo modprobe nf_tables&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        sudo modprobe xfs&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; &lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; Build and test&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; ${{matrix.env}}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;at&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;at&quot;&gt; ./.github/include/ci.py&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And to run a basic CI configuration locally:&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ NIX_TARGET=.#bpftrace-llvm10  ./.github/include/ci.py&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Full reproduction instructions are documented &lt;a
href=&quot;https://github.com/iovisor/bpftrace/blob/e32fdb3af87ea9afc571e8df626e9172ef322c3c/docs/developers.md#debugging-ci-failures&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;appimages&quot;&gt;Appimages&lt;/h3&gt;
&lt;p&gt;The embedded builds required a bit more lateral thinking. Semi-static
builds were clearly not tenable, so they were out. But we still need to
give users a replacement. At the end of the day, we can’t screw our
users just to make maintenance easier.&lt;/p&gt;
&lt;p&gt;Fortunately, I had learned about &lt;a
href=&quot;https://appimage.org/&quot;&gt;AppImage&lt;/a&gt;s recently. &lt;a
href=&quot;https://blogs.gnome.org/tvb/2013/12/10/application-bundles-for-glade/&quot;&gt;This&lt;/a&gt;
is a particularly well written motivation on the topic if you’re not
already familiar. The make matters even better, there already exists Nix
support for appimage builds in the form of &lt;a
href=&quot;https://github.com/ralismark/nix-appimage&quot;&gt;nix-appimage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nix and appimages are a well-made match. Basically what a nix
appimage does is bundle a binary and all its runtime dependencies inside
a squashfs image. It then prepends to the image a statically linked
entrypoint binary that handles mounting the concatenated squashfs image
through &lt;a href=&quot;https://github.com/vasi/squashfuse&quot;&gt;squashfuse&lt;/a&gt;.
Once the image is mounted, control is transferred to the
&lt;code&gt;apprun&lt;/code&gt; binary which bind mounts the Nix store in a mount
namespace at the places the final binary expects and then runs the final
binary.&lt;/p&gt;
&lt;p&gt;To drive the elegance home, consider the &lt;a
href=&quot;https://github.com/iovisor/bpftrace/commit/e32fdb3af87ea9afc571e8df626e9172ef322c3c&quot;&gt;commit
adding support to bpftrace&lt;/a&gt;. With support merged, the following is
all you need to locally build a fully static bpftrace binary:&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ nix build .#appimage
$ ldd ./result
        not a dynamic executable
$ sudo ./result -e &amp;#39;BEGIN { print(&amp;quot;static!&amp;quot;); exit() }&amp;#39;
Attaching 1 probe...
static!&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this, we can &lt;a
href=&quot;https://github.com/iovisor/bpftrace/pull/2742&quot;&gt;delete&lt;/a&gt; the
embedded workflow and start shipping appimages instead.&lt;/p&gt;
&lt;h3 id=&quot;codeql&quot;&gt;CodeQL&lt;/h3&gt;
&lt;p&gt;Last but not least is the code scanning. The previous code scanning
workflow installed all the requisite build dependencies on the root host
and then ran the standard cmake build. That was fine, but it was a
separate maintenance path.&lt;/p&gt;
&lt;p&gt;This &lt;a
href=&quot;https://github.com/iovisor/bpftrace/commit/529ef55e7fa64f23eb734f984a6d4867eabd071b&quot;&gt;commit&lt;/a&gt;
brings Nix to the workflow. Note how we can leverage the bpftrace flake
while at the same time making things simpler.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Like I mentioned earlier, while my Nix journey started off as an
experiment, it eventually proved to be useful beyond my wildest
imagination. With one new small file we now control developer
experience, continuous integration, and binary artifacts. All while
greatly reducing maintenance burden.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>AppImage explosions</title><id>https://dxuuu.xyz/appimage.html</id><updated>2023-09-13T06:40:45-07:00</updated><link href="https://dxuuu.xyz/appimage.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;AppImage explosions&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;AppImage explosions&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;In a &lt;a href=&quot;https://dxuuu.xyz/bpftrace-nix.html&quot;&gt;previous post&lt;/a&gt;,
I detailed how bpftrace’s CI was reworked to use Nix. As part of that
effort, the project-distributed semi-static binary was replaced with an
appimage. In this post I dive into an issue I had to debug.&lt;/p&gt;
&lt;h3 id=&quot;the-problem&quot;&gt;The problem&lt;/h3&gt;
&lt;p&gt;The first thing I did after building the appimage was try to run it.
&lt;code&gt;./result --help&lt;/code&gt; worked as expected.
&lt;code&gt;sudo bpftrace --info&lt;/code&gt; (a quick and dirty way to validate end
to end functionality) seemed to work as well. But shortly after, while
trying to open a new terminal, I was getting
&lt;code&gt;unable to allocate pty: No such device&lt;/code&gt; errors. This
resulted in a bit of head scratching. I don’t remember how I figured it
out, but eventually I noticed the mount table was all messed up.&lt;/p&gt;
&lt;p&gt;To be more specific, here is what was happening:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[vagrant@fedora vagrant]$ mount
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)
devtmpfs on /dev type devtmpfs (rw,nosuid,seclabel,size=997040k,nr_inodes=249260,mode=755,inode64)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,seclabel,inode64)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,seclabel,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,seclabel,size=404844k,nr_inodes=819200,mode=755,inode64)
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate,memory_recursiveprot)
pstore on /sys/fs/pstore type pstore (rw,nosuid,nodev,noexec,relatime,seclabel)
none on /sys/fs/bpf type bpf (rw,nosuid,nodev,noexec,relatime,mode=700)
/dev/sda1 on / type ext4 (rw,relatime,seclabel)
selinuxfs on /sys/fs/selinux type selinuxfs (rw,nosuid,noexec,relatime)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=36,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=14870)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime,seclabel)
debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime,seclabel)
tracefs on /sys/kernel/tracing type tracefs (rw,nosuid,nodev,noexec,relatime,seclabel)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,seclabel,pagesize=2M)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,seclabel,nr_inodes=409600,inode64)
fusectl on /sys/fs/fuse/connections type fusectl (rw,nosuid,nodev,noexec,relatime)
configfs on /sys/kernel/config type configfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,seclabel,size=202420k,nr_inodes=50605,mode=700,uid=1000,gid=1000,inode64)

[vagrant@fedora vagrant]$ sudo ./result --info &amp;amp;&amp;gt;/dev/null

[vagrant@fedora vagrant]$ mount
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime,seclabel)
devtmpfs on /dev type devtmpfs (rw,nosuid,seclabel,size=997040k,nr_inodes=249260,mode=755,inode64)
tmpfs on /run type tmpfs (rw,nosuid,nodev,seclabel,size=404844k,nr_inodes=819200,mode=755,inode64)
/dev/sda1 on / type ext4 (rw,relatime,seclabel)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,seclabel,nr_inodes=409600,inode64)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obviously this is not ok. &lt;code&gt;bpftrace&lt;/code&gt; tries very hard not
to mess up the host. After all, one of it its selling points is that you
can safely use it on a production host.&lt;/p&gt;
&lt;h3 id=&quot;whats-an-appimage-anyways&quot;&gt;What’s an AppImage anyways?&lt;/h3&gt;
&lt;p&gt;To the user, an appimage is a binary that looks and feels like a
statically linked binary. In fact, you’d have a hard time discovering a
binary is an appimage at all.&lt;/p&gt;
&lt;p&gt;At its core, an appimage is a squashfs image that contains an
application and all of its dependencies. Prepended to the binary is a
statically linked runtime that:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Knows where the squashfs image starts&lt;/li&gt;
&lt;li&gt;Mounts the squashfs image via squashfuse&lt;/li&gt;
&lt;li&gt;Transfers control to (yet another statically linked) entrypoint
binary inside the squashfs mount&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the case of &lt;code&gt;nix-appimage&lt;/code&gt;, this entrypoint binary
creates a new user and mount namespace. The user namespace is necessary
to perform privileged operations like mounting. If the appimage is being
run as root, the user namespace may be omitted.&lt;/p&gt;
&lt;p&gt;Inside the new mount namespace, the entrypoint binary then:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Mounts a tmpfs at the “mountroot”&lt;/li&gt;
&lt;li&gt;Bind mounts everything in the hosts’s root directory into
&lt;code&gt;$mountroot&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Bind mounts the embedded nix store to
&lt;code&gt;$mountroot/nix/store&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Chroot to the mountroot&lt;/li&gt;
&lt;li&gt;Transfers control to the (possibly dynamically linked) application
in the Nix store&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this way, the application’s dynamic linker can “just find” the
shared libraries without any additional &lt;code&gt;rpath&lt;/code&gt;
manipulation.&lt;/p&gt;
&lt;p&gt;As you can see, appimages integrate quite elegantly with Nix — it’s
fairly trivial with Nix to query and embed a derivation and all its
dependencies into a squashfs image.&lt;/p&gt;
&lt;h3 id=&quot;everyone-loves-printf&quot;&gt;Everyone loves printf&lt;/h3&gt;
&lt;p&gt;Back to the problem. The good news is that both the appimage runtime
and entrypoint binary amount to about 1000 lines of fairly
straightforward C. So it is easy to both debug and maintain if the need
arises.&lt;/p&gt;
&lt;p&gt;Since the mount logic was getting fancy, I figured it was a good
place to start debugging. After a few choice placements of
&lt;code&gt;system(&quot;cat /proc/self/mountinfo | column -t&quot;)&lt;/code&gt;s, I got the
following dump:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/            /                                                                                 shared:1
/            /sys                                                                              shared:2
/            /sys/kernel/security                                                              shared:3
/            /sys/fs/cgroup                                                                    shared:4
/            /sys/fs/pstore                                                                    shared:5
/            /sys/fs/bpf                                                                       shared:6
/            /sys/fs/selinux                                                                   shared:7
/            /sys/kernel/tracing                                                               shared:16
/            /sys/kernel/debug                                                                 shared:18
/            /sys/kernel/config                                                                shared:19
/            /sys/fs/fuse/connections                                                          shared:20
/            /dev                                                                              shared:8
/            /dev/shm                                                                          shared:9
/            /dev/pts                                                                          shared:10
/            /dev/hugepages                                                                    shared:14
/            /dev/mqueue                                                                       shared:15
/            /run                                                                              shared:11
/            /run/user/1000                                                                    shared:210
/            /proc                                                                             shared:12
/            /proc/sys/fs/binfmt_misc                                                          shared:13
/            /tmp                                                                              shared:17
/            /tmp/.FLCABm                                                                      shared:255
/            /tmp/.FLCABm/mountroot                                                            shared:350
/            /tmp/.FLCABm/mountroot/proc                                                       shared:12
/            /tmp/.FLCABm/mountroot/proc/sys/fs/binfmt_misc                                    shared:13
/usr/bin     /tmp/.FLCABm/mountroot/bin                                                        shared:1
/            /tmp/.FLCABm/mountroot/run                                                        shared:11
/            /tmp/.FLCABm/mountroot/run/user/1000                                              shared:210
/root        /tmp/.FLCABm/mountroot/root                                                       shared:1
/usr/lib64   /tmp/.FLCABm/mountroot/lib64                                                      shared:1
/media       /tmp/.FLCABm/mountroot/media                                                      shared:1
/home        /tmp/.FLCABm/mountroot/home                                                       shared:1
/vagrant     /tmp/.FLCABm/mountroot/vagrant                                                    shared:1
/opt         /tmp/.FLCABm/mountroot/opt                                                        shared:1
/mnt         /tmp/.FLCABm/mountroot/mnt                                                        shared:1
/lost+found  /tmp/.FLCABm/mountroot/lost+found                                                 shared:1
/srv         /tmp/.FLCABm/mountroot/srv                                                        shared:1
/            /tmp/.FLCABm/mountroot/sys                                                        shared:2
/            /tmp/.FLCABm/mountroot/sys/kernel/security                                        shared:3
/            /tmp/.FLCABm/mountroot/sys/fs/cgroup                                              shared:4
/            /tmp/.FLCABm/mountroot/sys/fs/pstore                                              shared:5
/            /tmp/.FLCABm/mountroot/sys/fs/bpf                                                 shared:6
/            /tmp/.FLCABm/mountroot/sys/fs/selinux                                             shared:7
/            /tmp/.FLCABm/mountroot/sys/kernel/tracing                                         shared:16
/            /tmp/.FLCABm/mountroot/sys/kernel/debug                                           shared:18
/            /tmp/.FLCABm/mountroot/sys/kernel/config                                          shared:19
/            /tmp/.FLCABm/mountroot/sys/fs/fuse/connections                                    shared:20
/usr         /tmp/.FLCABm/mountroot/usr                                                        shared:1
/            /tmp/.FLCABm/mountroot/tmp                                                        shared:17
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm                                    shared:255
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot                          shared:350
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/proc                     shared:12
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/proc/sys/fs/binfmt_misc  shared:13
/usr/bin     /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/bin                      shared:1
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/run                      shared:11
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/run/user/1000            shared:210
/root        /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/root                     shared:1
/usr/lib64   /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/lib64                    shared:1
/media       /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/media                    shared:1
/home        /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/home                     shared:1
/vagrant     /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/vagrant                  shared:1
/opt         /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/opt                      shared:1
/mnt         /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/mnt                      shared:1
/lost+found  /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/lost+found               shared:1
/srv         /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/srv                      shared:1
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys                      shared:2
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys/kernel/security      shared:3
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys/fs/cgroup            shared:4
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys/fs/pstore            shared:5
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys/fs/bpf               shared:6
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys/fs/selinux           shared:7
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys/kernel/tracing       shared:16
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys/kernel/debug         shared:18
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys/kernel/config        shared:19
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sys/fs/fuse/connections  shared:20
/usr         /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/usr                      shared:1
/            /tmp/.FLCABm/mountroot/dev                                                        shared:8
/            /tmp/.FLCABm/mountroot/dev/shm                                                    shared:9
/            /tmp/.FLCABm/mountroot/dev/pts                                                    shared:10
/            /tmp/.FLCABm/mountroot/dev/hugepages                                              shared:14
/            /tmp/.FLCABm/mountroot/dev/mqueue                                                 shared:15
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/dev                      shared:8
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/dev/shm                  shared:9
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/dev/pts                  shared:10
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/dev/hugepages            shared:14
/            /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/dev/mqueue               shared:15
/var         /tmp/.FLCABm/mountroot/var                                                        shared:1
/var         /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/var                      shared:1
/usr/sbin    /tmp/.FLCABm/mountroot/sbin                                                       shared:1
/usr/sbin    /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/sbin                     shared:1
/etc         /tmp/.FLCABm/mountroot/etc                                                        shared:1
/etc         /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/etc                      shared:1
/boot        /tmp/.FLCABm/mountroot/boot                                                       shared:1
/boot        /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/boot                     shared:1
/usr/lib     /tmp/.FLCABm/mountroot/lib                                                        shared:1
/usr/lib     /tmp/.FLCABm/mountroot/tmp/.mount_resultFLCABm/mountroot/lib                      shared:1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Note that I’ve trimmed some of the columns to make the output more
legible.)&lt;/p&gt;
&lt;p&gt;There are two problems to notice here.&lt;/p&gt;
&lt;p&gt;First is that we are sharing quite a few mounts with the root
namespace in peer group 1 (see &lt;code&gt;shared:1&lt;/code&gt; at the end of the
mount entries).&lt;/p&gt;
&lt;p&gt;Second is the “mount explosion” problem, as described in &lt;a
href=&quot;https://www.man7.org/linux/man-pages/man7/mount_namespaces.7.html&quot;&gt;&lt;code&gt;mount_namespaces(7)&lt;/code&gt;&lt;/a&gt;.
By virtue of iterating through the root namespace’s &lt;code&gt;/&lt;/code&gt;, the
entrypoint binary is recursively binding the root namespace’s mounts
into the new mount namespace over and over again.&lt;/p&gt;
&lt;h3 id=&quot;problem-1&quot;&gt;Problem 1&lt;/h3&gt;
&lt;p&gt;According to &lt;code&gt;mount_namespaces(7)&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This mount shares events with members of a peer group. mount(2) and
umount(2) events immediately under this mount will propagate to the
other mounts that are members of the peer group. Propagation here means
that the same mount(2) or umount(2) will automatically occur under all
of the other mounts in the peer group. Conversely, mount(2) and
umount(2) events that take place under peer mounts will propagate to
this mount.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, if a mount &lt;code&gt;M&lt;/code&gt; is shared in a peer group,
any events that occur &lt;em&gt;under&lt;/em&gt; &lt;code&gt;M&lt;/code&gt; are propagated to
all peers. This explains the host’s mounts were getting messed up after
the appimage exits. When the appimage exits, its FUSE mount is cleaned
up. This leads to all the mounts under the FUSE being unmounted. And
since these lower mounts are shared, the umount event is propagated to
the root namespace. Note that this would only occur for appimages run as
root — an unprivileged user namespace would not have sufficient
permissions to umount mounts from the root namespace.&lt;/p&gt;
&lt;p&gt;As for why the system doesn’t immediately crash, presumably mounts
which have any of their files still opened are not automatically
umounted.&lt;/p&gt;
&lt;p&gt;The fix is to rebind the mountroot as &lt;code&gt;MS_PRIVATE&lt;/code&gt;. This
prevents events from under the mountroot from propagating out.&lt;/p&gt;
&lt;h3 id=&quot;problem-2&quot;&gt;Problem 2&lt;/h3&gt;
&lt;p&gt;The second problem is the “mount explosion”. Granted, this is not a
critically important problem. It is, however, kinda ugly and probably
wastes resources. Fortunately the fix is simple: use
&lt;code&gt;MS_UNBINDABLE&lt;/code&gt; to prevent recursive mount explosion
problems.&lt;/p&gt;
&lt;p&gt;But what about the previous &lt;code&gt;MS_PRIVATE&lt;/code&gt; fix? The good
news is that the VFS developers have thought of that already!
&lt;code&gt;MS_UNBINDABLE&lt;/code&gt; is simply a more powerful
&lt;code&gt;MS_PRIVATE&lt;/code&gt;. Put differently: &lt;code&gt;MS_UNBINDABLE&lt;/code&gt; is
strictly additive.&lt;/p&gt;
&lt;p&gt;Two birds with one stone, as they say.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Appimages are quite an elegant mechanism in my opinion. They attempt
solve a difficult problem — how we ship increasingly complex software.
And they do it with relative simplicity w.r.t. lines of code. While this
bug was a little tricky to debug, it didn’t take much time at all b/c I
could hold all the code in my head.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Truthiness in C</title><id>https://dxuuu.xyz/casts.html</id><updated>2023-09-19T00:58:03-07:00</updated><link href="https://dxuuu.xyz/casts.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Truthiness in C&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Truthiness in C&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This week someone mentioned that C supports casting from
&lt;code&gt;int&lt;/code&gt; to &lt;code&gt;bool&lt;/code&gt;. That naturally triggered my
curiosity – what does the generated code look like?&lt;/p&gt;
&lt;p&gt;First I think it’s important to point out many casts in C are “free”.
“Free” in the sense that the compiler changes its internal understanding
of an expression. But in actual assembly nothing really changes –
registers don’t have types. (NB: architecture dependent)&lt;/p&gt;
&lt;p&gt;For example, consider:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; a&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; x&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;x&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; b&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; x&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;x&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;c&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;x&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*)&lt;/span&gt;x&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The generated code looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a(int):
        mov     eax, edi
        ret
b(char):
        movsx   eax, dil
        ret
c(int*):
        mov     rax, rdi
        ret&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clearly we are just moving values between the argument register and
the return register. So the cast is “free” (ignoring the sign extension
in &lt;code&gt;b&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;But what about casting from &lt;code&gt;int&lt;/code&gt; to
&lt;code&gt;bool&lt;/code&gt;?&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;bool&lt;/span&gt; d&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; x&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;x&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Well, the compiler gives us:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;d(int):
        test    edi, edi
        setne   al
        ret&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We see that it generates code to first &lt;code&gt;test eax&lt;/code&gt; and then
to &lt;code&gt;setne al&lt;/code&gt;. &lt;a
href=&quot;https://web.itu.edu.tr/kesgin/mul06/intel/instr/test.html&quot;&gt;&lt;code&gt;test&lt;/code&gt;&lt;/a&gt;
is used to set the status flags. &lt;a
href=&quot;https://web.itu.edu.tr/kesgin/mul06/intel/instr/setne_setnz.html&quot;&gt;&lt;code&gt;setne&lt;/code&gt;&lt;/a&gt;
is used to set the lowest 8 bit subregister in &lt;code&gt;rax&lt;/code&gt;.
&lt;code&gt;rax&lt;/code&gt; is used to &lt;a
href=&quot;https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI&quot;&gt;return
integer values&lt;/a&gt; from a function in the System V ABI.&lt;/p&gt;
&lt;p&gt;Note that the top 56 bits in &lt;code&gt;rax&lt;/code&gt; are not zeroed – they
contain junk. This is fine b/c the compiler will only make callers check
the lowest bit of a register for boolean operations. This is why
changing the compiler’s “understanding” (ie the cast) is necessary.&lt;/p&gt;
&lt;p&gt;So, two otherwise extra instructions. Not too bad for how useful it
is.&lt;/p&gt;
&lt;p&gt;See the full code &lt;a
href=&quot;https://godbolt.org/z/osTjnqnn9&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;errata&quot;&gt;Errata&lt;/h3&gt;
&lt;p&gt;Thanks thxg on HN for pointing out that I was incorrectly compiling
with &lt;code&gt;-m32&lt;/code&gt; but talking about x86-64.&lt;/p&gt;
&lt;p&gt;And also to AshamedCaptain for pointing out the x86 centered
assumptions.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Packet drop reasons</title><id>https://dxuuu.xyz/dropreason.html</id><updated>2023-09-19T02:17:36-07:00</updated><link href="https://dxuuu.xyz/dropreason.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Packet drop reasons&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Packet drop reasons&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Figuring out why the kernel is dropping packets can be challenging.
Fortunately, newer kernel releases contain &lt;code&gt;dropreason&lt;/code&gt;
infrastructure that can make the problem more tractable.&lt;/p&gt;
&lt;p&gt;We can easily tap into &lt;code&gt;dropreason&lt;/code&gt; by using bpftrace.
Consider this one-liner:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -e &amp;#39;tracepoint:skb:kfree_skb { printf(&amp;quot;%-18s %d\n&amp;quot;, comm, args-&amp;gt;reason); }&amp;#39;
Attaching 1 probe...
irq/160-iwlwifi    50
irq/160-iwlwifi    50
irq/160-iwlwifi    50
irq/170-iwlwifi    6
irq/170-iwlwifi    2
irq/160-iwlwifi    50
syncthing          6
syncthing          6
syncthing          6
irq/170-iwlwifi    6
irq/170-iwlwifi    2
irq/160-iwlwifi    50
irq/160-iwlwifi    50

^C&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we see some output. But what does &lt;code&gt;args-&amp;gt;reason&lt;/code&gt;
correspond to? Find out by querying the tracepoint arguments:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -lv &amp;#39;tracepoint:skb:kfree_skb&amp;#39;
tracepoint:skb:kfree_skb
    void * skbaddr
    void * location
    unsigned short protocol
    enum skb_drop_reason reason&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that we know it’s an &lt;code&gt;enum skb_drop_reason&lt;/code&gt;, query the
values of the enum with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -lv &amp;#39;enum skb_drop_reason&amp;#39;
enum skb_drop_reason {
        SKB_NOT_DROPPED_YET = 0,
        SKB_CONSUMED = 1,
        SKB_DROP_REASON_NOT_SPECIFIED = 2,
        SKB_DROP_REASON_NO_SOCKET = 3,
        SKB_DROP_REASON_PKT_TOO_SMALL = 4,
        SKB_DROP_REASON_TCP_CSUM = 5,
        SKB_DROP_REASON_SOCKET_FILTER = 6,
        SKB_DROP_REASON_UDP_CSUM = 7,
        SKB_DROP_REASON_NETFILTER_DROP = 8,
        SKB_DROP_REASON_OTHERHOST = 9,
        SKB_DROP_REASON_IP_CSUM = 10,
        SKB_DROP_REASON_IP_INHDR = 11,
        SKB_DROP_REASON_IP_RPFILTER = 12,
        SKB_DROP_REASON_UNICAST_IN_L2_MULTICAST = 13,
        [...]
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now suppose we are curious about the
&lt;code&gt;SKB_DROP_REASON_SOCKET_FILTER&lt;/code&gt; (6) drops. Let’s see where in
the kernel this is happening:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace -e &amp;#39;t:skb:kfree_skb / args-&amp;gt;reason == SKB_DROP_REASON_SOCKET_FILTER / { print(kstack) }&amp;#39;
Attaching 1 probe...

        kfree_skb_reason+143
        kfree_skb_reason+143
        rawv6_rcv+792
        raw6_local_deliver+269
        ip6_protocol_deliver_rcu+134
        ip6_input_finish+67
        ip6_mc_input+238
        ip6_sublist_rcv_finish+130
        ip6_sublist_rcv+552
        ipv6_list_rcv+319
        __netif_receive_skb_list_core+501
        netif_receive_skb_list_internal+465
        napi_complete_done+114
        iwl_pcie_napi_poll_msix+173
        __napi_poll+40
        net_rx_action+676
        __do_softirq+209
        do_softirq.part.0+95
        __local_bh_enable_ip+104
        iwl_pcie_irq_rx_msix_handler+205
        irq_thread_fn+32
        irq_thread+251
        kthread+229
        ret_from_fork+41
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives us a call stack in the kernel where the drop occurs. Now
the problem is within reach – we know where to start reading code.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Kernel IPIs</title><id>https://dxuuu.xyz/ipi.html</id><updated>2023-11-24T19:53:36-08:00</updated><link href="https://dxuuu.xyz/ipi.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Kernel IPIs&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Kernel IPIs&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;An &lt;a
href=&quot;https://en.wikipedia.org/wiki/Inter-processor_interrupt&quot;&gt;inter-processor
interrupt&lt;/a&gt; (IPI) is a way for one processor to signal to another
processor that some work needs to be done. I’m not sure why I got
curious about this today. But since I dug into it, I thought I’d write
it down.&lt;/p&gt;
&lt;h3 id=&quot;interface&quot;&gt;Interface&lt;/h3&gt;
&lt;p&gt;Since it looks like there’s quite a few IPI vectors, I narrowed down
the scope by only looking at a fairly general user:
&lt;code&gt;smp_call_function_single()&lt;/code&gt;. It helps that it has an
intuitive API:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;/*&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * smp_call_function_single - Run a function on a specific CPU&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * @func: The function to run. This must be fast and non-blocking.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * @info: An arbitrary pointer to pass to the function.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * @wait: If true, wait until function has completed on other CPUs.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; * Returns 0 on success, else a negative status code.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; smp_call_function_single&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; cpu&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; smp_call_func_t func&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;info&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; wait&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;where &lt;code&gt;smp_call_func_t&lt;/code&gt; is:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(*&lt;/span&gt;smp_call_func_t&lt;span class=&quot;op&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;info&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In otherwords, this API lets you run code on another processor.&lt;/p&gt;
&lt;h3 id=&quot;implementation&quot;&gt;Implementation&lt;/h3&gt;
&lt;p&gt;Since I and many others run x86-64, I’m only looked at the x86
codepaths. And to spare you the code walkthough, here is the rough call
chain instead:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;smp_call_function_single(cpu, ..)
    generic_exec_single(cpu, ..)
        __smp_call_single_queue(cpu, ..)
            llist_add(node, &amp;amp;per_cpu(call_single_queue, cpu))              /* (1) */
            send_call_function_single_ipi(cpu)
                arch_send_call_function_single_ipi(cpu)
                    native_send_call_func_single_ipi(cpu)
                        __apic_send_IPI(cpu, CALL_FUNCTION_SINGLE_VECTOR)  /* (2) */&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;(1)&lt;/code&gt; is the crucial part. Basically what’s happening is
that the calling CPU enqueues some data onto the target CPU’s percpu
queue. That’s why when &lt;code&gt;(2)&lt;/code&gt; returns void, this all still
makes sense - the target CPU will be interrupted and can then pull
functions off its queue to run.&lt;/p&gt;
&lt;p&gt;But just to confirm that theory, let’s check the target CPU
codepath.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CALL_FUNCTION_SINGLE_VECTOR&lt;/code&gt;, if you grep for it, is
mapped to the following handler:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;DECLARE_IDTENTRY_SYSVEC&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;CALL_FUNCTION_SINGLE_VECTOR&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;        sysvec_call_function_single&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;sysvec_call_function_single()&lt;/code&gt;’s call chain, in turn,
is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sysvec_call_function_single()
    generic_smp_call_function_single_interrupt()
        __flush_smp_call_function_queue(..)
            llist_for_each_entry_safe(..)
                csd_do_func(func, info, ..)
                    func(info)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s basically it. I’m sure there’s quite a bit more complexity
under the surface of this, but the high level view of the implementation
is fairly straightforward.&lt;/p&gt;
&lt;h3 id=&quot;aside&quot;&gt;Aside&lt;/h3&gt;
&lt;p&gt;I don’t know if it’s just me or not, but seeing and re-seeing
basically the same technique for running code on other CPUs is kind of a
mind bender. You see remotely appending to percpu queues quite often,
for example with BPF &lt;code&gt;cpumap&lt;/code&gt;’s &lt;code&gt;struct ptr_ring&lt;/code&gt;
data structure or with the core networking stack’s
&lt;code&gt;enqueue_to_backlog()&lt;/code&gt; as used by Receive Packet Steering
(RPS):&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        cpu &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; get_rps_cpu&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;skb&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;dev&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; skb&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;rflow&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;cpu &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                cpu &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; smp_processor_id&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        ret &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; enqueue_to_backlog&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;skb&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; cpu&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt;rflow&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;last_qtail&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In userspace you would typically use threads and queues and maybe
some kind of signaling mechanism like a semaphore to keep a thread
parked while waiting for data. I’d have thought in the kernel there was
a wildly different technique. But at some level, IPIs and the regular
userspace stuff are quite similar.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Pull request review: still files!</title><id>https://dxuuu.xyz/prr2.html</id><updated>2023-12-10T16:43:08-08:00</updated><link href="https://dxuuu.xyz/prr2.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Pull request review: still files!&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Pull request review: still files!&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;It’s been &lt;a href=&quot;https://dxuuu.xyz/prr.html&quot;&gt;about a year&lt;/a&gt; since
the core &lt;code&gt;prr&lt;/code&gt; features features went in. From my
perspective, one surprising thing is that there’s now a small group of
dedicated users who not only report bugs, but are also willing to
implement new features! Speaking for myself, the only thing better to a
maintainer than happy users are happy users who also send high quality
PRs.&lt;/p&gt;
&lt;p&gt;The following are some of the major features that myself or others
have added. And as always, reviews are still files!&lt;/p&gt;
&lt;h2 id=&quot;review-management&quot;&gt;Review management&lt;/h2&gt;
&lt;p&gt;There is now rudimentary support for review management. To get a
quick look at local state, run &lt;code&gt;prr-status&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ prr status
Handle                  Status     Review file
danobi/prr/18           NEW        /home/dxu/dev/review/danobi/prr/18.prr
danobi/prr/20           NEW        /home/dxu/dev/review/danobi/prr/20.prr
danobi/prr/33           NEW        /home/dxu/dev/review/danobi/prr/33.prr
danobi/prr-test-repo/3  SUBMITTED  /home/dxu/dev/review/danobi/prr-test-repo/3.prr
iovisor/bpftrace/2387   NEW        /home/dxu/dev/review/iovisor/bpftrace/2387.prr
iovisor/bpftrace/2392   REVIEWED   /home/dxu/dev/review/iovisor/bpftrace/2392.prr
iovisor/bpftrace/2397   NEW        /home/dxu/dev/review/iovisor/bpftrace/2397.prr
iovisor/bpftrace/2399   SUBMITTED  /home/dxu/dev/review/iovisor/bpftrace/2399.prr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On top of the existing &lt;code&gt;prr-submit&lt;/code&gt; you can now also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prr-apply&lt;/code&gt; to locally apply a review file to your
working directory&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prr-remove&lt;/code&gt; and to delete a review file&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;advanced-vim-integration-syntax-colors&quot;&gt;Advanced Vim integration
(syntax colors)&lt;/h2&gt;
&lt;p&gt;To enable advanced Vim integration, simply add this (or simliar) to
your plugin manager config:&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;Plugin &amp;#39;danobi/prr&amp;#39;, {&amp;#39;rtp&amp;#39;: &amp;#39;vim/&amp;#39;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can now control exactly what syntax colors are used down to a
fairly low level. This is relatively important for viewing diffs as
otherwise it’s visually difficult to pick out changes.&lt;/p&gt;
&lt;p&gt;For example, I have this in my &lt;code&gt;.vimrc&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;&amp;quot;Automatically set up highlighting for `.prr` review files
augroup Prr
  autocmd!
  autocmd BufRead,BufNewFile *.prr set syntax=on

  &amp;quot;Make prr added/deleted highlighting more apparent
  autocmd BufRead,BufNewFile *.prr hi! link prrAdded Function
  autocmd BufRead,BufNewFile *.prr hi! link prrRemoved Keyword
  autocmd BufRead,BufNewFile *.prr hi! link prrFile Special

  &amp;quot;Make file delimiters more apparent
  autocmd BufRead,BufNewFile *.prr hi! link prrHeader Directory

  &amp;quot;Reduce all the noise from color
  autocmd BufRead,BufNewFile *.prr hi! link prrIndex Special
  autocmd BufRead,BufNewFile *.prr hi! link prrChunk Special
  autocmd BufRead,BufNewFile *.prr hi! link prrChunkH Special
  autocmd BufRead,BufNewFile *.prr hi! link prrTagName Special
  autocmd BufRead,BufNewFile *.prr hi! link prrResult Special
augroup END&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and this is how my review files look:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/prr2/colors.png&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;advanced-vim-integration-diff-aware-folds&quot;&gt;Advanced Vim
integration (diff-aware folds)&lt;/h2&gt;
&lt;p&gt;Folds are useful in general. But for diff review they are extremely
powerful. If you install &lt;code&gt;prr&lt;/code&gt;’s Vim “plugin” (as shown
above), then this works out of the box.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;prr&lt;/code&gt; reviews, folds allow you to mark regions as
“done” for organization. For example, when I’m done reviewing a file in
a multi-file PR, I’ll close the file’s fold. You do this by putting your
cursor inside the file preamble hitting &lt;code&gt;za&lt;/code&gt; to toggle the
fold:&lt;/p&gt;
&lt;p&gt;So from this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/prr2/start.png&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;to this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/prr2/file_folded.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The same also works for hunks &lt;em&gt;inside&lt;/em&gt; a file. For example,
this shows the second hunk in &lt;code&gt;src/parser.rs&lt;/code&gt; as folded:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/prr2/hunk_folded.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Thanks &lt;a href=&quot;https://github.com/hauleth&quot;&gt;&lt;span class=&quot;citation&quot;
data-cites=&quot;hauleth&quot;&gt;@hauleth&lt;/span&gt;&lt;/a&gt; for adding better Vim
integration!&lt;/p&gt;
&lt;h2 id=&quot;file-level-comments&quot;&gt;File level comments&lt;/h2&gt;
&lt;p&gt;Github recently added the ability to comment on entire files.
&lt;code&gt;prr&lt;/code&gt; now also supports this functionality. A file level
comment might look something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; diff --git a/ch3.txt b/ch3.txt

file comment

&amp;gt; index 159cf1c..20814b6 100644
&amp;gt; --- a/ch3.txt
&amp;gt; +++ b/ch3.txt
&amp;gt; @@ -8,22 +8,6 @@ CHAPTER 3. ATTACK BY STRATAGEM
&amp;gt;                                                                                                               &amp;gt;  4. The rule is, not to besiege walled cities if it can possibly be avoided. The preparation of mantlets, movable shelters, and various implements of war, will take up three whole months; and the piling up of mounds over against the walls will take three months more.
&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When submitted, the web UI shows:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/prr2/file_comment.png&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Thanks &lt;a href=&quot;https://github.com/bcspragu&quot;&gt;&lt;span class=&quot;citation&quot;
data-cites=&quot;bcspragu&quot;&gt;@bcspragu&lt;/span&gt;&lt;/a&gt; for adding this!&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Innovative –help messages</title><id>https://dxuuu.xyz/innovate.html</id><updated>2023-12-24T14:02:24-08:00</updated><link href="https://dxuuu.xyz/innovate.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Innovative –help messages&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Innovative –help messages&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Last week I heard about how &lt;a href=&quot;https://ai.google.dev/&quot;&gt;Google
Gemini&lt;/a&gt; was offering a very generous free tier on their API. So
yesterday I wrote a small CLI application to interface with Gemini. It
took about 30 minutes to get something reasonable working. I was
satisfied - but something was missing.&lt;/p&gt;
&lt;p&gt;Fortunately, I woke up with an idea to innovate on a crusty old
staple of CLI applications: the help message. Most &lt;em&gt;boring&lt;/em&gt; CLI
applications would do something like this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode go&quot;&gt;&lt;code class=&quot;sourceCode go&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;func&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;// Handle help message&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; _&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; arg &lt;span class=&quot;op&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;range&lt;/span&gt; os&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Args &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; arg &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;-h&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;||&lt;/span&gt; arg &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;--help&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                        fmt&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Fprintf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;os&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Stderr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;llm [-][context]..&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Fast and reliable; who would want that? Bleh!&lt;/p&gt;
&lt;p&gt;Try this on for size instead:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode go&quot;&gt;&lt;code class=&quot;sourceCode go&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;//go:embed main.go&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;var&lt;/span&gt; src &lt;span class=&quot;dt&quot;&gt;string&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;func&lt;/span&gt; help&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;// Boring, non-innovate help message&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; innovate &lt;span class=&quot;op&quot;&gt;:=&lt;/span&gt; os&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Getenv&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;INNOVATE&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt; innovate &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                fmt&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Fprintf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;os&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Stderr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;llm [-][context]..&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;// Now we&amp;#39;re talking - it&amp;#39;s time to innovate&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        prompt &lt;span class=&quot;op&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;                Given the following go program that compiles to a binary titled&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;                &amp;#39;llm&amp;#39;, print out an appropriate --help message.  Your response&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;                should be human readable text suitable to immediately print to&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-16&quot;&gt;&lt;a href=&quot;#cb2-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;                terminal.  Do not use any code blocks or backticks.  Only show&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-17&quot;&gt;&lt;a href=&quot;#cb2-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;                short form help text which at minimum explains the positional&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-18&quot;&gt;&lt;a href=&quot;#cb2-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;                parameters.  Do not show anything like a man page.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-19&quot;&gt;&lt;a href=&quot;#cb2-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;        `&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-20&quot;&gt;&lt;a href=&quot;#cb2-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        parts &lt;span class=&quot;op&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;[]&lt;/span&gt;genai&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Part&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-21&quot;&gt;&lt;a href=&quot;#cb2-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                genai&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Text&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;prompt&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-22&quot;&gt;&lt;a href=&quot;#cb2-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                genai&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Text&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;src&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-23&quot;&gt;&lt;a href=&quot;#cb2-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-24&quot;&gt;&lt;a href=&quot;#cb2-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; err &lt;span class=&quot;op&quot;&gt;:=&lt;/span&gt; ask&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;parts&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt; err &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;ot&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-25&quot;&gt;&lt;a href=&quot;#cb2-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                log&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;Fatalf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;Failed to innovate: %v&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; err&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-26&quot;&gt;&lt;a href=&quot;#cb2-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-27&quot;&gt;&lt;a href=&quot;#cb2-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-28&quot;&gt;&lt;a href=&quot;#cb2-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-29&quot;&gt;&lt;a href=&quot;#cb2-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you can innovate while you’re getting help:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ INNOVATE=1 llm -h
Usage: llm [-][context]..

Queries gemini to provide conversation continuation.  If no parameters are
provided, input is read from stdin.  Parameters beginning with &amp;#39;-&amp;#39; are
considered prompts and passed directly to stdin.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Try out &lt;code&gt;llm&lt;/code&gt; &lt;a
href=&quot;https://github.com/danobi/llm&quot;&gt;here&lt;/a&gt;!&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>errno and libc</title><id>https://dxuuu.xyz/errno.html</id><updated>2024-01-30T11:10:07-08:00</updated><link href="https://dxuuu.xyz/errno.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;errno and libc&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;errno and libc&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;A few weeks ago I wanted to confirm if &lt;code&gt;errno&lt;/code&gt; was a libc
abstraction or a kernel feature. The glibc docs are deliberately vague
on the topic, so experimentation seemed like the best course.&lt;/p&gt;
&lt;h3 id=&quot;using-libc&quot;&gt;Using libc&lt;/h3&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; use_wrapper&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; cmd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;union&lt;/span&gt; bpf_attr &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;attr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; size&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;long&lt;/span&gt; ret&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/* Clear errno */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    errno &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    ret &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; syscall&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;__NR_bpf&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; cmd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; attr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ret &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;wrapped syscall failed, ret=&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;, errno=&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%d\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; ret&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; errno&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;wrapped syscall succeeded&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we make a syscall to &lt;code&gt;bpf(2)&lt;/code&gt;. Mostly b/c I’m quite
familiar with it.&lt;/p&gt;
&lt;h3 id=&quot;using-assembly&quot;&gt;Using assembly&lt;/h3&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; use_raw&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; cmd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;union&lt;/span&gt; bpf_attr &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;attr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; size&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;long&lt;/span&gt; ret&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/* Clear errno */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    errno &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    __asm__&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;st&quot;&gt;&amp;quot;movq %1, &lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;rax&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;        &lt;span class=&quot;co&quot;&gt;/* syscall number */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;st&quot;&gt;&amp;quot;movq %2, &lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;rdi&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;        &lt;span class=&quot;co&quot;&gt;/* arg1 */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;st&quot;&gt;&amp;quot;movq %3, &lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;rsi&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;        &lt;span class=&quot;co&quot;&gt;/* arg2 */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;st&quot;&gt;&amp;quot;movq %4, &lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;rdx&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;        &lt;span class=&quot;co&quot;&gt;/* arg3 */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;st&quot;&gt;&amp;quot;syscall&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;st&quot;&gt;&amp;quot;movq &lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;rax, %0&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-16&quot;&gt;&lt;a href=&quot;#cb2-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;/* retval */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-17&quot;&gt;&lt;a href=&quot;#cb2-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;=r&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ret&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-18&quot;&gt;&lt;a href=&quot;#cb2-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-19&quot;&gt;&lt;a href=&quot;#cb2-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;/* input operands */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-20&quot;&gt;&lt;a href=&quot;#cb2-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;__NR_bpf&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;cmd&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;attr&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;size&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-21&quot;&gt;&lt;a href=&quot;#cb2-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-22&quot;&gt;&lt;a href=&quot;#cb2-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;co&quot;&gt;/* clobbers */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-23&quot;&gt;&lt;a href=&quot;#cb2-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;op&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;rax&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;rdi&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;rsi&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;rdx&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-24&quot;&gt;&lt;a href=&quot;#cb2-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;       &lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-25&quot;&gt;&lt;a href=&quot;#cb2-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-26&quot;&gt;&lt;a href=&quot;#cb2-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;/* Check return value */&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-27&quot;&gt;&lt;a href=&quot;#cb2-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ret &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-28&quot;&gt;&lt;a href=&quot;#cb2-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;raw syscall failed, ret=&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;, errno=&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%d\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; ret&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; errno&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-29&quot;&gt;&lt;a href=&quot;#cb2-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-30&quot;&gt;&lt;a href=&quot;#cb2-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        printf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;raw syscall succeeded&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-31&quot;&gt;&lt;a href=&quot;#cb2-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;use_raw()&lt;/code&gt; does the exact same thing as
&lt;code&gt;use_wrapper()&lt;/code&gt;, except we use inline assembly. Even if you
don’t know assembly or inline assembler, it should be quite clear the
semantics from the comments.&lt;/p&gt;
&lt;h3 id=&quot;trying-it-out&quot;&gt;Trying it out&lt;/h3&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode c&quot;&gt;&lt;code class=&quot;sourceCode c&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;sys/syscall.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;errno.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;linux/bpf.h&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;[..]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-11&quot;&gt;&lt;a href=&quot;#cb3-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; cmd &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; BPF_PROG_LOAD&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-12&quot;&gt;&lt;a href=&quot;#cb3-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;kw&quot;&gt;union&lt;/span&gt; bpf_attr &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;attr &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; NULL&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-13&quot;&gt;&lt;a href=&quot;#cb3-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;dt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; size &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-14&quot;&gt;&lt;a href=&quot;#cb3-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-15&quot;&gt;&lt;a href=&quot;#cb3-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    use_raw&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;cmd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; attr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-16&quot;&gt;&lt;a href=&quot;#cb3-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    use_wrapper&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;cmd&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; attr&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-17&quot;&gt;&lt;a href=&quot;#cb3-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, we put it together in &lt;code&gt;main()&lt;/code&gt;. Consider this
output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gcc main.c

$ ./a.out
raw syscall failed, ret=-1, errno=0
wrapped syscall failed, ret=-1, errno=1

$ sudo ./a.out
raw syscall failed, ret=-7, errno=0
wrapped syscall failed, ret=-1, errno=7&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice how &lt;code&gt;errno&lt;/code&gt; is always 0 when skiping libc. Further
notice how the return value of the raw syscall flipped to a positive
value and stored into &lt;code&gt;errno&lt;/code&gt; by libc.&lt;/p&gt;
&lt;p&gt;So that settles it – &lt;code&gt;errno&lt;/code&gt; is a libc abstraction.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Reading local variables with bpftrace</title><id>https://dxuuu.xyz/local-vars.html</id><updated>2024-04-07T10:59:39-07:00</updated><link href="https://dxuuu.xyz/local-vars.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Reading local variables with bpftrace&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Reading local variables with bpftrace&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Most tracers are designed around functions. You attach a probe to a
function and then when the function is called and the probe is run, you
access the function arguments and/or the return value. Function
arguments are sufficient for the majority of use cases, as function
bodies typically process and manipulate the arguments. But sometimes
they are not enough. Sometimes we want to access the local variables
defined in the function body.&lt;/p&gt;
&lt;p&gt;This post walks through a hypothetical example of accessing local
variables. More specifically, we will use &lt;code&gt;bpftrace&lt;/code&gt; to trace
bpftrace.&lt;/p&gt;
&lt;h3 id=&quot;async-ids&quot;&gt;Async IDs&lt;/h3&gt;
&lt;p&gt;Whenever bpftrace needs userspace to take an action (such as printing
a message to console), we must have kernelspace send a message to
userspace. In order to coordinate actions, we assign unique IDs to all
possible actions. For example, each &lt;code&gt;print()&lt;/code&gt; or
&lt;code&gt;printf()&lt;/code&gt; will have its own unique ID. Userspace and
kernelspace share this map of ID to action. Thus, when kernelspace sends
up a message, it prefixes the blob with the ID so userspace can know how
to interpret the blob.&lt;/p&gt;
&lt;p&gt;Now that we know that async IDs are critical to bpftrace machinery,
let’s find a way to trace it. For legacy reasons, in source it’s called
&lt;code&gt;printf_id&lt;/code&gt;. The editorialized source follows:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; perf_event_printer&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;cb_cookie&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; size&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;vector&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;uint8_t&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; data_aligned&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  data_aligned&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;resize&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;size&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  memcpy&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;data_aligned&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;op&quot;&gt;(),&lt;/span&gt; data&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; size&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; err&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; bpftrace &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;BPFtrace &lt;span class=&quot;op&quot;&gt;*&amp;gt;(&lt;/span&gt;cb_cookie&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;#cb1-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; arg_data &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; data_aligned&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;#cb1-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; printf_id &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;reinterpret_cast&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;dt&quot;&gt;uint64_t&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;*&amp;gt;(&lt;/span&gt;arg_data&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;#cb1-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;#cb1-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;bpftrace&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;finalize_&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;#cb1-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;#cb1-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;bpftrace&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;exitsig_recv&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-15&quot;&gt;&lt;a href=&quot;#cb1-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    bpftrace&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;request_finalize&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-16&quot;&gt;&lt;a href=&quot;#cb1-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-17&quot;&gt;&lt;a href=&quot;#cb1-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-18&quot;&gt;&lt;a href=&quot;#cb1-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-19&quot;&gt;&lt;a href=&quot;#cb1-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;printf_id &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; asyncactionint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;AsyncAction&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;exit&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-20&quot;&gt;&lt;a href=&quot;#cb1-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    bpftrace&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;request_finalize&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-21&quot;&gt;&lt;a href=&quot;#cb1-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-22&quot;&gt;&lt;a href=&quot;#cb1-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;printf_id &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; asyncactionint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;AsyncAction&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;print&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-23&quot;&gt;&lt;a href=&quot;#cb1-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-24&quot;&gt;&lt;a href=&quot;#cb1-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;printf_id &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; asyncactionint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;AsyncAction&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;print_non_map&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-25&quot;&gt;&lt;a href=&quot;#cb1-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-26&quot;&gt;&lt;a href=&quot;#cb1-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;printf_id &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; asyncactionint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;AsyncAction&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;clear&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-27&quot;&gt;&lt;a href=&quot;#cb1-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-28&quot;&gt;&lt;a href=&quot;#cb1-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice how it’d be tricky to derive the ID only from function
arguments. If we tried to, we’d risk taking page faults or accessing
unaligned memory.&lt;/p&gt;
&lt;h3 id=&quot;technique&quot;&gt;Technique&lt;/h3&gt;
&lt;p&gt;The basic technique for accessing a local variable is to:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Find where in the function the variable is live&lt;/li&gt;
&lt;li&gt;Find which register the variable is live in&lt;/li&gt;
&lt;li&gt;Attach a probe at correct offset reading the correct register&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The hand-wavy explanation for this (see &lt;a
href=&quot;https://en.wikipedia.org/wiki/Register_allocation&quot;&gt;register
allocation&lt;/a&gt; for a more detailed discussion) is that variables, when
used in an operation, must be in a register. And since there can be a
lot more variables than registers, the compiler only keeps a subset of
variables in registers at any given time and leaves the rest on the
stack. As such, &lt;em&gt;when&lt;/em&gt; (offset) a variable is “live” is just as
important as &lt;em&gt;where&lt;/em&gt; (register) is live.&lt;/p&gt;
&lt;h3 id=&quot;finding-our-register&quot;&gt;Finding our register&lt;/h3&gt;
&lt;p&gt;I wouldn’t say I’m particularly good at reading assembly, so don’t
worry if you’re not good either. Here I’ll show off a neat trick that
helps cut through all the noise.&lt;/p&gt;
&lt;p&gt;But first we must disassemble. There’s many ways to do this, but I’ll
be using &lt;code&gt;nm&lt;/code&gt; and &lt;code&gt;objdump&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ nm /usr/bin/bpftrace | grep perf_event_printer
00000000000ecb00 t _ZN8bpftrace18perf_event_printerEPvS0_i
0000000000020765 t _ZN8bpftrace18perf_event_printerEPvS0_i.cold&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’ll ignore the &lt;code&gt;.cold&lt;/code&gt; function since I think that’s
where the compiler keeps code unlikely to be executed (in order to
reduce icache footprint).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ objdump --disassemble=_ZN8bpftrace18perf_event_printerEPvS0_i /usr/bin/bpftrace

/usr/bin/bpftrace:     file format elf64-x86-64


Disassembly of section .init:

Disassembly of section .text:

00000000000ecb00 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i&amp;gt;:
   ecb00:       f3 0f 1e fa             endbr64
   ecb04:       41 57                   push   %r15
   ecb06:       41 56                   push   %r14
   ecb08:       41 55                   push   %r13
   ecb0a:       41 54                   push   %r12
   ecb0c:       55                      push   %rbp
   ecb0d:       53                      push   %rbx
   ecb0e:       48 81 ec 00 10 00 00    sub    $0x1000,%rsp
   ecb15:       48 83 0c 24 00          orq    $0x0,(%rsp)
   ecb1a:       48 81 ec e8 06 00 00    sub    $0x6e8,%rsp
   ecb21:       66 0f ef c0             pxor   %xmm0,%xmm0
   ecb25:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
   ecb2c:       00 00
   ecb2e:       48 89 84 24 d8 16 00    mov    %rax,0x16d8(%rsp)
   ecb35:       00
   ecb36:       31 c0                   xor    %eax,%eax
   ecb38:       48 63 ea                movslq %edx,%rbp
   ecb3b:       49 89 ff                mov    %rdi,%r15
   ecb3e:       48 89 f3                mov    %rsi,%rbx
   ecb41:       48 c7 44 24 70 00 00    movq   $0x0,0x70(%rsp)
   ecb48:       00 00
   ecb4a:       49 89 ec                mov    %rbp,%r12
   ecb4d:       31 ff                   xor    %edi,%edi
   ecb4f:       0f 29 44 24 60          movaps %xmm0,0x60(%rsp)
   ecb54:       48 85 ed                test   %rbp,%rbp
   ecb57:       0f 85 5b 03 00 00       jne    eceb8 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x3b8&amp;gt;
   ecb5d:       48 89 ea                mov    %rbp,%rdx
   ecb60:       48 89 de                mov    %rbx,%rsi
   ecb63:       ff 15 47 8e 33 00       call   *0x338e47(%rip)        # 4259b0 &amp;lt;memcpy@GLIBC_2.14&amp;gt;
   ecb69:       4c 8b 6c 24 60          mov    0x60(%rsp),%r13
   ecb6e:       45 0f b6 77 28          movzbl 0x28(%r15),%r14d
   ecb73:       49 8b 45 00             mov    0x0(%r13),%rax
   ecb77:       45 84 f6                test   %r14b,%r14b
   ecb7a:       0f 85 20 03 00 00       jne    ecea0 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x3a0&amp;gt;
   ecb80:       8b 2d 22 ac 33 00       mov    0x33ac22(%rip),%ebp        # 4277a8 &amp;lt;_ZN8bpftrace8BPFtrace12exitsig_recvE&amp;gt;
   ecb86:       85 ed                   test   %ebp,%ebp
   ecb88:       0f 85 72 02 00 00       jne    ece00 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x300&amp;gt;
   ecb8e:       48 3d 30 75 00 00       cmp    $0x7530,%rax
   ecb94:       0f 84 46 05 00 00       je     ed0e0 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x5e0&amp;gt;
   ecb9a:       48 3d 31 75 00 00       cmp    $0x7531,%rax
   ecba0:       0f 84 f2 04 00 00       je     ed098 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x598&amp;gt;
   ecba6:       48 3d 37 75 00 00       cmp    $0x7537,%rax
   ecbac:       0f 84 1e 03 00 00       je     eced0 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x3d0&amp;gt;
   ecbb2:       48 3d 32 75 00 00       cmp    $0x7532,%rax
   ecbb8:       0f 84 82 05 00 00       je     ed140 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x640&amp;gt;
   ecbbe:       48 3d 33 75 00 00       cmp    $0x7533,%rax
   ecbc4:       0f 84 de 0a 00 00       je     ed6a8 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0xba8&amp;gt;
   ecbca:       48 3d 34 75 00 00       cmp    $0x7534,%rax
   ecbd0:       0f 84 0a 09 00 00       je     ed4e0 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x9e0&amp;gt;
   ecbd6:       48 3d 35 75 00 00       cmp    $0x7535,%rax
   ecbdc:       0f 84 fe 0c 00 00       je     ed8e0 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0xde0&amp;gt;
   ecbe2:       48 3d 36 75 00 00       cmp    $0x7536,%rax
   ecbe8:       0f 84 fb 0f 00 00       je     edbe9 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x10e9&amp;gt;
   ecbee:       48 3d 39 75 00 00       cmp    $0x7539,%rax
   ecbf4:       0f 85 3e 0e 00 00       jne    eda38 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0xf38&amp;gt;
   [...]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Experienced assembly programmers can probably read this and make
sense of the structure. But if you’re like me and can only nod along to
explanations, you can use this trick:&lt;/p&gt;
&lt;p&gt;Basically, you’re going to look for a constant value that a variable
is being compared to. This creates a mapping between source to
assembly.&lt;/p&gt;
&lt;p&gt;In our example, notice the following code:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;printf_id &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; asyncactionint&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;AsyncAction&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;exit&lt;span class=&quot;op&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Also notice &lt;code&gt;AsyncAction::exit&lt;/code&gt; is a constant
(&lt;code&gt;30000&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;class&lt;/span&gt; AsyncAction &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  printf  &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;     &lt;span class=&quot;co&quot;&gt;// printf reserves 0-9999 for printf_ids&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  syscall &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;// system reserves 10000-19999 for printf_ids&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  cat     &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;20000&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;// cat reserves 20000-29999 for printf_ids&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  exit    &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;30000&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  print&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  clear&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  zero&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  time&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  join&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-11&quot;&gt;&lt;a href=&quot;#cb5-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  helper_error&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-12&quot;&gt;&lt;a href=&quot;#cb5-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  print_non_map&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-13&quot;&gt;&lt;a href=&quot;#cb5-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  strftime&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-14&quot;&gt;&lt;a href=&quot;#cb5-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  watchpoint_attach&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-15&quot;&gt;&lt;a href=&quot;#cb5-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  watchpoint_detach&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-16&quot;&gt;&lt;a href=&quot;#cb5-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  skboutput&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-17&quot;&gt;&lt;a href=&quot;#cb5-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Converting that to hex, we get:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; hex(30000)
&amp;#39;0x7530&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And when we check the assembly for that constant, we see:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   ecb8e:       48 3d 30 75 00 00       cmp    $0x7530,%rax
   ecb94:       0f 84 46 05 00 00       je     ed0e0 &amp;lt;_ZN8bpftrace18perf_event_printerEPvS0_i+0x5e0&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells us both &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;where&lt;/em&gt; our
&lt;code&gt;printf_id&lt;/code&gt; is live. To get the offset, we do:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; 0xecb8e - 0xecb00
142&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;0xecb8e&lt;/code&gt; is the offset of the &lt;code&gt;cmp&lt;/code&gt;
instruction. And &lt;code&gt;0xecb00&lt;/code&gt; is the offset of the function (see
&lt;code&gt;objdump&lt;/code&gt; output). The &lt;code&gt;cmp&lt;/code&gt; instruction is
acceptable b/c it is unconditionally run after the initial exit
checks.&lt;/p&gt;
&lt;p&gt;To get the register the variable is live in, look at the other
operand in &lt;code&gt;cmp&lt;/code&gt;: &lt;code&gt;%rax&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;putting-it-all-together&quot;&gt;Putting it all together&lt;/h3&gt;
&lt;p&gt;We have two probes: &lt;code&gt;BEGIN&lt;/code&gt; and our accessor. We use the
&lt;code&gt;BEGIN&lt;/code&gt; probe as a trigger to actually run
&lt;code&gt;BPFtrace::perf_event_printer&lt;/code&gt;. This makes the example a nice
one liner. The accessor probe uses all the information we gathered.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo bpftrace - &amp;lt;&amp;lt;EOF
    BEGIN { print(&amp;quot;trigger!&amp;quot;) }
    uprobe:/usr/bin/bpftrace:_ZN8bpftrace18perf_event_printerEPvS0_i+142 { print(reg(&amp;quot;ax&amp;quot;)); exit() }
EOF
Attaching 2 probes...
trigger!
30007&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The script is telling us the value of our local variable is
&lt;code&gt;30007&lt;/code&gt;. Consulting the source, we see &lt;code&gt;30007&lt;/code&gt;
maps to &lt;code&gt;AsyncAction::print_non_map&lt;/code&gt;. This checks out – the
&lt;code&gt;BEGIN&lt;/code&gt; probe indeed uses a non-map print.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Big strings in bpftrace</title><id>https://dxuuu.xyz/big-strings.html</id><updated>2024-09-16T04:46:09-07:00</updated><link href="https://dxuuu.xyz/big-strings.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Big strings in bpftrace&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Big strings in bpftrace&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;If you’ve ever written BPF code you’ve probably run into the limits
of the BPF programming model. bpftrace, a high level tracing language
built on BPF, does its best to hide these limits – usually through
language design but sometimes through clever code generation. Even so,
some fundamental issues still leak through.&lt;/p&gt;
&lt;p&gt;One such example is with the string type.&lt;/p&gt;
&lt;h2 id=&quot;bpf-memory&quot;&gt;BPF memory&lt;/h2&gt;
&lt;p&gt;The BPF programming model makes an implicit distinction between
kernel memory, user memory, and BPF memory. BPF memory is memory the
verifier knows is safe to access. This includes the BPF stack, map
allocated memory, etc. In order to work with data originating from the
first two categories, a BPF program first needs to pull it into BPF
memory through &lt;code&gt;bpf_probe_read_[user|kernel][_str]()&lt;/code&gt; helper
functions. Sometimes the line is blurry. With BPF Type Format (BTF) the
verifier can type check and ensure the memory being read is safely
paged-in and in-bounds. For example, if the verifier can prove you have
a pointer to valid kernel memory, the program can directly use the
pointer in string functions without the aforementioned helpers.&lt;/p&gt;
&lt;p&gt;To paper over such differences and expose a unified interface,
bpftrace users are required to call &lt;code&gt;str()&lt;/code&gt; on C-strings to
get a handle to a string they can interact with. For example, assuming
&lt;code&gt;foo&lt;/code&gt; is a kernel function declared as
&lt;code&gt;void foo(char *s)&lt;/code&gt;, the following bpftrace program counts
the occurrences of every string passed to &lt;code&gt;foo&lt;/code&gt; and stores
the results into map &lt;code&gt;@occurences&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# bpftrace -e ‘kfunc:foo { @occurences[str(args.s)] = count() }’&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;bpf-memory-limitations&quot;&gt;BPF memory limitations&lt;/h2&gt;
&lt;p&gt;Because there is no way to efficiently allocate dynamic BPF memory
(at least, until &lt;a
href=&quot;https://lore.kernel.org/all/20240308010812.89848-1-alexei.starovoitov@gmail.com/&quot;&gt;very
recently&lt;/a&gt;) in BPF program context, all strings need to be read onto
the stack. However, the verifier imposes both a 512 byte stack limit as
well as a prohibition on variable sized stack allocations. The
implication being that all strings need to be pre-sized at compile time
- a classic right-sizing problem.&lt;/p&gt;
&lt;p&gt;As a result, bpftrace now has the now infamous
&lt;code&gt;BPFTRACE_MAX_STRLEN&lt;/code&gt; configuration. This knob defaulted to
64 bytes and was tunable up to around 200 bytes, at which point both
LLVM and the verifier would start complaining. In the above example, any
string over 63 bytes (excluding NUL) would be summarily truncated. Any
experienced programmer can tell you 63 bytes (or even 200) is not nearly
enough for real world strings.&lt;/p&gt;
&lt;p&gt;Even so, this has been the status quo for some number of years… until
now.&lt;/p&gt;
&lt;h2 id=&quot;everything-is-a-map&quot;&gt;Everything is a map&lt;/h2&gt;
&lt;p&gt;Astute readers might wonder: in the above example, why does the
string need to exist on the stack at all? Can’t it just be read directly
into &lt;code&gt;@occurences&lt;/code&gt;’s storage, where there are no size
limitations? The answer is perhaps one day, if the kernel adds support
for it. The current CRUD interface to BPF maps requires pointers for
keys and values, thus implying storage &lt;em&gt;somewhere&lt;/em&gt; in BPF
memory.&lt;/p&gt;
&lt;p&gt;This is a good thought - is there somewhere else in BPF memory
without size limitations we can read the string into? The answer, as
with many questions in BPF, is to use a map.&lt;/p&gt;
&lt;p&gt;The 512 byte stack limit is a well known limitation in BPF. While
there are new &lt;a
href=&quot;https://lore.kernel.org/all/20240716011647.811746-1-yonghong.song@linux.dev/&quot;&gt;developments
in this area&lt;/a&gt;, the long-standing workaround has been to use an array
map sized to a single entry as scratch space. At load time, the verifier
rewrites array map lookups to regular memory accesses (without the
source-level helper call). This means that performance remains good
despite appearances.&lt;/p&gt;
&lt;p&gt;So what if we created an array map with a single entry of arbitrary
&lt;code&gt;BPFTRACE_MAX_STRLEN&lt;/code&gt;? Well, it wouldn’t work as a single
global, as the same program can concurrently run on different CPUs. So
it would have to be a per-cpu array map, which the kernel already
supports. But consider the following case:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# bpftrace -e ‘kfunc:bar { @m[str(args.s)] = str(args.s2) }’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The update to map &lt;code&gt;@m&lt;/code&gt; is a single
&lt;code&gt;bpf_map_update_elem()&lt;/code&gt; call. Meaning both strings have to be
alive at the same time. In other words, we have an overlapping lifetime
problem for that single array entry. This is the key issue that has
blocked progress on big strings for so long.&lt;/p&gt;
&lt;h2 id=&quot;one-entry-per-node&quot;&gt;One entry per node&lt;/h2&gt;
&lt;p&gt;Fortunately there is a rather simple and general (as you’ll see)
solution lurking in plain sight. Consider the following script:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$s = str(args.s);                           // (1)
@m[$s, str(args.s2)] = str(args.s3);        // (2), (3)
$i = 0;
while ($i &amp;lt; 5) {
    @m2[$i] = str(args.s4);                 // (4)
    $i++;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This program creates 8 strings at runtime but only 4 unique storage
slots are necessary to avoid all potential lifetime conflicts. To
accurately count and assign slots, a compiler need only walk the
abstract syntax tree (AST) and assign each &lt;code&gt;str()&lt;/code&gt; node an
increasing index or id. As long as bpftrace is careful to load strings
into their assigned slot, the whole thing will work. Note it is
&lt;em&gt;very&lt;/em&gt; simple for any compiler to walk and count nodes like
this.&lt;/p&gt;
&lt;p&gt;Once all the slots are tallied up, we can create a per-cpu array map
with &lt;code&gt;nr_slots&lt;/code&gt; entries sized to any arbitrary
&lt;code&gt;BPFTRACE_MAX_STRLEN&lt;/code&gt; size. Note this size is basically
unlimited now - multiple gigabytes should work as long as you have
enough memory. The downside to this approach is that we are
pessimistically pre-allocating memory. Strings can be smaller than
&lt;code&gt;BPFTRACE_MAX_STRLEN&lt;/code&gt; or worse: the strings may never be
created. In this case, we’ve found in practice that our users are happy
to trade some wasted memory for smoother debugging sessions.&lt;/p&gt;
&lt;h2 id=&quot;printing-big-strings&quot;&gt;Printing big strings&lt;/h2&gt;
&lt;p&gt;While assigning storage slots to each string is a novel trick, its
implementation exposed a few long standing assumptions. The biggest
challenge was printing big strings. For example, consider:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# bpftrace -e ‘kfunc:foo { printf(“%s, %s\n”, str(args.s), str(args.s)) }’&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, the program will allocate a two string “tuple” on the
stack, copy both strings into the tuple, and then copy the tuple into a
ring buffer for userspace to consume. Note that the stack allocation is
not strictly necessary for &lt;a
href=&quot;https://docs.kernel.org/6.6/bpf/ringbuf.html&quot;&gt;BPF ring buffer&lt;/a&gt;
(as it allows reserving and committing buffer space), but for simplicity
we try to keep perf and BPF ring buffer support on as similar codepaths
as possible.&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;printf()&lt;/code&gt; (and also &lt;code&gt;print()&lt;/code&gt;) were
implemented assuming that all the arguments can fit neatly on the stack.
Now that strings do not necessarily fit on the stack, we must rework the
printing code.&lt;/p&gt;
&lt;p&gt;Fortunately, we can just reuse the same per-cpu buffer trick as with
big strings. Except this time there are no lifetime overlap issues so we
can simply give the per-cpu array one entry sized to the largest tuple
the program can create. Determining the largest tuple is also easy for a
compiler - walk the AST again and keep the running max.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Now that the big issues (as well as some smaller ones we’ve glossed
over) are solved, bpftrace plans to change the default value of
&lt;code&gt;BPFTRACE_MAX_STRLEN&lt;/code&gt; up to 1024 bytes. Assuming all goes
well, scripts limited by small strings will magically start working
better and new users will be none the wiser about any underlying BPF
limitations.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Application blackbox</title><id>https://dxuuu.xyz/blackbox.html</id><updated>2024-12-23T16:19:45-08:00</updated><link href="https://dxuuu.xyz/blackbox.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Application blackbox&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Application blackbox&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;In aviation, a “black box” is the colloquial term for the &lt;a
href=&quot;https://en.wikipedia.org/wiki/Flight_recorder&quot;&gt;flight
recorder&lt;/a&gt;, a device that records the recent history of a flight. This
device is designed to be robust to a potential crash such that the
recovered data can be later used during investigation.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/danobi/blackbox&quot;&gt;blackbox&lt;/a&gt; applies
this idea to software. The principle goal of &lt;code&gt;blackbox&lt;/code&gt; is to
enable applications to save arbitrary (but structured) data during
runtime and allow that data to survive any kind of crash, even
&lt;code&gt;SIGKILL&lt;/code&gt;. In addition, the blackbox can be extracted from
outside the application (live or post-mortem) without introducing
&lt;em&gt;any&lt;/em&gt; blocking in the application.&lt;/p&gt;
&lt;h2 id=&quot;api&quot;&gt;API&lt;/h2&gt;
&lt;p&gt;Let’s first start with the API. The following is the abbreviated
application-side API. The full documentation is available in &lt;a
href=&quot;https://github.com/danobi/blackbox/blob/master/blackbox.h&quot;&gt;&lt;code&gt;blackbox.h&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; init&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;size_t&lt;span class=&quot;op&quot;&gt; &lt;/span&gt;size &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; DEFAULT_SIZE&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;noexcept&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; write&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;string_view&lt;span class=&quot;op&quot;&gt; &lt;/span&gt;s&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;noexcept&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;#cb1-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; write&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;int64_t&lt;span class=&quot;op&quot;&gt; &lt;/span&gt;i&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;noexcept&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;#cb1-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; write&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;string_view&lt;span class=&quot;op&quot;&gt; &lt;/span&gt;key&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;string_view&lt;span class=&quot;op&quot;&gt; &lt;/span&gt;value&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;noexcept&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;#cb1-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;[..]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;#cb1-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;#cb1-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; dump&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;ostream&lt;span class=&quot;op&quot;&gt; &amp;amp;&lt;/span&gt;out&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For example, it could be used like this:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;chrono&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;cstring&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;lt;thread&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;pp&quot;&gt;#include &lt;/span&gt;&lt;span class=&quot;im&quot;&gt;&amp;quot;blackbox.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;int&lt;/span&gt; main&lt;span class=&quot;op&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; err &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; blackbox&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;init&lt;span class=&quot;op&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cerr&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;strerror&lt;span class=&quot;op&quot;&gt;(-&lt;/span&gt;err&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  blackbox&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;write&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;hello world!&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a href=&quot;#cb2-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  blackbox&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;write&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-16&quot;&gt;&lt;a href=&quot;#cb2-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  blackbox&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;write&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;key1&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;val1&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-17&quot;&gt;&lt;a href=&quot;#cb2-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-18&quot;&gt;&lt;a href=&quot;#cb2-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  blackbox&lt;span class=&quot;op&quot;&gt;::&lt;/span&gt;dump&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-19&quot;&gt;&lt;a href=&quot;#cb2-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;this_thread&lt;span class=&quot;bu&quot;&gt;::&lt;/span&gt;sleep_for&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;chrono&lt;span class=&quot;bu&quot;&gt;::&lt;/span&gt;milliseconds&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-20&quot;&gt;&lt;a href=&quot;#cb2-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;which when run, would produce this output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./demo
hello world!
123
key1=val1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatively, you could do a live external extraction:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ./demo &amp;gt;/dev/null &amp;amp;; ./extractor $(pidof demo)
hello world!
123
key1=val1&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;
&lt;h3 id=&quot;crash-resilience&quot;&gt;Crash resilience&lt;/h3&gt;
&lt;p&gt;In line with the idea of a flight recorder, we want to save data in
the event of a crash. However, because &lt;code&gt;blackbox&lt;/code&gt; implements
this with POSIX shared memory, we want to be conservative with system
resources. To that end, &lt;code&gt;blackbox&lt;/code&gt; registers an
&lt;code&gt;atexit(3)&lt;/code&gt; handler that unlinks the shared memory. This is a
clean mechanism that gives us for free the following properties:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Blackbox deletion on normal exit (return from &lt;code&gt;main()&lt;/code&gt; or
&lt;code&gt;std::exit()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Blackbox deletion on normal exit from signal handler&lt;/li&gt;
&lt;li&gt;Blackbox preservation on unhandled signal (SIGSEGV, SIGABRT,
etc.)&lt;/li&gt;
&lt;li&gt;Blackbox preservation on uncatchable signal (SIGKILL)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The rationale behind properties 1 and 2 is that the application has
the chance to dump the blackbox so we can assume it will be explicitly
preserved if necessary. Property 2 is why &lt;code&gt;blackbox::dump()&lt;/code&gt;
is async-signal-safe. That is, it can be safely called from signal
handlers as long as &lt;code&gt;operator&amp;lt;&amp;lt;&lt;/code&gt; on the
&lt;code&gt;std::ostream&lt;/code&gt; is also async-signal-safe.&lt;/p&gt;
&lt;p&gt;There are various corner cases (for example &lt;code&gt;_exit(3)&lt;/code&gt; or
&lt;code&gt;std::terminate()&lt;/code&gt;) that skip &lt;code&gt;atexit&lt;/code&gt; handlers.
In those cases, blackbox still achieves its design goal but only fails
to conserve resources. For this reason, it’s recommended to have a cron
job or equivalent to reap old blackboxes.&lt;/p&gt;
&lt;h3 id=&quot;non-blocking-extraction&quot;&gt;Non-blocking extraction&lt;/h3&gt;
&lt;p&gt;Above we mentioned POSIX shared memory. However, crash resilience is
not the only reason for this technical choice. Shared memory was chosen
to also satisfy our non-blocking design goal by exploiting shared
memory’s linux implementation.&lt;/p&gt;
&lt;p&gt;More specifically, POSIX shared memory is backed by a
&lt;code&gt;tmpfs&lt;/code&gt; mount at &lt;code&gt;/dev/shm&lt;/code&gt;.
&lt;code&gt;mmap(2)&lt;/code&gt;ing files in tmpfs does not acquire
&lt;code&gt;mmap_lock&lt;/code&gt; in the application. Constrast this with something
like a remote &lt;code&gt;process_vm_readv(2)&lt;/code&gt; which &lt;em&gt;will&lt;/em&gt; take
&lt;code&gt;mmap_lock&lt;/code&gt; in the application.&lt;/p&gt;
&lt;p&gt;Why all the effort to avoid &lt;code&gt;mmap_lock&lt;/code&gt;?
&lt;code&gt;mmap_lock&lt;/code&gt; is a &lt;a
href=&quot;https://lwn.net/Articles/893906/&quot;&gt;particularly thorny subject&lt;/a&gt;
in the kernel. In particular, it’s been known to cause priority
inversions during out-of-memory (OOM) scenarios, which
&lt;code&gt;blackbox&lt;/code&gt; was initially designed to help troubleshoot. For
this reason, we chose shared memory as it will not induce any blocking
in the application.&lt;/p&gt;
&lt;h3 id=&quot;data-consistency&quot;&gt;Data consistency&lt;/h3&gt;
&lt;p&gt;So we communicate through shared memory, fine. But what about
synchronization?&lt;/p&gt;
&lt;p&gt;Traditionally, shared memory mutexes are chosen for synchronizing
shared memory. However, it has &lt;a
href=&quot;https://man7.org/linux/man-pages/man3/pthread_mutexattr_setrobust.3.html&quot;&gt;somwhat
peculiar corner cases&lt;/a&gt; on top of being blocking for the application
even if we were to get clever with multi-reader locks. Therefore,
another solution was needed.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;blackbox&lt;/code&gt;, we chose to implement a userspace &lt;a
href=&quot;https://en.wikipedia.org/wiki/Seqlock&quot;&gt;sequence lock&lt;/a&gt;
(seqlock). In short, a seqlock does not ever block the writer. Instead,
the reader will retry if a modification was detected during the read.
This has all the properties we need, except that excessive writes may
starve readers. We don’t expect heavy writes to the blackbox, so this
caveat is fine.&lt;/p&gt;
&lt;p&gt;The same code is used during post-mortem extraction to check if the
blackbox crashed during a write. In the unlikely event that occurred, we
would know the data was lost. Or if we’re OK with best effort, that the
extracted data is unreliable.&lt;/p&gt;
&lt;p&gt;See further below for more details on the userspace seqlock.&lt;/p&gt;
&lt;h3 id=&quot;structured-data&quot;&gt;Structured data&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;../examples/blackbox/tlv.jpg&quot; style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Under the hood &lt;code&gt;blackbox&lt;/code&gt; is backed by a ring buffer to
bound memory usage. However, unlike typical ring buffers, we write
Tag-Length-Value (TLV) entries into the ring. This is important for two
reasons:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Arbitrary structured data can be supported&lt;/li&gt;
&lt;li&gt;It allows for perfect forward compatability&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;An alternative to (1) would be to force the user to serialize all
data to strings. However, this prevents structured extraction.
Monitoring systems (eg. prometheus) support strongly typed data. It’s
wise to be sympathetic to modern monitoring systems and allow users to
leverage their full analytical power.&lt;/p&gt;
&lt;p&gt;For (2), in the event that the extractor is newer than the
application’s blackbox, we are fine as long as &lt;code&gt;blackbox&lt;/code&gt; is
careful about backwards compatability. However, equally likely is if the
extractor is older than the application blackbox. In that case, TLVs
allow the extractor to skip unknown entries by looking at the type and
length fields.&lt;/p&gt;
&lt;h2 id=&quot;novel-techniques&quot;&gt;Novel techniques&lt;/h2&gt;
&lt;h3 id=&quot;userspace-sequence-lock&quot;&gt;Userspace sequence lock&lt;/h3&gt;
&lt;p&gt;Seqlocks are a somewhat obscure lock originating from the linux
kernel. The basic principle is that prior to entering write side
critical section, a sequence counter is incremented. Immediately after
exiting the write side critical section, the counter is incremented
again. With this, the reader knows it was interrupted during a read if
the sequence counter value is &lt;strong&gt;not even&lt;/strong&gt; and &lt;strong&gt;not
the same&lt;/strong&gt; before and after the read. Since this is all done
without traditional locks, lock-free techniques must be carefully
used.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;blackbox&lt;/code&gt; offers a rather unique addition to the
landscape in that we did a somewhat thorough review of the literature
before attempting an implementation, going as far as discovering a &lt;a
href=&quot;https://lore.kernel.org/all/0eaea03ecc9df536649763cfecda356fc38b6938.1734477414.git.dxu@dxuuu.xyz/&quot;&gt;very
small&lt;/a&gt; but long-standing bug in the kernel. We also didn’t find any
userspace seqlock implementations that seemed correct, so a custom
implementation was called for.&lt;/p&gt;
&lt;p&gt;Lock-free programming is a tricky topic, so we’ll spare the details.
Suffice to say, it’s about controlling the observed order of memory
operations. In this case, it’s ensuring that the first sequence
increment is visible before (and the second sequence increment after)
the critical section.&lt;/p&gt;
&lt;p&gt;For reference, here are the writer and reader bits. They come with
comments which hopefully justify the choice of memory barriers.&lt;/p&gt;
&lt;p&gt;Writer side critical section:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;typename&lt;/span&gt; F&lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; write_locked&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;F &lt;span class=&quot;op&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;f&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;decltype&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;op&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// Ensure only one writer is writing&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  lock&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;lock&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// Transition into write and prevent any stores from being reordered around&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// this increment.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// memory_order_acq_rel is chosen b/c the critial section (subsequent stores)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// must not be reordered before the sequence is incremented.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// memory_order_release is not sufficient as it only guarantees prior stores&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-11&quot;&gt;&lt;a href=&quot;#cb5-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// are not reordered after the increment, and not the other way around (which&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-12&quot;&gt;&lt;a href=&quot;#cb5-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// we need).&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-13&quot;&gt;&lt;a href=&quot;#cb5-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  blackbox&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;sequence&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;fetch_add&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;memory_order_relaxed&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-14&quot;&gt;&lt;a href=&quot;#cb5-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;atomic_thread_fence&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;memory_order_acq_rel&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-15&quot;&gt;&lt;a href=&quot;#cb5-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-16&quot;&gt;&lt;a href=&quot;#cb5-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// Write new entry&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-17&quot;&gt;&lt;a href=&quot;#cb5-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; retval &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; f&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-18&quot;&gt;&lt;a href=&quot;#cb5-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-19&quot;&gt;&lt;a href=&quot;#cb5-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// Transition out of write and prevent any previous stores from being&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-20&quot;&gt;&lt;a href=&quot;#cb5-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// reordered after this increment.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-21&quot;&gt;&lt;a href=&quot;#cb5-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-22&quot;&gt;&lt;a href=&quot;#cb5-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// Note we do not need acquire_release semantics like above b/c release&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-23&quot;&gt;&lt;a href=&quot;#cb5-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// semantics are strong enough to ensure stores in the critical section will&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-24&quot;&gt;&lt;a href=&quot;#cb5-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// be visible before the sequence increment.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-25&quot;&gt;&lt;a href=&quot;#cb5-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-26&quot;&gt;&lt;a href=&quot;#cb5-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// Any subsequent stores are free to move into the critical section if it&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-27&quot;&gt;&lt;a href=&quot;#cb5-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// makes the program run faster. Any subsequent critical sections will be&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-28&quot;&gt;&lt;a href=&quot;#cb5-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// fenced by its corresponding acquire_release increment.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-29&quot;&gt;&lt;a href=&quot;#cb5-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  blackbox&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;sequence&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;fetch_add&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;memory_order_release&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-30&quot;&gt;&lt;a href=&quot;#cb5-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-31&quot;&gt;&lt;a href=&quot;#cb5-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// Pair with above lock()&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-32&quot;&gt;&lt;a href=&quot;#cb5-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  lock&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;unlock&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-33&quot;&gt;&lt;a href=&quot;#cb5-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-34&quot;&gt;&lt;a href=&quot;#cb5-34&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; retval&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-35&quot;&gt;&lt;a href=&quot;#cb5-35&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Reader side critical section (abbreviated):&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;uint64_t&lt;span class=&quot;op&quot;&gt; &lt;/span&gt;read_seq&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;atomic_uint64_t&lt;span class=&quot;op&quot;&gt; &amp;amp;&lt;/span&gt;seq&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// memory_order_acquire is sufficient here b/c we only need ensure&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// subsequent loads are not reordered before the sequence load.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// The `&amp;amp; ~0x1` is just to ensure we retry in the event there is&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// a writer in the critical section. The sequence will be odd if&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// there is a write in progress.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; seq&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;load&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;memory_order_acquire&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;bn&quot;&gt;0x1&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;ULL&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-9&quot;&gt;&lt;a href=&quot;#cb6-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-10&quot;&gt;&lt;a href=&quot;#cb6-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-11&quot;&gt;&lt;a href=&quot;#cb6-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;// Returns whether or not to retry the read critical section&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-12&quot;&gt;&lt;a href=&quot;#cb6-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;bool&lt;/span&gt; read_retry&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;atomic_uint64_t&lt;span class=&quot;op&quot;&gt; &amp;amp;&lt;/span&gt;seq&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;uint64_t&lt;span class=&quot;op&quot;&gt; &lt;/span&gt;old_seq&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-13&quot;&gt;&lt;a href=&quot;#cb6-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// memory_order_acq_rel is necessary here to ensure prior loads&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-14&quot;&gt;&lt;a href=&quot;#cb6-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// are not reordered after the sequence load. memory_order_acquire&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-15&quot;&gt;&lt;a href=&quot;#cb6-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// only guarantees subsequent loads are not reordered before the&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-16&quot;&gt;&lt;a href=&quot;#cb6-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// sequence load, and not the other way around.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-17&quot;&gt;&lt;a href=&quot;#cb6-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;//&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-18&quot;&gt;&lt;a href=&quot;#cb6-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// If we see that the sequence was even _and_ unchanged before and&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-19&quot;&gt;&lt;a href=&quot;#cb6-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// after the critical section, it means we got a consistent view&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-20&quot;&gt;&lt;a href=&quot;#cb6-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;co&quot;&gt;// of the blackbox.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-21&quot;&gt;&lt;a href=&quot;#cb6-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;atomic_thread_fence&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;memory_order_acq_rel&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-22&quot;&gt;&lt;a href=&quot;#cb6-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; seq&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;load&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;memory_order_relaxed&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;!=&lt;/span&gt; old_seq&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-23&quot;&gt;&lt;a href=&quot;#cb6-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-24&quot;&gt;&lt;a href=&quot;#cb6-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-25&quot;&gt;&lt;a href=&quot;#cb6-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;bool&lt;/span&gt; work&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;Blackbox &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;bb&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-26&quot;&gt;&lt;a href=&quot;#cb6-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;uint64_t&lt;span class=&quot;op&quot;&gt; &lt;/span&gt;seq&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-27&quot;&gt;&lt;a href=&quot;#cb6-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-28&quot;&gt;&lt;a href=&quot;#cb6-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;cf&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-29&quot;&gt;&lt;a href=&quot;#cb6-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    seq &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; read_seq&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;bb&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;sequence&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-30&quot;&gt;&lt;a href=&quot;#cb6-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    critial_section&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;bb&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-31&quot;&gt;&lt;a href=&quot;#cb6-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;read_retry&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;bb&lt;span class=&quot;op&quot;&gt;-&amp;gt;&lt;/span&gt;sequence&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; seq&lt;span class=&quot;op&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-32&quot;&gt;&lt;a href=&quot;#cb6-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;double-mapped-ring-buffer&quot;&gt;Double mapped ring buffer&lt;/h3&gt;
&lt;p&gt;One interesting consequence of writing TLVs into the ring buffer is
that things get tricky when the entry header is split between the
beginning and the end of the array. When this happens, a simple pointer
cast to the entry is not possible. Naively, you would copy the header to
a temporary buffer sized to the largest possible header:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/blackbox/single_mapped.jpg&quot;
style=&quot;width:70.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;But we can do better. &lt;code&gt;blackbox&lt;/code&gt; makes use of a classic
(but possibly esoteric) ring buffer technique: double mapping:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;../examples/blackbox/double_mapped.jpg&quot;
style=&quot;width:100.0%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;With a double mapped ring buffer, it is always possible to do a
linear read or write. No extra memory is required - just an extra copy
of page table entries that the hardware resolves to the same physical
memory. This solves the header split problem on top of being more
efficient.&lt;/p&gt;
&lt;p&gt;Consider the case when the data portion of the entry needs to be
split between head and tail. The writer would need to either issue two
&lt;code&gt;memcpy(3)&lt;/code&gt;s or write a loop containing a modulo on each
iteration to simulate a ring-aware memcpy. Both leave performance on the
table:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Two memcpy’s makes poor use of hardware prefetching and branch
prediction.&lt;/li&gt;
&lt;li&gt;A custom memcpy would be hard-pressed to make use of architecture
specific optimized memcpy instructions. The modulo in each iteration is
also relative expensive.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing thoughts&lt;/h2&gt;
&lt;p&gt;There’s currently no plans to make the code any more reusable than it
currently is. If you want to use it, please reach out and we’ll see what
can be done.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Flaky tests, or: why not to ignore mysteries</title><id>https://dxuuu.xyz/flaky.html</id><updated>2025-01-17T16:57:11-08:00</updated><link href="https://dxuuu.xyz/flaky.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Flaky tests, or: why not to ignore mysteries&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
  &lt;!--[if lt IE 9]&gt;
    &lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js&quot;&gt;&lt;/script&gt;
  &lt;![endif]--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Flaky tests, or: why not to ignore mysteries&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;I spent a few weeks earlier this year &lt;a
href=&quot;https://github.com/bpftrace/bpftrace/issues/3080&quot;&gt;tracking
down&lt;/a&gt; a set of flaky end-to-end tests where bpftrace would
occasionally cease to print output. I had gotten as far as figuring out
&lt;code&gt;std::cout&lt;/code&gt; had &lt;a
href=&quot;https://en.cppreference.com/w/cpp/io/ios_base/iostate&quot;&gt;badbit&lt;/a&gt;
set after a write but had run out of ideas on how to debug it. At the
time, because I could not reproduce it locally, I had assumed it was an
oddity with pipes and CI and given up.&lt;/p&gt;
&lt;p&gt;Except bugs never go away. They only lay dormant.&lt;/p&gt;
&lt;h3 id=&quot;the-return-of-the-king-bug&quot;&gt;The Return of the &lt;del&gt;King&lt;/del&gt;
Bug&lt;/h3&gt;
&lt;p&gt;This week the issue re-appeared. Except in the form of new flakiness
after a seemingly harmless &lt;a
href=&quot;https://github.com/bpftrace/bpftrace/commit/c3cb6d6d1295316bf877dce33922c467d467de37&quot;&gt;test
reliability change&lt;/a&gt;. I’ll spare you the details - just tedious printf
bisection through many CI runs - but I essentially picked up where I
left off in March and isolated the buggy code down to:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;LOG&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;DEBUG&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;before std::cout good=&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;good&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;#cb1-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt; fmt&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;format_str&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;arg_values&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;endl&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;#cb1-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;LOG&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;DEBUG&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;after std::cout good=&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;std::&lt;/span&gt;cout&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;good&lt;span class=&quot;op&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note &lt;code&gt;stderr&lt;/code&gt; (&lt;code&gt;LOG(DEBUG)&lt;/code&gt;) continued to work
while &lt;code&gt;stdout&lt;/code&gt; did not. The above code would show the
following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;before std::cout good=1
after std::cout good=0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’m not sure why I didn’t think to drop down to syscall level and
actually read &lt;a href=&quot;https://dxuuu.xyz/errno.html&quot;&gt;the errno&lt;/a&gt; last
time, but fortunately I had a fresh chance to redeem myself:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;auto&lt;/span&gt; ret &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; write&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;STDOUT_FILENO&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; fmted&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;c_str&lt;span class=&quot;op&quot;&gt;(),&lt;/span&gt; fmted&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;op&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ret &lt;span class=&quot;op&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    LOG&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;DEBUG&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;write was ok&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;ret &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    LOG&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;DEBUG&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;write wrote nothing?&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    LOG&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;DEBUG&lt;span class=&quot;op&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;write failed: errno=&amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; errno &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;: &amp;quot;&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; strerror&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;errno&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above revealed:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;write failed: errno=9: Bad file descriptor&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;EBADF&lt;/code&gt; is interesting. According to the
&lt;code&gt;write(2)&lt;/code&gt; man page:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;EBADF fd is not a valid file descriptor or is not open for
writing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To not rule out either case out of hand, I opted to &lt;code&gt;lsof&lt;/code&gt;
on bpftrace startup as well as right before the &lt;code&gt;write(2)&lt;/code&gt;. I
used this chunk of code:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre
class=&quot;sourceCode cpp&quot;&gt;&lt;code class=&quot;sourceCode cpp&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;char&lt;/span&gt; buf&lt;span class=&quot;op&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;snprintf&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;op&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;lsof -p &lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;st&quot;&gt; 1&amp;gt;&amp;amp;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;,&lt;/span&gt; getpid&lt;span class=&quot;op&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;system&lt;span class=&quot;op&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;op&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On startup, we see:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[..]
bpftrace 7526 root   0r  FIFO   0,14       0t0   16880 pipe
bpftrace 7526 root   1w  FIFO   0,14       0t0   28011 pipe
bpftrace 7526 root   2w  FIFO   0,14       0t0   28011 pipe
[..]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but later at the write:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[..]
bpftrace 7526 root   0r     FIFO   0,14       0t0   16880 pipe
bpftrace 7526 root   2w     FIFO   0,14       0t0   28011 pipe
[..]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can only mean something inside the process is closing FD 1.&lt;/p&gt;
&lt;h3 id=&quot;clear-and-present-data&quot;&gt;Clear and present data&lt;/h3&gt;
&lt;p&gt;bpftrace works with raw file descriptors quite often. So it wasn’t
really practical to audit every &lt;code&gt;close(2)&lt;/code&gt; callsite. Not to
mention all the dependencies. Therefore, I opted for some runtime
instrumentation by scripting GDB. I originally had bpftrace to do this,
but due to all the debug logs the output started getting confusing -
multiple copies of everything was getting logged.&lt;/p&gt;
&lt;p&gt;Regardless, I switched the end-to-end test invocation to this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RUN gdb -q -ex &amp;quot;set confirm off&amp;quot; -ex &amp;quot;break close if \$rdi==1&amp;quot; -ex &amp;quot;commands;backtrace;kill;end&amp;quot; -ex run --args {{BPFTRACE}} -e &amp;#39;uprobe:/proc/{{BEFORE_PID}}/root/uprobe_test:uprobeFunction1 { printf(&amp;quot;func %s\n&amp;quot;, func); exit() }&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What this snippet does is set a breakpoint on &lt;code&gt;close(2)&lt;/code&gt;
but only dump backtrace if the argument value is &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Running that in CI reveals:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Attaching 1 probe...
__BPFTRACE_NOTIFY_PROBES_ATTACHED

Thread 1 &amp;quot;bpftrace&amp;quot; hit Breakpoint 1.2, 0x00007fffe4504910 in close ()
   from /nix/store/wn7v2vhyyyi6clcyn0s9ixvl7d4d87ic-glibc-2.40-36/lib/libc.so.6
(gdb)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The lack of a stack seemed to indicate missing debug information.
However, these CI jobs configure bpftrace to be built with DWARF.
Therefore, I started to suspect one of bpftrace’s dependencies.&lt;/p&gt;
&lt;h3 id=&quot;phantom-thread&quot;&gt;Phantom thread&lt;/h3&gt;
&lt;p&gt;The idea that it could be one of bpftrace’s dependencies sparked an
interesting question: what do all these failing tests have in common?
Given that the above test case was really only using the
&lt;code&gt;func&lt;/code&gt; builtin, I checked how that feature is implemented. To
my surprise, it’s implemented through userspace symbolication!&lt;/p&gt;
&lt;p&gt;That makes the common thread userspace symbolication, as the original
4 disabled tests involve symbolizing userspace stacks. So the obvious
next place to look is &lt;code&gt;bcc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Upon inspection, there’s indeed a bit of suspicious looking code in
&lt;code&gt;ProcSyms::ModulePath::fd_&lt;/code&gt; where &lt;code&gt;fd_&lt;/code&gt; is
declared without a default value and &lt;code&gt;ModulePath()&lt;/code&gt; has an
early return that does not set &lt;code&gt;fd_&lt;/code&gt;. In turn,
&lt;code&gt;~ModulePath()&lt;/code&gt; does &lt;code&gt;if (fd_ &amp;gt; 0) close(fd_)&lt;/code&gt;
which would be buggy if &lt;code&gt;fd_&lt;/code&gt; is not initialized to
&lt;code&gt;-1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It’s also more clear why &lt;a
href=&quot;https://github.com/bpftrace/bpftrace/commit/c3cb6d6d1295316bf877dce33922c467d467de37&quot;&gt;the
above reliability change&lt;/a&gt; started triggering flakiness. It’s b/c
before the change, &lt;code&gt;uprobe_test&lt;/code&gt; probably exited before
symbolization occurred, so we were not tickling the bad codepath in bcc.
After the change the process hangs around, so symbolization does
occur.&lt;/p&gt;
&lt;h3 id=&quot;the-validator&quot;&gt;The Validator&lt;/h3&gt;
&lt;p&gt;Continuing with the GDB approach, I thought if I could turn on debug
information for bcc it could give me a second opinion on the source.
Through our &lt;a href=&quot;https://dxuuu.xyz/bpftrace-nix.html&quot;&gt;Nix based
CI&lt;/a&gt;, this was as easy as adding to the bcc package overlay:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cmakeFlags = old.cmakeFlags ++ [ &amp;quot;-DCMAKE_BUILD_TYPE=Debug&amp;quot; ];&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, stacks still did not work. I’m guessing it’s b/c glibc
doesn’t have frame pointers enabled. And changing that would probably
take too much compute to rebuild everything. So it was a matter of luck
that I started thinking about dependencies - the lack of stacks is
unrelated.&lt;/p&gt;
&lt;p&gt;So I opted to check a different way: through printf debugging the
dependency. Through the power of Nix, I applied a patch to bcc:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb11&quot;&gt;&lt;pre
class=&quot;sourceCode diff&quot;&gt;&lt;code class=&quot;sourceCode diff&quot;&gt;&lt;span id=&quot;cb11-1&quot;&gt;&lt;a href=&quot;#cb11-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;From e5609182cf0ede7c9bb32bf54670cbfba754a6c0 Mon Sep 17 00:00:00 2001&lt;/span&gt;
&lt;span id=&quot;cb11-2&quot;&gt;&lt;a href=&quot;#cb11-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Message-ID: &amp;lt;e5609182cf0ede7c9bb32bf54670cbfba754a6c0.1737135820.git.dxu@dxuuu.xyz&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb11-3&quot;&gt;&lt;a href=&quot;#cb11-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;From: Daniel Xu &amp;lt;dxu@dxuuu.xyz&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb11-4&quot;&gt;&lt;a href=&quot;#cb11-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Date: Fri, 17 Jan 2025 10:43:33 -0700&lt;/span&gt;
&lt;span id=&quot;cb11-5&quot;&gt;&lt;a href=&quot;#cb11-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Subject: [PATCH] XXX: Log ~ModulePath close()&lt;/span&gt;
&lt;span id=&quot;cb11-6&quot;&gt;&lt;a href=&quot;#cb11-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-7&quot;&gt;&lt;a href=&quot;#cb11-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Signed-off-by: Daniel Xu &amp;lt;dxu@dxuuu.xyz&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb11-8&quot;&gt;&lt;a href=&quot;#cb11-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-9&quot;&gt;&lt;a href=&quot;#cb11-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; src/cc/syms.h | 2 ++&lt;/span&gt;
&lt;span id=&quot;cb11-10&quot;&gt;&lt;a href=&quot;#cb11-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; 1 file changed, 2 insertions(+)&lt;/span&gt;
&lt;span id=&quot;cb11-11&quot;&gt;&lt;a href=&quot;#cb11-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-12&quot;&gt;&lt;a href=&quot;#cb11-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;diff --git a/src/cc/syms.h b/src/cc/syms.h&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-13&quot;&gt;&lt;a href=&quot;#cb11-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;index 3dffdda7..415fe28f 100644&lt;/span&gt;
&lt;span id=&quot;cb11-14&quot;&gt;&lt;a href=&quot;#cb11-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;--- a/src/cc/syms.h&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-15&quot;&gt;&lt;a href=&quot;#cb11-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;+++ b/src/cc/syms.h&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-16&quot;&gt;&lt;a href=&quot;#cb11-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;@@ -16,6 +16,7 @@&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-17&quot;&gt;&lt;a href=&quot;#cb11-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; #pragma once&lt;/span&gt;
&lt;span id=&quot;cb11-18&quot;&gt;&lt;a href=&quot;#cb11-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-19&quot;&gt;&lt;a href=&quot;#cb11-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; #include &amp;lt;algorithm&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb11-20&quot;&gt;&lt;a href=&quot;#cb11-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+#include &amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-21&quot;&gt;&lt;a href=&quot;#cb11-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; #include &amp;lt;memory&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb11-22&quot;&gt;&lt;a href=&quot;#cb11-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; #include &amp;lt;string&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb11-23&quot;&gt;&lt;a href=&quot;#cb11-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; #include &amp;lt;sys/types.h&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb11-24&quot;&gt;&lt;a href=&quot;#cb11-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;@@ -144,6 +145,7 @@ class ProcSyms : SymbolCache {&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-25&quot;&gt;&lt;a href=&quot;#cb11-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;       return proc_root_path_.c_str();&lt;/span&gt;
&lt;span id=&quot;cb11-26&quot;&gt;&lt;a href=&quot;#cb11-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     }&lt;/span&gt;
&lt;span id=&quot;cb11-27&quot;&gt;&lt;a href=&quot;#cb11-27&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     ~ModulePath() {&lt;/span&gt;
&lt;span id=&quot;cb11-28&quot;&gt;&lt;a href=&quot;#cb11-28&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+      std::cerr &amp;lt;&amp;lt; &amp;quot;XXX BCC: trying to ~ModulePath() close fd_=&amp;quot; &amp;lt;&amp;lt; fd_ &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-29&quot;&gt;&lt;a href=&quot;#cb11-29&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;       if (fd_ &amp;gt; 0)&lt;/span&gt;
&lt;span id=&quot;cb11-30&quot;&gt;&lt;a href=&quot;#cb11-30&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;         close(fd_);&lt;/span&gt;
&lt;span id=&quot;cb11-31&quot;&gt;&lt;a href=&quot;#cb11-31&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     }&lt;/span&gt;
&lt;span id=&quot;cb11-32&quot;&gt;&lt;a href=&quot;#cb11-32&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;--&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-33&quot;&gt;&lt;a href=&quot;#cb11-33&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;2.47.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And to the flake:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;patches = old.patches ++ [
    # Need to use pkgs.fetchpatch for remote patches or pkgs.writeText for local ones
    (pkgs.writeText &amp;quot;my-patch&amp;quot; (builtins.readFile ./0001-XXX-Log-ModulePath-close.patch))
];&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From this, we finally get:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;XXX BCC: trying to ~ModulePath() close fd_=1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So mystery solved. To validate, I applied this patch through the same
mechanism:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb14&quot;&gt;&lt;pre
class=&quot;sourceCode diff&quot;&gt;&lt;code class=&quot;sourceCode diff&quot;&gt;&lt;span id=&quot;cb14-1&quot;&gt;&lt;a href=&quot;#cb14-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;From 02fffe05dec4eca98da053d8f6d4741a758c184d Mon Sep 17 00:00:00 2001&lt;/span&gt;
&lt;span id=&quot;cb14-2&quot;&gt;&lt;a href=&quot;#cb14-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Message-ID: &amp;lt;02fffe05dec4eca98da053d8f6d4741a758c184d.1737137000.git.dxu@dxuuu.xyz&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb14-3&quot;&gt;&lt;a href=&quot;#cb14-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;From: Daniel Xu &amp;lt;dxu@dxuuu.xyz&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb14-4&quot;&gt;&lt;a href=&quot;#cb14-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Date: Fri, 17 Jan 2025 11:02:55 -0700&lt;/span&gt;
&lt;span id=&quot;cb14-5&quot;&gt;&lt;a href=&quot;#cb14-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Subject: [PATCH] XXX: FIX&lt;/span&gt;
&lt;span id=&quot;cb14-6&quot;&gt;&lt;a href=&quot;#cb14-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-7&quot;&gt;&lt;a href=&quot;#cb14-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;Signed-off-by: Daniel Xu &amp;lt;dxu@dxuuu.xyz&amp;gt;&lt;/span&gt;
&lt;span id=&quot;cb14-8&quot;&gt;&lt;a href=&quot;#cb14-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-9&quot;&gt;&lt;a href=&quot;#cb14-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; src/cc/syms.h | 2 +-&lt;/span&gt;
&lt;span id=&quot;cb14-10&quot;&gt;&lt;a href=&quot;#cb14-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt; 1 file changed, 1 insertion(+), 1 deletion(-)&lt;/span&gt;
&lt;span id=&quot;cb14-11&quot;&gt;&lt;a href=&quot;#cb14-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-12&quot;&gt;&lt;a href=&quot;#cb14-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;diff --git a/src/cc/syms.h b/src/cc/syms.h&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-13&quot;&gt;&lt;a href=&quot;#cb14-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;index 415fe28f..b9563e87 100644&lt;/span&gt;
&lt;span id=&quot;cb14-14&quot;&gt;&lt;a href=&quot;#cb14-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;--- a/src/cc/syms.h&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-15&quot;&gt;&lt;a href=&quot;#cb14-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;+++ b/src/cc/syms.h&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-16&quot;&gt;&lt;a href=&quot;#cb14-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;@@ -131,7 +131,7 @@ class ProcSyms : SymbolCache {&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-17&quot;&gt;&lt;a href=&quot;#cb14-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     // process by storing a file descriptor created from openat(2) if possible&lt;/span&gt;
&lt;span id=&quot;cb14-18&quot;&gt;&lt;a href=&quot;#cb14-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     // if openat fails, falls back to process-dependent path with /proc/.../root&lt;/span&gt;
&lt;span id=&quot;cb14-19&quot;&gt;&lt;a href=&quot;#cb14-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    private:&lt;/span&gt;
&lt;span id=&quot;cb14-20&quot;&gt;&lt;a href=&quot;#cb14-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;-    int fd_;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-21&quot;&gt;&lt;a href=&quot;#cb14-21&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;+    int fd_ = -1;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-22&quot;&gt;&lt;a href=&quot;#cb14-22&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     std::string proc_root_path_;&lt;/span&gt;
&lt;span id=&quot;cb14-23&quot;&gt;&lt;a href=&quot;#cb14-23&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     std::string path_;&lt;/span&gt;
&lt;span id=&quot;cb14-24&quot;&gt;&lt;a href=&quot;#cb14-24&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-25&quot;&gt;&lt;a href=&quot;#cb14-25&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;--&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb14-26&quot;&gt;&lt;a href=&quot;#cb14-26&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;dt&quot;&gt;2.47.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A 90 minute bake (failures usually appeared after 5 minutes) shows no
failures.&lt;/p&gt;
&lt;h3 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h3&gt;
&lt;p&gt;This is a really nasty bug. Arbitrarily closing file descriptors as a
library dependency is very not nice. Anything can happen. For bpftrace,
this is particularly risky, as bcc could’ve been closing probe file
descriptors which would lead to silent data loss.&lt;/p&gt;
&lt;p&gt;One takeaway I have is that as a tool’s developer, we are best
positioned to debug crazy mysteries like this. Our users likely have
very little chance of figuring this stuff out. So when we find an
alarming mystery (like truncated output!), we should be doing our best
to chase it to its conclusion.&lt;/p&gt;
&lt;p&gt;Also that making puns out of movie titles got pretty hard after 2
titles.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Nix dependency tree</title><id>https://dxuuu.xyz/nix-tree.html</id><updated>2025-02-09T14:10:00-08:00</updated><link href="https://dxuuu.xyz/nix-tree.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Nix dependency tree&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    /* The extra [class] is a hack that increases specificity enough to
       override a similar rule in reveal.js */
    ul.task-list[class]{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      font-size: inherit;
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Nix dependency tree&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;This tip is so useful to me but simultaneously so hard to find that
I’m going to dedicate an entire entry to it.&lt;/p&gt;
&lt;p&gt;How to find all the dependencies a flake output pulls in:&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ nix path-info .#bpftrace-llvm18
[..]
this derivation will be built:
  /nix/store/ada4fcj69rqqqxvdzg3f0gvwm6pmzrch-bpftrace.drv

$ nix-store --query --tree /nix/store/ada4fcj69rqqqxvdzg3f0gvwm6pmzrch-bpftrace.drv
/nix/store/ada4fcj69rqqqxvdzg3f0gvwm6pmzrch-bpftrace.drv
├───/nix/store/v6x3cs394jgqfbi0a42pam708flxaphh-default-builder.sh
├───/nix/store/s63zivn27i8qv5cqiy8r5hf48r323qwa-bash-5.2p37.drv
│   ├───/nix/store/05q48dcd4lgk4vh7wyk330gr2fr082i2-bootstrap-tools.drv
│   │   ├───/nix/store/0m4y3j4pnivlhhpr5yqdvlly86p93fwc-busybox.drv
[...]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There’s a lot of output, but the full dependency tree should be
there. It’ll help you answer questions like “why is XXX package being
pulled in?”.&lt;/p&gt;
&lt;p&gt;A secondary tip is that if a dependency is directly attached to your
root, it means some kind of Nix magic is pulling it in. For example, a
build rule could be directly referencing a package.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry><entry><title>Parameter-efficient fine-tuning in tinygrad</title><id>https://dxuuu.xyz/peft.html</id><updated>2026-01-01T10:04:04-08:00</updated><link href="https://dxuuu.xyz/peft.html" rel="alternate"/><content xml:base="https://dxuuu.xyz/" type="html">&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; lang=&quot;&quot; xml:lang=&quot;&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;generator&quot; content=&quot;pandoc&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, user-scalable=yes&quot; /&gt;
  &lt;title&gt;Parameter-efficient fine-tuning in tinygrad&lt;/title&gt;
  &lt;style&gt;
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    /* The extra [class] is a hack that increases specificity enough to
       override a similar rule in reveal.js */
    ul.task-list[class]{list-style: none;}
    ul.task-list li input[type=&quot;checkbox&quot;] {
      font-size: inherit;
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    pre &gt; code.sourceCode { white-space: pre; position: relative; }
    pre &gt; code.sourceCode &gt; span { line-height: 1.25; }
    pre &gt; code.sourceCode &gt; span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode &gt; span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre &gt; code.sourceCode { white-space: pre-wrap; }
    pre &gt; code.sourceCode &gt; span { display: inline-block; text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code &gt; span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code &gt; span &gt; a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre &gt; code.sourceCode &gt; span &gt; a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  &lt;/style&gt;
  &lt;link rel=&quot;stylesheet&quot; href=&quot;css/pandoc.css&quot; /&gt;
  &lt;a href=&quot;https://dxuuu.xyz&quot;&gt;Home&lt;/a&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header id=&quot;title-block-header&quot;&gt;
&lt;h1 class=&quot;title&quot;&gt;Parameter-efficient fine-tuning in tinygrad&lt;/h1&gt;
&lt;/header&gt;
&lt;p&gt;Parameter-efficient fine-tuning (PEFT) is a family of techniques used
to adapt LLMs (along with other types of large models) to specific tasks
or datasets. For example, if you had a private dataset from your legal
practice, you could take &lt;a
href=&quot;https://openai.com/index/introducing-gpt-oss/&quot;&gt;gpt-oss&lt;/a&gt; off the
shelf and customize it to be really good at your specific legal
specialty. Unlike full fine-tuning (FFT), with PEFT you only need to
update a subset of the weights in the model, leading to better
computational efficiency while requiring significantly less storage.&lt;/p&gt;
&lt;p&gt;This holiday season, I decided to implement &lt;a
href=&quot;https://arxiv.org/abs/2106.09685&quot;&gt;Low Rank Adaptation&lt;/a&gt; (LoRA)
using &lt;a href=&quot;https://github.com/tinygrad/tinygrad&quot;&gt;tinygrad&lt;/a&gt;.
Tinygrad because it was different enough from pytorch where I would
learn more but similar enough so that any learning would transfer.&lt;/p&gt;
&lt;h2 id=&quot;borrowing-from-tinygrad&quot;&gt;Borrowing from tinygrad&lt;/h2&gt;
&lt;p&gt;For this exercise I chose Llama 3.2 1B to build on, as I had a
tinygrad inference demo to base my work off of, as well as a 1B model
being quicker to iterate on. Much credit goes to tinygrad for providing
this example, as it would’ve been a much larger exercise to re-implement
the llama architecture by hand.&lt;/p&gt;
&lt;p&gt;While getting the tinygrad demo to work as-is, I found a nice bug
where the demo failed to account for Llama3 1B and 3B having &lt;a
href=&quot;https://arxiv.org/abs/1608.05859&quot;&gt;tied embeddings&lt;/a&gt;, for which I
&lt;a
href=&quot;https://github.com/tinygrad/tinygrad/commit/4edaaf19e5598c6e5325ffae263ae470ec2db6d3&quot;&gt;fixed
upstream&lt;/a&gt;. It was a small edge case that only triggered on the
smaller models, and only if using Huggingface safetensor checkpoints. I
suspect GGUF, when quantizing, denormalizes the input and output
embedding tensors.&lt;/p&gt;
&lt;h2 id=&quot;towards-full-fine-tuning&quot;&gt;Towards full fine-tuning&lt;/h2&gt;
&lt;p&gt;After that, to create a solid starting point, I inlined all the &lt;a
href=&quot;https://github.com/tinygrad/tinygrad/blob/2bb07d48241bc750b54b91938db409358c290ea6/examples/llama3.py&quot;&gt;code
from tinygrad examples&lt;/a&gt; into &lt;a
href=&quot;https://github.com/danobi/tinygrad-llama3/blob/e3b22823b3edf18fbc0dce3dff98d95f72798d19/main.py&quot;&gt;a
single file&lt;/a&gt; outside of the tinygrad tree. Might just be me, but a
single file ends up being a lot simpler to hack on that having a bunch
of files everywhere.&lt;/p&gt;
&lt;p&gt;With that, I started moving the code towards being trainable.
Training, at this point, implies FFT, as weight updates would apply to
all layers of the original base model. It ended up being fairly
straightforward and not missing that many things, namely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ensuring batch dimension worked, by &lt;a
href=&quot;https://github.com/danobi/tinygrad-llama3/commit/1cb29d418dbdbc8c96357c045f53d5ffee926b03&quot;&gt;forcing
batch prefill&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Making &lt;a
href=&quot;https://github.com/danobi/tinygrad-llama3/commit/702c2f13a71c06166b1060e5ef2359801d11772b&quot;&gt;forward
pass return logits&lt;/a&gt;, so I could calculate loss&lt;/li&gt;
&lt;li&gt;Implementing &lt;a
href=&quot;https://github.com/danobi/tinygrad-llama3/commit/30cc484311dc31261ba6313148f1e8008f535951&quot;&gt;weighted
cross entropy&lt;/a&gt; loss&lt;/li&gt;
&lt;li&gt;Removing the bf16 -&amp;gt; &lt;a
href=&quot;https://github.com/danobi/tinygrad-llama3/commit/3543b5eea05b3d672f79e39dae901c0fda96e80d&quot;&gt;float16
casts&lt;/a&gt; to stabilize training&lt;/li&gt;
&lt;li&gt;Adding &lt;a
href=&quot;https://github.com/danobi/tinygrad-llama3/commit/3f49d4cbd3c6035248d5bee23eaf5622e2e4f62d&quot;&gt;greedy&lt;/a&gt;
&lt;a
href=&quot;https://github.com/danobi/tinygrad-llama3/commit/d6948756f92018d9d66388dfd23368e95b1397ed&quot;&gt;sampling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With all the above, I could successfully adapt llama to speak pig
latin, following the general recipe for pig-latin &lt;a
href=&quot;https://tinker-docs.thinkingmachines.ai/training-sampling&quot;&gt;documented
in the Tinker quickstart&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ uv run main.py --model ~/weights/llama3.2-1b-instruct/ --size 1B
[..]
loaded weights in 2308.98 ms, 2.47 GB loaded at 1.07 GB/s
step 0: loss 9.0799
step 1: loss 5.8170
step 2: loss 3.4434
step 3: loss 2.0425
step 4: loss 1.1673
step 5: loss 0.5927
step 6: loss 0.2497

--- Inference ---
Input: hello world
Output: ellohay orldway&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note LoRA learning rates should be 10x higher than FFT (see &lt;a
href=&quot;https://thinkingmachines.ai/blog/lora/#optimal-learning-rates-for-lora-vs-fullft&quot;&gt;LoRA
without Regret&lt;/a&gt;), hence Tinker’s &lt;code&gt;1e-4&lt;/code&gt; vs my
&lt;code&gt;1e-5&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;lora-in-a-nutshell&quot;&gt;LoRA in a nutshell&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/2106.09685&quot;&gt;LoRA&lt;/a&gt; is a popular PEFT
method. In short, it “attaches” to targetted layers in the base model
and replaces it with a modified version. For each targetted layer, given
base weights &lt;span class=&quot;math inline&quot;&gt;&lt;em&gt;W&lt;/em&gt;&lt;/span&gt; with shape
&lt;span class=&quot;math inline&quot;&gt;(&lt;em&gt;X&lt;/em&gt;, &lt;em&gt;Y&lt;/em&gt;)&lt;/span&gt;, LoRA replaces
the layer with:&lt;/p&gt;
&lt;p&gt;&lt;span
class=&quot;math display&quot;&gt;&lt;em&gt;W&lt;/em&gt;′ = &lt;em&gt;W&lt;/em&gt; + &lt;em&gt;γ&lt;/em&gt;&lt;em&gt;B&lt;/em&gt;&lt;em&gt;A&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class=&quot;math inline&quot;&gt;&lt;em&gt;γ&lt;/em&gt;&lt;/span&gt; is a constant
scaling factor, &lt;span class=&quot;math inline&quot;&gt;&lt;em&gt;A&lt;/em&gt;&lt;/span&gt; is a matrix
with shape &lt;span class=&quot;math inline&quot;&gt;(&lt;em&gt;r&lt;/em&gt;, &lt;em&gt;Y&lt;/em&gt;)&lt;/span&gt;,
&lt;span class=&quot;math inline&quot;&gt;&lt;em&gt;B&lt;/em&gt;&lt;/span&gt; is a matrix with shape &lt;span
class=&quot;math inline&quot;&gt;(&lt;em&gt;X&lt;/em&gt;, &lt;em&gt;r&lt;/em&gt;)&lt;/span&gt;, and &lt;span
class=&quot;math inline&quot;&gt;&lt;em&gt;r&lt;/em&gt;&lt;/span&gt; is a rank, tunable to match the
capacity needed for a task. During weight updates, &lt;span
class=&quot;math inline&quot;&gt;&lt;em&gt;W&lt;/em&gt;&lt;/span&gt; is frozen - only &lt;span
class=&quot;math inline&quot;&gt;&lt;em&gt;B&lt;/em&gt;&lt;/span&gt; and &lt;span
class=&quot;math inline&quot;&gt;&lt;em&gt;A&lt;/em&gt;&lt;/span&gt; are updated. There are a bunch of
benefits to this technique that I won’t redescribe - the reader is
encouraged to consult the referenced literature.&lt;/p&gt;
&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;/h2&gt;
&lt;p&gt;The implementation is fairly straightforward, especially if you’re
not writing production grade code. There are two parts: a generic LoRA
layer to perform the &lt;span class=&quot;math inline&quot;&gt;&lt;em&gt;W&lt;/em&gt;′&lt;/span&gt; update
and a mechanism to attach the LoRA to relevent base weights.&lt;/p&gt;
&lt;p&gt;For the LoRA layer:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre
class=&quot;sourceCode python&quot;&gt;&lt;code class=&quot;sourceCode python&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a href=&quot;#cb2-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;class&lt;/span&gt; LoraLinearLayer:&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a href=&quot;#cb2-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;__init__&lt;/span&gt;(&lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;, base_layer, rank:&lt;span class=&quot;bu&quot;&gt;int&lt;/span&gt;, alpha:&lt;span class=&quot;bu&quot;&gt;float&lt;/span&gt;):&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a href=&quot;#cb2-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.base_layer &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; base_layer&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a href=&quot;#cb2-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.out_features, &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.in_features &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.base_layer.weight.shape&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a href=&quot;#cb2-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a href=&quot;#cb2-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.lora_A &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; nn.Linear(&lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.in_features, rank, bias&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a href=&quot;#cb2-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.lora_B &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; nn.Linear(rank, &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.out_features, bias&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a href=&quot;#cb2-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.lora_B.weight &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; Tensor.zeros(&lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.out_features, rank)&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a href=&quot;#cb2-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.scaling &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; alpha &lt;span class=&quot;op&quot;&gt;/&lt;/span&gt; rank&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a href=&quot;#cb2-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a href=&quot;#cb2-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;__call__&lt;/span&gt;(&lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;, &lt;span class=&quot;bu&quot;&gt;input&lt;/span&gt;:Tensor, &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;args, &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt;kwargs):&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a href=&quot;#cb2-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    result &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.base_layer(&lt;span class=&quot;bu&quot;&gt;input&lt;/span&gt;, &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;args, &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt;kwargs)&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a href=&quot;#cb2-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    lora_result &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; result &lt;span class=&quot;op&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.lora_B(&lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.lora_A(&lt;span class=&quot;bu&quot;&gt;input&lt;/span&gt;)) &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.scaling&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a href=&quot;#cb2-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; lora_result&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and for the attachment:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre
class=&quot;sourceCode python&quot;&gt;&lt;code class=&quot;sourceCode python&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;class&lt;/span&gt; Lora:&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  LORA_LAYERS &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; {&lt;span class=&quot;st&quot;&gt;&amp;quot;feed_forward&amp;quot;&lt;/span&gt;, &lt;span class=&quot;st&quot;&gt;&amp;quot;attention&amp;quot;&lt;/span&gt;, &lt;span class=&quot;st&quot;&gt;&amp;quot;output&amp;quot;&lt;/span&gt;}&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-4&quot;&gt;&lt;a href=&quot;#cb3-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;__init__&lt;/span&gt;(&lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;, model, rank:&lt;span class=&quot;bu&quot;&gt;int&lt;/span&gt;, alpha:&lt;span class=&quot;bu&quot;&gt;float&lt;/span&gt;, linear&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;nn.Linear):&lt;/span&gt;
&lt;span id=&quot;cb3-5&quot;&gt;&lt;a href=&quot;#cb3-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    linear_modules &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; []&lt;/span&gt;
&lt;span id=&quot;cb3-6&quot;&gt;&lt;a href=&quot;#cb3-6&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; name, module &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; named_modules(model):&lt;/span&gt;
&lt;span id=&quot;cb3-7&quot;&gt;&lt;a href=&quot;#cb3-7&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;any&lt;/span&gt;(s &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; name &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; s &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.LORA_LAYERS) &lt;span class=&quot;kw&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;isinstance&lt;/span&gt;(module, linear):&lt;/span&gt;
&lt;span id=&quot;cb3-8&quot;&gt;&lt;a href=&quot;#cb3-8&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;        linear_modules.append((name, module))&lt;/span&gt;
&lt;span id=&quot;cb3-9&quot;&gt;&lt;a href=&quot;#cb3-9&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-10&quot;&gt;&lt;a href=&quot;#cb3-10&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;# Freeze base weights&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-11&quot;&gt;&lt;a href=&quot;#cb3-11&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.model &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; model&lt;/span&gt;
&lt;span id=&quot;cb3-12&quot;&gt;&lt;a href=&quot;#cb3-12&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; param &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; get_parameters(&lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.model):&lt;/span&gt;
&lt;span id=&quot;cb3-13&quot;&gt;&lt;a href=&quot;#cb3-13&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      param.requires_grad_(&lt;span class=&quot;va&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb3-14&quot;&gt;&lt;a href=&quot;#cb3-14&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-15&quot;&gt;&lt;a href=&quot;#cb3-15&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;for&lt;/span&gt; name, linear &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; linear_modules:&lt;/span&gt;
&lt;span id=&quot;cb3-16&quot;&gt;&lt;a href=&quot;#cb3-16&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      lora &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; LoraLinearLayer(linear, rank, alpha)&lt;/span&gt;
&lt;span id=&quot;cb3-17&quot;&gt;&lt;a href=&quot;#cb3-17&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;      nested_setattr(model, name, lora)&lt;/span&gt;
&lt;span id=&quot;cb3-18&quot;&gt;&lt;a href=&quot;#cb3-18&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-19&quot;&gt;&lt;a href=&quot;#cb3-19&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;kw&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;__call__&lt;/span&gt;(&lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;, &lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;args, &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt;kwargs):&lt;/span&gt;
&lt;span id=&quot;cb3-20&quot;&gt;&lt;a href=&quot;#cb3-20&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.model(&lt;span class=&quot;op&quot;&gt;*&lt;/span&gt;args, &lt;span class=&quot;op&quot;&gt;**&lt;/span&gt;kwargs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Applying LoRA to the full fine-tunable model is simple:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre
class=&quot;sourceCode python&quot;&gt;&lt;code class=&quot;sourceCode python&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;model &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; build_transformer(args.model, model_size&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;args.size, device&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;device, disable_kv_cache&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;not&lt;/span&gt; args.chat)&lt;/span&gt;
&lt;span id=&quot;cb4-2&quot;&gt;&lt;a href=&quot;#cb4-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; args.lora:&lt;/span&gt;
&lt;span id=&quot;cb4-3&quot;&gt;&lt;a href=&quot;#cb4-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;  model &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; Lora(model, rank&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;, alpha&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dv&quot;&gt;32&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb4-4&quot;&gt;&lt;a href=&quot;#cb4-4&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;[..]&lt;/span&gt;
&lt;span id=&quot;cb4-5&quot;&gt;&lt;a href=&quot;#cb4-5&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;train(model, args)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using &lt;span class=&quot;math inline&quot;&gt;&lt;em&gt;r&lt;/em&gt; = 4&lt;/span&gt; with a fixed
&lt;span class=&quot;math inline&quot;&gt;&lt;em&gt;α&lt;/em&gt; = 25&lt;/span&gt; (thus &lt;span
class=&quot;math inline&quot;&gt;&lt;em&gt;γ&lt;/em&gt; = 25/4 = 6.25&lt;/span&gt;), we get:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ uv run main.py --model ~/weights/llama3.2-1b-instruct/ --size 1B --lora
[..]
loaded weights in 2273.75 ms, 2.47 GB loaded at 1.09 GB/s
step 0: loss 9.0882
step 1: loss 6.6885
step 2: loss 3.7176
step 3: loss 2.0421
step 4: loss 1.1277
step 5: loss 0.5100
step 6: loss 0.1654

--- Inference ---
Input: hello world
Output: ellohay orld-way&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The astute reader will notice the output isn’t exactly identical to
the FFT output. If I had to guess, it’d be that it’s a combination of
the training corpus being too limited and the model size being too
small, or more likely scenario of me messing up the implementation
somewhere.&lt;/p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing thoughts&lt;/h2&gt;
&lt;p&gt;This was a pretty fun exercise where I ended up going just a bit
deeper than I expected, which is always nice, especially if something
kind-of works by the end.&lt;/p&gt;
&lt;p&gt;With respect to tinygrad, I thoroughly enjoyed using the framework.
Despite the docs not being as full featured as I would’ve liked, the
internals were extremely hackable, so I didn’t mind at all reading the
code to answer my questions.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</content></entry></feed>
