[pve-devel] [PATCH v3 container 09/12] prestart-hook: use staged mountpoints on newer kernels

Wolfgang Bumiller w.bumiller at proxmox.com
Tue Nov 19 10:34:41 CET 2019


This way we operate on defined paths in the monitor
namespace (/run/pve/mountpoint/{rootfs,mp0,mp1,...}) while
performing the mount, and can use `move_mount()` without
passing the MOVE_MOUNT_T_SYMLINKS flag when putting the
hierarchy in place.

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
Changes to v2: use mountpoint_insert_staged.

 src/lxc-pve-prestart-hook | 78 +++++++++++++++++++++++++++++++++------
 1 file changed, 67 insertions(+), 11 deletions(-)

diff --git a/src/lxc-pve-prestart-hook b/src/lxc-pve-prestart-hook
index c0965ab..229af8e 100755
--- a/src/lxc-pve-prestart-hook
+++ b/src/lxc-pve-prestart-hook
@@ -5,9 +5,9 @@ package lxc_pve_prestart_hook;
 use strict;
 use warnings;
 
-use POSIX;
+use Fcntl qw(O_DIRECTORY :mode);
 use File::Path;
-use Fcntl ':mode';
+use POSIX;
 
 use PVE::Cluster;
 use PVE::LXC::Config;
@@ -15,7 +15,8 @@ use PVE::LXC::Setup;
 use PVE::LXC::Tools;
 use PVE::LXC;
 use PVE::Storage;
-use PVE::Tools;
+use PVE::Syscall qw(:fsmount);
+use PVE::Tools qw(AT_FDCWD O_PATH);
 
 PVE::LXC::Tools::lxc_hook('pre-start', 'lxc', sub {
     my ($vmid, $vars, undef, undef) = @_;
@@ -51,19 +52,74 @@ PVE::LXC::Tools::lxc_hook('pre-start', 'lxc', sub {
 
     my (undef, $rootuid, $rootgid) = PVE::LXC::parse_id_maps($conf);
 
-    my $setup_mountpoint = sub {
-	my ($ms, $mountpoint) = @_;
-
-	#return if $ms eq 'rootfs';
-	my (undef, undef, $dev) = PVE::LXC::mountpoint_mount($mountpoint, $rootdir, $storage_cfg, undef, $rootuid, $rootgid);
-	push @$devices, $dev if $dev && $mountpoint->{quota};
-    };
-
     # Unmount first when the user mounted the container with "pct mount".
     eval {
 	PVE::Tools::run_command(['umount', '--recursive', $rootdir], outfunc => sub {}, errfunc => sub {});
     };
 
+    my $setup_mountpoint;
+    if (!PVE::LXC::Tools::can_use_new_mount_api()) {
+	# Legacy mode for old kernels:
+	$setup_mountpoint = sub {
+	    my ($opt, $mountpoint) = @_;
+
+	    my (undef, undef, $dev) = PVE::LXC::mountpoint_mount(
+		$mountpoint,
+		$rootdir,
+		$storage_cfg,
+		undef,
+		$rootuid,
+		$rootgid,
+	    );
+	    push @$devices, $dev if $dev && $mountpoint->{quota};
+	};
+    } else {
+	# With newer kernels we stage mount points and then use move_mount().
+	my $rootdir_fd = undef;
+	$setup_mountpoint = sub {
+	    my ($opt, $mountpoint) = @_;
+
+	    my $dir = PVE::LXC::get_staging_mount_path($opt);
+	    my (undef, undef, $dev, $mount_fd) = PVE::LXC::mountpoint_stage(
+		$mountpoint,
+		$dir,
+		$storage_cfg,
+		undef,
+		$rootuid,
+		$rootgid,
+	    );
+
+	    my $ddir;
+	    if ($rootdir_fd) {
+		# Mount relative to the rootdir fd.
+		$ddir = './' . $mountpoint->{mp};
+	    } else {
+		# Assert that 'rootfs' is the first one:
+		die "foreach_mount() error\n" if $opt ne 'rootfs';
+
+		# Mount the rootfs absolutely (rootdir_fd=undef uses AT_FDCWD).
+		# $rootdir is not controlled by the container, so this is fine.
+		$ddir = $rootdir;
+	    }
+
+	    PVE::LXC::mountpoint_insert_staged(
+		$mount_fd,
+		$rootdir_fd,
+		$ddir,
+		$opt,
+		$rootuid,
+		$rootgid,
+	    );
+
+	    # From now on we mount inside our rootfs:
+	    if (!$rootdir_fd) {
+		$rootdir_fd = $mount_fd;
+	    }
+
+	    push @$devices, $dev if $dev && $mountpoint->{quota};
+	};
+    }
+
     PVE::LXC::Config->foreach_mountpoint($conf, $setup_mountpoint);
 
     my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir);
-- 
2.20.1





More information about the pve-devel mailing list