Skip to content

Commit d60fd5b

Browse files
committed
fix(LVMSR): vdi_revert fix coalesce issue, leaking vdi and remove tmp vdi
Signed-off-by: Antoine Bartuccio <antoine.bartuccio@vates.tech>
1 parent 9c8bdbb commit d60fd5b

2 files changed

Lines changed: 41 additions & 35 deletions

File tree

drivers/LVMSR.py

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,18 @@ def __init__(
9696
uuid: str,
9797
lvname: str,
9898
backup_lvname: str,
99-
tmp_lvname: str,
10099
is_cbt_enabled: bool,
101100
):
102101
self.uuid = uuid
103102
self.lvname = lvname
104103
self.backup_lvname = backup_lvname
105-
self.tmp_lvname = tmp_lvname
106104
self.is_cbt_enabled = is_cbt_enabled
107105

108106
def to_dict(self) -> Dict[str, Union[str, bool]]:
109107
return {
110108
"uuid": self.uuid,
111109
"lvname": self.lvname,
112110
"backup_lvname": self.backup_lvname,
113-
"tmp_lvname": self.tmp_lvname,
114111
"is_cbt_enabled": self.is_cbt_enabled,
115112
}
116113

@@ -120,7 +117,6 @@ def from_dict(cls, data: Dict[str, Union[str, bool]]) -> "RevertLogDestinationVD
120117
uuid=str(data["uuid"]),
121118
lvname=str(data["lvname"]),
122119
backup_lvname=str(data["backup_lvname"]),
123-
tmp_lvname=str(data["tmp_lvname"]),
124120
is_cbt_enabled=bool(data["is_cbt_enabled"]),
125121
)
126122

@@ -334,14 +330,13 @@ def load(self, sr_uuid) -> None:
334330
if lvutil._checkVG(self.vgname):
335331
# Disable SR on slaves when mounting VDIs if
336332
# a critical journal is pending
337-
if (
338-
not self.isMaster
339-
and self.cmd not in ["vdi_detach", "vdi_activate", "vdi_deactivate", "nop"]
340-
and self._has_critical_journals()
341-
):
342-
raise xs_errors.XenError(
343-
"SRUnavailable", opterr="Critical journals are pending"
344-
)
333+
# and force journal undo if on master
334+
if self._has_critical_journals():
335+
if not self.isMaster:
336+
raise xs_errors.XenError(
337+
"SRUnavailable", opterr="Critical journals are pending. A scan is required."
338+
)
339+
self._undoAllJournals()
345340

346341
if self.isMaster and not self.cmd in [
347342
"vdi_attach",
@@ -350,7 +345,6 @@ def load(self, sr_uuid) -> None:
350345
"vdi_deactivate",
351346
]:
352347
self._undoAllJournals()
353-
354348
if not self.cmd in ["sr_attach", "sr_probe"]:
355349
self._checkMetadataVolume()
356350

@@ -1334,10 +1328,6 @@ def _undo_revert_journals(self):
13341328
self.journaler.remove(RevertLogEntry.JRN_KEY, journal_id)
13351329

13361330
def _rollback_revert_vdi(self, entry: RevertLogEntry):
1337-
util.SMlog(f"Removing temporary file {entry.dest.tmp_lvname}")
1338-
if self.lvmCache.checkLV(entry.dest.tmp_lvname):
1339-
self.lvmCache.remove(entry.dest.tmp_lvname)
1340-
13411331
util.SMlog(
13421332
f"Reverting vdi {entry.dest.uuid} from backup {entry.dest.backup_lvname}"
13431333
)
@@ -1362,6 +1352,7 @@ def _rollback_revert_vdi(self, entry: RevertLogEntry):
13621352
src.cowutil.setHidden(str(src.path), False)
13631353
src.update_from_disk()
13641354
src._db_update()
1355+
src.disable_leaf_on_secondary(src.uuid)
13651356

13661357
# CBT cannot be added by accident on src, we can skip checking if it exists
13671358
util.SMlog(f"CBT rollback: restoring cbtlog for src {entry.src.uuid}")
@@ -1375,6 +1366,17 @@ def _rollback_revert_vdi(self, entry: RevertLogEntry):
13751366
if self.lvmCache.checkLV(entry.dest.lvname):
13761367
self.lvmCache.remove(entry.dest.lvname)
13771368

1369+
# Ensure that inserted node is hidden so that it doesn't leak
1370+
if self.lvmCache.checkLV(entry.inserted.lvname):
1371+
inserted: "LVMVDI" = self.vdi(entry.inserted.uuid) # type: ignore[assignment]
1372+
with inserted.activated(False):
1373+
inserted.cowutil.setHidden(str(inserted.path), True)
1374+
inserted.update_from_disk()
1375+
inserted_ref = inserted._db_update_or_introduce()
1376+
1377+
inserted.session.xenapi.VDI.set_managed(inserted_ref, False)
1378+
inserted.disable_leaf_on_secondary(inserted.uuid)
1379+
13781380
# Once we move the backup to it's old name, the journal can't be run again
13791381
# If something fails from now, we might lose some info, most of them
13801382
# will be back from a simple scan
@@ -1979,7 +1981,8 @@ def _revert(
19791981

19801982
self.sr._ensureSpaceAvailable(size_req)
19811983

1982-
dest_tmp_uuid = util.gen_uuid() # Will be replaced by dest.uuid at the end
1984+
# We create a valid backup VDI so that it properly protect
1985+
# it's parent chain in case of a coalesce
19831986
dest_backup_name = LV_PREFIX[self.vdi_type] + util.gen_uuid()
19841987

19851988
# Create journal
@@ -1989,7 +1992,6 @@ def _revert(
19891992
dest.uuid,
19901993
dest.lvname,
19911994
dest_backup_name,
1992-
LV_PREFIX[self.vdi_type] + dest_tmp_uuid,
19931995
bool(dest_cbtlog),
19941996
),
19951997
src=RevertLogSourceVDI(
@@ -2017,6 +2019,8 @@ def _revert(
20172019
self.sr.lvActivator.deactivate(self.uuid, False)
20182020
self.sr.lvmCache.rename(self.lvname, inserted_lvname)
20192021

2022+
util.fistpoint.activate("LVM_revert_create_insert", self.sr.uuid)
2023+
20202024
inserted = LVMVDI(self.sr, inserted_uuid)
20212025
inserted.label = "base copy"
20222026
inserted.read_only = False
@@ -2030,41 +2034,40 @@ def _revert(
20302034
## Protect the new parent from being coalesced by the GC
20312035
inserted.sr.lvActivator.activate(inserted.uuid, inserted.lvname, False)
20322036
inserted.cowutil.setHidden(inserted.path, False)
2037+
inserted_ref = inserted._db_introduce()
2038+
2039+
util.fistpoint.activate("LVM_revert_create_src", self.sr.uuid)
2040+
2041+
inserted.disable_leaf_on_secondary(inserted.uuid, True)
20332042

20342043
# Recreate src
20352044
## Since src is a snapshot, we use the minimal size on it
20362045
_ = inserted._createSnap(
20372046
self.uuid, self.vdi_type, inserted_size, False, False
20382047
)
20392048

2040-
inserted._db_introduce()
2041-
20422049
# Update src
20432050
self.sr.lvActivator.activate(self.uuid, self.lvname, False)
20442051
self.update_from_disk()
20452052
self._db_update()
20462053

20472054
# Create snapshot
2048-
dest_tmp = inserted._createSnap(
2049-
dest_tmp_uuid, inserted.vdi_type, destination_size, False, False
2055+
_ = inserted._createSnap(
2056+
dest.uuid, inserted.vdi_type, destination_size, False, False
20502057
)
2051-
## Force parent (it can be simplified by vhd tools)
2052-
self.cowutil.setParent(dest_tmp.path, inserted.path, False)
20532058

2054-
inserted.read_only = True
2055-
inserted._db_update()
2059+
util.fistpoint.activate("LVM_revert_create_dest", self.sr.uuid)
2060+
2061+
dest.update_from_disk()
2062+
dest._db_update()
20562063

20572064
## The new parent can now be set hidden and don't need to be protected by the GC
2065+
inserted.update_from_disk()
2066+
inserted.read_only = True
2067+
inserted._db_update()
20582068
inserted.cowutil.setHidden(inserted.path, True)
20592069
inserted.sr.lvmCache.setReadonly(inserted.lvname, True)
2060-
2061-
# Apply snapshot
2062-
dest.sr.lvActivator.deactivate(dest_tmp.uuid, False)
2063-
dest.sr.lvmCache.rename(dest_tmp.lvname, dest.lvname)
2064-
dest.sr.lvActivator.activate(dest.uuid, dest.lvname, False)
2065-
2066-
dest.update_from_disk()
2067-
dest._db_update()
2070+
self.session.xenapi.VDI.set_managed(inserted_ref, False)
20682071

20692072
if src_cbtlog:
20702073
self._revert_cbt(dest)

drivers/util.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,9 @@ def list_find(f, seq):
14751475
"FileSR_revert_create_insert",
14761476
"FileSR_revert_create_src",
14771477
"FileSR_revert_create_dest",
1478+
"LVM_revert_create_insert",
1479+
"LVM_revert_create_src",
1480+
"LVM_revert_create_dest",
14781481
"LVM_journaler_exists",
14791482
"LVM_journaler_none",
14801483
"LVM_journaler_badname",

0 commit comments

Comments
 (0)