Skip to content

Commit

Permalink
Reserve space for the 'pmspare' LV in a VG
Browse files Browse the repository at this point in the history
The 'pmspare' LV is created by LVM behind our back and it serves as a temporary
space for some metadata reorganizations/cleanup/... so its size is equal to the
size of the biggest metadata LV in the VG. If we ignore it, we lack free space
in the VG later when creating LVs.
  • Loading branch information
vpodzime committed Aug 19, 2015
1 parent ed2ca91 commit c6ad606
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
13 changes: 13 additions & 0 deletions blivet/devices/lvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ def reservedSpace(self):
elif self.reserved_space > Size(0):
reserved = self.reserved_space

# reserve space for the pmspare LV LVM creates behind our back
reserved += self.pmSpareSize

return self.align(reserved, roundup=True)

@property
Expand Down Expand Up @@ -421,6 +424,16 @@ def thinlvs(self):
def cachedLVs(self):
return [l for l in self._lvs if l.cached]

@property
def pmSpareSize(self):
"""Size of the pmspare LV LVM creates in every VG that contains some metadata
(even internal) LV. The size of such LV is equal to the size of the
biggest metadata LV in the VG.
"""
# TODO: report correctly/better for existing VGs
return max([lv.metaDataSize for lv in self.lvs] + [Size(0)])

@property
def complete(self):
"""Check if the vg has all its pvs in the system
Expand Down
5 changes: 3 additions & 2 deletions tests/devices_test/device_properties_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -791,8 +791,9 @@ def testLVMLogicalVolumeDeviceInit(self):

def testLVMLogicalVolumeDeviceInitCached(self):
self.stateCheck(self.cached_lv,
# 2 * (1 GiB - one extent) - 512 MiB
maxSize=xform(lambda x, m: self.assertEqual(x, Size("1528 MiB"), m) and
# 2 * (1 GiB - one extent) - 512 MiB - 8 MiB
# PVfree cache pmspare
maxSize=xform(lambda x, m: self.assertEqual(x, Size("1520 MiB"), m) and
self.assertIsInstance(x, Size, m)),
snapshots=xform(lambda x, m: self.assertEqual(x, [], m)),
segType=xform(lambda x, m: self.assertEqual(x, "linear", m)),
Expand Down
13 changes: 8 additions & 5 deletions tests/partitioning_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,10 @@ def testVGChunk(self):
def testVGChunkWithCache(self):
pv = StorageDevice("pv1", size=Size("40 GiB"),
fmt=getFormat("lvmpv"))
# 1025 MiB so that the PV provides 1024 MiB of free space (see LVMVolumeGroupDevice.extents)
pv2 = StorageDevice("pv2", size=Size("1025 MiB"),
# 1033 MiB so that the PV provides 1032 MiB of free space (see
# LVMVolumeGroupDevice.extents) -- 1024 MiB for caches, 8 MiB for the
# pmspare LV
pv2 = StorageDevice("pv2", size=Size("1033 MiB"),
fmt=getFormat("lvmpv"))
vg = LVMVolumeGroupDevice("vg", parents=[pv, pv2])

Expand Down Expand Up @@ -550,10 +552,11 @@ def testVGChunkWithCache(self):
def testVGChunkWithCachePVfree(self):
pv = StorageDevice("pv1", size=Size("40 GiB"),
fmt=getFormat("lvmpv"))
# 1069 MiB so that the PV provides 1068 MiB of free space (see
# 1077 MiB so that the PV provides 1076 MiB of free space (see
# LVMVolumeGroupDevice.extents) which is 44 MiB more than the caches
# need and which should thus be split into the LVs
pv2 = StorageDevice("pv2", size=Size("1069 MiB"),
# need (including the 8MiB pmspare LV) and which should thus be split
# into the LVs
pv2 = StorageDevice("pv2", size=Size("1077 MiB"),
fmt=getFormat("lvmpv"))
vg = LVMVolumeGroupDevice("vg", parents=[pv, pv2])

Expand Down

0 comments on commit c6ad606

Please sign in to comment.