Skip to content

Commit 2190bb1

Browse files
committed
WIP for cancelling coalesce for VDI activation
Signed-off-by: Damien Thenot <[email protected]>
1 parent d61737c commit 2190bb1

File tree

3 files changed

+107
-6
lines changed

3 files changed

+107
-6
lines changed

drivers/blktap2.py

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# blktap2: blktap/tapdisk management layer
1919
#
2020

21-
from sm_typing import Any, Callable, ClassVar, Dict, override
21+
from sm_typing import Any, Callable, ClassVar, Dict, override, List
2222

2323
from abc import abstractmethod
2424

@@ -1657,6 +1657,85 @@ def activate(self, sr_uuid, vdi_uuid, writable, caching_params):
16571657
time.sleep(1)
16581658
raise util.SMException("VDI %s locked" % vdi_uuid)
16591659

1660+
def _get_host_ref(self) -> str:
1661+
sr = self.target.vdi.sr
1662+
if sr.is_shared():
1663+
util.SMlog("DAMS: SR is shared")
1664+
host_ref = util.get_master_ref(self._session)
1665+
else:
1666+
util.SMlog("DAMS: SR is not shared, using local host")
1667+
host_ref = sr.host_ref
1668+
return host_ref
1669+
1670+
def _get_chain(self, cowutil, extractUuid) -> List[str]:
1671+
vdi_chain = []
1672+
path = self.target.get_vdi_path()
1673+
1674+
vdi_chain.append(extractUuid(path))
1675+
parent = cowutil.getParentNoCheck(path)
1676+
while parent:
1677+
vdi_chain.append(extractUuid(parent))
1678+
parent = cowutil.getParentNoCheck(parent)
1679+
vdi_chain.reverse()
1680+
return vdi_chain
1681+
1682+
def _check_journal_coalesce_chain(self, sr_uuid, vdi_uuid: str) -> bool:
1683+
vdi_type = self.target.get_vdi_type()
1684+
cowutil = getCowUtil(vdi_type)
1685+
if not cowutil.isCoalesceableOnRemote(): #We only need to stop the coalesce in case of QCOW2
1686+
return True
1687+
1688+
level = 0
1689+
path = self.target.get_vdi_path()
1690+
1691+
# Different extractUUID & journaler function for LVMSR and FileSR
1692+
journaler = None
1693+
extractUuid = None
1694+
if path.startswith("/dev/"): #TODO: How to identify SR type easily, we could ask XAPI since we have the sruuid (and even ref)
1695+
from lvmcowutil import LvmCowUtil
1696+
import lvmcache
1697+
import journaler
1698+
vgName = "VG_XenStorage-{}".format(sr_uuid)
1699+
lvmCache = lvmcache.LVMCache(vgName)
1700+
journaler = journaler.Journaler(lvmCache)
1701+
1702+
extractUuid = LvmCowUtil.extractUuid
1703+
else:
1704+
from FileSR import FileVDI
1705+
import fjournaler
1706+
journaler = fjournaler.Journaler(os.getcwd())
1707+
extractUuid = FileVDI.extractUuid
1708+
1709+
# Get the VDI chain
1710+
vdi_chain = self._get_chain(cowutil, extractUuid)
1711+
1712+
util.SMlog("DAMS: VDI chain:")
1713+
for vdi in vdi_chain:
1714+
prefix = " " * level
1715+
level += 1
1716+
util.SMlog("{}{}".format(prefix, vdi))
1717+
1718+
if len(vdi_chain) == 1:
1719+
#We only have a leaf, do nothing
1720+
util.SMlog("DAMS: VDI is only a leaf, continuing...")
1721+
return True
1722+
1723+
vdi_to_cancel = []
1724+
for entry in journaler.getAll("coalesce").keys():
1725+
if entry in vdi_chain:
1726+
vdi_to_cancel.append(entry)
1727+
util.SMlog("{} in chain".format(entry))
1728+
1729+
# Get the host_ref from the host doing the GC work
1730+
host_ref = self._get_host_ref()
1731+
for vdi in vdi_to_cancel:
1732+
args = {"sr_uuid": sr_uuid, "vdi_uuid": vdi}
1733+
util.SMlog("args: {}".format(args))
1734+
self._session.xenapi.host.call_plugin(\
1735+
host_ref, PLUGIN_ON_SLAVE, "cancel_coalesce_master", args)
1736+
1737+
return True
1738+
16601739
@locking("VDIUnavailable")
16611740
def _activate_locked(self, sr_uuid, vdi_uuid, options):
16621741
"""Wraps target.activate and adds a tapdisk"""
@@ -1692,6 +1771,8 @@ def _activate_locked(self, sr_uuid, vdi_uuid, options):
16921771

16931772
vdi_type = self.target.get_vdi_type()
16941773

1774+
self._check_journal_coalesce_chain(sr_uuid, vdi_uuid)
1775+
16951776
# Take lvchange-p Lock before running
16961777
# tap-ctl open
16971778
# Needed to avoid race with lvchange -p which is

drivers/cleanup.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,10 @@ def _call_plug_cancel(self, hostRef):
835835

836836
def _call_plugin_coalesce(self, hostRef):
837837
args = {"path": self.path, "vdi_type": self.vdi_type}
838-
self.sr.xapi.session.xenapi.host.call_plugin( \
838+
util.SMlog("DAMS: Calling remote coalesce with: {}".format(args))
839+
ret = self.sr.xapi.session.xenapi.host.call_plugin( \
839840
hostRef, XAPI.PLUGIN_ON_SLAVE, "commit_tapdisk", args)
841+
util.SMlog("DAMS: Remote coalesce returned {}".format(ret))
840842

841843
def _doCoalesceOnHost(self, hostRef):
842844
self.validate()
@@ -852,6 +854,7 @@ def abortTest():
852854
with open(file, "r") as f:
853855
if not f.read():
854856
#TODO: Need to call commit cancel on the hostRef if we stop
857+
util.SMlog("DAMS: Cancelling")
855858
self._call_plug_cancel(hostRef)
856859
return True
857860
except OSError as e:
@@ -862,6 +865,7 @@ def abortTest():
862865
return True
863866
return False
864867

868+
#TODO: Add exception handling here like when callinng in a runAbortable situation_doCoalesceCOWImage
865869
Util.runAbortable(lambda: self._call_plugin_coalesce(hostRef),
866870
None, self.sr.uuid, abortTest, VDI.POLL_INTERVAL, 0)
867871

@@ -2752,7 +2756,7 @@ def _snapshotCoalesce(self, vdi):
27522756
return False
27532757
return True
27542758

2755-
def _liveLeafCoalesce(self, vdi) -> bool:
2759+
def _liveLeafCoalesce(self, vdi: VDI) -> bool:
27562760
util.fistpoint.activate("LVHDRT_coaleaf_delay_3", self.uuid)
27572761
self.lock()
27582762
try:

drivers/on_slave.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,29 @@ def refresh_lun_size_by_SCSIid(session, args):
163163
return "False"
164164

165165
def commit_tapdisk(session, args):
166-
path = args["path"]
166+
path: str = args["path"]
167167
vdi_type = args["vdi_type"]
168-
#TODO: Miss activating/changing RW, naming should reflect that it does more than coalesceing
168+
#TODO: naming should reflect that it does more than coalesceing, like setting volume RW
169+
170+
def set_RW(path):
171+
try:
172+
util.pread2(["lvchange", "-p", "rw", path])
173+
except:
174+
pass
175+
#TODO: need to make children RW. Or we let the relink happen with a refresh on master and hope it doesn't corrupt the disk
176+
if path.startswith("/dev/"):
177+
set_RW(path)
178+
169179
from cowutil import getCowUtil
170180
cowutil = getCowUtil(vdi_type)
171181
try:
182+
parent = cowutil.getParentNoCheck(path)
183+
if parent.startswith("/dev/"):
184+
set_RW(parent)
172185
return str(cowutil.coalesceOnline(path))
173186
except:
174-
return "0"
187+
util.logException("Couldn't coalesce online")
188+
raise
175189

176190
def commit_cancel(session, args):
177191
path = args["path"]
@@ -205,6 +219,7 @@ def cancel_coalesce_master(session, args):
205219

206220
# return "True"
207221

222+
util.SMlog("DAMS cancel_coalesce_master plugin: {}".format(vdi_uuid))
208223
path = "/run/nonpersistent/sm/{}/gc_running_{}".format(sr_uuid, vdi_uuid)
209224

210225
try:
@@ -236,4 +251,5 @@ def is_openers(session, args):
236251
"is_openers": is_openers,
237252
"commit_tapdisk": commit_tapdisk,
238253
"commit_cancel": commit_cancel,
254+
"cancel_coalesce_master": cancel_coalesce_master,
239255
})

0 commit comments

Comments
 (0)