| # Inspect VMO file format | 
 |  | 
 | [TOC] | 
 |  | 
 | This document describes the **Component Inspection File Format** (Inspect Format). | 
 |  | 
 | Files formatted using the Inspect Format are known as **Inspect Files**, | 
 | which commonly have a `.inspect` file extension. | 
 |  | 
 | For information on how to change the format. Please see | 
 | [Extending the Inspect file format][updating-format] | 
 |  | 
 | # Overview | 
 |  | 
 | [Component Inspection][inspect] provides components with the ability to | 
 | expose structured, hierarchical information about their state at runtime. | 
 |  | 
 | Components host a mapped Virtual Memory Object ([VMO]) using the Inspect | 
 | Format to expose an **Inspect Hierarchy** containing this internal state. | 
 |  | 
 | An Inspect Hierarchy consists of nested **Nodes** containing typed **Properties**. | 
 |  | 
 | ## Goals | 
 |  | 
 | The Inspect Format described in this document has the following goals: | 
 |  | 
 | - **Low-overhead mutations to data** | 
 |  | 
 | The Inspect File Format allows data to be changed in-place. For instance, | 
 | the overhead of incrementing an integer is ~2 atomic increments. | 
 |  | 
 | - **Support a non-static hierarchy** | 
 |  | 
 | The hierarchy stored in an Inspect File can be modified at | 
 | runtime. Children can be added or removed from the hierarchy at any | 
 | time. In this way, the hierarchy can closely represent the hierarchy of | 
 | objects in the component's working set. | 
 |  | 
 | - **Single writer, multiple reader concurrency without explicit synchronization** | 
 |  | 
 | Readers operating concurrently with the writer map the VMO and attempt to | 
 | take a snapshot of the data. Writers indicate being in a critical section | 
 | though a *generation counter* that requires no explicit synchronization | 
 | with readers. Readers use the generation counter to determine when a | 
 | snapshot of the VMO is consistent and may be safely read. | 
 |  | 
 | - **Data may remain available after component termination** | 
 |  | 
 | A reader may maintain a handle to the VMO containing Inspect data even | 
 | after the writing component terminates. | 
 |  | 
 | [inspect]: /docs/development/diagnostics/inspect/README.md | 
 | [updating-format]: /docs/reference/diagnostics/inspect/updating-vmo-format.md | 
 |  | 
 | ## Terminology | 
 |  | 
 | This section defines common terminology used in this document. | 
 |  | 
 | * Inspect File - A bounded sequence of bytes using the format described in this document. | 
 | * Inspect VMO - An Inspect File stored in a Virtual Memory Object (VMO). | 
 | * Block - A sized section of an Inspect File. Blocks have an Index and an Order. | 
 | * Index - A unique identifier for a particular Block. `byte_offset = index * 16` | 
 | * Order - The size of a block given as a bit shift from the minimum | 
 |           size. `size_in_bytes = 16 << order`. Separates blocks into | 
 |           classes by their (power of two) size. | 
 | * Node  - A named value in the hierarchy under which other values may | 
 |           be nested. Only Nodes may be parents in the Hierarchy. | 
 | * Property - A named value that contains typed data (e.g. String, | 
 |              Integer, etc). | 
 | * Hierarchy - A tree of Nodes, descending from a single "root" node, that | 
 |               may each contain Properties. An Inspect File contains a | 
 |               single Hierarchy. | 
 |  | 
 | This document uses MUST, SHOULD/RECOMMENDED, and MAY keywords as defined in [RFC 2119][rfc2119] | 
 |  | 
 | All bit field diagrams are stored in little-endian ordering. | 
 |  | 
 | Note: For reference on how to read the bit field diagrams, see | 
 | [Bitfield Diagram reference][bitfield-diagram]. | 
 |  | 
 | # Blocks | 
 |  | 
 | Inspect files are split into a number of `Blocks` whose size must be a | 
 | power of 2. | 
 |  | 
 | The minimum block size must be 16 bytes (`MIN_BLOCK_SIZE`) and the | 
 | maximum block size must be a multiple of 16 bytes. Implementers are | 
 | recommended specify a maximum block size less than the size of a page | 
 | (typically 4096 bytes). In our reference implementation, the maximum | 
 | block size is 2048 bytes (`MAX_BLOCK_SIZE`). | 
 |  | 
 | All blocks must be aligned on 16-byte boundaries, and addressing within | 
 | the VMO is in terms of an Index, specifying a 16-byte offsets (`offset = | 
 | index * 16`). | 
 |  | 
 | We use 28 bits for indexes, so Inspect Files may be at most 4GiB. | 
 |  | 
 | A `block_header` consists of 16 bytes as follows: | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------------------------------| | 
 | | O | R | Type  |                                               | | 
 | |---------------------------------------------------------------| | 
 | |                                                               | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | The rest (left blank) depends on the payload | 
 | ``` | 
 |  | 
 | Each block has an `order`, specifying its size. | 
 |  | 
 | If the maximum block size is 2048 bytes, then there are 8 possible block | 
 | orders (`NUM_ORDERS`), numbered 0...7, corresponding to blocks of sizes | 
 | 16, 32, 64, 128, 256, 512, 1024, and 2048 bytes respectively. | 
 |  | 
 | Each block also has a type, which is used to determine how the rest of | 
 | the bytes in the block are to be interpreted. | 
 |  | 
 | ## Buddy Allocation | 
 |  | 
 | This block layout permits efficient allocation of blocks using [buddy | 
 | allocation][buddy]. Buddy allocation is the recommended allocation | 
 | strategy, but it is not a requirement for using the Inspect Format. | 
 |  | 
 | # Types | 
 |  | 
 | All the supported types are defined in | 
 | [//zircon/system/ulib/inspect/include/lib/inspect/cpp/vmo/block.h][block.h] | 
 | which fall into categories as follows: | 
 |  | 
 | enum             | value | type name | category | 
 | -----------------|-------|----------------|------- | 
 | `kFree`          | 0     | `FREE`             | Internal | 
 | `kReserved`      | 1     | `RESERVED`         | Internal | 
 | `kHeader`        | 2     | `HEADER`           | Header | 
 | `kNodeValue`     | 3     | `NODE_VALUE`       | Value | 
 | `kIntValue`      | 4     | `INT_VALUE`        | Value | 
 | `kUintValue`     | 5     | `UINT_VALUE`       | Value | 
 | `kDoubleValue`   | 6     | `DOUBLE_VALUE`     | Value | 
 | `kBufferValue`   | 7     | `BUFFER_VALUE`     | Value | 
 | `kExtent`        | 8     | `EXTENT`           | Extent | 
 | `kName`          | 9     | `NAME`             | Name | 
 | `kTombstone`     | 10    | `TOMBSTONE`        | Value | 
 | `kArrayValue`    | 11    | `ARRAY_VALUE`      | Value | 
 | `kLinkValue`     | 12    | `LINK_VALUE`       | Value | 
 | `kBoolValue`     | 13    | `BOOL_VALUE`       | Value | 
 |  | 
 | * *Internal* - These types are provided for implementing block allocation, and | 
 | they must be ignored by readers. | 
 |  | 
 | * *Header* - This type allows readers to detect Inspect Files and reason | 
 | about snapshot consistency. This block must exist at index 0. | 
 |  | 
 | * *Value* - These types appear directly in the hierarchy. Values must have a *Name* | 
 | and a parent (which must be a `NODE_VALUE`). | 
 |  | 
 | * *Extent* - This type stores long binary data that may not fit in a single block. | 
 |  | 
 | * *Name* - This type stores binary data that fits in a single block, | 
 | and it is typically used to store the name of values. | 
 |  | 
 | Each type interprets the payload differently, as follows: | 
 |  | 
 | * [FREE](#free) | 
 | * [RESERVED](#reserved) | 
 | * [HEADER](#header) | 
 | * [Common VALUE fields](#value) | 
 | * [NODE\_VALUE](#node) | 
 | * [INT\_VALUE](#numeric) | 
 | * [UINT\_VALUE](#numeric) | 
 | * [DOUBLE\_VALUE](#numeric) | 
 | * [BUFFER\_VALUE](#buffer_value) | 
 | * [EXTENT](#extent) | 
 | * [NAME](#name) | 
 | * [TOMBSTONE](#node) | 
 | * [ARRAY\_VALUE](#array) | 
 | * [LINK](#link) | 
 | * [BOOL\_VALUE](#numeric) | 
 |  | 
 | ## FREE {#free} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------+-----------------------| | 
 | | O | R | Type  | Next free block       |                       | | 
 | |---------------------------------------------------------------| | 
 | |                                                               | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = 0 | 
 | Next free block = index (optional) | 
 | ``` | 
 |  | 
 | A `FREE` block is available for allocation. Importantly, the zero-valued | 
 | block (16 bytes of `\0`) is interpreted as a `FREE` block of order 0, | 
 | so buffers may simply be zeroed to free all blocks. | 
 |  | 
 | Writer implementations may use the unused bits from 8..63 of `FREE` | 
 | blocks for any purpose. Writer implementation must set all other unused | 
 | bits to 0. | 
 |  | 
 | It is recommended that writers use the location specified above to store | 
 | the index of the next free block of the same order. Using this field, | 
 | free blocks may create singly linked lists of free blocks of each size | 
 | for fast allocation. The end of the list is reached when NextFreeBlock | 
 | points to a location that is either not `FREE` or not of the same order | 
 | (commonly the Header block at index 0). | 
 |  | 
 | ## RESERVED {#reserved} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------------------------------| | 
 | | O | R | Type  |                                               | | 
 | |---------------------------------------------------------------| | 
 | |                                                               | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = 1 | 
 | ``` | 
 |  | 
 | `RESERVED` blocks are simply available to be changed to a different | 
 | type.  It is an optional transitional state between the allocation of a | 
 | block and setting its type that is useful for correctness checking of | 
 | implementations (to ensure that blocks that are about to be used are | 
 | not treated as free). | 
 |  | 
 | ## HEADER {#header} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+---------------+-------------------------------| | 
 | | O | R | Type  | Version       | Magic number                  | | 
 | |---------------------------------------------------------------| | 
 | | Generation count                                              | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = 2 | 
 | Version = 1 | 
 | Magic number = "INSP" | 
 | ``` | 
 |  | 
 | There must be one `HEADER` block at the beginning of the file. It consists | 
 | of a **Magic Number** ("INSP"), a **Version** (currently 1), and the | 
 | **Generation Count** for concurrency control. The first byte of the header | 
 | must not be a valid ASCII character. | 
 |  | 
 | See the [next section](#concurrency) for how concurrency control must be | 
 | implemented using the generation count. | 
 |  | 
 | ## NODE\_VALUE and TOMBSTONE {#node} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------+-----------------------| | 
 | | O | R | Type  | Parent index          | Name index            | | 
 | |---------------------------------------------------------------| | 
 | | Reference count (optional)                                    | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = {3,10} | 
 | ``` | 
 |  | 
 | Nodes are anchor points for further nesting, and the `ParentID` field | 
 | of values must only refer to blocks of type `NODE_VALUE`. | 
 |  | 
 | `NODE_VALUE` blocks support optional *reference counting* and *tombstoning* | 
 | to permit efficient implementations as follows: | 
 |  | 
 | The `Refcount` field may contain the number of values referencing a given | 
 | `NODE_VALUE` as their parent. On deletion, the `NODE_VALUE` becomes a new | 
 | special type called `TOMBSTONE`. `TOMBSTONE`s are deleted only when their | 
 | `Refcount` is 0. | 
 |  | 
 | This allows for writer implementations that do not need to explicitly | 
 | keep track of children for Nodes, and it prevents the following scenario: | 
 |  | 
 | ``` | 
 | // "b" has a parent "a" | 
 | Index | Value | 
 | 0     | HEADER | 
 | 1     | NODE "a", parent 0 | 
 | 2     | NODE "b", parent 1 | 
 |  | 
 | /* delete "a", allocate "c" as a child of "b" which reuses index 1 */ | 
 |  | 
 | // "b"'s parent is now suddenly "c", introducing a cycle! | 
 | Index | Value | 
 | 0     | HEADER | 
 | 1     | NODE "c", parent 2 | 
 | 2     | NODE "b", parent 1 | 
 | ``` | 
 |  | 
 | ## \{INT,UINT,DOUBLE,BOOL\}\_VALUE {#numeric} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------+-----------------------| | 
 | | O | R | Type  | Parent index          | Name index            | | 
 | |---------------------------------------------------------------| | 
 | | Inlined numeric value                                         | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = {4,5,6,13} | 
 | ``` | 
 |  | 
 | Numeric `VALUE` blocks all contain the 64-bit numeric type inlined into | 
 | the second 8 bytes of the block. | 
 |  | 
 | ## BUFFER\_VALUE {#buffer_value} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------+-----------------------| | 
 | | O | R | Type  | Parent index          | Name index            | | 
 | |---------------------------------------------------------------| | 
 | | Total length                  | Extent index              | F | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = 7 | 
 | Total length = size of the buffer | 
 | Extent index = index of the first extent containing bytes for the buffer | 
 | F = Display format {0,1} | 
 | ``` | 
 |  | 
 | General `BUFFER_VALUE` blocks reference arbitrary byte data across | 
 | one or more linked `EXTENT` blocks. | 
 |  | 
 | `BUFFER_VALUE` blocks contain the index of the first `EXTENT` block holding | 
 | the binary data, and they contain the total length of the data in bytes | 
 | across all extents. | 
 |  | 
 | The format flags specify how the byte data should be interpreted, | 
 | as follows: | 
 |  | 
 | Enum    | Value | Meaning | 
 | ----    | ----  | ---- | 
 | kUtf8   | 0     | The byte data may be interpreted as a UTF-8 string. | 
 | kBinary | 1     | The byte data is arbitrary binary data and may not be printable. | 
 |  | 
 | ## EXTENT {#extent} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------+-----------------------| | 
 | | O | R | Type  | Next extent index     | R                     | | 
 | |---------------------------------------------------------------| | 
 | | Payload                                                       | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = 8 | 
 | Next extent index = index of next extent in the chain | 
 | Extent index = index of the extent containing bytes for the string | 
 | Payload = byte data payload up to at most the end of the block. Size | 
 |           depends on the order | 
 | ``` | 
 |  | 
 | `EXTENT` blocks contain an arbitrary byte data payload and the index of | 
 | the next `EXTENT` in the chain. The byte data for an buffer_value is retrieved | 
 | by reading each `EXTENT` in order until **Total Length** bytes are read. | 
 |  | 
 | ## NAME {#name} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------------------------------| | 
 | | O | R | Type  | Length    | Reserved                          | | 
 | |---------------------------------------------------------------| | 
 | | Payload                                                       | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = 9 | 
 | Payload = contents of the name. Size depends on the order | 
 | ``` | 
 |  | 
 | `NAME` blocks give objects and values a human-readable identifier. They | 
 | consist of a UTF-8 payload that fits entirely within the given block. | 
 |  | 
 | ## ARRAY\_VALUE {#array} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------+-----------------------| | 
 | | O | R | Type  | Parent index          | Name index            | | 
 | |---------------------------------------------------------------| | 
 | | T | F | Count | Reserved                                      | | 
 | |---------------------------------------------------------------| | 
 | | Payload                                                       | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = 11 | 
 | T = Type of the stored values {4,5,6} | 
 | F = Display format {0,1,2} | 
 | Count = Count of stored values | 
 | Payload = array of size |count| | 
 | ``` | 
 |  | 
 | `ARRAY_VALUE` blocks contain an array of specifically 64-bit numeric | 
 | values.  The **Stored Value Type** field is interpreted exactly like | 
 | the **Type** field, but may only indicate `INT_VALUE`, `UINT_VALUE`, or | 
 | `DOUBLE_VALUE`. | 
 |  | 
 | Exactly **Count** entries of the given **Stored Value Type** appear in | 
 | the bytes at offset 16 into the block. | 
 |  | 
 | The **Display Format** field is used to affect how the array should be | 
 | displayed, and it is interpreted as follows: | 
 |  | 
 | Enum                  | Value | Description | 
 | ---------             | ----  | ---- | 
 | kFlat                 | 0     | Display as an ordered flat array with no additional formatting. | 
 | kLinearHistogram      | 1     | Interpret the first two entries as `floor` and `step_size` parameters for a linear histogram, as defined below. | 
 | kExponentialHistogram | 2     | Interpret the first three entries as `floor`, `initial_step`, and `step_multiplier` for an exponential histogram, as defined below. | 
 |  | 
 | ### Linear Histogram | 
 |  | 
 | The array is a linear histogram that stores its parameters inline and | 
 | contains both an overflow and underflow bucket. | 
 |  | 
 | The first two elements are parameters `floor` and `step_size`, respectively | 
 | (as defined below). | 
 |  | 
 | The number of buckets (N) is implicitly `Count - 4`. | 
 |  | 
 | The remaining elements are buckets: | 
 |  | 
 | ``` | 
 | 2:     (-inf, floor), | 
 | 3:     [floor, floor+step_size), | 
 | i+3:   [floor + step_size*i, floor + step_size*(i+1)), | 
 | ... | 
 | N+3:   [floor+step_size*N, +inf) | 
 | ``` | 
 |  | 
 | ### Exponential Histogram | 
 |  | 
 | The array is an exponential histogram that stores its parameters inline | 
 | and contains both an overflow and underflow bucket. | 
 |  | 
 | The first three elements are parameters `floor`, `initial_step`, and | 
 | `step_multiplier` respectively (as defined below). | 
 |  | 
 | The number of buckets (N) is implicitly Count - 5. | 
 |  | 
 | The remaining are buckets: | 
 |  | 
 | ``` | 
 | 3:     (-inf, floor), | 
 | 4:     [floor, floor+initial_step), | 
 | i+4:   [floor + initial_step * step_multiplier^i, floor + initial_step * step_multiplier^(i+1)) | 
 | N+4:   [floor + initial_step * step_multiplier^N, +inf) | 
 | ``` | 
 |  | 
 | ## LINK\_VALUE {#link} | 
 |  | 
 | ``` | 
 | .---------------------------------------------------------------. | 
 | |       |1|1|1|1|1|2|2|2|2|2|3|3|3|3|3|4|4|4|4|4|5|5|5|5|5|6|6|6| | 
 | |2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4|6|8|0|2|4| | 
 | |---+---+-------+-----------------------------------------------| | 
 | | O | R | Type  | Parent index          | Name index            | | 
 | |---------------------------------------------------------------| | 
 | | Content index     |                                       | F | | 
 | '---------------------------------------------------------------' | 
 |  | 
 | O = Order | 
 | R = Reserved, must be 0 | 
 | Type = 12 | 
 | Parent index = Index of the parent block | 
 | Name index = Index of the name of this value | 
 | Content index = Index of the content of this link (as a NAME node) | 
 | F = Disposition flags {0,1} | 
 | ``` | 
 |  | 
 | `LINK_VALUE` blocks allow nodes to support children that are present | 
 | in a separate Inspect File. | 
 |  | 
 | The **Content Index** specifies another `NAME` block whose contents | 
 | are a unique identifier referring to another Inspect File. Readers are | 
 | expected to obtain a bundle of `(Identifier, File)` pairs (through either | 
 | a directory read or another interface) and they may attempt to follow | 
 | links by splicing the trees together using the stored identifiers. | 
 |  | 
 | The **Disposition Flags** instruct readers on how to splice the trees, as follows: | 
 |  | 
 | Enum               | Value | Description | 
 | ----               | ----  | ---- | 
 | kChildDisposition  | 0     | The hierarchy stored in the linked file should be a child of the `LINK_VALUE`'s parent. | 
 | kInlineDisposition | 1     | The children and properties of the root stored in the linked file should be added to the `LINK_VALUE`'s parent. | 
 |  | 
 | For example: | 
 |  | 
 | ``` | 
 | // root.inspect | 
 | root: | 
 |   int_value = 10 | 
 |   child = LINK("other.inspect") | 
 |  | 
 | // other.inspect | 
 | root: | 
 |   test = "Hello World" | 
 |   next: | 
 |     value = 0 | 
 |  | 
 |  | 
 | // kChildDisposition produces: | 
 | root: | 
 |   int_value = 10 | 
 |   child: | 
 |     test = "Hello World" | 
 |     next: | 
 |       value = 0 | 
 |  | 
 | // kInlineDisposition produces: | 
 | root: | 
 |   int_value = 10 | 
 |   test = "Hello World" | 
 |   next: | 
 |     value = 0 | 
 | ``` | 
 |  | 
 | Note: In all cases the name of the root node in the linked file is ignored. | 
 |  | 
 | In the event of a collision in child names between a Node and values being | 
 | added by its inline linked child, precedence is reader defined. Most | 
 | readers, however, would find it useful to have linked values take | 
 | precedence so they may override the original values. | 
 |  | 
 | # Concurrency Control {#concurrency} | 
 |  | 
 | Writers must use a global version counter so that readers can | 
 | detect in-flight modifications and modifications between reads without | 
 | communicating with the writer. This supports single-writer multi-reader | 
 | concurrency. | 
 |  | 
 | The strategy is for writers to increment a global *generation counter* | 
 | both when they begin and when they end a write operation. | 
 |  | 
 | This is a simple strategy with a significant benefit: between incrementing | 
 | the version number for beginning and ending a write the writer can perform | 
 | any number of operations on the buffer without regard for atomicity of | 
 | data updates. | 
 |  | 
 | The main drawback is that reads could be delayed indefinitely due to a | 
 | frequently updating writer, but readers can have mitigations in place | 
 | in practice. | 
 |  | 
 | ## Reader Algorithm | 
 |  | 
 | Readers use the following algorithm to obtain a consistent snapshot of | 
 | an Inspect VMO: | 
 |  | 
 | 1. Spinlock until the version number is even (no concurrent write), | 
 | 2. Copy the entire VMO buffer, and | 
 | 3. Check that the version number from the buffer is equal to the version | 
 | number from step 1. | 
 |  | 
 | As long as the version numbers match, the client may read their local | 
 | copy to construct the shared state. | 
 | If the version numbers do not match, the client may retry the whole | 
 | process. | 
 |  | 
 |  | 
 | ## Writer Lock Algorithm | 
 |  | 
 | Writers lock an Inspect VMO for modification by doing the following: | 
 |  | 
 | ```c | 
 | atomically_increment(generation_counter, acquire_ordering); | 
 | ``` | 
 |  | 
 | This locks the file against concurrent reads by setting the generation to an | 
 | odd number. Acquire ordering ensures that loads are not reordered before | 
 | this change. | 
 |  | 
 | ## Writer Unlock Algorithm | 
 |  | 
 | Writers unlock an Inspect VMO following modification by doing the | 
 | following: | 
 |  | 
 | ```c | 
 | atomically_increment(generation_counter, release_ordering); | 
 | ``` | 
 |  | 
 | Unlock the file allowing concurrent reads by setting the generation to | 
 | a new even number. Release ordering ensures that writes to the file are | 
 | visible before the generation count update is visible. | 
 |  | 
 | <!-- xrefs --> | 
 | [bitfield-diagram]: /docs/reference/diagnostics/bitfield-diagram.md | 
 | [block.h]: /zircon/system/ulib/inspect/include/lib/inspect/cpp/vmo/block.h | 
 | [buddy]: https://en.wikipedia.org/wiki/Buddy_memory_allocation | 
 | [rfc2119]: https://www.ietf.org/rfc/rfc2119.txt | 
 | [VMO]: /docs/reference/kernel_objects/vm_object.md |