btrfs_stream: GraphViz block diagram (.dot) source

Btrfs is a copy on write file system based on B-trees focusing on fault tolerance, repair and easy administration. Btrfs is intended to address the lack of pooling, snapshots, checksums, and integral multi-device spanning in Linux file systems. Given any pair of subvolumes (or snapshots), Btrfs can generate a binary diff between them by using the btrfs send command that can be replayed later by using btrfs receive, possibly on a different Btrfs file system. The btrfs send command creates a set of data modifications required for converting one subvolume into another. This spec can be used to disassemble the binary diff created by the btrfs send command. If you want a text representation you may want to checkout btrfs receive --dump instead.

Application

Btrfs

KS implementation details

License: CC0-1.0

References

This page hosts a formal specification of btrfs_stream using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

GraphViz block diagram source

btrfs_stream.dot

digraph {
	rankdir=LR;
	node [shape=plaintext];
	subgraph cluster__btrfs_stream {
		label="BtrfsStream";
		graph[style=dotted];

		btrfs_stream__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
			<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
			<TR><TD PORT="header_pos">0</TD><TD PORT="header_size">17</TD><TD>SendStreamHeader</TD><TD PORT="header_type">header</TD></TR>
			<TR><TD PORT="commands_pos">17</TD><TD PORT="commands_size">...</TD><TD>SendCommand</TD><TD PORT="commands_type">commands</TD></TR>
			<TR><TD COLSPAN="4" PORT="commands__repeat">repeat to end of stream</TD></TR>
		</TABLE>>];
		subgraph cluster__send_stream_header {
			label="BtrfsStream::SendStreamHeader";
			graph[style=dotted];

			send_stream_header__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="magic_pos">0</TD><TD PORT="magic_size">13</TD><TD></TD><TD PORT="magic_type">magic</TD></TR>
				<TR><TD PORT="version_pos">13</TD><TD PORT="version_size">4</TD><TD>u4le</TD><TD PORT="version_type">version</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__send_command {
			label="BtrfsStream::SendCommand";
			graph[style=dotted];

			send_command__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="len_data_pos">0</TD><TD PORT="len_data_size">4</TD><TD>u4le</TD><TD PORT="len_data_type">len_data</TD></TR>
				<TR><TD PORT="type_pos">4</TD><TD PORT="type_size">2</TD><TD>u2le→Command</TD><TD PORT="type_type">type</TD></TR>
				<TR><TD PORT="checksum_pos">6</TD><TD PORT="checksum_size">4</TD><TD></TD><TD PORT="checksum_type">checksum</TD></TR>
				<TR><TD PORT="data_pos">10</TD><TD PORT="data_size">len_data</TD><TD>Tlvs</TD><TD PORT="data_type">data</TD></TR>
			</TABLE>>];
			subgraph cluster__tlv {
				label="BtrfsStream::SendCommand::Tlv";
				graph[style=dotted];

				tlv__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="type_pos">0</TD><TD PORT="type_size">2</TD><TD>u2le→Attribute</TD><TD PORT="type_type">type</TD></TR>
					<TR><TD PORT="length_pos">2</TD><TD PORT="length_size">2</TD><TD>u2le</TD><TD PORT="length_type">length</TD></TR>
					<TR><TD PORT="value_pos">4</TD><TD PORT="value_size">...</TD><TD>switch (type)</TD><TD PORT="value_type">value</TD></TR>
				</TABLE>>];
tlv__seq_value_switch [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
	<TR><TD BGCOLOR="#F0F2E4">case</TD><TD BGCOLOR="#F0F2E4">type</TD></TR>
	<TR><TD>:attribute_clone_uuid</TD><TD PORT="case0">Uuid</TD></TR>
	<TR><TD>:attribute_otime</TD><TD PORT="case1">Timespec</TD></TR>
	<TR><TD>:attribute_atime</TD><TD PORT="case2">Timespec</TD></TR>
	<TR><TD>:attribute_ctime</TD><TD PORT="case3">Timespec</TD></TR>
	<TR><TD>:attribute_uuid</TD><TD PORT="case4">Uuid</TD></TR>
	<TR><TD>:attribute_xattr_name</TD><TD PORT="case5">String</TD></TR>
	<TR><TD>:attribute_mtime</TD><TD PORT="case6">Timespec</TD></TR>
	<TR><TD>:attribute_path_link</TD><TD PORT="case7">String</TD></TR>
	<TR><TD>:attribute_path_to</TD><TD PORT="case8">String</TD></TR>
	<TR><TD>:attribute_path</TD><TD PORT="case9">String</TD></TR>
	<TR><TD>:attribute_clone_path</TD><TD PORT="case10">String</TD></TR>
</TABLE>>];
			}
			subgraph cluster__uuid {
				label="BtrfsStream::SendCommand::Uuid";
				graph[style=dotted];

				uuid__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="uuid_pos">0</TD><TD PORT="uuid_size">16</TD><TD></TD><TD PORT="uuid_type">uuid</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__tlvs {
				label="BtrfsStream::SendCommand::Tlvs";
				graph[style=dotted];

				tlvs__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="tlv_pos">0</TD><TD PORT="tlv_size">...</TD><TD>Tlv</TD><TD PORT="tlv_type">tlv</TD></TR>
					<TR><TD COLSPAN="4" PORT="tlv__repeat">repeat to end of stream</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__string {
				label="BtrfsStream::SendCommand::String";
				graph[style=dotted];

				string__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="string_pos">0</TD><TD PORT="string_size"></TD><TD>str(UTF-8)</TD><TD PORT="string_type">string</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__timespec {
				label="BtrfsStream::SendCommand::Timespec";
				graph[style=dotted];

				timespec__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="ts_sec_pos">0</TD><TD PORT="ts_sec_size">8</TD><TD>s8le</TD><TD PORT="ts_sec_type">ts_sec</TD></TR>
					<TR><TD PORT="ts_nsec_pos">8</TD><TD PORT="ts_nsec_size">4</TD><TD>s4le</TD><TD PORT="ts_nsec_type">ts_nsec</TD></TR>
				</TABLE>>];
			}
		}
	}
	btrfs_stream__seq:header_type -> send_stream_header__seq [style=bold];
	btrfs_stream__seq:commands_type -> send_command__seq [style=bold];
	send_command__seq:len_data_type -> send_command__seq:data_size [color="#404040"];
	send_command__seq:data_type -> tlvs__seq [style=bold];
	tlv__seq:value_type -> tlv__seq_value_switch [style=bold];
	tlv__seq_value_switch:case0 -> uuid__seq [style=bold];
	tlv__seq_value_switch:case1 -> timespec__seq [style=bold];
	tlv__seq_value_switch:case2 -> timespec__seq [style=bold];
	tlv__seq_value_switch:case3 -> timespec__seq [style=bold];
	tlv__seq_value_switch:case4 -> uuid__seq [style=bold];
	tlv__seq_value_switch:case5 -> string__seq [style=bold];
	tlv__seq_value_switch:case6 -> timespec__seq [style=bold];
	tlv__seq_value_switch:case7 -> string__seq [style=bold];
	tlv__seq_value_switch:case8 -> string__seq [style=bold];
	tlv__seq_value_switch:case9 -> string__seq [style=bold];
	tlv__seq_value_switch:case10 -> string__seq [style=bold];
	tlv__seq:type_type -> tlv__seq:value_type [color="#404040"];
	tlvs__seq:tlv_type -> tlv__seq [style=bold];
}