[virt-tools-list] [virt-manager PATCH 1/3] virt-clone: introduce --reflink for btrfs COW copy

Chen Hanxiao chenhanxiao at cn.fujitsu.com
Wed Jan 28 04:12:11 UTC 2015


libvirt commit 466b29c8c3593b2dac92acad5dd8ec923c428259
introduce btrfsCloneFile() for COW copy.
This patch add support for --reflink option for virt-clone.
When specified --reflink, if src and dst images all on a btrfs
fs, we could take advantage of COW copy.
If not, error out.

Signed-off-by: Chen Hanxiao <chenhanxiao at cn.fujitsu.com>
---
 virt-clone              |  4 +++-
 virtinst/cloner.py      |  5 +++--
 virtinst/devicedisk.py  |  4 ++--
 virtinst/diskbackend.py | 14 ++++++++------
 virtinst/storage.py     |  5 ++++-
 5 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/virt-clone b/virt-clone
index e6699a0..1e189f8 100755
--- a/virt-clone
+++ b/virt-clone
@@ -120,6 +120,8 @@ def parse_args():
     geng.add_argument("-n", "--name", dest="new_name",
                     help=_("Name for the new guest"))
     geng.add_argument("-u", "--uuid", dest="new_uuid", help=argparse.SUPPRESS)
+    geng.add_argument("--reflink", action="store_true", dest="reflink",
+            help=_("use btrfs lightweight copy"))
 
     stog = parser.add_argument_group(_("Storage Configuration"))
     stog.add_argument("-f", "--file", dest="new_diskfile", action="append",
@@ -198,7 +200,7 @@ def main(conn=None):
     else:
         # start cloning
         meter = progress.TextMeter(fo=sys.stdout)
-        design.start_duplicate(meter)
+        design.start_duplicate(meter, options.reflink)
 
     print_stdout("")
     print_stdout(_("Clone '%s' created successfully.") % design.clone_name)
diff --git a/virtinst/cloner.py b/virtinst/cloner.py
index 5e76413..7d1ef3e 100644
--- a/virtinst/cloner.py
+++ b/virtinst/cloner.py
@@ -415,7 +415,7 @@ class Cloner(object):
         self.setup_original()
         self.setup_clone()
 
-    def start_duplicate(self, meter=None):
+    def start_duplicate(self, meter=None, reflink=None):
         """
         Actually perform the duplication: cloning disks if needed and defining
         the new clone xml.
@@ -436,7 +436,8 @@ class Cloner(object):
 
             if self.preserve:
                 for dst_dev in self.clone_disks:
-                    dst_dev.setup(meter=meter)
+                    # seed for test reflink!!!!
+                    dst_dev.setup(meter=meter, reflink=reflink)
         except Exception, e:
             logging.debug("Duplicate failed: %s", str(e))
             if dom:
diff --git a/virtinst/devicedisk.py b/virtinst/devicedisk.py
index ac03716..813cbfe 100644
--- a/virtinst/devicedisk.py
+++ b/virtinst/devicedisk.py
@@ -857,7 +857,7 @@ class VirtualDisk(VirtualDevice):
 
         self._storage_backend.validate(self)
 
-    def setup(self, meter=None):
+    def setup(self, meter=None, reflink=None):
         """
         Build storage (if required)
 
@@ -872,7 +872,7 @@ class VirtualDisk(VirtualDevice):
         if not self._storage_backend.will_create_storage():
             return
 
-        vol_object = self._storage_backend.create(meter)
+        vol_object = self._storage_backend.create(meter, reflink)
         if not vol_object:
             return
 
diff --git a/virtinst/diskbackend.py b/virtinst/diskbackend.py
index 2bcd064..2e1250a 100644
--- a/virtinst/diskbackend.py
+++ b/virtinst/diskbackend.py
@@ -202,7 +202,7 @@ class _StorageBase(object):
     # Storage creation routines
     def is_size_conflict(self):
         raise NotImplementedError()
-    def create(self, progresscb):
+    def create(self, progresscb, reflink):
         raise NotImplementedError()
     def will_create_storage(self):
         raise NotImplementedError()
@@ -226,7 +226,7 @@ class _StorageCreator(_StorageBase):
     # Public API #
     ##############
 
-    def create(self, progresscb):
+    def create(self, progresscb, reflink):
         raise NotImplementedError()
 
     def get_path(self):
@@ -341,7 +341,8 @@ class CloneStorageCreator(_StorageCreator):
                         ((need / (1024 * 1024)), (avail / (1024 * 1024))))
         return (ret, msg)
 
-    def create(self, progresscb):
+    def create(self, progresscb, reflink):
+        ignore = reflink
         text = (_("Cloning %(srcfile)s") %
                 {'srcfile' : os.path.basename(self._input_path)})
 
@@ -432,8 +433,8 @@ class ManagedStorageCreator(_StorageCreator):
         self._pool = vol_install.pool
         self._vol_install = vol_install
 
-    def create(self, progresscb):
-        return self._vol_install.install(meter=progresscb)
+    def create(self, progresscb, reflink=None):
+        return self._vol_install.install(meter=progresscb, reflink=reflink)
     def is_size_conflict(self):
         return self._vol_install.is_size_conflict()
 
@@ -573,7 +574,8 @@ class StorageBackend(_StorageBase):
         return (False, None)
     def will_create_storage(self):
         return False
-    def create(self, progresscb):
+    def create(self, progresscb, reflink):
         ignore = progresscb
+        ignore = reflink
         raise RuntimeError("programming error: %s can't create storage" %
             self.__class__.__name__)
diff --git a/virtinst/storage.py b/virtinst/storage.py
index bdbd064..fe7f9cb 100644
--- a/virtinst/storage.py
+++ b/virtinst/storage.py
@@ -723,7 +723,7 @@ class StorageVolume(_StorageObject):
                                "setting allocation equal to capacity"))
                 self.allocation = self.capacity
 
-    def install(self, meter=None):
+    def install(self, meter=None, reflink=None):
         """
         Build and install storage volume from xml
         """
@@ -748,6 +748,9 @@ class StorageVolume(_StorageObject):
                 self.conn.SUPPORT_POOL_METADATA_PREALLOC, self.pool)):
             createflags |= libvirt.VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA
 
+        if reflink:
+            cloneflags |= libvirt.VIR_STORAGE_VOL_CREATE_REFLINK
+
 
         try:
             self._install_finished = False
-- 
2.1.0




More information about the virt-tools-list mailing list