From d138b59aa23df198584e56535f60e0b2047ff76a Mon Sep 17 00:00:00 2001 From: "sewon.oh" Date: Tue, 3 Sep 2019 13:49:23 +0900 Subject: [PATCH] Add hugepage info to v1 node structure Signed-off-by: sewon.oh --- info/v1/machine.go | 7 +++--- machine/machine.go | 49 ++++++++++++++++++++++++++++++++++++++++ machine/topology_test.go | 4 ++++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/info/v1/machine.go b/info/v1/machine.go index cf5e828d..cb25501c 100644 --- a/info/v1/machine.go +++ b/info/v1/machine.go @@ -38,9 +38,10 @@ type FsInfo struct { type Node struct { Id int `json:"node_id"` // Per-node memory - Memory uint64 `json:"memory"` - Cores []Core `json:"cores"` - Caches []Cache `json:"caches"` + Memory uint64 `json:"memory"` + HugePages []HugePagesInfo `json:"huge_pages"` + Cores []Core `json:"cores"` + Caches []Cache `json:"caches"` } type Core struct { diff --git a/machine/machine.go b/machine/machine.go index d85e38f1..f1aad5e8 100644 --- a/machine/machine.go +++ b/machine/machine.go @@ -23,6 +23,7 @@ import ( "regexp" "strconv" "strings" + // s390/s390x changes "runtime" @@ -45,10 +46,12 @@ var ( cpuClockSpeedMHz = regexp.MustCompile(`(?:cpu MHz|clock)\s*:\s*([0-9]+\.[0-9]+)(?:MHz)?`) memoryCapacityRegexp = regexp.MustCompile(`MemTotal:\s*([0-9]+) kB`) swapCapacityRegexp = regexp.MustCompile(`SwapTotal:\s*([0-9]+) kB`) + hugePageSizeRegexp = regexp.MustCompile(`hugepages-\s*([0-9]+)kB`) ) const maxFreqFile = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" const cpuBusPath = "/sys/bus/cpu/devices/" +const nodePath = "/sys/devices/system/node" // GetClockSpeed returns the CPU clock speed, given a []byte formatted as the /proc/cpuinfo file. func GetClockSpeed(procInfo []byte) (uint64, error) { @@ -191,6 +194,45 @@ func getNodeIdFromCpuBus(cpuBusPath string, threadId int) (int, error) { return nodeId, nil } +/* Look for per-node hugepages info using node id */ +/* Such as: /sys/devices/system/node/node%d/hugepages */ +func getHugePagesInfoFromNode(nodePath string, nodeIndex int) ([]info.HugePagesInfo, error) { + hugePagesInfo := []info.HugePagesInfo{} + path := filepath.Join(nodePath, fmt.Sprintf("node%d/hugepages", nodeIndex)) + files, err := ioutil.ReadDir(path) + // Ignore if per-node info is not available. + if err != nil { + klog.Errorf("failed to get hugepages information for node %d: %v", nodeIndex, err) + return nil, nil + } + + for _, file := range files { + fileName := file.Name() + pageSize, err := parseCapacity([]byte(fileName), hugePageSizeRegexp) + if err != nil { + return nil, err + } + + file := filepath.Join(path, fileName, "nr_hugepages") + num, err := ioutil.ReadFile(file) + if err != nil { + return nil, err + } + + pageNum, err := strconv.ParseUint(string(bytes.TrimSpace(num)), 10, 64) + if err != nil { + return nil, err + } + + hugePagesInfo = append(hugePagesInfo, info.HugePagesInfo{ + PageSize: pageSize / 1024, // Convert to kB. + NumPages: pageNum, + }) + } + + return hugePagesInfo, nil +} + func GetTopology(sysFs sysfs.SysFs, cpuinfo string) ([]info.Node, int, error) { nodes := []info.Node{} @@ -305,6 +347,13 @@ func GetTopology(sysFs sysfs.SysFs, cpuinfo string) ([]info.Node, int, error) { } // Ignore unknown caches. } + + // Add a node-level huge pages info. + hugePagesInfo, err := getHugePagesInfoFromNode(nodePath, node.Id) + if err != nil { + return nil, -1, err + } + nodes[idx].HugePages = hugePagesInfo } return nodes, numCores, nil } diff --git a/machine/topology_test.go b/machine/topology_test.go index ca25ef7d..5144daf0 100644 --- a/machine/topology_test.go +++ b/machine/topology_test.go @@ -59,6 +59,8 @@ func TestTopology(t *testing.T) { node := info.Node{Id: i} // Copy over Memory from result. TODO(rjnagal): Use memory from fake. node.Memory = topology[i].Memory + // Copy over HugePagesInfo from result. TODO(ohsewon): Use HugePagesInfo from fake. + node.HugePages = topology[i].HugePages for j := 0; j < numCoresPerNode; j++ { core := info.Core{Id: i*numCoresPerNode + j} core.Caches = append(core.Caches, cache) @@ -100,6 +102,8 @@ func TestTopologyWithSimpleCpuinfo(t *testing.T) { node.Cores = append(node.Cores, core) // Copy over Memory from result. TODO(rjnagal): Use memory from fake. node.Memory = topology[0].Memory + // Copy over HugePagesInfo from result. TODO(ohsewon): Use HugePagesInfo from fake. + node.HugePages = topology[0].HugePages expected := []info.Node{node} if !reflect.DeepEqual(topology, expected) { t.Errorf("Expected topology %+v, got %+v", expected, topology)