@@ -21,8 +21,10 @@ import (
2121 "os"
2222 "path"
2323
24+ "github.com/Azure/azure-sdk-for-go/arm/resources/resources"
2425 "github.com/golang/glog"
2526 "k8s.io/api/core/v1"
27+ "k8s.io/apimachinery/pkg/api/resource"
2628 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2729 "k8s.io/apimachinery/pkg/types"
2830 "k8s.io/kubernetes/pkg/util/mount"
@@ -104,15 +106,19 @@ func (plugin *emptyDirPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, opts vo
104106
105107func (plugin * emptyDirPlugin ) newMounterInternal (spec * volume.Spec , pod * v1.Pod , mounter mount.Interface , mountDetector mountDetector , opts volume.VolumeOptions ) (volume.Mounter , error ) {
106108 medium := v1 .StorageMediumDefault
109+ size := ""
107110 if spec .Volume .EmptyDir != nil { // Support a non-specified source as EmptyDir.
108111 medium = spec .Volume .EmptyDir .Medium
112+ size = spec .Volume .EmptyDir .HugetlbfsSize
109113 }
114+
110115 return & emptyDir {
111116 pod : pod ,
112117 volName : spec .Name (),
113118 medium : medium ,
114119 mounter : mounter ,
115120 mountDetector : mountDetector ,
121+ size : size ,
116122 plugin : plugin ,
117123 MetricsProvider : volume .NewMetricsDu (getPath (pod .UID , spec .Name (), plugin .host )),
118124 }, nil
@@ -159,8 +165,9 @@ type mountDetector interface {
159165type storageMedium int
160166
161167const (
162- mediumUnknown storageMedium = 0 // assume anything we don't explicitly handle is this
163- mediumMemory storageMedium = 1 // memory (e.g. tmpfs on linux)
168+ mediumUnknown storageMedium = 0 // assume anything we don't explicitly handle is this
169+ mediumMemory storageMedium = 1 // memory (e.g. tmpfs on linux)
170+ mediumHugepages storageMedium = 2 // hugepages
164171)
165172
166173// EmptyDir volumes are temporary directories exposed to the pod.
@@ -172,6 +179,7 @@ type emptyDir struct {
172179 mounter mount.Interface
173180 mountDetector mountDetector
174181 plugin * emptyDirPlugin
182+ size string
175183 volume.MetricsProvider
176184}
177185
@@ -221,6 +229,8 @@ func (ed *emptyDir) SetUpAt(dir string, fsGroup *int64) error {
221229 err = ed .setupDir (dir )
222230 case v1 .StorageMediumMemory :
223231 err = ed .setupTmpfs (dir )
232+ case v1 .StorageMediumHugetlbfs :
233+ err = ed .setupHugepages (dir )
224234 default :
225235 err = fmt .Errorf ("unknown storage medium %q" , ed .medium )
226236 }
@@ -257,6 +267,36 @@ func (ed *emptyDir) setupTmpfs(dir string) error {
257267 return ed .mounter .Mount ("tmpfs" , dir , "tmpfs" , nil /* options */ )
258268}
259269
270+ // setupHugepages creates a hugepage mount at the specified directory.
271+ func (ed * emptyDir ) setupHugepages (dir string ) error {
272+ if ed .mounter == nil {
273+ return fmt .Errorf ("memory storage requested, but mounter is nil" )
274+ }
275+ if err := ed .setupDir (dir ); err != nil {
276+ return err
277+ }
278+ // Make SetUp idempotent.
279+ medium , isMnt , err := ed .mountDetector .GetMountMedium (dir )
280+ if err != nil {
281+ return err
282+ }
283+ // If the directory is a mountpoint with medium memory, there is no
284+ // work to do since we are already in the desired state.
285+ if isMnt && medium == mediumHugepages {
286+ return nil
287+ }
288+ if ed .size == "" {
289+ return fmt .Errorf ("size is not provided" )
290+ }
291+ if _ , err := resource .ParseQuantity (ed .size ); err != nil {
292+ return fmt .Errorf ("unsupported hugetlbfs size: %v" , err )
293+ }
294+
295+ glog .V (3 ).Infof ("pod %v: mounting hugepages for volume %v" , ed .pod .UID , ed .volName )
296+ mountOptions := []string {fmt .Sprintf ("size=%s" , ed .size )}
297+ return ed .mounter .Mount ("nodev" , dir , "hugetlbfs" , mountOptions )
298+ }
299+
260300// setupDir creates the directory with the default permissions specified by the perm constant.
261301func (ed * emptyDir ) setupDir (dir string ) error {
262302 // Create the directory if it doesn't already exist.
0 commit comments