mirror of https://github.com/k3s-io/k3s
Merge pull request #57124 from JiangtianLi/jiangtli-memfunc
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Use GlobalMemoryStatusEx to get total physical memory on Windows node **What this PR does / why we need it**: This PR fixes issue #57110 due to failure in getting total physical memory on some Windows VM such as in VMWare Fusion or Virtualbox. This change uses GlobalMemoryStatusEx instead of GetPhysicallyInstalledSystemMemory to retrieve total physical memory on Windows node. The amount obtained this way is also closer in parity with reading MemTotal from /proc/meminfo on Linux node. (thanks to @martinivanov and @marono for the help) **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: Fixes #57110 **Special notes for your reviewer**: **Release note**: ```release-note ```pull/6/head
commit
8201e4ba00
|
@ -23,18 +23,32 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
cadvisorapi "github.com/google/cadvisor/info/v1"
|
cadvisorapi "github.com/google/cadvisor/info/v1"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MemoryStatusEx is the same as Windows structure MEMORYSTATUSEX
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770(v=vs.85).aspx
|
||||||
|
type MemoryStatusEx struct {
|
||||||
|
Length uint32
|
||||||
|
MemoryLoad uint32
|
||||||
|
TotalPhys uint64
|
||||||
|
AvailPhys uint64
|
||||||
|
TotalPageFile uint64
|
||||||
|
AvailPageFile uint64
|
||||||
|
TotalVirtual uint64
|
||||||
|
AvailVirtual uint64
|
||||||
|
AvailExtendedVirtual uint64
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
procGetPhysicallyInstalledSystemMemory = modkernel32.NewProc("GetPhysicallyInstalledSystemMemory")
|
procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPerfCounterClient creates a client using perf counters
|
// NewPerfCounterClient creates a client using perf counters
|
||||||
|
@ -163,20 +177,24 @@ func (p *perfCounterNodeStatsClient) convertCPUValue(cpuValue uint64) uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPhysicallyInstalledSystemMemoryBytes() (uint64, error) {
|
func getPhysicallyInstalledSystemMemoryBytes() (uint64, error) {
|
||||||
var physicalMemoryKiloBytes uint64
|
// We use GlobalMemoryStatusEx instead of GetPhysicallyInstalledSystemMemory
|
||||||
|
// on Windows node for the following reasons:
|
||||||
|
// 1. GetPhysicallyInstalledSystemMemory retrieves the amount of physically
|
||||||
|
// installed RAM from the computer's SMBIOS firmware tables.
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/cc300158(v=vs.85).aspx
|
||||||
|
// On some VM, it is unable to read data from SMBIOS and fails with ERROR_INVALID_DATA.
|
||||||
|
// 2. On Linux node, total physical memory is read from MemTotal in /proc/meminfo.
|
||||||
|
// GlobalMemoryStatusEx returns the amount of physical memory that is available
|
||||||
|
// for the operating system to use. The amount returned by GlobalMemoryStatusEx
|
||||||
|
// is closer in parity with Linux
|
||||||
|
// https://www.kernel.org/doc/Documentation/filesystems/proc.txt
|
||||||
|
var statex MemoryStatusEx
|
||||||
|
statex.Length = uint32(unsafe.Sizeof(statex))
|
||||||
|
ret, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&statex)))
|
||||||
|
|
||||||
if ok := getPhysicallyInstalledSystemMemory(&physicalMemoryKiloBytes); !ok {
|
if ret == 0 {
|
||||||
return 0, errors.New("unable to read physical memory")
|
return 0, errors.New("unable to read physical memory")
|
||||||
}
|
}
|
||||||
|
|
||||||
return physicalMemoryKiloBytes * 1024, nil // convert kilobytes to bytes
|
return statex.TotalPhys, nil
|
||||||
}
|
|
||||||
|
|
||||||
func getPhysicallyInstalledSystemMemory(totalMemoryInKilobytes *uint64) bool {
|
|
||||||
ret, _, _ := syscall.Syscall(procGetPhysicallyInstalledSystemMemory.Addr(), 1,
|
|
||||||
uintptr(unsafe.Pointer(totalMemoryInKilobytes)),
|
|
||||||
0,
|
|
||||||
0)
|
|
||||||
|
|
||||||
return ret != 0
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue