Skip to content

Commit b2bef4a

Browse files
committed
fix(LinstorSR): remove SR lock during thin attach/detach
This lock is normally useless and can create a dead lock when thin mode is activated: - A task try to deactivate a volume during a VM shutdown on a slave (so a VDI A is locked). Then a new task is created on the master host, we try to get the SR lock on the master. - In parallel a tap-pause is asked from the master to the slave, the master SR lock is now locked. The tap-pause request is received on the slave, but we can't lock VDI A because it's already locked. So to resume: a dead lock is only possible if we try to shutdown a VM with a particular VDI and if we try to snapshot it in the same time. Signed-off-by: Ronan Abhamon <[email protected]>
1 parent f0535fd commit b2bef4a

File tree

1 file changed

+45
-57
lines changed

1 file changed

+45
-57
lines changed

drivers/LinstorSR.py

Lines changed: 45 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -148,78 +148,66 @@ def attach_thin(session, journaler, linstor, sr_uuid, vdi_uuid):
148148
if image_type == vhdutil.VDI_TYPE_RAW:
149149
return
150150

151-
lock = Lock(vhdutil.LOCK_TYPE_SR, sr_uuid)
152-
try:
153-
lock.acquire()
151+
device_path = linstor.get_device_path(vdi_uuid)
152+
153+
# If the virtual VHD size is lower than the LINSTOR volume size,
154+
# there is nothing to do.
155+
vhd_size = compute_volume_size(
156+
# TODO: Replace pylint comment with this feature when possible:
157+
# https://github.com/PyCQA/pylint/pull/2926
158+
LinstorVhdUtil(session, linstor).get_size_virt(vdi_uuid), # pylint: disable = E1120
159+
image_type
160+
)
154161

155-
device_path = linstor.get_device_path(vdi_uuid)
162+
volume_info = linstor.get_volume_info(vdi_uuid)
163+
volume_size = volume_info.virtual_size
156164

157-
# If the virtual VHD size is lower than the LINSTOR volume size,
158-
# there is nothing to do.
159-
vhd_size = compute_volume_size(
160-
# TODO: Replace pylint comment with this feature when possible:
161-
# https://github.com/PyCQA/pylint/pull/2926
162-
LinstorVhdUtil(session, linstor).get_size_virt(vdi_uuid), # pylint: disable = E1120
163-
image_type
165+
if vhd_size > volume_size:
166+
inflate(
167+
journaler, linstor, vdi_uuid, device_path,
168+
vhd_size, volume_size
164169
)
165170

166-
volume_info = linstor.get_volume_info(vdi_uuid)
167-
volume_size = volume_info.virtual_size
168-
169-
if vhd_size > volume_size:
170-
inflate(
171-
journaler, linstor, vdi_uuid, device_path,
172-
vhd_size, volume_size
173-
)
174-
finally:
175-
lock.release()
176-
177171

178172
def detach_thin_impl(session, linstor, sr_uuid, vdi_uuid):
179173
volume_metadata = linstor.get_volume_metadata(vdi_uuid)
180174
image_type = volume_metadata.get(VDI_TYPE_TAG)
181175
if image_type == vhdutil.VDI_TYPE_RAW:
182176
return
183177

184-
lock = Lock(vhdutil.LOCK_TYPE_SR, sr_uuid)
185-
try:
186-
lock.acquire()
187-
188-
def check_vbd_count():
189-
vdi_ref = session.xenapi.VDI.get_by_uuid(vdi_uuid)
190-
vbds = session.xenapi.VBD.get_all_records_where(
191-
'field "VDI" = "{}"'.format(vdi_ref)
192-
)
178+
def check_vbd_count():
179+
vdi_ref = session.xenapi.VDI.get_by_uuid(vdi_uuid)
180+
vbds = session.xenapi.VBD.get_all_records_where(
181+
'field "VDI" = "{}"'.format(vdi_ref)
182+
)
193183

194-
num_plugged = 0
195-
for vbd_rec in vbds.values():
196-
if vbd_rec['currently_attached']:
197-
num_plugged += 1
198-
if num_plugged > 1:
199-
raise xs_errors.XenError(
200-
'VDIUnavailable',
201-
opterr='Cannot deflate VDI {}, already used by '
202-
'at least 2 VBDs'.format(vdi_uuid)
203-
)
184+
num_plugged = 0
185+
for vbd_rec in vbds.values():
186+
if vbd_rec['currently_attached']:
187+
num_plugged += 1
188+
if num_plugged > 1:
189+
raise xs_errors.XenError(
190+
'VDIUnavailable',
191+
opterr='Cannot deflate VDI {}, already used by '
192+
'at least 2 VBDs'.format(vdi_uuid)
193+
)
204194

205-
# We can have multiple VBDs attached to a VDI during a VM-template clone.
206-
# So we use a timeout to ensure that we can detach the volume properly.
207-
util.retry(check_vbd_count, maxretry=10, period=1)
195+
# We can have multiple VBDs attached to a VDI during a VM-template clone.
196+
# So we use a timeout to ensure that we can detach the volume properly.
197+
util.retry(check_vbd_count, maxretry=10, period=1)
208198

209-
device_path = linstor.get_device_path(vdi_uuid)
210-
new_volume_size = LinstorVolumeManager.round_up_volume_size(
211-
# TODO: Replace pylint comment with this feature when possible:
212-
# https://github.com/PyCQA/pylint/pull/2926
213-
LinstorVhdUtil(session, linstor).get_size_phys(vdi_uuid) # pylint: disable = E1120
214-
)
199+
device_path = linstor.get_device_path(vdi_uuid)
200+
new_volume_size = LinstorVolumeManager.round_up_volume_size(
201+
# TODO: Replace pylint comment with this feature when possible:
202+
# https://github.com/PyCQA/pylint/pull/2926
203+
LinstorVhdUtil(session, linstor).get_size_phys(vdi_uuid) # pylint: disable = E1120
204+
)
215205

216-
volume_info = linstor.get_volume_info(vdi_uuid)
217-
old_volume_size = volume_info.virtual_size
218-
deflate(
219-
linstor, vdi_uuid, device_path, new_volume_size, old_volume_size
220-
)
221-
finally:
222-
lock.release()
206+
volume_info = linstor.get_volume_info(vdi_uuid)
207+
old_volume_size = volume_info.virtual_size
208+
deflate(
209+
linstor, vdi_uuid, device_path, new_volume_size, old_volume_size
210+
)
223211

224212

225213
def detach_thin(session, linstor, sr_uuid, vdi_uuid):

0 commit comments

Comments
 (0)