k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/volume/emptydir/empty_dir_linux.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 Copyright 2015 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package emptydir 21 22 import ( 23 "fmt" 24 "strings" 25 26 "golang.org/x/sys/unix" 27 "k8s.io/apimachinery/pkg/api/resource" 28 "k8s.io/klog/v2" 29 "k8s.io/mount-utils" 30 31 "k8s.io/api/core/v1" 32 ) 33 34 // Defined by Linux - the type number for tmpfs mounts. 35 const ( 36 linuxTmpfsMagic = 0x01021994 37 linuxHugetlbfsMagic = 0x958458f6 38 ) 39 40 // realMountDetector implements mountDetector in terms of syscalls. 41 type realMountDetector struct { 42 mounter mount.Interface 43 } 44 45 // getPageSize obtains page size from the 'pagesize' mount option of the 46 // mounted volume 47 func getPageSize(path string, mounter mount.Interface) (*resource.Quantity, error) { 48 // Get mount point data for the path 49 mountPoints, err := mounter.List() 50 if err != nil { 51 return nil, fmt.Errorf("error listing mount points: %v", err) 52 } 53 // Find mount point for the path 54 mountPoint, err := func(mps []mount.MountPoint, mpPath string) (*mount.MountPoint, error) { 55 for _, mp := range mps { 56 if mp.Path == mpPath { 57 return &mp, nil 58 } 59 } 60 return nil, fmt.Errorf("mount point for %s not found", mpPath) 61 }(mountPoints, path) 62 if err != nil { 63 return nil, err 64 } 65 // Get page size from the 'pagesize' option value 66 for _, opt := range mountPoint.Opts { 67 opt = strings.TrimSpace(opt) 68 prefix := "pagesize=" 69 if strings.HasPrefix(opt, prefix) { 70 // NOTE: Adding suffix 'i' as result should be comparable with a medium size. 71 // pagesize mount option is specified without a suffix, 72 // e.g. pagesize=2M or pagesize=1024M for x86 CPUs 73 trimmedOpt := strings.TrimPrefix(opt, prefix) 74 if !strings.HasSuffix(trimmedOpt, "i") { 75 trimmedOpt = trimmedOpt + "i" 76 } 77 pageSize, err := resource.ParseQuantity(trimmedOpt) 78 if err != nil { 79 return nil, fmt.Errorf("error getting page size from '%s' mount option: %v", opt, err) 80 } 81 return &pageSize, nil 82 } 83 } 84 return nil, fmt.Errorf("no pagesize option specified for %s mount", mountPoint.Path) 85 } 86 87 func (m *realMountDetector) GetMountMedium(path string, requestedMedium v1.StorageMedium) (v1.StorageMedium, bool, *resource.Quantity, error) { 88 klog.V(5).Infof("Determining mount medium of %v", path) 89 notMnt, err := m.mounter.IsLikelyNotMountPoint(path) 90 if err != nil { 91 return v1.StorageMediumDefault, false, nil, fmt.Errorf("IsLikelyNotMountPoint(%q): %v", path, err) 92 } 93 94 buf := unix.Statfs_t{} 95 if err := unix.Statfs(path, &buf); err != nil { 96 return v1.StorageMediumDefault, false, nil, fmt.Errorf("statfs(%q): %v", path, err) 97 } 98 99 klog.V(3).Infof("Statfs_t of %v: %+v", path, buf) 100 101 if buf.Type == linuxTmpfsMagic { 102 return v1.StorageMediumMemory, !notMnt, nil, nil 103 } else if int64(buf.Type) == linuxHugetlbfsMagic { 104 // Skip page size detection if requested medium doesn't have size specified 105 if requestedMedium == v1.StorageMediumHugePages { 106 return v1.StorageMediumHugePages, !notMnt, nil, nil 107 } 108 // Get page size for the volume mount 109 pageSize, err := getPageSize(path, m.mounter) 110 if err != nil { 111 return v1.StorageMediumHugePages, !notMnt, nil, err 112 } 113 return v1.StorageMediumHugePages, !notMnt, pageSize, nil 114 } 115 return v1.StorageMediumDefault, !notMnt, nil, nil 116 }