[lxc-devel] [lxd/master] lxd/storage/btrfs: Optimize create from image
stgraber on Github
lxc-bot at linuxcontainers.org
Fri Mar 16 19:34:22 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 354 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180316/3da4d531/attachment.bin>
-------------- next part --------------
From 7cd72a9df32d813d60babd23e887762321c82914 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 16 Mar 2018 15:33:51 -0400
Subject: [PATCH] lxd/storage/btrfs: Optimize create from image
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/storage_btrfs.go | 72 +++++++++++++++++++++++++++-------------------------
1 file changed, 37 insertions(+), 35 deletions(-)
diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index 1e70aa628..e6140a2fb 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -808,7 +808,7 @@ func (s *storageBtrfs) ContainerCreateFromImage(container container, fingerprint
// from the mounted ro image snapshot mounted at
// ${LXD_DIR}/storage-pools/<pool>/images/<fingerprint>
containerSubvolumeName := getContainerMountPoint(s.pool.Name, container.Name())
- err = s.btrfsPoolVolumesSnapshot(imageMntPoint, containerSubvolumeName, false)
+ err = s.btrfsPoolVolumesSnapshot(imageMntPoint, containerSubvolumeName, false, false)
if err != nil {
return err
}
@@ -898,7 +898,7 @@ func (s *storageBtrfs) copyContainer(target container, source container) error {
}
}
- err := s.btrfsPoolVolumesSnapshot(sourceContainerSubvolumeName, targetContainerSubvolumeName, false)
+ err := s.btrfsPoolVolumesSnapshot(sourceContainerSubvolumeName, targetContainerSubvolumeName, false, true)
if err != nil {
return err
}
@@ -945,7 +945,7 @@ func (s *storageBtrfs) copySnapshot(target container, source container) error {
}
}
- err = s.btrfsPoolVolumesSnapshot(sourceContainerSubvolumeName, targetContainerSubvolumeName, false)
+ err = s.btrfsPoolVolumesSnapshot(sourceContainerSubvolumeName, targetContainerSubvolumeName, false, true)
if err != nil {
return err
}
@@ -1130,7 +1130,7 @@ func (s *storageBtrfs) ContainerRestore(container container, sourceContainer con
_, targetPool, _ := s.GetContainerPoolInfo()
if targetPool == sourcePool {
// They are on the same storage pool, so we can simply snapshot.
- err := s.btrfsPoolVolumesSnapshot(sourceContainerSubvolumeName, targetContainerSubvolumeName, false)
+ err := s.btrfsPoolVolumesSnapshot(sourceContainerSubvolumeName, targetContainerSubvolumeName, false, true)
if err != nil {
failure = err
}
@@ -1209,7 +1209,7 @@ func (s *storageBtrfs) ContainerSnapshotCreate(snapshotContainer container, sour
srcContainerSubvolumeName := getContainerMountPoint(s.pool.Name, sourceContainer.Name())
snapshotSubvolumeName := getSnapshotMountPoint(s.pool.Name, snapshotContainer.Name())
- err = s.btrfsPoolVolumesSnapshot(srcContainerSubvolumeName, snapshotSubvolumeName, true)
+ err = s.btrfsPoolVolumesSnapshot(srcContainerSubvolumeName, snapshotSubvolumeName, true, true)
if err != nil {
return err
}
@@ -1279,7 +1279,7 @@ func (s *storageBtrfs) ContainerSnapshotStart(container container) (bool, error)
return false, err
}
- err = s.btrfsPoolVolumesSnapshot(roSnapshotSubvolumeName, snapshotSubvolumeName, false)
+ err = s.btrfsPoolVolumesSnapshot(roSnapshotSubvolumeName, snapshotSubvolumeName, false, true)
if err != nil {
return false, err
}
@@ -1442,7 +1442,7 @@ func (s *storageBtrfs) ImageCreate(fingerprint string) error {
// Now create a read-only snapshot of the subvolume.
// The path with which we do this is
// ${LXD_DIR}/storage-pools/<pool>/images/<fingerprint>.
- err = s.btrfsPoolVolumesSnapshot(tmpImageSubvolumeName, imageSubvolumeName, true)
+ err = s.btrfsPoolVolumesSnapshot(tmpImageSubvolumeName, imageSubvolumeName, true, true)
if err != nil {
return err
}
@@ -1698,37 +1698,39 @@ func (s *storageBtrfs) btrfsPoolVolumeSnapshot(source string, dest string, reado
return btrfsSnapshot(source, dest, readonly)
}
-func (s *storageBtrfs) btrfsPoolVolumesSnapshot(source string, dest string, readonly bool) error {
- // Get a list of subvolumes of the root
- subsubvols, err := btrfsSubVolumesGet(source)
- if err != nil {
- return err
- }
- sort.Sort(sort.StringSlice(subsubvols))
-
- if len(subsubvols) > 0 && readonly {
- // A root with subvolumes can never be readonly,
- // also don't make subvolumes readonly.
- readonly = false
-
- logger.Warnf("Subvolumes detected, ignoring ro flag.")
- }
-
+func (s *storageBtrfs) btrfsPoolVolumesSnapshot(source string, dest string, readonly bool, recursive bool) error {
// First snapshot the root
- err = s.btrfsPoolVolumeSnapshot(source, dest, readonly)
+ err := s.btrfsPoolVolumeSnapshot(source, dest, readonly)
if err != nil {
return err
}
// Now snapshot all subvolumes of the root.
- for _, subsubvol := range subsubvols {
- // Clear the target for the subvol to use
- os.Remove(path.Join(dest, subsubvol))
-
- err := s.btrfsPoolVolumeSnapshot(path.Join(source, subsubvol), path.Join(dest, subsubvol), readonly)
+ if recursive {
+ // Get a list of subvolumes of the root
+ subsubvols, err := btrfsSubVolumesGet(source)
if err != nil {
return err
}
+ sort.Sort(sort.StringSlice(subsubvols))
+
+ if len(subsubvols) > 0 && readonly {
+ // A root with subvolumes can never be readonly,
+ // also don't make subvolumes readonly.
+ readonly = false
+
+ logger.Warnf("Subvolumes detected, ignoring ro flag.")
+ }
+
+ for _, subsubvol := range subsubvols {
+ // Clear the target for the subvol to use
+ os.Remove(path.Join(dest, subsubvol))
+
+ err := s.btrfsPoolVolumeSnapshot(path.Join(source, subsubvol), path.Join(dest, subsubvol), readonly)
+ if err != nil {
+ return err
+ }
+ }
}
return nil
@@ -1891,7 +1893,7 @@ func (s *btrfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *
migrationSendSnapshot := fmt.Sprintf("%s/.migration-send", tmpContainerMntPoint)
snapshotMntPoint := getSnapshotMountPoint(containerPool, containerName)
- err = s.btrfs.btrfsPoolVolumesSnapshot(snapshotMntPoint, migrationSendSnapshot, true)
+ err = s.btrfs.btrfsPoolVolumesSnapshot(snapshotMntPoint, migrationSendSnapshot, true, true)
if err != nil {
return err
}
@@ -1929,7 +1931,7 @@ func (s *btrfsMigrationSourceDriver) SendWhileRunning(conn *websocket.Conn, op *
migrationSendSnapshot := fmt.Sprintf("%s/.migration-send", tmpContainerMntPoint)
containerMntPoint := getContainerMountPoint(containerPool, sourceName)
- err = s.btrfs.btrfsPoolVolumesSnapshot(containerMntPoint, migrationSendSnapshot, true)
+ err = s.btrfs.btrfsPoolVolumesSnapshot(containerMntPoint, migrationSendSnapshot, true, true)
if err != nil {
return err
}
@@ -1955,7 +1957,7 @@ func (s *btrfsMigrationSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, b
s.stoppedSnapName = fmt.Sprintf("%s/.root", tmpPath)
parentName, _, _ := containerGetParentAndSnapshotName(s.container.Name())
containerMntPt := getContainerMountPoint(s.btrfs.pool.Name, parentName)
- err = s.btrfs.btrfsPoolVolumesSnapshot(containerMntPt, s.stoppedSnapName, true)
+ err = s.btrfs.btrfsPoolVolumesSnapshot(containerMntPt, s.stoppedSnapName, true, true)
if err != nil {
return err
}
@@ -2080,9 +2082,9 @@ func (s *storageBtrfs) MigrationSink(live bool, container container, snapshots [
}
if isSnapshot {
receivedSnapshot = fmt.Sprintf("%s/%s", btrfsPath, snapName)
- err = s.btrfsPoolVolumesSnapshot(receivedSnapshot, targetPath, true)
+ err = s.btrfsPoolVolumesSnapshot(receivedSnapshot, targetPath, true, true)
} else {
- err = s.btrfsPoolVolumesSnapshot(receivedSnapshot, targetPath, false)
+ err = s.btrfsPoolVolumesSnapshot(receivedSnapshot, targetPath, false, true)
}
if err != nil {
logger.Errorf("Problem with btrfs snapshot: %s.", err)
@@ -2309,7 +2311,7 @@ func (s *storageBtrfs) StoragePoolVolumeCopy(source *api.StorageVolumeSource) er
}
}
- err := s.btrfsPoolVolumesSnapshot(srcMountPoint, dstMountPoint, false)
+ err := s.btrfsPoolVolumesSnapshot(srcMountPoint, dstMountPoint, false, true)
if err != nil {
logger.Errorf("Failed to create BTRFS snapshot for storage volume \"%s\" on storage pool \"%s\": %s", s.volume.Name, s.pool.Name, err)
return err
More information about the lxc-devel
mailing list