[lxc-devel] [lxd/master] Preserves inodes

tych0 on Github lxc-bot at linuxcontainers.org
Wed Jun 1 16:59:32 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160601/41f71956/attachment.bin>
-------------- next part --------------
From 57c20794331d7da74f5b4b97ab40f57c40dc2ee2 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 1 Jun 2016 10:40:55 -0600
Subject: [PATCH 1/2] c/r: switch to the new ->migrate API

We'll use this in the next patch to enable use of new liblxc features.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 lxd/container.go     |  5 ++---
 lxd/container_lxc.go | 14 +++++++++-----
 lxd/migrate.go       |  3 +--
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/lxd/container.go b/lxd/container.go
index 761cf63..0bd0bc2 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -343,7 +343,7 @@ type container interface {
 
 	// Snapshots & migration
 	Restore(sourceContainer container) error
-	Checkpoint(opts lxc.CheckpointOptions) error
+	Migrate(cmd uint, stateDir string, stop bool) error
 	StartFromMigration(imagesDir string) error
 	Snapshots() ([]container, error)
 
@@ -529,8 +529,7 @@ func containerCreateAsSnapshot(d *Daemon, args containerArgs, sourceContainer co
 		 * after snapshotting will fail.
 		 */
 
-		opts := lxc.CheckpointOptions{Directory: stateDir, Stop: false, Verbose: true}
-		err = sourceContainer.Checkpoint(opts)
+		err = sourceContainer.Migrate(lxc.MIGRATE_DUMP, stateDir, false)
 		err2 := CollectCRIULogFile(sourceContainer, stateDir, "snapshot", "dump")
 		if err2 != nil {
 			shared.Log.Warn("failed to collect criu log file", log.Ctx{"error": err2})
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 2f48cfa..6f3f117 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1385,8 +1385,7 @@ func (c *containerLXC) Stop(stateful bool) error {
 		}
 
 		// Checkpoint
-		opts := lxc.CheckpointOptions{Directory: stateDir, Stop: true, Verbose: true}
-		err = c.Checkpoint(opts)
+		err = c.Migrate(lxc.MIGRATE_DUMP, stateDir, true)
 		err2 := CollectCRIULogFile(c, stateDir, "snapshot", "dump")
 		if err2 != nil {
 			shared.Log.Warn("failed to collect criu log file", log.Ctx{"error": err2})
@@ -2712,14 +2711,19 @@ func (c *containerLXC) Export(w io.Writer) error {
 	return tw.Close()
 }
 
-func (c *containerLXC) Checkpoint(opts lxc.CheckpointOptions) error {
-	// Load the go-lxc struct
+func (c *containerLXC) Migrate(cmd uint, stateDir string, stop bool) error {
 	err := c.initLXC()
 	if err != nil {
 		return err
 	}
 
-	return c.c.Checkpoint(opts)
+	opts := lxc.MigrateOptions{
+		Stop: stop,
+		Directory: stateDir,
+		Verbose: true,
+	}
+
+	return c.c.Migrate(cmd, opts)
 }
 
 func (c *containerLXC) TemplateApply(trigger string) error {
diff --git a/lxd/migrate.go b/lxd/migrate.go
index fdaab35..627e6d0 100644
--- a/lxd/migrate.go
+++ b/lxd/migrate.go
@@ -368,8 +368,7 @@ func (s *migrationSourceWs) Do(op *operation) error {
 		}
 		defer os.RemoveAll(checkpointDir)
 
-		opts := lxc.CheckpointOptions{Stop: true, Directory: checkpointDir, Verbose: true}
-		err = s.container.Checkpoint(opts)
+		err = s.container.Migrate(lxc.MIGRATE_DUMP, checkpointDir, true)
 
 		if err2 := CollectCRIULogFile(s.container, checkpointDir, "migration", "dump"); err2 != nil {
 			shared.Debugf("Error collecting checkpoint log file %s", err)

From c450e82b606545ccf3413af9839fc88abebbbe8a Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 1 Jun 2016 10:43:59 -0600
Subject: [PATCH 2/2] use liblxc's new preserves_inodes feature

We know that some filesystems (BTRFS, ZFS) preserve inodes across sends and
receives, so we can use this to optimize the inotify handling when these
filesystems are used.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 lxd/container_lxc.go | 9 +++++++++
 lxd/storage.go       | 8 ++++++++
 lxd/storage_btrfs.go | 8 ++++++++
 lxd/storage_dir.go   | 4 ++++
 lxd/storage_lvm.go   | 4 ++++
 lxd/storage_zfs.go   | 4 ++++
 6 files changed, 37 insertions(+)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 6f3f117..ba841ee 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -2717,10 +2717,19 @@ func (c *containerLXC) Migrate(cmd uint, stateDir string, stop bool) error {
 		return err
 	}
 
+	preservesInodes := c.storage.PreservesInodes()
+	/* This feature was only added in 2.0.1, let's not ask for it
+	 * before then or migrations will fail.
+	 */
+	if !lxc.VersionAtLeast(2, 0, 1) {
+		preservesInodes = false
+	}
+
 	opts := lxc.MigrateOptions{
 		Stop: stop,
 		Directory: stateDir,
 		Verbose: true,
+		PreservesInodes: preservesInodes,
 	}
 
 	return c.c.Migrate(cmd, opts)
diff --git a/lxd/storage.go b/lxd/storage.go
index a17b205..7d92d16 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -169,6 +169,10 @@ type storage interface {
 	ImageDelete(fingerprint string) error
 
 	MigrationType() MigrationFSType
+	/* does this storage backend preserve inodes when it is moved across
+	 * LXD hosts?
+	 */
+	PreservesInodes() bool
 
 	// Get the pieces required to migrate the source. This contains a list
 	// of the "object" (i.e. container or snapshot, depending on whether or
@@ -543,6 +547,10 @@ func (lw *storageLogWrapper) MigrationType() MigrationFSType {
 	return lw.w.MigrationType()
 }
 
+func (lw *storageLogWrapper) PreservesInodes() bool {
+	return lw.w.PreservesInodes()
+}
+
 func (lw *storageLogWrapper) MigrationSource(container container) (MigrationStorageSourceDriver, error) {
 	lw.log.Debug("MigrationSource", log.Ctx{"container": container.Name()})
 	return lw.w.MigrationSource(container)
diff --git a/lxd/storage_btrfs.go b/lxd/storage_btrfs.go
index e9903c0..aa7065a 100644
--- a/lxd/storage_btrfs.go
+++ b/lxd/storage_btrfs.go
@@ -948,6 +948,14 @@ func (s *storageBtrfs) MigrationType() MigrationFSType {
 	}
 }
 
+func (s *storageBtrfs) PreservesInodes() bool {
+	if runningInUserns {
+		return false
+	} else {
+		return true
+	}
+}
+
 func (s *storageBtrfs) MigrationSource(c container) (MigrationStorageSourceDriver, error) {
 	if runningInUserns {
 		return rsyncMigrationSource(c)
diff --git a/lxd/storage_dir.go b/lxd/storage_dir.go
index f0c892e..7d082c6 100644
--- a/lxd/storage_dir.go
+++ b/lxd/storage_dir.go
@@ -274,6 +274,10 @@ func (s *storageDir) MigrationType() MigrationFSType {
 	return MigrationFSType_RSYNC
 }
 
+func (s *storageDir) PreservesInodes() bool {
+	return false
+}
+
 func (s *storageDir) MigrationSource(container container) (MigrationStorageSourceDriver, error) {
 	return rsyncMigrationSource(container)
 }
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 2c729a5..e66c189 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -948,6 +948,10 @@ func (s *storageLvm) MigrationType() MigrationFSType {
 	return MigrationFSType_RSYNC
 }
 
+func (s *storageLvm) PreservesInodes() bool {
+	return false
+}
+
 func (s *storageLvm) MigrationSource(container container) (MigrationStorageSourceDriver, error) {
 	return rsyncMigrationSource(container)
 }
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index d138918..7696dcc 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -1303,6 +1303,10 @@ func (s *storageZfs) MigrationType() MigrationFSType {
 	return MigrationFSType_ZFS
 }
 
+func (s *storageZfs) PreservesInodes() bool {
+	return true
+}
+
 func (s *storageZfs) MigrationSource(ct container) (MigrationStorageSourceDriver, error) {
 	/* If the container is a snapshot, let's just send that; we don't need
 	 * to send anything else, because that's all the user asked for.


More information about the lxc-devel mailing list