@@ -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