Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Linux Logical Volume Manager (LVM) format

The Linux Logical Volume Manager (LVM) format is used by the Logical Volume Manager (LVM) on Linux.

Overview

A Linux LVM consist of:

  • Volume group
  • Physical volumes
  • Logical volumes

Characteristics

CharacteristicsDescription
Byte orderlittle-endian
Date and time valuesPOSIX timestamp in local timezone and/or ctime date and time string
Character stringsASCII string with an end-of-string character

According to “RHEL 5 - Logical Volume Manager Administration” the number of bytes per sector is 512.

Checksums use a “weak” CRC-32, which is a CRC-32 without the initial and final XOR with 0xffffffff, using the polynominal 0xedb88320 and initial value 0xf597a6cf.

Terminology

TermDescription
logical extent (LE)An extent (data range) that makes up the logical volume
logical volume (LV)A volume within the LVM, comparable to a partition in a MBR or GPT volume system
physical extent (PE)An extent (data range) that makes up the physical volume
physical volume (PV)Typically a physical volume is a hard disk, though it may well just be any other device that behaves like a hard disk, such as a software RAID device
volume group (VG)A collection of Logical Volumes and Physical Volumes

Physical volume

A physical volume consist of:

  • Empty sector
  • The physical volume label header
    • The physical volume header
      • data area descriptor list
      • metadata area descriptor list
  • The metadata area
  • Data area (or data extents)

Physical volume label

The physical volume label is stored in the second sector of the physical volume. The physical volume label is currently 512 bytes in size and consists of:

  • physical volume label header
  • physical volume header

Note that according to “RHEL 5 - Logical Volume Manager Administration” the physical volume label can be stored in any of the first 4 sectors.

Physical volume label header

The physical volume label header (struct label_header) is 32 bytes in size and consist of:

OffsetSizeValueDescription
08"LABELONE"Signature (or identifier)
88Sector number, which contains the sector number of the physical volume label header
164Checksum, which contains a CRC-32 for offset 20 to end of the physical volume label sector
204Data offset (or header size), which contains an offset in bytes relative from the start of the physical volume label header
248"LVM2\x20001"Type indicator

Physical volume header

The physical volume header (struct pv_header) is of variable size and consist of:

OffsetSizeValueDescription
032Physical volume identifier, which contains a UUID stored as an ASCII string
328Physical volume size, in number of bytes
40...List of data area descriptors, where the last descriptor in the list is terminator and consists of 0-byte values
......List of metadata area descriptors, where the last descriptor in the list is terminator and consists of 0-byte values

The physical volume identifier can be used to uniquely identify a physical volume. The physical volume identifier is stored as “9LBcEB7PQTGIlLI0KxrtzrynjuSL983W” but is equivalent to its formatted variant “9LBcEB-7PQT-GIlL-I0Kx-rtzr-ynju-SL983W”, which is used in the metadata.

Note that the data area size can be 0, and currently it is assumed that this represents all remaining (available) space within the physical volume.

Data area descriptor

OffsetSizeValueDescription
08Data area offset, which contains an offset in bytes relative to the start of the physical volume
88Data area size, in number of bytes

The metadata area

The metadata area consist of:

  • Metadata area header
  • Metadata

According to “RHEL 5 - Logical Volume Manager Administration” the metadata area is a circular buffer. New metadata is appended to the old metadata and then the pointer to the start of it is updated. The metadata area, therefore, can contain copies of older versions of the metadata.

Metadata area header

The metadata area header (struct mda_header) is 512 bytes in size and consist of:

OffsetSizeValueDescription
04Checksum, which contains the CRC-32 for offset 4 to end of the metadata area header
416"\x20LVM2\x20x[5A%r0N*>"Signature
2041Format version
248Metadata area offset, which contains an offset in bytes relative to the start of the physical volume
328Metadata area size, in number of bytes
404 x 24 = 96List of raw location descriptors, where the last descriptor in the list is terminator and consists of 0-byte values
1363760Unknown (unused)

Raw location descriptor

The raw location descriptor (struct raw_locn) is 24 bytes in size and consist of:

OffsetSizeValueDescription
08Data area offset, which contains an offset in bytes relative to the start of the metadata area
88Data area size, in number of bytes
164Checksum, which contains the CRC-32 of the data area described by the raw location descriptor
204Flags

Note that the data area size can be 0. It is assumed it represents the remaining available data.

Raw location descriptor flags

ValueIdentifierDescription
0x00000001RAW_LOCN_IGNOREDThe raw location descriptor should be ignored

Metadata

The metadata consist of:

  • Volume group main section
    • Physical volumes object
      • Physical volume object
    • Logical volumes object
      • Logical volume object
        • Segment object
  • Top level properties

According to “RHEL 5 - Logical Volume Manager Administration” by default, an identical copy of the metadata is maintained in every metadata area in every physical volume within the volume group. The metadata is stored as ASCII.

The metadata can also be stored in a stand-alone file.

Example

# Generated by LVM2: Tue Jan 30 16:28:15 2007

contents = "Text Format Volume Group"
version = 1

description = "Created *before* executing 'lvextend -L+5G /dev/myvg/mylv /dev/sdc'"

creation_host = "tng3-1"  # Linux tng3-1 2.6.18-8.el5 #1 SMP Fri Jan 26 14:15:21 EST 2007 i686
creation_time = 1170196095  # Tue Jan 30 16:28:15 2007

myvg {
  id = "0zd3UT-wbYT-lDHq-lMPs-EjoE-0o18-wL28X4"
  seqno = 3
  status = ["RESIZEABLE", "READ", "WRITE"]
  extent_size = 8192    # 4 Megabytes
  max_lv = 0
  max_pv = 0

  physical_volumes {

    pv0 {
      id = "ZBW5qW-dXF2-0bGw-ZCad-2RlV-phwu-1c1RFt"
      device = "/dev/sda"   # Hint only

      status = ["ALLOCATABLE"]
      dev_size = 35964301   # 17.1491 Gigabytes
      pe_start = 384
      pe_count = 4390 # 17.1484 Gigabytes
    }

    ...
  }
  logical_volumes {

    mylv {
      id = "GhUYSF-qVM3-rzQo-a6D2-o0aV-LQet-Ur9OF9"
      status = ["READ", "WRITE", "VISIBLE"]
      segment_count = 2

      segment1 {
        start_extent = 0
        extent_count = 1280   # 5 Gigabytes

        type = "striped"
        stripe_count = 1  # linear

        stripes = [
          "pv0", 0
        ]
      }
      segment2 {
        start_extent = 1280
        extent_count = 1280   # 5 Gigabytes

        type = "striped"
        stripe_count = 1  # linear

        stripes = [
          "pv1", 0
        ]
      }
    }
  }
}

Properties

The metadata is textual and uses properties, where a property is defined as:

<identifier> = <value>

The identifier contains an unique name of the property and <value> is one of the following types:

ValueDescription
[0-9]+An integer
"..."A string
["...", "...", ...]A list (or array) of strings

Note that white space, such as space and new line characters, seem to be ignored.

The # character is used for comments. A comment continues to the end-of-line.

Note that for now it is assumed that the # character is not allowed to be used in any of the values.

Top level properties

ValueDescription
"contents"The contents of the metadata area, which contains the string "Text Format Volume Group"
"creation_host"The hostname of the system on which metadata area was created, which can contain a trailing comment that contains the output equivalent to "uname -a"
"creation_time"The creation time of the metadata area, which contains an interger containing the number of seconds since January 1, 1970 00:00:00 UTC and can contain a trailing comment that contains the creation time as a ctime (function) string in UTC
"description"Unknown (Description of the metadata area?)
<volume group name>Volume group object
"version"The metadata area version, which contains an integer value of 1

Note it is assumed that there can only be 1 volume group object.

Volume group and logical volume names

  • Allowed characters: “a-z”, “A-Z”, “0-9”, “_”, “+”, “.”, and “-” (hypen)
  • A volume group name should not start with a hypen
  • A logical volume name can start with a hypen, but it is reserved for logical volumes that have been removed but are stil being tracked by the format

Note that some implementations use lv_ as the prefix for a logical volume, however this is not enforced by the format.

Volume group object

The volume group object contains the following properties:

ValueDescription
"extent_size"The size of an extent, in number of sectors
"flags"Flags
"format"Optional format identifier, such as "lvm2"
"id"Volume group identifier (VG UUID), which contains an ASCII string in the following format: fg1fKZ-xoHz-CfAD-yQPx-l2HL-Y7kA-9kJ9LD
"logical_volumes"Logical volumes object
"max_lv"Maximum number of logical volumes
"max_pv"Maximum number of physical volumes
"metadata_copies"Unknown (The number of metadata copies?)
"physical_volumes"Physical volumes object
"seqno"Metadata sequence number
"status"The status flags, which contains a list of strings

Physical volumes object

The physical volumes object contains the following properties:

ValueDescription
pv#Individual physical volume object, where # is a place holder for a the physical volume number e.g. pv0. 0 appears to be the first number that is used

Physical volume object

Each physical volume object contains the following properties:

ValueDescription
"device"The device filename, which contains an ASCII string, e.g. /dev/dm-0
"device_id"Unknown (device identifier "/tmp/lvm.raw")
"device_id_type"Unknown (device type "loop_file")
"dev_size"The physical volume size including non-usable space, in number of sectors
"flags"Flags
"id"Physical volume identifier (PV UUID), which contains an ASCII string in the following format: 9LBcEB-7PQT-GIlL-I0Kx-rtzr-ynju-SL983W
"pe_count"The number of (allocated) extents in the physical volume
"pe_start"The start extent, which contains an offset in bytes relative from the start of the physical volume
"status"The status flags, which contains a list of strings

Logical volumes object

The logical volumes object contains the following properties:

ValueDescription
<logical volume name>Individual logical volume object, where <name> is a place holder for a the logical volume name

Logical volume object

Each logical volume object contains the following properties:

ValueDescription
"creation_host"The hostname of the system on which the logical volume was created
"creation_time"The creation time of the metadata area, which contains an interger containing the number of seconds since January 1, 1970 00:00:00 UTC and can contain a trailing comment that contains the creation time as a ctime (function) string in UTC
"flags"Flags
"idPhysical volume identifier (PV UUID), which contains an ASCII string in the following format: 9LBcEB-7PQT-GIlL-I0Kx-rtzr-ynju-SL983W
"segment_count"The number of segments
"segment#"Individual segment objects, where # is a place holder for the segment number e.g. segment1. 1 appears to be the first number that is used
"status"Status flags, which contains a list of strings

Segment object

Each segment object contains the following properties:

ValueDescription
"extent_count"The number of extents in the segment (or current logical extent)
"start_extent"The start extent of the segment, which contains an offset in number of extents relative from the start of the segment
"stripe_count"The number of stripes in the segment, where 1 represents linear striping
"stripes"Stripes list
"type"Segment type

Segment types

ValueDescription
cacheSegment that is used as a cache, e.g. SSD for a HDD
cache-poolSegment used as a cache for both data and metadata
errorSegment that fails read and write operations, intended for testing
freeUnallocated segment
integritySegment with integrity checksum
linearLinear physical volume
mirrorSegment that mirrors data across multiple physical volumes (comparable to RAID1)
raid0Segment that contains a stripe of data (RAID0)
raid0_metaRAID0 physical volume that contains data and metadata
raid1Segment that mirrors data across multiple physical volumes (RAID1)
raid10Segment that contains a stripe of data (RAID0) that mirrors data across multiple physical volumes (RAID1)
raid10_nearRAID10 segment that copies data sectors near each other
raid4Segment with stripes across multiple physical volumes with parity data (RAID4)
raid5Segment with stripes across multiple physical volumes with parity data (RAID5)
raid5_laRAID5 variant that uses left asymmetric layout
raid5_lsRAID5 variant that uses left symmetric layout
raid5_nRAID5 variant with dedicated parity layout
raid5_raRAID5 variant that uses right asymmetric layout
raid5_rsRAID5 variant that uses right symmetric layout
raid6Segment with stripes across multiple physical volumes with dual parity data (RAID6)
raid6_la_6RAID6 variant that uses left asymmetric layout
raid6_ls_6RAID6 variant that uses left symmetric layout
raid6_n_6RAID6 variant with dedicated parity layout
raid6_ncRAID6 variant that uses no-change layout
raid6_nrRAID6 variant that uses non-rotating layout
raid6_ra_6RAID6 variant that uses right asymmetric layout
raid6_rs_6RAID6 variant that uses right symmetric layout
raid6_zrRAID6 variant that uses zero-restart layout
snapshotSegment that contains a snapshot
stripedSegment that contains a stripe of data (comparable to RAID0)
thinSegment that allocated on write
thin-poolSegment that manages a shared pool of data and metadata
vdoVirtual Data Optimizer (VDO) physical volume
vdo-poolVirtual Data Optimizer (VDO) pool
writecacheSegment that is used as a write-only cache
zeroSegment that is sparse (filled with 0-byte values)

Note that a comparable list can be retrieved using lvm segtypes.

Stripes list

stripes = [
<physical volume name>, <start extent number>
]

Where:

  • <physical volume name> is a string containing the physical volume name e.g. “pv0”.
  • <start extent number> the segment start extent number relative from the start of the data area.
start_extent_offset = (
    (start_extent_number * extent_size * sector_size) + physical_volume_data_area_start_offset
)

Status flags

ValueDescription
ALLOCATABLEIs allocatable (physical volume only)
RESIZEABLECan be re-sized (volume group only)
READCan be read
VISIBLEIs visible (logical volume only). Hidden if not set.
WRITECan be written

Flags

TODO: complete section

Comments

Textual metadata such as:

# Generated by LVM2 version 2.02.39 (2008-06-27): Sat Jan 17 11:45:29 2009

References