From: Vratislav Podzimek vpodzime@redhat.com
LVM creates small internal LVs for RAID LVs that hold the necessary metadata. We need to account for that in order to be able to do calculations of PV/VG free space etc. This requires us to do some of the calculations in a more granular manner -- separating data and metadata parts. --- blivet/devices/lvm.py | 37 +++++++++++++++++++++++++++++++------ blivet/partitioning.py | 11 ++++++----- 2 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py index 2e3b8d8..31fdf31 100644 --- a/blivet/devices/lvm.py +++ b/blivet/devices/lvm.py @@ -620,7 +620,11 @@ def __init__(self, name, parents=None, size=None, uuid=None, seg_type=None, self.req_size = self._size self.req_percent = util.numeric_type(percent)
- self._metadata_size = Size(0) + if not self.exists and self.seg_type.startswith("raid"): + # RAID LVs create one extent big internal metadata LVs + self._metadata_size = self.vg.pe_size + else: + self._metadata_size = Size(0) self._internal_lvs = [] self._cache = None
@@ -653,10 +657,10 @@ def __init__(self, name, parents=None, size=None, uuid=None, seg_type=None,
def _assign_pv_space(self): if self.seg_type == "linear" or not self._raid_level: - # nothing to do for non-RAID (including striped) LVs here + # nothing to do for non-RAID (and thus non-striped) LVs here return for spec in self._pv_specs: - spec.size = self._raid_level.get_base_member_size(self.size, len(self._pv_specs)) + spec.size = self._raid_level.get_base_member_size(self.size + self._metadata_size, len(self._pv_specs))
def _check_parents(self): """Check that this device has parents as expected""" @@ -691,7 +695,12 @@ def log_size(self): @property def metadata_size(self): if self._metadata_size: - return self._metadata_size + if self.seg_type != "linear" and self._raid_level: + zero_superblock = lambda x: Size(0) + return self._raid_level.get_space(self._metadata_size, len(self._pv_specs), + superblock_size_func=zero_superblock) + else: + return self._metadata_size elif self.cached: return self.cache.md_size
@@ -751,14 +760,30 @@ def max_size(self): return min(max_lv, max_format) if max_format else max_lv
@property + def data_vg_space_used(self): + """ Space occupied by the data part of this LV, not including snapshots """ + rounded_size = self.vg.align(self.size, roundup=True) + if self.seg_type != "linear" and self._raid_level: + zero_superblock = lambda x: Size(0) + return self._raid_level.get_space(rounded_size, len(self._pv_specs), + superblock_size_func=zero_superblock) + else: + return rounded_size + + @property + def metadata_vg_space_used(self): + """ Space occupied by the metadata part of this LV, not including snapshots """ + return self.log_size + self.metadata_size + + @property def vg_space_used(self): """ Space occupied by this LV, not including snapshots. """ if self.cached: cache_size = self.cache.size else: cache_size = Size(0) - return (self.vg.align(self.size, roundup=True) * self.copies - + self.log_size + self.metadata_size + cache_size) + + return self.data_vg_space_used + self.metadata_vg_space_used + cache_size
@property def pv_space_used(self): diff --git a/blivet/partitioning.py b/blivet/partitioning.py index c5c1a20..dfbd218 100644 --- a/blivet/partitioning.py +++ b/blivet/partitioning.py @@ -1039,7 +1039,7 @@ def __init__(self, lv):
# Round up to nearest pe. For growable requests this will mean that # first growth is to fill the remainder of any unused extent. - self.base = int(lv.vg.align(lv.req_size, roundup=True) // lv.vg.pe_size) + self.base = int(lv.data_vg_space_used // lv.vg.pe_size)
if lv.req_grow: limits = [int(l // lv.vg.pe_size) for l in @@ -1055,11 +1055,12 @@ def __init__(self, lv):
@property def reserve_request(self): + lv = self.device reserve = super(LVRequest, self).reserve_request - if self.device.cached: - total_cache_size = self.device.cache.size + self.device.cache.md_size - reserve += int(self.device.vg.align(total_cache_size, roundup=True) / self.device.vg.pe_size) - + if lv.cached: + reserve += int(lv.vg.align(lv.cache.size, roundup=True) / lv.vg.pe_size) + if lv.metadata_size: + reserve += int(lv.vg.align(lv.metadata_vg_space_used, roundup=True) / lv.vg.pe_size) return reserve
anaconda-patches@lists.fedorahosted.org