Module: Lvm2Scanner

Defined in:
lib/VolumeManager/LVM/scanner.rb

Constant Summary collapse

LVM_PARTITION_TYPE =
142
SECTOR_SIZE =
512
LABEL_SCAN_SECTORS =
4
LVM_ID_LEN =
8
LVM_TYPE_LEN =
8
LVM_ID =
"LABELONE".freeze
PV_ID_LEN =
32
MDA_MAGIC_LEN =
16
FMTT_MAGIC =
"\040\114\126\115\062\040\170\133\065\101\045\162\060\116\052\076".freeze
LABEL_HEADER =

On disk label header.

BinaryStruct.new(
  [
    "A#{LVM_ID_LEN}",   'lvm_id',
    'Q',                'sector_xl',
    'L',                'crc_xl',
    'L',                'offset_xl',
    "A#{LVM_TYPE_LEN}", 'lvm_type'
  ]
)
PV_HEADER =

On disk physical volume header.

BinaryStruct.new(
  [
    "A#{PV_ID_LEN}", 'pv_uuid',
    "Q",             'device_size_xl'
  ]
)
DISK_LOCN =

On disk disk location structure.

BinaryStruct.new(
  [
    "Q", 'offset',
    "Q", 'size'
  ]
)
MDA_HEADER =

On disk metadata area header.

BinaryStruct.new(
  [
    "L",                 'checksum_xl',
    "A#{MDA_MAGIC_LEN}", 'magic',
    "L",                 'version',
    "Q",                 'start',
    "Q",                 'size'
  ]
)
RAW_LOCN =

On disk raw location header, points to metadata.

BinaryStruct.new(
  [
    "Q", 'offset',
    "Q", 'size',
    "L", 'checksum',
    "L", 'filler'
  ]
)

Class Method Summary collapse

Class Method Details

.labelScan(d) ⇒ Object

Scan the physical volume for LVM headers. Return nil if no label is found. Otherwise, return a physical volume header containing a list of metadata areas.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/VolumeManager/LVM/scanner.rb', line 77

def self.labelScan(d)
  lh = nil
  (0...LABEL_SCAN_SECTORS).each do |s|
    lh = readLabel(d, s)
    break if lh
  end
  return nil unless lh

  pvh = readPvHeader(d, lh)

  mdList = []
  pvh.metadataDiskLocations.each do |dlh|
    mdah = readMdah(d, dlh)
    mdah.rawLocations.each do |rl|
      mdList << readRaw(d, rl)
    end
  end
  pvh.mdList = mdList
  pvh.lvm_type = lh.lvm_type.split(" ").first
  pvh
end

.readLabel(d, s) ⇒ Object



101
102
103
104
105
106
# File 'lib/VolumeManager/LVM/scanner.rb', line 101

def self.readLabel(d, s)
  d.seek(s * SECTOR_SIZE, IO::SEEK_SET)
  lh = readStruct(d, LABEL_HEADER)
  return lh if lh&.lvm_id == LVM_ID
  nil
end

.readMdah(d, dlh) ⇒ Object

def self.readPvHeader



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/VolumeManager/LVM/scanner.rb', line 136

def self.readMdah(d, dlh)
  d.seek(dlh.offset, IO::SEEK_SET)
  mdah = readStruct(d, MDA_HEADER)
  raise "** readMdah: unknown magic number" if mdah.magic != FMTT_MAGIC

  #
  # Read and save raw loaction headers for metadata.
  #
  mdah.rawLocations = []
  loop do
    rlh = readStruct(d, RAW_LOCN)
    break if rlh.offset == 0
    rlh.base = mdah.start
    mdah.rawLocations << rlh
  end

  mdah
end

.readPvHeader(d, lh) ⇒ Object

def self.readLabel



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/VolumeManager/LVM/scanner.rb', line 108

def self.readPvHeader(d, lh)
  pvho = (lh.sector_xl * SECTOR_SIZE) + lh.offset_xl
  d.seek(pvho)
  pvh = readStruct(d, PV_HEADER)

  #
  # Read and save disk location structures for data areas.
  #
  pvh.dataDiskLocations = []
  loop do
    dlh = readStruct(d, DISK_LOCN)
    break if dlh.offset == 0
    pvh.dataDiskLocations << dlh
  end

  #
  # Read and save disk location structures for metadata headers.
  #
  pvh.metadataDiskLocations = []
  loop do
    dlh = readStruct(d, DISK_LOCN)
    break if dlh.offset == 0
    pvh.metadataDiskLocations << dlh
  end

  pvh
end

.readRaw(d, rlh) ⇒ Object

def self.readMdah



155
156
157
158
159
160
161
# File 'lib/VolumeManager/LVM/scanner.rb', line 155

def self.readRaw(d, rlh)
  osp = d.seekPos
  d.seek(rlh.base + rlh.offset, IO::SEEK_SET)
  da = d.read(rlh.size)
  d.seek(osp, IO::SEEK_SET)
  da
end

.readStruct(d, struct) ⇒ Object

def self.readRaw



163
164
165
166
167
168
# File 'lib/VolumeManager/LVM/scanner.rb', line 163

def self.readStruct(d, struct)
  OpenStruct.new(struct.decode(d.read(struct.size)))
rescue StandardError => err
  $log&.debug err.to_s
  nil
end