--- rsnapshot-program.pl.orig	2017-01-09 08:29:08.463526694 +0100
+++ rsnapshot-program.pl	2017-01-09 09:17:22.241970994 +0100
@@ -156,6 +156,9 @@
 my $default_ssh_args         = undef;
 my $default_du_args          = '-csh';
 
+# set default for acl_mount
+my $acl_mount = 0;
+
 # set default for use_lazy_deletes
 my $use_lazy_deletes = 0;    # do not delete the oldest archive until after backup
 
@@ -879,6 +882,18 @@
 			}
 		}
 
+		# CHECK FOR kpartx (optional)
+		if ($var eq 'linux_lvm_cmd_kpartx') {
+			if ((-f "$value") && (-x "$value") && (1 == is_real_local_abs_path($value))) {
+				$config_vars{'linux_lvm_cmd_kpartx'} = $value;
+				$line_syntax_ok = 1;
+				next;
+			} else {
+				config_err($file_line_num, "$line - $value is not executable");
+				next;
+			}
+		}
+
 		# CHECK FOR cmd_preexec (optional)
 		if ($var eq 'cmd_preexec') {
 			my $script;    # script file (no args)
@@ -1049,7 +1064,7 @@
 
 				# check for lvm
 			}
-			elsif (is_linux_lvm_path($src)) {
+			elsif ( my $return_val = is_linux_lvm_path($src) ) {
 
 				# if it's an lvm path, make sure we have lvm commands and arguments
 				if (!defined($config_vars{'linux_lvm_cmd_lvcreate'})) {
@@ -1072,6 +1087,10 @@
 						"$line - Cannot handle $src, linux_lvm_cmd_umount not defined in $config_file");
 					next;
 				}
+				if ($return_val == 2 and !defined($config_vars{'linux_lvm_cmd_kpartx'})) {
+					config_err($file_line_num, "$line - Cannot handle $src, linux_lvm_cmd_kpartx not defined in $config_file");
+					next;
+				}
 				if (!defined($config_vars{'linux_lvm_snapshotsize'})) {
 					config_err($file_line_num,
 						"$line - Cannot handle $src, linux_lvm_snapshotsize not defined in $config_file");
@@ -1258,6 +1277,24 @@
 			next;
 		}
 
+		# ACL_MOUNT
+		if ($var eq 'acl_mount') {
+			if (!defined($value)) {
+				config_err($file_line_num, "$line - acl_mount can not be blank");
+				next;
+			}
+			if (!is_boolean($value)) {
+				config_err(
+					$file_line_num, "$line - \"$value\" is not a legal value for acl_mount, must be 0 or 1 only"
+				);
+				next;
+			}
+
+			$acl_mount = $value;
+			$line_syntax_ok = 1;
+			next;
+		}
+
 		# LOCKFILE
 		if ($var eq 'lockfile') {
 			if (!defined($value)) { config_err($file_line_num, "$line - lockfile can not be blank"); }
@@ -1832,6 +1869,12 @@
 
 			# rsync_short_args
 		}
+		elsif ( $name eq 'acl_mount' ) {
+			if (!is_boolean($parsed_opts{'acl_mount'})) {
+				return (undef);
+			}
+			# acl_mount
+		}
 		elsif ($name eq 'rsync_short_args') {
 
 			# must be in the format '-abcde'
@@ -2902,7 +2945,8 @@
 	my $path = shift(@_);
 
 	if (!defined($path))        { return (undef); }
-	if ($path =~ m|^lvm://.*$|) { return (1); }
+	if ($path =~ m|^lvm://.*$|) { return (1); 
+	} elsif ($path =~ m|^lvm-kpartx://.*$|) { return (2); }
 
 	return (0);
 }
@@ -3593,8 +3637,10 @@
 	my $src       = $$bp_ref{'src'};
 	my $result    = undef;
 
+	my $linux_lvm_mountopts	= undef;
 	my $linux_lvm_oldpwd = undef;
 	my $lvm_src          = undef;
+	my $linux_lvm_kpartx	= undef;
 
 	# if we're using link-dest later, that target depends on whether we're doing a 'sync' or a regular interval
 	# if we're doing a "sync", then look at [lowest-interval].0 instead of [cur-interval].1
@@ -3734,6 +3780,15 @@
 		$rsync_short_args .= 'x';
 	}
 
+	# ACL_MOUNT
+	if ( defined($$bp_ref{'opts'}) && defined($$bp_ref{'opts'}->{'acl_mount'}) ) {
+		if (1 == $$bp_ref{'opts'}->{'acl_mount'}) {
+			$linux_lvm_mountopts .= ',acl';
+		}
+	} elsif ($acl_mount) {
+		$linux_lvm_mountopts .= ',acl';
+	}
+
 	# SEE WHAT KIND OF SOURCE WE'RE DEALING WITH
 	#
 	# local filesystem
@@ -3772,7 +3827,7 @@
 
 		# LVM path
 	}
-	elsif (is_linux_lvm_path($src)) {
+	elsif ( my $return_value = is_linux_lvm_path($src)) {
 
 		# take LVM snapshot and mount, reformat src into local path
 
@@ -3791,6 +3846,23 @@
 
 		$lvm_src = $src;
 
+		my ($linux_lvmvgname,$linux_lvmvolname, $linux_lvmpartnum, $linux_lvmpath);
+		if ($return_value == 2) {
+			# parse LVM src {'lvm-kpartx://vgname/volname/partnum/path'}
+			($linux_lvmvgname,$linux_lvmvolname, $linux_lvmpartnum, $linux_lvmpath) = ($src =~ m|^lvm-kpartx://([^/]+)/([^/]+)/(\d+)/(.*)$|);
+			# lvmvolname and/or path could be the string "0", so test for 'defined':
+			unless (defined($linux_lvmvgname) and defined($linux_lvmvolname) and defined($linux_lvmpartnum) and defined($linux_lvmpath)) {
+				bail("Could not understand LVM source \"$src\" in backup_lowest_interval()");
+			}
+		} else {
+			# parse LVM src ('lvm://vgname/volname/path')
+			($linux_lvmvgname,$linux_lvmvolname, $linux_lvmpath) = ($src =~ m|^lvm://([^/]+)/([^/]+)/(.*)$|);
+			# lvmvolname and/or path could be the string "0", so test for 'defined':
+			unless (defined($linux_lvmvgname) and defined($linux_lvmvolname) and defined($linux_lvmpath)) {
+				bail("Could not understand LVM source \"$src\" in backup_lowest_interval()");
+			}
+		}
+
 		linux_lvm_snapshot_create(linux_lvm_parseurl($lvm_src));
 		$traps{"linux_lvm_snapshot"} = $lvm_src;
 		linux_lvm_mount(linux_lvm_parseurl($lvm_src));
@@ -4084,16 +4156,38 @@
 		bail("linux_lvm_mount needs 3 parameters!");
 	}
 
+        # kpartx add snapshot
+        if ($return_value == 2) { 
+                @cmd_stack = ();
+                #static kpartx args
+                my $kpartx_add_args = '-ap_';
+                push(@cmd_stack, $config_vars{'linux_lvm_cmd_kpartx'});
+                push(@cmd_stack, $kpartx_add_args);
+                push (@cmd_stack, $linux_lvm_snapshotname);
+                print_cmd(@cmd_stack);
+                if (0 == $test) {
+                        $result = system(@cmd_stack);
+                        if ($result != 0) {
+                                bail("Kpartx add for LVM snapshot failed: $result");
+                        }
+                }
+        }
+
 	# mount the snapshot
 	my @cmd_stack = ();
 	push(@cmd_stack, split(' ', $config_vars{'linux_lvm_cmd_mount'}));
-
-	push(
-		@cmd_stack,
-		join('/',
-			$config_vars{'linux_lvm_vgpath'},
-			$linux_lvmvgname, $config_vars{'linux_lvm_snapshotname'})
-	);
+	push(@cmd_stack, '-o', $linux_lvm_mountopts) if (defined($linux_lvm_mountopts));
+	if ($return_value == 2) {
+		$linux_lvm_kpartx = join('/', $config_vars{'linux_lvm_vgpath'}, 'mapper', $config_vars{'linux_lvm_snapshotname'}) . '_' . $linux_lvmpartnum;
+		push(@cmd_stack, $linux_lvm_kpartx);
+	} else {
+		push(
+			@cmd_stack,
+			join('/',
+				$config_vars{'linux_lvm_vgpath'},
+				$linux_lvmvgname, $config_vars{'linux_lvm_snapshotname'})
+		);
+	}
 	push(@cmd_stack, $config_vars{'linux_lvm_mountpath'});
 
 	print_cmd(@cmd_stack);
@@ -4129,6 +4223,22 @@
 			bail("Unmount LVM snapshot failed: $result");
 		}
 	}
+	# kpartx mapping del for snapshot
+	if (defined($linux_lvm_kpartx)) {
+		@cmd_stack = ();
+		#static kpartx args
+		my $kpartx_del_args = '-dp_';
+		push(@cmd_stack, $config_vars{'linux_lvm_cmd_kpartx'});
+		push(@cmd_stack, $kpartx_del_args);
+		push (@cmd_stack, $linux_lvm_snapshotname);
+		print_cmd(@cmd_stack);
+		if (0 == $test) {
+			$result = system(@cmd_stack);
+			if ($result != 0) {
+				bail("Kpartx deletion for LVM snapshot failed: $result");
+			}
+		}
+	}
 }
 
 # accepts the name of the argument to split, and its value
