Skip to content

Commit c4dce9e

Browse files
AnthoineBNambrok
authored andcommitted
fix(cleanup): check earlier for chain attached on several hosts (#139)
The check is made in `onCoalesceable` to exclude the chain from the candidates. Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@vates.tech>
1 parent d5288ca commit c4dce9e

1 file changed

Lines changed: 22 additions & 11 deletions

File tree

drivers/cleanup.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -666,11 +666,20 @@ def getVDIBlocks(self):
666666

667667
def isCoalesceable(self):
668668
"""A VDI is coalesceable if it has no siblings and is not a leaf"""
669-
return not self.scanError and \
670-
self.parent and \
671-
len(self.parent.children) == 1 and \
672-
self.isHidden() and \
673-
len(self.children) > 0
669+
return (
670+
not self.scanError and
671+
self.parent and
672+
len(self.parent.children) == 1 and
673+
self.isHidden() and
674+
len(self.children) > 0 and (
675+
# Conditions below are Qcow2 specific:
676+
# A Qcow2 chain can't be coalesce with more than one leaf attached.
677+
# Put it another way, Qcow2 leaves activated on multiple hosts must
678+
# prevent the coalesce of the chain.
679+
self.vdi_type != VdiType.QCOW2 or
680+
(self.vdi_type == VdiType.QCOW2 and len(self.sr.hasLeavesAttachedOn(self)) <= 1)
681+
)
682+
)
674683

675684
def isLeafCoalesceable(self):
676685
"""A VDI is leaf-coalesceable if it has no siblings and is a leaf"""
@@ -2521,7 +2530,7 @@ def cleanupJournals(self, dryRun=False):
25212530
def cleanupCache(self, maxAge=-1) -> int:
25222531
return 0
25232532

2524-
def _hasLeavesAttachedOn(self, vdi: VDI):
2533+
def hasLeavesAttachedOn(self, vdi: VDI):
25252534
leaves = vdi.getAllLeaves()
25262535
leaves_vdi = [leaf.uuid for leaf in leaves]
25272536
return util.get_hosts_attached_on_with_vdi_uuid(self.xapi.session, leaves_vdi)
@@ -2559,11 +2568,13 @@ def _coalesce(self, vdi: VDI):
25592568
self._create_running_file(vdi)
25602569

25612570
self.journaler.create(vdi.JRN_COALESCE, vdi.uuid, "1")
2562-
host_refs = self._hasLeavesAttachedOn(vdi)
2563-
#TODO: this check of multiple host_refs should be done earlier in `is_coalesceable` to avoid stopping this late every time
2564-
if len(host_refs) > 1:
2571+
host_refs = self.hasLeavesAttachedOn(vdi)
2572+
# This check of multiple host_refs was done earlier in `isCoalesceable` but
2573+
# we recheck here to be sure another leaf wasn't activated in the meantime.
2574+
if vdi.cowutil.isCoalesceableOnRemote() and len(host_refs) > 1:
25652575
Util.log("Not coalesceable, chain activated more than once")
2566-
raise Exception("Not coalesceable, chain activated more than once") #TODO: Use correct error
2576+
Util.log(f"VDI '{vdi.uuid}' has leaves attached on {host_refs}")
2577+
raise Exception("Not coalesceable, chain activated more than once")
25672578

25682579
try:
25692580
if host_refs and vdi.cowutil.isCoalesceableOnRemote():
@@ -2903,7 +2914,7 @@ def _doCoalesceLeaf(self, vdi: VDI, coalesce_on_remote: bool):
29032914
self._prepareCoalesceLeaf(vdi)
29042915
vdi.parent._setHidden(False)
29052916
vdi.parent._increaseSizeVirt(vdi.sizeVirt, False)
2906-
host_refs = self._hasLeavesAttachedOn(vdi) if coalesce_on_remote else None
2917+
host_refs = self.hasLeavesAttachedOn(vdi) if coalesce_on_remote else None
29072918
if host_refs:
29082919
util.fistpoint.activate("LVHDRT_coaleaf_before_coalesce", self.uuid)
29092920
_, host_ref = next(iter(host_refs.items()))

0 commit comments

Comments
 (0)