New patch submitted by Federico Simoncelli (fsimonce(a)redhat.com)
You can review this change at:
http://gerrit.usersys.redhat.com/891
commit 1a3aa6f6cbf9913ff3ad8e8e481b519e54853bfe
Author: Federico Simoncelli <fsimonce(a)redhat.com>
Date: Fri Sep 2 16:36:33 2011 +0000
BZ#732980 MD tag must be in blocks unit
This patch fixes the unit used for the MD tag (blocks instead of
bytes) and completes the support for the new MS tag which holds
the size (in blocks) of the metadata.
Change-Id: Id268735f60a289f9e8f12a7d7bb3180bf3398c54
diff --git a/vdsm/storage/blockSD.py b/vdsm/storage/blockSD.py
index ab3241f..c5aa4a9 100644
--- a/vdsm/storage/blockSD.py
+++ b/vdsm/storage/blockSD.py
@@ -520,11 +520,11 @@ class BlockStorageDomain(sd.StorageDomain):
finally:
self._extendlock.release()
- def mapMetaOffset(self, vol_name):
+ def mapMetaOffset(self, vol_name, slotSize):
if self.getVersion() in VERS_METADATA_LV:
return self.getVolumeMetadataOffsetFromPvMapping(vol_name)
else:
- return self.getFreeMetadataSlot(blockVolume.VOLUME_METASIZE)
+ return self.getFreeMetadataSlot(slotSize)
def _getOccupiedMetadataSlots(self):
stripPrefix = lambda s, pfx : s[len(pfx):]
@@ -540,6 +540,9 @@ class BlockStorageDomain(sd.StorageDomain):
if tag.startswith(blockVolume.TAG_PREFIX_MD):
offset = int(stripPrefix(tag, blockVolume.TAG_PREFIX_MD))
+ if tag.startswith(blockVolume.TAG_PREFIX_MS):
+ size = int(stripPrefix(tag, blockVolume.TAG_PREFIX_MS))
+
if offset is not None and size is not None:
# I've found everything I need
break
@@ -549,7 +552,8 @@ class BlockStorageDomain(sd.StorageDomain):
continue
if size is None:
- size = blockVolume.VOLUME_METASIZE
+ self.log.warn("Could not find size for lv %s/%s", self.sdUUID,
lv.name)
+ continue
occupiedSlots.append((offset, size))
@@ -558,14 +562,21 @@ class BlockStorageDomain(sd.StorageDomain):
def getFreeMetadataSlot(self, slotSize):
occupiedSlots = self._getOccupiedMetadataSlots()
+ logBlkSize, phyBlkSize = lvm.getVGBlockSizes(self.sdUUID)
+
+ # It might look weird skipping the sd metadata when it has been moved
+ # to tags. But this is here because domain metadata and volume metadata
+ # look the same. The domain might get confused and think it has lv
+ # metadata if it finds something is written in that area.
+ # At the moment this check is trivial but it will be needed in the
+ # future when we'll support multiple block sizes.
+ if logBlkSize >= SD_METADATA_SIZE:
+ freeSlot = 1
+ else:
+ freeSlot, freeSlotRem = divmod(SD_METADATA_SIZE, logBlkSize)
+ if freeSlotRem > 0:
+ freeSlot += 1
- # It might look weird skipping the sd metadata
- # when it has been moved to tags. But this is
- # here because domain metadata and volume
- # metadata look the same. The domain might get
- # confused and think it has lv metadata if it
- # finds something is written in that area.
- freeSlot = SD_METADATA_SIZE
for offset, size in occupiedSlots:
if offset - freeSlot > slotSize:
break
diff --git a/vdsm/storage/blockVolume.py b/vdsm/storage/blockVolume.py
index 25ec92c..a83b1f7 100644
--- a/vdsm/storage/blockVolume.py
+++ b/vdsm/storage/blockVolume.py
@@ -38,15 +38,18 @@ from resourceFactories import LVM_ACTIVATION_NAMESPACE
import fileUtils
TAG_PREFIX_MD = "MD_"
+TAG_PREFIX_MS = "MS_"
TAG_PREFIX_IMAGE = "IU_"
TAG_PREFIX_PARENT = "PU_"
VOLUME_TAGS = [TAG_PREFIX_PARENT,
TAG_PREFIX_IMAGE,
- TAG_PREFIX_MD]
+ TAG_PREFIX_MD,
+ TAG_PREFIX_MS]
# volume meta data block size
VOLUME_METASIZE = 512
+VOLUME_METASLOT = 1
rmanager = rm.ResourceManager.getInstance()
@@ -215,8 +218,9 @@ class BlockVolume(volume.Volume):
try:
with cls._tagCreateLock:
- offs = mysd.mapMetaOffset(volUUID)
+ offs = mysd.mapMetaOffset(volUUID, VOLUME_METASLOT)
lvm.addLVTags(sdUUID, volUUID, ("%s%s" % (TAG_PREFIX_MD,
offs),
+ "%s%s" % (TAG_PREFIX_MS,
VOLUME_METASLOT),
"%s%s" % (TAG_PREFIX_PARENT,
srcVolUUID,),
"%s%s" % (TAG_PREFIX_IMAGE,
imgUUID,)))
diff --git a/vdsm/storage/lvm.py b/vdsm/storage/lvm.py
index 921cf3b..f1b25a3 100644
--- a/vdsm/storage/lvm.py
+++ b/vdsm/storage/lvm.py
@@ -934,6 +934,14 @@ def invalidateVG(vgName):
_lvminfo._invalidatevgs(vgName)
_lvminfo._invalidatelvs(vgName)
+def getVGBlockSizes(vgUUID):
+ pvs = [pv.name for pv in _lvminfo.getAllPvs() if pv.vg_name == vgUUID]
+ if not pvs:
+ return None
+ # Returning the block size of the first pv is correct since we don't allow
+ # devices with different block size to be on the same VG.
+ dmDevice = devicemapper.getDmId(os.path.basename(pvs[0]))
+ return multipath.getDeviceBlockSizes(dmDevice)
#
# Public Logical volume interface