From aa204ea41b88e6896f5505df2d35cdb275cf6187 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 13 Mar 2012 14:44:31 -0700 Subject: Fix backing file cp/resize race condition. * Fixes bug 953831 Change-Id: I39950b16c9b76159b16203f7b8b504cae5475516 --- nova/virt/libvirt/connection.py | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 8fd00457c..5603b1e26 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -46,6 +46,7 @@ import multiprocessing import os import shutil import sys +import time import uuid from eventlet import greenthread @@ -1012,22 +1013,26 @@ class LibvirtConnection(driver.ComputeDriver): # For raw it's quicker to just generate outside the cache call_if_not_exists(target, fn, *args, **kwargs) - if cow: - cow_base = base - if size: - size_gb = size / (1024 * 1024 * 1024) - cow_base += "_%d" % size_gb - if not os.path.exists(cow_base): - libvirt_utils.copy_image(base, cow_base) - disk.extend(cow_base, size) - libvirt_utils.create_cow_image(cow_base, target) - elif not generating: - libvirt_utils.copy_image(base, target) - # Resize after the copy, as it's usually much faster - # to make sparse updates, rather than potentially - # naively copying the whole image file. - if size: - disk.extend(target, size) + @utils.synchronized(base) + def copy_and_extend(cow, generating, base, target, size): + if cow: + cow_base = base + if size: + size_gb = size / (1024 * 1024 * 1024) + cow_base += "_%d" % size_gb + if not os.path.exists(cow_base): + libvirt_utils.copy_image(base, cow_base) + disk.extend(cow_base, size) + libvirt_utils.create_cow_image(cow_base, target) + elif not generating: + libvirt_utils.copy_image(base, target) + # Resize after the copy, as it's usually much faster + # to make sparse updates, rather than potentially + # naively copying the whole image file. + if size: + disk.extend(target, size) + + copy_and_extend(cow, generating, base, target, size) @staticmethod def _create_local(target, local_size, unit='G', -- cgit