[pve-devel] [PATCH qemu-server 5/8] property string update: numa*
Wolfgang Bumiller
w.bumiller at proxmox.com
Wed Mar 30 12:20:10 CEST 2016
Additionally since the cpu and host node list isn't
restricted to a single range one can now provide multipel
ranges separated by semicolons. (eg. cpus=0-3;5;7)
---
PVE/QemuServer.pm | 117 ++++++++++++++++++++++++++++++------------------------
1 file changed, 65 insertions(+), 52 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index bb9624b..bb8a94d 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -467,10 +467,38 @@ my $MAX_NUMA = 8;
my $MAX_MEM = 4194304;
my $STATICMEM = 1024;
+my $numa_fmt = {
+ cpus => {
+ type => "string",
+ pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
+ description => "CPUs accessing this numa node.",
+ format_description => "id[-id];...",
+ },
+ memory => {
+ type => "number",
+ description => "Amount of memory this numa node provides.",
+ format_description => "mb",
+ optional => 1,
+ },
+ hostnodes => {
+ type => "string",
+ pattern => qr/\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*/,
+ description => "host numa nodes to use",
+ format_description => "id[-id];...",
+ optional => 1,
+ },
+ policy => {
+ type => 'string',
+ enum => [qw(preferred bind interleave)],
+ format_description => 'preferred|bind|interleave',
+ description => "numa allocation policy.",
+ optional => 1,
+ },
+};
+PVE::JSONSchema::register_format('pve-qm-numanode', $numa_fmt);
my $numadesc = {
optional => 1,
- type => 'string', format => 'pve-qm-numanode',
- typetext => "cpus=<id[-id],memory=<mb>[[,hostnodes=<id[-id]>] [,policy=<preferred|bind|interleave>]]",
+ type => 'string', format => $numa_fmt,
description => "numa topology",
};
PVE::JSONSchema::register_standard_option("pve-qm-numanode", $numadesc);
@@ -1469,28 +1497,26 @@ sub drive_is_cdrom {
}
+sub parse_number_sets {
+ my ($set) = @_;
+ my $res = [];
+ foreach my $part (split(/;/, $set)) {
+ if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
+ die "invalid range: $part ($2 < $1)\n" if defined($2) && $2 < $1;
+ push @$res, [ $1, $2 ];
+ } else {
+ die "invalid range: $part\n";
+ }
+ }
+ return $res;
+}
+
sub parse_numa {
my ($data) = @_;
- my $res = {};
-
- foreach my $kvp (split(/,/, $data)) {
-
- if ($kvp =~ m/^memory=(\S+)$/) {
- $res->{memory} = $1;
- } elsif ($kvp =~ m/^policy=(preferred|bind|interleave)$/) {
- $res->{policy} = $1;
- } elsif ($kvp =~ m/^cpus=(\d+)(-(\d+))?$/) {
- $res->{cpus}->{start} = $1;
- $res->{cpus}->{end} = $3;
- } elsif ($kvp =~ m/^hostnodes=(\d+)(-(\d+))?$/) {
- $res->{hostnodes}->{start} = $1;
- $res->{hostnodes}->{end} = $3;
- } else {
- return undef;
- }
- }
-
+ my $res = PVE::JSONSchema::parse_property_string($numa_fmt, $data);
+ $res->{cpus} = parse_number_sets($res->{cpus}) if defined($res->{cpus});
+ $res->{hostnodes} = parse_number_sets($res->{hostnodes}) if defined($res->{hostnodes});
return $res;
}
@@ -1758,17 +1784,6 @@ sub verify_bootdisk {
die "invalid boot disk '$value'\n";
}
-PVE::JSONSchema::register_format('pve-qm-numanode', \&verify_numa);
-sub verify_numa {
- my ($value, $noerr) = @_;
-
- return $value if parse_numa($value);
-
- return undef if $noerr;
-
- die "unable to parse numa options\n";
-}
-
PVE::JSONSchema::register_format('pve-qm-net', \&verify_net);
sub verify_net {
my ($value, $noerr) = @_;
@@ -3076,28 +3091,26 @@ sub config_to_command {
my $numa_object = "memory-backend-ram,id=ram-node$i,size=${numa_memory}M";
# cpus
- my $cpus_start = $numa->{cpus}->{start};
- die "missing numa node$i cpus\n" if !defined($cpus_start);
- my $cpus_end = $numa->{cpus}->{end} if defined($numa->{cpus}->{end});
- my $cpus = $cpus_start;
- if (defined($cpus_end)) {
- $cpus .= "-$cpus_end";
- die "numa node$i : cpu range $cpus is incorrect\n" if $cpus_end <= $cpus_start;
- }
+ my $cpulists = $numa->{cpus};
+ die "missing numa node$i cpus\n" if !defined($cpulists);
+ my $cpus = join(',', map {
+ my ($start, $end) = @$_;
+ defined($end) ? "$start-$end" : $start
+ } @$cpulists);
# hostnodes
- my $hostnodes_start = $numa->{hostnodes}->{start};
- if (defined($hostnodes_start)) {
- my $hostnodes_end = $numa->{hostnodes}->{end} if defined($numa->{hostnodes}->{end});
- my $hostnodes = $hostnodes_start;
- if (defined($hostnodes_end)) {
- $hostnodes .= "-$hostnodes_end";
- die "host node $hostnodes range is incorrect\n" if $hostnodes_end <= $hostnodes_start;
- }
-
- my $hostnodes_end_range = defined($hostnodes_end) ? $hostnodes_end : $hostnodes_start;
- for (my $i = $hostnodes_start; $i <= $hostnodes_end_range; $i++ ) {
- die "host numa node$i don't exist\n" if ! -d "/sys/devices/system/node/node$i/";
+ my $hostnodelists = $numa->{hostnodes};
+ if (defined($hostnodelists)) {
+ my $hostnodes;
+ foreach my $hostnoderange (@$hostnodelists) {
+ my ($start, $end) = @$hostnoderange;
+ $hostnodes .= ',' if $hostnodes;
+ $hostnodes .= $start;
+ $hostnodes .= "-$end" if defined($end);
+ $end //= $start;
+ for (my $i = $start; $i <= $end; ++$i ) {
+ die "host numa node$i don't exist\n" if ! -d "/sys/devices/system/node/node$i/";
+ }
}
# policy
--
2.1.4
More information about the pve-devel
mailing list