X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=src%2FPVE%2FLXC.pm;h=df8bb28d6561aaf2a47e9b06e0d4432d01eec93e;hb=2d3f23be68fa1c9f29f78d18fe606ee4e665012f;hp=2426ac37b349608ac5060ff4ab6bd0bb5a74262c;hpb=471dd315e08424dab014acea3e21cd293f16eec0;p=pve-container.git diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm index 2426ac3..df8bb28 100644 --- a/src/PVE/LXC.pm +++ b/src/PVE/LXC.pm @@ -38,6 +38,7 @@ my $rootfs_desc = { volume => { type => 'string', default_key => 1, + format => 'pve-lxc-mp-string', format_description => 'volume', description => 'Volume, device or directory to mount into the container.', }, @@ -367,10 +368,29 @@ for (my $i = 0; $i < $MAX_LXC_NETWORKS; $i++) { }; } +PVE::JSONSchema::register_format('pve-lxc-mp-string', \&verify_lxc_mp_string); +sub verify_lxc_mp_string{ + my ($mp, $noerr) = @_; + + # do not allow: + # /./ or /../ + # /. or /.. at the end + # ../ at the beginning + + if($mp =~ m@/\.\.?/@ || + $mp =~ m@/\.\.?$@ || + $mp =~ m@^\.\./@){ + return undef if $noerr; + die "$mp contains illegal character sequences\n"; + } + return $mp; +} + my $mp_desc = { %$rootfs_desc, mp => { type => 'string', + format => 'pve-lxc-mp-string', format_description => 'Path', description => 'Path to the mountpoint as seen from inside the container.', }, @@ -517,9 +537,10 @@ sub parse_pct_config { if ($line =~ m/^(lxc\.[a-z0-9_\-\.]+)(:|\s*=)\s*(.*?)\s*$/) { my $key = $1; my $value = $3; - if ($valid_lxc_conf_keys->{$key} eq 1 || $key =~ m/^lxc\.cgroup\./) { + my $validity = $valid_lxc_conf_keys->{$key} || 0; + if ($validity eq 1 || $key =~ m/^lxc\.cgroup\./) { push @{$conf->{lxc}}, [$key, $value]; - } elsif (my $errmsg = $valid_lxc_conf_keys->{$key}) { + } elsif (my $errmsg = $validity) { warn "vm $vmid - $key: $errmsg\n"; } else { warn "vm $vmid - unable to parse config: $line\n"; @@ -623,76 +644,18 @@ sub lock_filename { return "$lockdir/pve-config-${vmid}.lock"; } -sub lock_aquire { - my ($vmid, $timeout) = @_; +sub lock_container { + my ($vmid, $timeout, $code, @param) = @_; $timeout = 10 if !$timeout; - my $mode = LOCK_EX; my $filename = lock_filename($vmid); mkdir $lockdir if !-d $lockdir; - my $lock_func = sub { - if (!$lock_handles->{$$}->{$filename}) { - my $fh = new IO::File(">>$filename") || - die "can't open file - $!\n"; - $lock_handles->{$$}->{$filename} = { fh => $fh, refcount => 0}; - } + my $res = PVE::Tools::lock_file_full($filename, $timeout, 0, $code, @param); - if (!flock($lock_handles->{$$}->{$filename}->{fh}, $mode |LOCK_NB)) { - print STDERR "trying to aquire lock..."; - my $success; - while(1) { - $success = flock($lock_handles->{$$}->{$filename}->{fh}, $mode); - # try again on EINTR (see bug #273) - if ($success || ($! != EINTR)) { - last; - } - } - if (!$success) { - print STDERR " failed\n"; - die "can't aquire lock - $!\n"; - } - - print STDERR " OK\n"; - } - - $lock_handles->{$$}->{$filename}->{refcount}++; - }; - - eval { PVE::Tools::run_with_timeout($timeout, $lock_func); }; - my $err = $@; - if ($err) { - die "can't lock file '$filename' - $err"; - } -} - -sub lock_release { - my ($vmid) = @_; - - my $filename = lock_filename($vmid); - - if (my $fh = $lock_handles->{$$}->{$filename}->{fh}) { - my $refcount = --$lock_handles->{$$}->{$filename}->{refcount}; - if ($refcount <= 0) { - $lock_handles->{$$}->{$filename} = undef; - close ($fh); - } - } -} - -sub lock_container { - my ($vmid, $timeout, $code, @param) = @_; - - my $res; - - lock_aquire($vmid, $timeout); - eval { $res = &$code(@param) }; - my $err = $@; - lock_release($vmid); - - die $err if $err; + die $@ if $@; return $res; } @@ -1307,13 +1270,22 @@ sub update_pct_config { my $wanted_swap = PVE::Tools::extract_param($param, 'swap'); if (defined($wanted_memory) || defined($wanted_swap)) { - $wanted_memory //= ($conf->{memory} || 512); - $wanted_swap //= ($conf->{swap} || 0); + my $old_memory = ($conf->{memory} || 512); + my $old_swap = ($conf->{swap} || 0); + + $wanted_memory //= $old_memory; + $wanted_swap //= $old_swap; my $total = $wanted_memory + $wanted_swap; if ($running) { - write_cgroup_value("memory", $vmid, "memory.limit_in_bytes", int($wanted_memory*1024*1024)); - write_cgroup_value("memory", $vmid, "memory.memsw.limit_in_bytes", int($total*1024*1024)); + my $old_total = $old_memory + $old_swap; + if ($total > $old_total) { + write_cgroup_value("memory", $vmid, "memory.memsw.limit_in_bytes", int($total*1024*1024)); + write_cgroup_value("memory", $vmid, "memory.limit_in_bytes", int($wanted_memory*1024*1024)); + } else { + write_cgroup_value("memory", $vmid, "memory.limit_in_bytes", int($wanted_memory*1024*1024)); + write_cgroup_value("memory", $vmid, "memory.memsw.limit_in_bytes", int($total*1024*1024)); + } } $conf->{memory} = $wanted_memory; $conf->{swap} = $wanted_swap; @@ -1743,7 +1715,8 @@ my $snapshot_prepare = sub { if defined($conf->{snapshots}->{$snapname}); my $storecfg = PVE::Storage::config(); - die "snapshot feature is not available\n" if !has_feature('snapshot', $conf, $storecfg); + my $feature = $snapname eq 'vzdump' ? 'vzdump' : 'snapshot'; + die "snapshot feature is not available\n" if !has_feature($feature, $conf, $storecfg); $snap = $conf->{snapshots}->{$snapname} = {}; @@ -1793,11 +1766,14 @@ sub has_feature { my ($feature, $conf, $storecfg, $snapname) = @_; my $err; + my $vzdump = $feature eq 'vzdump'; + $feature = 'snapshot' if $vzdump; foreach_mountpoint($conf, sub { my ($ms, $mountpoint) = @_; return if $err; # skip further test + return if $vzdump && $ms ne 'rootfs' && !$mountpoint->{backup}; $err = 1 if !PVE::Storage::volume_has_feature($storecfg, $feature, $mountpoint->{volume}, $snapname); @@ -2019,18 +1995,6 @@ sub mountpoint_names { return $reverse ? reverse @names : @names; } -# The container might have *different* symlinks than the host. realpath/abs_path -# use the actual filesystem to resolve links. -sub sanitize_mountpoint { - my ($mp) = @_; - $mp = '/' . $mp; # we always start with a slash - $mp =~ s@/{2,}@/@g; # collapse sequences of slashes - $mp =~ s@/\./@@g; # collapse /./ - $mp =~ s@/\.(/)?$@$1@; # collapse a trailing /. or /./ - $mp =~ s@(.*)/[^/]+/\.\./@$1/@g; # collapse /../ without regard for symlinks - $mp =~ s@/\.\.(/)?$@$1@; # collapse trailing /.. or /../ disregarding symlinks - return $mp; -} sub foreach_mountpoint_full { my ($conf, $reverse, $func) = @_; @@ -2041,11 +2005,6 @@ sub foreach_mountpoint_full { my $mountpoint = $key eq 'rootfs' ? parse_ct_rootfs($value, 1) : parse_ct_mountpoint($value, 1); next if !defined($mountpoint); - $mountpoint->{mp} = sanitize_mountpoint($mountpoint->{mp}); - - my $path = $mountpoint->{volume}; - $mountpoint->{volume} = sanitize_mountpoint($path) if $path =~ m|^/|; - &$func($key, $mountpoint); } }