From 48eecb36703fca9de411f01f59f26798b4f2bf7d Mon Sep 17 00:00:00 2001 From: Lukasz Wojciechowski Date: Tue, 3 Mar 2026 00:57:26 +0100 Subject: [PATCH] Replace cpuset.CPUSet{} with cpuset.New() This patch replaces direct struct initialization cpuset.CPUSet{} with cpuset.New() to ensure the internal map is properly initialized. While most CPUSet methods work correctly without this change, the Equals method uses reflect.DeepEqual which returns false when comparing CPUSet instances where one has a nil internal map and the other has an initialized (empty) map. This can lead to unexpected false negatives in equality checks. For example, the following comparison would incorrectly return false: cpuset.CPUSet{}.Equals(cpuset.New()) This change ensures consistent behavior across all CPUSet operations. Signed-off-by: Lukasz Wojciechowski --- pkg/kubelet/cm/cpumanager/cpu_manager.go | 3 +-- pkg/kubelet/cm/cpumanager/cpu_manager_test.go | 2 +- pkg/kubelet/cm/cpumanager/fake_cpu_manager.go | 8 ++++---- pkg/kubelet/cm/cpumanager/policy_static.go | 4 ++-- pkg/kubelet/cm/cpumanager/state/state_mem.go | 2 +- test/e2e_node/cpu_manager_test.go | 10 +++++----- test/e2e_node/podresources_test.go | 6 +++--- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager.go b/pkg/kubelet/cm/cpumanager/cpu_manager.go index c1b4b7dec04..bb87a7f0675 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager.go @@ -536,8 +536,7 @@ func (m *manager) GetExclusiveCPUs(podUID, containerName string) cpuset.CPUSet { if result, ok := m.state.GetCPUSet(podUID, containerName); ok { return result } - - return cpuset.CPUSet{} + return cpuset.New() } func (m *manager) GetCPUAffinity(podUID, containerName string) cpuset.CPUSet { diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager_test.go b/pkg/kubelet/cm/cpumanager/cpu_manager_test.go index 2361595a4bf..d99d07b51b5 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager_test.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager_test.go @@ -87,7 +87,7 @@ func (s *mockState) Delete(podUID string, containerName string) { } func (s *mockState) ClearState() { - s.defaultCPUSet = cpuset.CPUSet{} + s.defaultCPUSet = cpuset.New() s.assignments = make(state.ContainerCPUAssignments) } diff --git a/pkg/kubelet/cm/cpumanager/fake_cpu_manager.go b/pkg/kubelet/cm/cpumanager/fake_cpu_manager.go index 38ce4e655e7..791f2e5bec0 100644 --- a/pkg/kubelet/cm/cpumanager/fake_cpu_manager.go +++ b/pkg/kubelet/cm/cpumanager/fake_cpu_manager.go @@ -80,22 +80,22 @@ func (m *fakeManager) State() state.Reader { func (m *fakeManager) GetExclusiveCPUs(podUID, containerName string) cpuset.CPUSet { m.logger.Info("GetExclusiveCPUs", "podUID", podUID, "containerName", containerName) - return cpuset.CPUSet{} + return cpuset.New() } func (m *fakeManager) GetAllocatableCPUs() cpuset.CPUSet { m.logger.Info("Get Allocatable CPUs") - return cpuset.CPUSet{} + return cpuset.New() } func (m *fakeManager) GetCPUAffinity(podUID, containerName string) cpuset.CPUSet { m.logger.Info("GetCPUAffinity", "podUID", podUID, "containerName", containerName) - return cpuset.CPUSet{} + return cpuset.New() } func (m *fakeManager) GetAllCPUs() cpuset.CPUSet { m.logger.Info("GetAllCPUs") - return cpuset.CPUSet{} + return cpuset.New() } // NewFakeManager creates empty/fake cpu manager diff --git a/pkg/kubelet/cm/cpumanager/policy_static.go b/pkg/kubelet/cm/cpumanager/policy_static.go index e5042cc882f..53519390c45 100644 --- a/pkg/kubelet/cm/cpumanager/policy_static.go +++ b/pkg/kubelet/cm/cpumanager/policy_static.go @@ -582,7 +582,7 @@ func (p *staticPolicy) GetTopologyHints(logger logr.Logger, s state.State, pod * } logger.Info("Regenerating TopologyHints for CPUs already allocated") return map[string][]topologymanager.TopologyHint{ - string(v1.ResourceCPU): p.generateCPUTopologyHints(allocated, cpuset.CPUSet{}, requested), + string(v1.ResourceCPU): p.generateCPUTopologyHints(allocated, cpuset.New(), requested), } } @@ -646,7 +646,7 @@ func (p *staticPolicy) GetPodTopologyHints(logger logr.Logger, s state.State, po if assignedCPUs.Size() == requested { logger.Info("Regenerating TopologyHints for CPUs already allocated") return map[string][]topologymanager.TopologyHint{ - string(v1.ResourceCPU): p.generateCPUTopologyHints(assignedCPUs, cpuset.CPUSet{}, requested), + string(v1.ResourceCPU): p.generateCPUTopologyHints(assignedCPUs, cpuset.New(), requested), } } diff --git a/pkg/kubelet/cm/cpumanager/state/state_mem.go b/pkg/kubelet/cm/cpumanager/state/state_mem.go index 3da3c1a8d31..73a77920a07 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_mem.go +++ b/pkg/kubelet/cm/cpumanager/state/state_mem.go @@ -117,7 +117,7 @@ func (s *stateMemory) ClearState() { s.Lock() defer s.Unlock() - s.defaultCPUSet = cpuset.CPUSet{} + s.defaultCPUSet = cpuset.New() s.assignments = make(ContainerCPUAssignments) s.logger.V(2).Info("Cleared state") } diff --git a/test/e2e_node/cpu_manager_test.go b/test/e2e_node/cpu_manager_test.go index eaa78ceebe2..01a2aa1a883 100644 --- a/test/e2e_node/cpu_manager_test.go +++ b/test/e2e_node/cpu_manager_test.go @@ -199,7 +199,7 @@ var _ = SIGDescribe("CPU Manager", ginkgo.Ordered, ginkgo.ContinueOnFailure, fra ginkgo.It("should let the container access all the online CPUs without a reserved CPUs set", func(ctx context.Context) { updateKubeletConfigIfNeeded(ctx, f, configureCPUManagerInKubelet(oldCfg, &cpuManagerKubeletArguments{ policyName: string(cpumanager.PolicyStatic), - reservedSystemCPUs: cpuset.CPUSet{}, + reservedSystemCPUs: cpuset.New(), })) pod := makeCPUManagerPod("non-gu-pod", []ctnAttribute{ @@ -840,7 +840,7 @@ var _ = SIGDescribe("CPU Manager", ginkgo.Ordered, ginkgo.ContinueOnFailure, fra ginkgo.It("should let the container access all the online CPUs without a reserved CPUs set", func(ctx context.Context) { updateKubeletConfigIfNeeded(ctx, f, configureCPUManagerInKubelet(oldCfg, &cpuManagerKubeletArguments{ policyName: string(cpumanager.PolicyStatic), - reservedSystemCPUs: cpuset.CPUSet{}, + reservedSystemCPUs: cpuset.New(), enableCPUManagerOptions: true, options: map[string]string{ cpumanager.StrictCPUReservationOption: "true", @@ -2047,7 +2047,7 @@ var _ = SIGDescribe("CPU Manager Incompatibility Pod Level Resources", ginkgo.Or ginkgo.It("should let the container access all the online CPUs without a reserved CPUs set", func(ctx context.Context) { updateKubeletConfigIfNeeded(ctx, f, configureCPUManagerInKubelet(oldCfg, &cpuManagerKubeletArguments{ policyName: string(cpumanager.PolicyStatic), - reservedSystemCPUs: cpuset.CPUSet{}, + reservedSystemCPUs: cpuset.New(), enablePodLevelResources: true, })) @@ -2441,13 +2441,13 @@ func computeNUMADistribution(allocatedCPUs cpuset.CPUSet) map[int]int { func getContainerAllowedCPUs(pod *v1.Pod, ctnName string, isInit bool) (cpuset.CPUSet, error) { cgPath, err := makeCgroupPathForContainer(pod, ctnName, isInit, e2enodeCgroupV2Enabled) if err != nil { - return cpuset.CPUSet{}, err + return cpuset.New(), err } cgPath = filepath.Join(cgPath, cpusetFileNameFromVersion(e2enodeCgroupV2Enabled)) framework.Logf("pod %s/%s cnt %s qos=%s path %q", pod.Namespace, pod.Name, ctnName, pod.Status.QOSClass, cgPath) data, err := os.ReadFile(cgPath) if err != nil { - return cpuset.CPUSet{}, err + return cpuset.New(), err } cpus := strings.TrimSpace(string(data)) framework.Logf("pod %s/%s cnt %s cpuset %q", pod.Namespace, pod.Name, ctnName, cpus) diff --git a/test/e2e_node/podresources_test.go b/test/e2e_node/podresources_test.go index 6c88cf96998..3ca28573ec2 100644 --- a/test/e2e_node/podresources_test.go +++ b/test/e2e_node/podresources_test.go @@ -1163,7 +1163,7 @@ var _ = SIGDescribe("POD Resources API", framework.WithSerial(), feature.PodReso // intentionally passing empty cpuset instead of onlineCPUs because with none policy // we should get no allocatable cpus - no exclusively allocatable CPUs, depends on policy static - podresourcesGetAllocatableResourcesTests(ctx, cli, sd, cpuset.CPUSet{}, cpuset.CPUSet{}) + podresourcesGetAllocatableResourcesTests(ctx, cli, sd, cpuset.New(), cpuset.New()) }) }) }) @@ -1290,7 +1290,7 @@ var _ = SIGDescribe("POD Resources API", framework.WithSerial(), feature.PodReso // intentionally passing empty cpuset instead of onlineCPUs because with none policy // we should get no allocatable cpus - no exclusively allocatable CPUs, depends on policy static - podresourcesGetAllocatableResourcesTests(ctx, cli, nil, cpuset.CPUSet{}, cpuset.CPUSet{}) + podresourcesGetAllocatableResourcesTests(ctx, cli, nil, cpuset.New(), cpuset.New()) }) }) @@ -2066,7 +2066,7 @@ func requireLackOfSRIOVDevices() { func getOnlineCPUs() (cpuset.CPUSet, error) { onlineCPUList, err := os.ReadFile("/sys/devices/system/cpu/online") if err != nil { - return cpuset.CPUSet{}, err + return cpuset.New(), err } return cpuset.Parse(strings.TrimSpace(string(onlineCPUList))) }