X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=src%2FPVE%2FLXC.pm;h=32b0318b18e40aae8f3415271d610802c25df7de;hb=0389da0d5ef1fcafc8916e7046f69def280270bf;hp=35ce7962759810f5b976ba93d60ec89665c67cda;hpb=e756bdd60ca84ce4fea4dc5a93298d4150fc8831;p=pve-container.git diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm index 35ce796..32b0318 100644 --- a/src/PVE/LXC.pm +++ b/src/PVE/LXC.pm @@ -11,16 +11,18 @@ use File::Path; use File::Spec; use Cwd qw(); use Fcntl qw(O_RDONLY O_NOFOLLOW O_DIRECTORY); -use Errno qw(ELOOP EROFS); +use Errno qw(ELOOP ENOTDIR EROFS); use PVE::Exception qw(raise_perm_exc); use PVE::Storage; use PVE::SafeSyslog; use PVE::INotify; use PVE::Tools qw($IPV6RE $IPV4RE dir_glob_foreach lock_file lock_file_full O_PATH); +use PVE::CpuSet; use PVE::Network; use PVE::AccessControl; use PVE::ProcFSTools; +use PVE::Syscall; use PVE::LXC::Config; use Time::HiRes qw (gettimeofday); @@ -147,7 +149,8 @@ sub vmstatus { $d->{name} = $conf->{'hostname'} || "CT$vmid"; $d->{name} =~ s/[\s]//g; - $d->{cpus} = $conf->{cpulimit} || $cpucount; + $d->{cpus} = $conf->{cores} || $conf->{cpulimit}; + $d->{cpus} = $cpucount if !$d->{cpus}; $d->{lock} = $conf->{lock} || ''; @@ -192,8 +195,11 @@ sub vmstatus { my $ctime = (stat("/proc/$pid"))[10]; # 10 = ctime $d->{uptime} = time - $ctime; # the method lxcfs uses - $d->{mem} = read_cgroup_value('memory', $vmid, 'memory.usage_in_bytes'); - $d->{swap} = read_cgroup_value('memory', $vmid, 'memory.memsw.usage_in_bytes') - $d->{mem}; + my $memory_stat = read_cgroup_list('memory', $vmid, 'memory.stat'); + my $mem_usage_in_bytes = read_cgroup_value('memory', $vmid, 'memory.usage_in_bytes'); + + $d->{mem} = $mem_usage_in_bytes - $memory_stat->{total_cache}; + $d->{swap} = read_cgroup_value('memory', $vmid, 'memory.memsw.usage_in_bytes') - $mem_usage_in_bytes; my $blkio_bytes = read_cgroup_value('blkio', $vmid, 'blkio.throttle.io_service_bytes', 1); my @bytes = split(/\n/, $blkio_bytes); @@ -251,6 +257,14 @@ sub vmstatus { return $list; } +sub read_cgroup_list { + my ($group, $vmid, $name) = @_; + + my $content = read_cgroup_value($group, $vmid, $name, 1); + + return { split(/\s+/, $content) }; +} + sub read_cgroup_value { my ($group, $vmid, $name, $full) = @_; @@ -424,15 +438,30 @@ sub update_lxc_config { $raw .= "lxc.network.mtu = $d->{mtu}\n" if defined($d->{mtu}); } + my $had_cpuset = 0; if (my $lxcconf = $conf->{lxc}) { foreach my $entry (@$lxcconf) { my ($k, $v) = @$entry; $netcount++ if $k eq 'lxc.network.type'; + $had_cpuset = 1 if $k eq 'lxc.cgroup.cpuset.cpus'; $raw .= "$k = $v\n"; } } $raw .= "lxc.network.type = empty\n" if !$netcount; + + my $cores = $conf->{cores}; + if (!$had_cpuset && $cores) { + my $cpuset = eval { PVE::CpuSet->new_from_cgroup('lxc', 'effective_cpus') }; + $cpuset = PVE::CpuSet->new_from_cgroup('', 'effective_cpus') if !$cpuset; + my @members = $cpuset->members(); + while (scalar(@members) > $cores) { + my $randidx = int(rand(scalar(@members))); + $cpuset->delete($members[$randidx]); + splice(@members, $randidx, 1); # keep track of the changes + } + $raw .= "lxc.cgroup.cpuset.cpus = ".$cpuset->short_string()."\n"; + } File::Path::mkpath("$dir/rootfs"); @@ -862,14 +891,15 @@ sub check_ct_modify_config_perm { my $check = sub { my ($opt, $delete) = @_; - if ($opt eq 'cpus' || $opt eq 'cpuunits' || $opt eq 'cpulimit') { + if ($opt eq 'cores' || $opt eq 'cpuunits' || $opt eq 'cpulimit') { $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.CPU']); } elsif ($opt eq 'rootfs' || $opt =~ /^mp\d+$/) { $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Disk']); return if $delete; my $data = $opt eq 'rootfs' ? PVE::LXC::Config->parse_ct_rootfs($newconf->{$opt}) : PVE::LXC::Config->parse_ct_mountpoint($newconf->{$opt}); - raise_perm_exc("mountpoint type $data->{type}") if $data->{type} ne 'volume'; + raise_perm_exc("mount point type $data->{type} is only allowed for root\@pam") + if $data->{type} ne 'volume'; } elsif ($opt eq 'memory' || $opt eq 'swap') { $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Memory']); } elsif ($opt =~ m/^net\d+$/ || $opt eq 'nameserver' || @@ -1023,7 +1053,7 @@ sub walk_tree_nofollow($$$) { if (!$next) { # failed, check for symlinks and try to create the path - die "symlink encountered at: $dir\n" if $! == ELOOP; + die "symlink encountered at: $dir\n" if $! == ELOOP || $! == ENOTDIR; die "cannot open directory $dir: $!\n" if !$mkdir; # We don't check for errors on mkdirat() here and just try to @@ -1073,9 +1103,8 @@ sub __bindmount_verify { die "failed to open mount point: $!\n" if !$destdh; if ($ro) { my $dot = '.'; - # 269: faccessat() # no separate function because 99% of the time it's the wrong thing to use. - if (syscall(269, fileno($destdh), $dot, &POSIX::W_OK, 0) != -1) { + if (syscall(PVE::Syscall::faccessat, fileno($destdh), $dot, &POSIX::W_OK, 0) != -1) { die "failed to mark bind mount read only\n"; } die "read-only check failed: $!\n" if $! != EROFS;