Skip to content

Commit

Permalink
livemerge: prune bitmaps before measuring
Browse files Browse the repository at this point in the history
Prune stale bitmaps before a live merge to avoid
failing with ENOSPC.

Fixes: oVirt#352
Signed-off-by: Albert Esteve <aesteve@redhat.com>
  • Loading branch information
aesteve-rh committed Dec 12, 2022
1 parent 7b8c7b6 commit c3c100d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
23 changes: 23 additions & 0 deletions lib/vdsm/virt/livemerge.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,16 @@ def merge(self, driveSpec, base, top, bandwidth, job_id):
except JobExistsError as e:
raise exception.MergeFailed(str(e), job=job.id)

# Prune stale bitmaps if needed once before measuring the image.
# Currently, qemu-img ignores bitmaps in base, but future
# version may not.
if self._base_needs_prune_bitmaps(job, base_info):
self._dom._vm.prune_bitmaps(
drive.domainID,
drive.imageID,
job.top,
job.base)

needs_extend, new_size = self._base_needs_extend(
drive, job, base_info)

Expand Down Expand Up @@ -402,6 +412,19 @@ def _start_commit(self, drive, job):
self._untrack_job(job.id)
raise exception.MergeFailed(str(e), job=job.id)

def _base_needs_prune_bitmaps(self, job, base_info):
if base_info['format'] != 'COW':
log.debug("Base volume does not support bitmaps, "
"job=%r base=%r", job.id, job.base)
return False

if job.active_commit:
log.debug("Top volume is the active volume, "
"job=%r top=%r", job.id, job.top)
return False

return True

def _base_needs_extend(self, drive, job, base_info):
"""
Return True, new_size if base needs to be extended, otherwise False,
Expand Down
16 changes: 16 additions & 0 deletions lib/vdsm/virt/vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6106,6 +6106,22 @@ def onDeviceRemoved(self, device_alias):

# Accessing storage

def prune_bitmaps(self, domainID, imageID, topID, baseID):
"""
Prune stale bitmaps from the base volume.
"""
res = self.cif.irs.prune_bitmaps(
sdUUID=domainID,
imgUUID=imageID,
volUUID=topID,
baseUUID=baseID)

if res['status']['code'] != 0:
message = res['status']['message']
raise errors.StorageUnavailableError(
f"Unable to prune bitmaps in domain {domainID} "
f"image {imageID} top {topID} base {baseID}: {message}")

def measure(self, domainID, imageID, topID, dest_format, backing=True,
baseID=None):
"""
Expand Down
3 changes: 3 additions & 0 deletions tests/virt/vmfakelib.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ def appropriateDevice(self, guid, vmid):
def inappropriateDevices(self, ident):
pass

def prune_bitmaps(self, sdUUID, imgUUID, volUUID, baseUUID):
return response.success(result=None)

def measure(self, sdUUID, imgUUID, volUUID, dest_format, backing=True,
baseUUID=None):
# Return fake measure set up by the test. Not setting up anyting will
Expand Down

0 comments on commit c3c100d

Please sign in to comment.