Logical Volume Manager version 2: GraphViz block diagram (.dot) source

Building a test file

dd if=/dev/zero of=image.img bs=512 count=$(( 4 * 1024 * 2 ))
sudo losetup /dev/loop1 image.img
sudo pvcreate /dev/loop1
sudo vgcreate vg_test /dev/loop1
sudo lvcreate --name lv_test1 vg_test
sudo losetup -d /dev/loop1

Application

["linux", "grub2", "lvm tools", "libvslvm"]

KS implementation details

License: GFDL-1.3+

This page hosts a formal specification of Logical Volume Manager version 2 using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

GraphViz block diagram source

lvm2.dot

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

		lvm2__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="pv_pos">0</TD><TD PORT="pv_size">...</TD><TD>PhysicalVolume</TD><TD PORT="pv_type">pv</TD></TR>
		</TABLE>>];
		lvm2__inst__sector_size [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
			<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
			<TR><TD>sector_size</TD><TD>512</TD></TR>
		</TABLE>>];
		subgraph cluster__physical_volume {
			label="Lvm2::PhysicalVolume";
			graph[style=dotted];

			physical_volume__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="empty_sector_pos">0</TD><TD PORT="empty_sector_size">_root.sector_size</TD><TD></TD><TD PORT="empty_sector_type">empty_sector</TD></TR>
				<TR><TD PORT="label_pos">...</TD><TD PORT="label_size">...</TD><TD>Label</TD><TD PORT="label_type">label</TD></TR>
			</TABLE>>];
			subgraph cluster__label {
				label="Lvm2::PhysicalVolume::Label";
				graph[style=dotted];

				label__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="label_header_pos">0</TD><TD PORT="label_header_size">32</TD><TD>LabelHeader</TD><TD PORT="label_header_type">label_header</TD></TR>
					<TR><TD PORT="volume_header_pos">32</TD><TD PORT="volume_header_size">...</TD><TD>VolumeHeader</TD><TD PORT="volume_header_type">volume_header</TD></TR>
				</TABLE>>];
				subgraph cluster__label_header {
					label="Lvm2::PhysicalVolume::Label::LabelHeader";
					graph[style=dotted];

					label_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="signature_pos">0</TD><TD PORT="signature_size">8</TD><TD>4C 41 42 45 4C 4F 4E 45</TD><TD PORT="signature_type">signature</TD></TR>
						<TR><TD PORT="sector_number_pos">8</TD><TD PORT="sector_number_size">8</TD><TD>u8le</TD><TD PORT="sector_number_type">sector_number</TD></TR>
						<TR><TD PORT="checksum_pos">16</TD><TD PORT="checksum_size">4</TD><TD>u4le</TD><TD PORT="checksum_type">checksum</TD></TR>
						<TR><TD PORT="label_header__pos">20</TD><TD PORT="label_header__size">12</TD><TD>LabelHeader</TD><TD PORT="label_header__type">label_header_</TD></TR>
					</TABLE>>];
					subgraph cluster__label_header_ {
						label="Lvm2::PhysicalVolume::Label::LabelHeader::LabelHeader";
						graph[style=dotted];

						label_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="data_offset_pos">0</TD><TD PORT="data_offset_size">4</TD><TD>u4le</TD><TD PORT="data_offset_type">data_offset</TD></TR>
							<TR><TD PORT="type_indicator_pos">4</TD><TD PORT="type_indicator_size">8</TD><TD>4C 56 4D 32 20 30 30 31</TD><TD PORT="type_indicator_type">type_indicator</TD></TR>
						</TABLE>>];
					}
				}
				subgraph cluster__volume_header {
					label="Lvm2::PhysicalVolume::Label::VolumeHeader";
					graph[style=dotted];

					volume_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="id_pos">0</TD><TD PORT="id_size">32</TD><TD>str(ascii)</TD><TD PORT="id_type">id</TD></TR>
						<TR><TD PORT="size_pos">32</TD><TD PORT="size_size">8</TD><TD>u8le</TD><TD PORT="size_type">size</TD></TR>
						<TR><TD PORT="data_area_descriptors_pos">40</TD><TD PORT="data_area_descriptors_size">16</TD><TD>DataAreaDescriptor</TD><TD PORT="data_area_descriptors_type">data_area_descriptors</TD></TR>
						<TR><TD COLSPAN="4" PORT="data_area_descriptors__repeat">repeat until  ((_.size != 0) &amp;&amp; (_.offset != 0)) </TD></TR>
						<TR><TD PORT="metadata_area_descriptors_pos">...</TD><TD PORT="metadata_area_descriptors_size">16</TD><TD>MetadataAreaDescriptor</TD><TD PORT="metadata_area_descriptors_type">metadata_area_descriptors</TD></TR>
						<TR><TD COLSPAN="4" PORT="metadata_area_descriptors__repeat">repeat until  ((_.size != 0) &amp;&amp; (_.offset != 0)) </TD></TR>
					</TABLE>>];
					subgraph cluster__data_area_descriptor {
						label="Lvm2::PhysicalVolume::Label::VolumeHeader::DataAreaDescriptor";
						graph[style=dotted];

						data_area_descriptor__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="offset_pos">0</TD><TD PORT="offset_size">8</TD><TD>u8le</TD><TD PORT="offset_type">offset</TD></TR>
							<TR><TD PORT="size_pos">8</TD><TD PORT="size_size">8</TD><TD>u8le</TD><TD PORT="size_type">size</TD></TR>
						</TABLE>>];
						data_area_descriptor__inst__data [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="data_pos">offset</TD><TD PORT="data_size">size</TD><TD>str(ascii)</TD><TD PORT="data_type">data</TD></TR>
						</TABLE>>];
					}
					subgraph cluster__metadata_area_descriptor {
						label="Lvm2::PhysicalVolume::Label::VolumeHeader::MetadataAreaDescriptor";
						graph[style=dotted];

						metadata_area_descriptor__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="offset_pos">0</TD><TD PORT="offset_size">8</TD><TD>u8le</TD><TD PORT="offset_type">offset</TD></TR>
							<TR><TD PORT="size_pos">8</TD><TD PORT="size_size">8</TD><TD>u8le</TD><TD PORT="size_type">size</TD></TR>
						</TABLE>>];
						metadata_area_descriptor__inst__data [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="data_pos">offset</TD><TD PORT="data_size">size</TD><TD>MetadataArea</TD><TD PORT="data_type">data</TD></TR>
						</TABLE>>];
					}
					subgraph cluster__metadata_area {
						label="Lvm2::PhysicalVolume::Label::VolumeHeader::MetadataArea";
						graph[style=dotted];

						metadata_area__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">...</TD><TD>MetadataAreaHeader</TD><TD PORT="header_type">header</TD></TR>
						</TABLE>>];
						subgraph cluster__metadata_area_header {
							label="Lvm2::PhysicalVolume::Label::VolumeHeader::MetadataArea::MetadataAreaHeader";
							graph[style=dotted];

							metadata_area_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="checksum_pos">0</TD><TD PORT="checksum_size">...</TD><TD>MetadataAreaHeader</TD><TD PORT="checksum_type">checksum</TD></TR>
								<TR><TD PORT="signature_pos">...</TD><TD PORT="signature_size">16</TD><TD>20 4C 56 4D 32 20 78 5B 35 41 25 72 30 4E 2A 3E</TD><TD PORT="signature_type">signature</TD></TR>
								<TR><TD PORT="version_pos">...</TD><TD PORT="version_size">4</TD><TD>u4le</TD><TD PORT="version_type">version</TD></TR>
								<TR><TD PORT="metadata_area_offset_pos">...</TD><TD PORT="metadata_area_offset_size">8</TD><TD>u8le</TD><TD PORT="metadata_area_offset_type">metadata_area_offset</TD></TR>
								<TR><TD PORT="metadata_area_size_pos">...</TD><TD PORT="metadata_area_size_size">8</TD><TD>u8le</TD><TD PORT="metadata_area_size_type">metadata_area_size</TD></TR>
								<TR><TD PORT="raw_location_descriptors_pos">...</TD><TD PORT="raw_location_descriptors_size">24</TD><TD>RawLocationDescriptor</TD><TD PORT="raw_location_descriptors_type">raw_location_descriptors</TD></TR>
								<TR><TD COLSPAN="4" PORT="raw_location_descriptors__repeat">repeat until  ((_.offset != 0) &amp;&amp; (_.size != 0) &amp;&amp; (_.checksum != 0)) </TD></TR>
							</TABLE>>];
							metadata_area_header__inst__metadata [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="metadata_pos">metadata_area_offset</TD><TD PORT="metadata_size">metadata_area_size</TD><TD></TD><TD PORT="metadata_type">metadata</TD></TR>
							</TABLE>>];
							subgraph cluster__raw_location_descriptor {
								label="Lvm2::PhysicalVolume::Label::VolumeHeader::MetadataArea::MetadataAreaHeader::RawLocationDescriptor";
								graph[style=dotted];

								raw_location_descriptor__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="offset_pos">0</TD><TD PORT="offset_size">8</TD><TD>u8le</TD><TD PORT="offset_type">offset</TD></TR>
									<TR><TD PORT="size_pos">8</TD><TD PORT="size_size">8</TD><TD>u8le</TD><TD PORT="size_type">size</TD></TR>
									<TR><TD PORT="checksum_pos">16</TD><TD PORT="checksum_size">4</TD><TD>u4le</TD><TD PORT="checksum_type">checksum</TD></TR>
									<TR><TD PORT="flags_pos">20</TD><TD PORT="flags_size">4</TD><TD>u4le→RawLocationDescriptorFlags</TD><TD PORT="flags_type">flags</TD></TR>
								</TABLE>>];
							}
						}
					}
				}
			}
		}
	}
	lvm2__seq:pv_type -> physical_volume__seq [style=bold];
	lvm2__inst__sector_size:sector_size_type -> physical_volume__seq:empty_sector_size [color="#404040"];
	physical_volume__seq:label_type -> label__seq [style=bold];
	label__seq:label_header_type -> label_header__seq [style=bold];
	label__seq:volume_header_type -> volume_header__seq [style=bold];
	label_header__seq:label_header__type -> label_header___seq [style=bold];
	volume_header__seq:data_area_descriptors_type -> data_area_descriptor__seq [style=bold];
	data_area_descriptor__seq:size_type -> volume_header__seq:data_area_descriptors__repeat [color="#404040"];
	data_area_descriptor__seq:offset_type -> volume_header__seq:data_area_descriptors__repeat [color="#404040"];
	volume_header__seq:metadata_area_descriptors_type -> metadata_area_descriptor__seq [style=bold];
	metadata_area_descriptor__seq:size_type -> volume_header__seq:metadata_area_descriptors__repeat [color="#404040"];
	metadata_area_descriptor__seq:offset_type -> volume_header__seq:metadata_area_descriptors__repeat [color="#404040"];
	data_area_descriptor__seq:offset_type -> data_area_descriptor__inst__data:data_pos [color="#404040"];
	data_area_descriptor__seq:size_type -> data_area_descriptor__inst__data:data_size [color="#404040"];
	metadata_area_descriptor__seq:offset_type -> metadata_area_descriptor__inst__data:data_pos [color="#404040"];
	metadata_area_descriptor__seq:size_type -> metadata_area_descriptor__inst__data:data_size [color="#404040"];
	metadata_area_descriptor__inst__data:data_type -> metadata_area__seq [style=bold];
	metadata_area__seq:header_type -> metadata_area_header__seq [style=bold];
	metadata_area_header__seq:checksum_type -> metadata_area_header__seq [style=bold];
	metadata_area_header__seq:raw_location_descriptors_type -> raw_location_descriptor__seq [style=bold];
	raw_location_descriptor__seq:offset_type -> metadata_area_header__seq:raw_location_descriptors__repeat [color="#404040"];
	raw_location_descriptor__seq:size_type -> metadata_area_header__seq:raw_location_descriptors__repeat [color="#404040"];
	raw_location_descriptor__seq:checksum_type -> metadata_area_header__seq:raw_location_descriptors__repeat [color="#404040"];
	metadata_area_header__seq:metadata_area_offset_type -> metadata_area_header__inst__metadata:metadata_pos [color="#404040"];
	metadata_area_header__seq:metadata_area_size_type -> metadata_area_header__inst__metadata:metadata_size [color="#404040"];
}