[pve-devel] [RFC pve-container 2/3] vzdump: suspend mode fixes

Wolfgang Bumiller w.bumiller at proxmox.com
Wed Sep 16 16:42:03 CEST 2015


-) '-x' is '--one-file-system' (the longer version is easier
to spot.)
-) Use --relative's special handling of `/./` in paths in
order to make --one-file-system and --exclude options work
together the way they should.

Here's the issue:
Say you have thse files in your container:
  /the-file
  /mp0/the-file
And assume /mp0 is a mountpoint.
Naturally you want `-exclude-path /the-file` to only exclude
the first of the two files. This is hard when rsyncing each
mountpoint separately, as the rsync command for mp0 would
see files relative to /mp0, and thus both files would be
excluded unless we modify exclude paths accordingly - which
we can't as they can be arbitrary glob patterns.
Now with rsync's --relative option - assume the container is
mounted at /temp (iow: /temp/ and /temp/mp0). Passing
/temp/mp0/ to rsync would copy the contents of the mp0
mountpoint into the root directory of the destination
(essentially doing the equivalent of `mv mp0/* /` in the
container's backup.). However, rsync's special treatment of
/./ with the --relative option allows us to pass
/temp/./mp0/ which tells rsync that `/mp0` is supposed to be
included in the path, iow. we're actually copying from
/temp/, but we want only its mp0/ directory.
See rsync(1)'s section about --relative for a detailed
description.
---
 src/PVE/VZDump/LXC.pm | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/src/PVE/VZDump/LXC.pm b/src/PVE/VZDump/LXC.pm
index 21dc1ce..167e5fb 100644
--- a/src/PVE/VZDump/LXC.pm
+++ b/src/PVE/VZDump/LXC.pm
@@ -24,17 +24,27 @@ my $rsync_vm = sub {
 
     my $opts = $self->{vzdump}->{opts};
 
-    my $base = ['rsync', '--stats', '-x', '-X', '--numeric-ids',
-                '-aH', '--delete', '--no-whole-file', '--inplace'];
+    my $base = ['rsync', '--stats', '-X', '--numeric-ids',
+                '-aH', '--delete', '--no-whole-file', '--inplace',
+                '--one-file-system', '--relative'];
     push @$base, "--bwlimit=$opts->{bwlimit}" if $opts->{bwlimit};
     push @$base, map { "--exclude=$_" } @{$self->{vzdump}->{findexcl}};
     push @$base, map { "--exclude=$_" } @{$task->{exclude_dirs}};
 
-    # FIXME: to support --one-file-system we have to make all exclude paths
-    # relative to the current mountpoint
-
     my $starttime = time();
-    $self->cmd([@$base, $from, $to]);
+    # See the rsync(1) manpage for --relative in conjunction with /./ in paths.
+    # This is the only way to have exclude-dirs work together with the
+    # --one-file-system option.
+    # This way we can pass multiple source paths and tell rsync which directory
+    # they're supposed to be relative to.
+    # Otherwise with eg. using multiple rsync commands means the --exclude
+    # directives need to be modified for every command as they are meant to be
+    # relative to the rootdir, while rsync treats them as relative to the
+    # source dir.
+    foreach my $disk (@$disks) {
+	push @$base, "$from/.$disk->{mp}";
+    }
+    $self->cmd([@$base, $to]);
     my $delay = time () - $starttime;
 
     $self->loginfo ("$text sync finished ($delay seconds)");
@@ -239,6 +249,7 @@ sub archive {
     my ($self, $task, $vmid, $filename, $comp) = @_;
 
     my $disks = $task->{disks};
+    my @sources;
 
     if ($task->{mode} eq 'stop') {
 	my $rootdir = $default_mount_point;
@@ -246,8 +257,15 @@ sub archive {
 	foreach my $disk (@$disks) {
 	    $disk->{dir} = "${rootdir}$disk->{mp}";
 	    PVE::LXC::mountpoint_mount($disk, $rootdir, $storage_cfg);
+	    # add every enabled mountpoint (since we use --one-file-system)
+	    # mp already starts with a / so we only need to add the dot
+	    push @sources, ".$disk->{mp}";
 	}
 	$task->{snapdir} = $rootdir;
+    } else {
+	# the data was rsynced to a temporary location, only use '.' to avoid
+	# having mountpoints duplicated
+	push @sources, '.';
     }
 
     my $opts = $self->{vzdump}->{opts};
@@ -272,9 +290,7 @@ sub archive {
     push @$tar, "--directory=$snapdir";
     push @$tar, map { "--exclude=.$_" } @{$self->{vzdump}->{findexcl}};
 
-    # add every enabled mountpoint (since we use --one-file-system)
-    # mp already starts with a / so we only need to add the dot
-    push @$tar, map { '.' . $_->{mp} } @$disks;
+    push @$tar, @sources;
 
     my $cmd = [ $tar ];
 
-- 
2.1.4




More information about the pve-devel mailing list