]> git.proxmox.com Git - pve-common.git/blame - src/PVE/CpuSet.pm
bump version to 8.2.1
[pve-common.git] / src / PVE / CpuSet.pm
CommitLineData
a1c3f18e
DM
1package PVE::CpuSet;
2
3use strict;
4use warnings;
5use PVE::Tools;
ae97d553 6use PVE::ProcFSTools;
a1c3f18e 7
a1c3f18e 8sub new {
591be969 9 my ($class, $members) = @_;
a1c3f18e 10
591be969
WB
11 $members //= {};
12 my $self = bless { members => $members }, $class;
3f76daba 13
a1c3f18e
DM
14 return $self;
15}
16
dd13f183 17# Create a new set with the contents of a cgroup-v1 subdirectory.
b60a44e0 18# Deprecated:
a1c3f18e 19sub new_from_cgroup {
3e02302a 20 my ($class, $cgroup, $effective) = @_;
a1c3f18e 21
dd13f183
WB
22 return $class->new_from_path("/sys/fs/cgroup/cpuset/$cgroup", $effective);
23}
24
25# Create a new set from the contents of a complete path to a cgroup directory.
26sub new_from_path {
27 my ($class, $path, $effective) = @_;
28
7c3db4b8
WB
29 my $filename;
30 if ($effective) {
31 $filename = "$path/cpuset.effective_cpus";
32 if (!-e $filename) {
33 # cgroupv2:
34 $filename = "$path/cpuset.cpus.effective";
35 }
36 } else {
37 $filename = "$path/cpuset.cpus";
38 }
a1c3f18e 39
a1c3f18e
DM
40 my $set_text = PVE::Tools::file_read_firstline($filename) // '';
41
591be969 42 my ($count, $members) = parse_cpuset($set_text);
9bbc4e17 43
591be969
WB
44 return $class->new($members);
45}
a1c3f18e 46
591be969
WB
47sub parse_cpuset {
48 my ($set_text) = @_;
49
50 my $members = {};
a1c3f18e
DM
51 my $count = 0;
52
53 foreach my $part (split(/,/, $set_text)) {
54 if ($part =~ /^\s*(\d+)(?:-(\d+))?\s*$/) {
55 my ($from, $to) = ($1, $2);
56 $to //= $1;
a1c3f18e
DM
57 die "invalid range: $part ($to < $from)\n" if $to < $from;
58 for (my $i = $from; $i <= $to; $i++) {
59 $members->{$i} = 1;
60 $count++;
61 };
62 } else {
63 die "invalid range: $part\n";
64 }
65 }
66
591be969 67 return ($count, $members);
a1c3f18e
DM
68}
69
b60a44e0 70# Deprecated:
a1c3f18e
DM
71sub write_to_cgroup {
72 my ($self, $cgroup) = @_;
73
b60a44e0
WB
74 return $self->write_to_path("/sys/fs/cgroup/cpuset/$cgroup");
75}
76
77# Takes the cgroup directory containing the cpuset.cpus file (to be closer to
78# new_from_path behavior this doesn't take the complete file name).
79sub write_to_path {
80 my ($self, $path) = @_;
81
82 my $filename = "$path/cpuset.cpus";
a1c3f18e
DM
83
84 my $value = '';
85 my @members = $self->members();
86 foreach my $cpuid (@members) {
87 $value .= ',' if length($value);
88 $value .= $cpuid;
89 }
90
a1c3f18e
DM
91 open(my $fh, '>', $filename) || die "failed to open '$filename' - $!\n";
92 PVE::Tools::safe_print($filename, $fh, "$value\n");
dbfaa2b8 93 close($fh) || die "failed to close '$filename' - $!\n";
a1c3f18e
DM
94}
95
96sub insert {
97 my ($self, @members) = @_;
98
99 my $count = 0;
9bbc4e17 100
a1c3f18e 101 foreach my $cpu (@members) {
a1c3f18e
DM
102 next if $self->{members}->{$cpu};
103 $self->{members}->{$cpu} = 1;
104 $count++;
105 }
106
107 return $count;
108}
109
110sub delete {
111 my ($self, @members) = @_;
112
113 my $count = 0;
9bbc4e17 114
a1c3f18e 115 foreach my $cpu (@members) {
a1c3f18e
DM
116 next if !$self->{members}->{$cpu};
117 delete $self->{members}->{$cpu};
118 $count++;
119 }
120
121 return $count;
122}
123
124sub has {
125 my ($self, $cpuid) = @_;
126
127 return $self->{members}->{$cpuid};
128}
129
130# members: this list is always sorted!
131sub members {
132 my ($self) = @_;
133
967e9823
TL
134 my @sorted_members = sort { $a <=> $b } keys %{$self->{members}};
135 return @sorted_members;
9bbc4e17 136}
a1c3f18e
DM
137
138sub size {
139 my ($self) = @_;
140
141 return scalar(keys %{$self->{members}});
142}
143
144sub is_equal {
145 my ($self, $set2) = @_;
146
147 my $members1 = $self->{members};
148 my $members2 = $set2->{members};
149
150 foreach my $id (keys %$members1) {
151 return 0 if !$members2->{$id};
152 }
153 foreach my $id (keys %$members2) {
154 return 0 if !$members1->{$id};
155 }
9bbc4e17 156
a1c3f18e
DM
157 return 1;
158}
159
284dca70
DM
160sub short_string {
161 my ($self) = @_;
162
163 my @members = $self->members();
164
165 my $res = '';
166 my ($last, $next);
167 foreach my $cpu (@members) {
168 if (!defined($last)) {
169 $last = $next = $cpu;
170 } elsif (($next + 1) == $cpu) {
171 $next = $cpu;
172 } else {
173 $res .= ',' if length($res);
74116083
DM
174 if ($last != $next) {
175 $res .= "$last-$next";
176 } else {
177 $res .= "$last";
178 }
9c07db40 179 $last = $next = $cpu;
284dca70
DM
180 }
181 }
182
183 if (defined($last)) {
184 $res .= ',' if length($res);
185 if ($last != $next) {
186 $res .= "$last-$next";
187 } else {
188 $res .= "$last";
189 }
190 }
191
192 return $res;
193}
194
a1c3f18e 1951;