diff --git a/pkg/util/cgroup/common/types.go b/pkg/util/cgroup/common/types.go index 59b708c009..4aed31e859 100644 --- a/pkg/util/cgroup/common/types.go +++ b/pkg/util/cgroup/common/types.go @@ -58,7 +58,13 @@ const ( type MemoryData struct { LimitInBytes int64 TCPMemLimitInBytes int64 - WmarkRatio int32 + // SoftLimitInBytes for memory.low + // Best effort memory protection, cgroup memory that will not be reclaimed in soft_limit_reclaim phase of kswapd. + SoftLimitInBytes int64 + // MinInBytes for memory.min + // cgroup memory that can never be reclaimed by kswapd + MinInBytes int64 + WmarkRatio int32 } // CPUData set cgroup cpu data diff --git a/pkg/util/cgroup/manager/v1/fs_linux.go b/pkg/util/cgroup/manager/v1/fs_linux.go index 8b48af63b9..84d51c9230 100644 --- a/pkg/util/cgroup/manager/v1/fs_linux.go +++ b/pkg/util/cgroup/manager/v1/fs_linux.go @@ -52,6 +52,14 @@ func (m *manager) ApplyMemory(absCgroupPath string, data *common.MemoryData) err } } + if data.SoftLimitInBytes > 0 { + if err, applied, oldData := common.WriteFileIfChange(absCgroupPath, "memory.soft_limit_in_bytes", strconv.FormatInt(data.SoftLimitInBytes, 10)); err != nil { + return err + } else if applied { + klog.Infof("[CgroupV1] apply memory soft_limit_in_bytes successfully, cgroupPath: %s, data: %v, old data: %v\n", absCgroupPath, data.SoftLimitInBytes, oldData) + } + } + if data.TCPMemLimitInBytes > 0 { if err, applied, oldData := common.WriteFileIfChange(absCgroupPath, "memory.kmem.tcp.limit_in_bytes", strconv.FormatInt(data.TCPMemLimitInBytes, 10)); err != nil { return err diff --git a/pkg/util/cgroup/manager/v1/fs_linux_test.go b/pkg/util/cgroup/manager/v1/fs_linux_test.go new file mode 100644 index 0000000000..9b66362ede --- /dev/null +++ b/pkg/util/cgroup/manager/v1/fs_linux_test.go @@ -0,0 +1,94 @@ +//go:build linux +// +build linux + +/* +Copyright 2022 The Katalyst Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "reflect" + "testing" + + "github.com/kubewharf/katalyst-core/pkg/util/cgroup/common" +) + +func TestNewManager(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + want *manager + }{ + { + name: "test new manager", + want: &manager{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewManager(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewManager() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_manager_ApplyMemory(t *testing.T) { + t.Parallel() + + type args struct { + absCgroupPath string + data *common.MemoryData + } + tests := []struct { + name string + m *manager + args args + wantErr bool + }{ + { + name: "test apply memory with LimitInBytes", + m: NewManager(), + args: args{ + absCgroupPath: "test-fake-path", + data: &common.MemoryData{ + LimitInBytes: 1234, + }, + }, + wantErr: true, + }, + { + name: "test apply memory with SoftLimitInBytes", + m: NewManager(), + args: args{ + absCgroupPath: "test-fake-path", + data: &common.MemoryData{ + SoftLimitInBytes: 2234, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &manager{} + if err := m.ApplyMemory(tt.args.absCgroupPath, tt.args.data); (err != nil) != tt.wantErr { + t.Errorf("manager.ApplyMemory() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/util/cgroup/manager/v2/fs_linux.go b/pkg/util/cgroup/manager/v2/fs_linux.go index 67a6f4265f..43dd806fab 100644 --- a/pkg/util/cgroup/manager/v2/fs_linux.go +++ b/pkg/util/cgroup/manager/v2/fs_linux.go @@ -57,6 +57,22 @@ func (m *manager) ApplyMemory(absCgroupPath string, data *common.MemoryData) err } } + if data.SoftLimitInBytes > 0 { + if err, applied, oldData := common.WriteFileIfChange(absCgroupPath, "memory.low", numToStr(data.SoftLimitInBytes)); err != nil { + return err + } else if applied { + klog.Infof("[CgroupV2] apply memory low successfully, cgroupPath: %s, data: %v, old data: %v\n", absCgroupPath, data.SoftLimitInBytes, oldData) + } + } + + if data.MinInBytes > 0 { + if err, applied, oldData := common.WriteFileIfChange(absCgroupPath, "memory.min", numToStr(data.MinInBytes)); err != nil { + return err + } else if applied { + klog.Infof("[CgroupV2] apply memory min successfully, cgroupPath: %s, data: %v, old data: %v\n", absCgroupPath, data.MinInBytes, oldData) + } + } + if data.WmarkRatio != 0 { newRatio := fmt.Sprintf("%d", data.WmarkRatio) if err, applied, oldData := common.WriteFileIfChange(absCgroupPath, "memory.wmark_ratio", newRatio); err != nil { diff --git a/pkg/util/cgroup/manager/v2/fs_linux_test.go b/pkg/util/cgroup/manager/v2/fs_linux_test.go index fe4809c077..1f9389429c 100644 --- a/pkg/util/cgroup/manager/v2/fs_linux_test.go +++ b/pkg/util/cgroup/manager/v2/fs_linux_test.go @@ -61,7 +61,7 @@ func Test_manager_ApplyMemory(t *testing.T) { wantErr bool }{ { - name: "test apply memory", + name: "test apply memory with LimitInBytes", m: NewManager(), args: args{ absCgroupPath: "test-fake-path", @@ -71,6 +71,28 @@ func Test_manager_ApplyMemory(t *testing.T) { }, wantErr: true, }, + { + name: "test apply memory with SoftLimitInBytes", + m: NewManager(), + args: args{ + absCgroupPath: "test-fake-path", + data: &common.MemoryData{ + SoftLimitInBytes: 2234, + }, + }, + wantErr: true, + }, + { + name: "test apply memory with MinInBytes", + m: NewManager(), + args: args{ + absCgroupPath: "test-fake-path", + data: &common.MemoryData{ + MinInBytes: 3234, + }, + }, + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {