From: Wolfgang Bumiller Date: Fri, 3 Apr 2020 14:37:40 +0000 (+0200) Subject: cleanup cgroups in pre-start hook X-Git-Url: https://git.proxmox.com/?p=pve-container.git;a=commitdiff_plain;h=51ae28ecf1f452041f0ab9679696136707d287e4 cleanup cgroups in pre-start hook Though I wish perl had an fdopendir equivalent... Signed-off-by: Wolfgang Bumiller --- diff --git a/src/lxc-pve-prestart-hook b/src/lxc-pve-prestart-hook index 1d62f3b..be0063d 100755 --- a/src/lxc-pve-prestart-hook +++ b/src/lxc-pve-prestart-hook @@ -34,6 +34,8 @@ PVE::LXC::Tools::lxc_hook('pre-start', 'lxc', sub { PVE::LXC::Config->check_lock($conf); } + cleanup_cgroups($vmid); + my $storage_cfg = PVE::Storage::config(); my $vollist = PVE::LXC::Config->get_vm_volumes($conf); @@ -140,3 +142,50 @@ PVE::LXC::Tools::lxc_hook('pre-start', 'lxc', sub { PVE::Tools::file_set_contents($devlist_file, $devlist); } }); + +# Leftover cgroups prevent lxc from starting without any useful information +# showing up in the journal, it is also often unable to properly clean them up +# at shutdown, so we do this here. +sub cleanup_cgroups($) { + my ($vmid) = @_; + + if (PVE::LXC::CGroup::cgroup_mode() == 2) { + rmdir_recursive("/sys/fs/cgroup/lxc/$vmid"); + rmdir_recursive("/sys/fs/cgroup/lxc.monitor/$vmid"); + } else { + my ($v1, $v2) = PVE::LXC::get_cgroup_subsystems(); + + my @controllers_cgv1 = keys %$v1; + foreach my $controller (@controllers_cgv1) { + $controller =~ s/^name=//; # `name=systemd` is mounted just as `systemd` + my $cgpath = "/sys/fs/cgroup/$controller/lxc/$vmid"; + rmdir_recursive($cgpath); + } + + if ($v2) { + rmdir_recursive("/sys/fs/cgroup/unified/lxc/$vmid"); + rmdir_recursive("/sys/fs/cgroup/unified/lxc.monitor/$vmid"); + } + } +} + +# FIXME: This is an ugly version without openat() because perl has no equivalent +# of fdopendir() so we cannot readdir from an openat() opened handle. +sub rmdir_recursive { + my ($path) = @_; + + my $dh; + if (!opendir($dh, $path)) { + return if $!{ENOENT}; + die "failed to open directory '$path': $!\n"; + } + + while (defined(my $entry = readdir($dh))) { + next if $entry eq '.' || $entry eq '..'; + my $next = "$path/$entry"; + next if ! -d $next; + rmdir_recursive($next); + } + + rmdir($path) or die "failed to remove directory '$path': $!\n"; +}