@@ -17,12 +17,15 @@ limitations under the License.
17
17
package memory
18
18
19
19
import (
20
+ "errors"
20
21
"fmt"
21
22
"os"
22
23
"path/filepath"
24
+ "regexp"
23
25
"strconv"
24
26
"strings"
25
27
28
+ "k8s.io/apimachinery/pkg/api/resource"
26
29
"k8s.io/klog/v2"
27
30
28
31
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
@@ -40,9 +43,12 @@ const NvFeature = "nv"
40
43
// NumaFeature is the name of the feature set that holds all NUMA related features.
41
44
const NumaFeature = "numa"
42
45
43
- // SwapFeature is the name of the feature set that holds all Swap related features
46
+ // SwapFeature is the name of the feature set that holds all Swap related features.
44
47
const SwapFeature = "swap"
45
48
49
+ // HugePages is the name of the feature set that holds information about huge pages.
50
+ const HugePages = "hugepages"
51
+
46
52
// memorySource implements the FeatureSource and LabelSource interfaces.
47
53
type memorySource struct {
48
54
features * nfdv1alpha1.Features
@@ -115,6 +121,13 @@ func (s *memorySource) Discover() error {
115
121
s .features .Instances [NvFeature ] = nfdv1alpha1.InstanceFeatureSet {Elements : nv }
116
122
}
117
123
124
+ // Detect Huge Pages
125
+ if hp , err := detectHugePages (); err != nil {
126
+ klog .ErrorS (err , "failed to detect huge pages" )
127
+ } else {
128
+ s .features .Attributes [HugePages ] = nfdv1alpha1.AttributeFeatureSet {Elements : hp }
129
+ }
130
+
118
131
klog .V (3 ).InfoS ("discovered features" , "featureSource" , s .Name (), "features" , utils .DelayedDumper (s .features ))
119
132
120
133
return nil
@@ -179,6 +192,71 @@ func detectNv() ([]nfdv1alpha1.InstanceFeature, error) {
179
192
return info , nil
180
193
}
181
194
195
+ // detectHugePages checks whether huge pages are enabled on the node
196
+ // and retrieves the configured huge page sizes.
197
+ func detectHugePages () (map [string ]string , error ) {
198
+ hugePages := map [string ]string {
199
+ "enabled" : "false" ,
200
+ }
201
+
202
+ basePath := hostpath .SysfsDir .Path ("kernel/mm/hugepages" )
203
+ subdirs , err := os .ReadDir (basePath )
204
+ if err != nil {
205
+ if errors .Is (err , os .ErrNotExist ) {
206
+ return hugePages , nil
207
+ }
208
+ return nil , fmt .Errorf ("unable to read huge pages size: %w" , err )
209
+ }
210
+
211
+ reg := regexp .MustCompile (`hugepages-(\d+)` )
212
+ for _ , entry := range subdirs {
213
+ if ! entry .IsDir () {
214
+ continue
215
+ }
216
+
217
+ pageSize , err := getHugePageSize (basePath , entry .Name (), reg )
218
+ if err != nil {
219
+ klog .ErrorS (err , "skipping huge page entry" , "entry" , entry .Name ())
220
+ continue
221
+ }
222
+ if pageSize != "" {
223
+ hugePages ["enabled" ] = "true"
224
+ hugePages [pageSize ] = "true"
225
+ }
226
+ }
227
+
228
+ return hugePages , nil
229
+ }
230
+
231
+ func getHugePageSize (basePath , dirName string , reg * regexp.Regexp ) (string , error ) {
232
+ matches := reg .FindStringSubmatch (dirName )
233
+ if len (matches ) != 2 {
234
+ return "" , fmt .Errorf ("unexpected directory format: %s" , dirName )
235
+ }
236
+
237
+ totalPagesFile := filepath .Join (basePath , dirName , "nr_hugepages" )
238
+ totalPagesRaw , err := os .ReadFile (totalPagesFile )
239
+ if err != nil {
240
+ return "" , fmt .Errorf ("unable to read total number of huge pages from the file name: %s" , totalPagesFile )
241
+ }
242
+
243
+ totalPages , err := strconv .Atoi (strings .TrimSpace (string (totalPagesRaw )))
244
+ if err != nil {
245
+ return "" , fmt .Errorf ("unable to convert total pages to integer - %s: %s" , totalPagesFile , totalPagesRaw )
246
+ }
247
+ if totalPages < 1 {
248
+ return "" , nil
249
+ }
250
+
251
+ sizeFormat := matches [1 ] + "Ki"
252
+ quantity , err := resource .ParseQuantity (sizeFormat )
253
+ if err != nil {
254
+ return "" , fmt .Errorf ("invalid size format: %s" , sizeFormat )
255
+ }
256
+
257
+ return "hugepages-" + quantity .String (), nil
258
+ }
259
+
182
260
// ndDevAttrs is the list of sysfs files (under each nd device) that we're trying to read
183
261
var ndDevAttrs = []string {"devtype" , "mode" }
184
262
0 commit comments