Skip to content

Commit bc58abe

Browse files
authored
Merge pull request #1018 from andyzhangx/volume-stat-cache-1.21
[release-1.21] fix: add VolumeStats cache to avoid massive statfs calls
2 parents 3951e9e + 1602df8 commit bc58abe

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

pkg/blob/blob.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ type DriverOptions struct {
166166
MountPermissions uint64
167167
KubeAPIQPS float64
168168
KubeAPIBurst int
169+
VolStatsCacheExpireInMinutes int
169170
}
170171

171172
// Driver implements all interfaces of CSI drivers
@@ -203,6 +204,8 @@ type Driver struct {
203204
dataPlaneAPIVolCache *azcache.TimedCache
204205
// a timed cache storing account search history (solve account list throttling issue)
205206
accountSearchCache *azcache.TimedCache
207+
// a timed cache storing volume stats <volumeID, volumeStats>
208+
volStatsCache *azcache.TimedCache
206209
}
207210

208211
// NewDriver Creates a NewCSIDriver object. Assumes vendor version is equal to driver version &
@@ -240,6 +243,13 @@ func NewDriver(options *DriverOptions) *Driver {
240243
if d.dataPlaneAPIVolCache, err = azcache.NewTimedcache(10*time.Minute, getter); err != nil {
241244
klog.Fatalf("%v", err)
242245
}
246+
247+
if options.VolStatsCacheExpireInMinutes <= 0 {
248+
options.VolStatsCacheExpireInMinutes = 10 // default expire in 10 minutes
249+
}
250+
if d.volStatsCache, err = azcache.NewTimedcache(time.Duration(options.VolStatsCacheExpireInMinutes)*time.Minute, getter); err != nil {
251+
klog.Fatalf("%v", err)
252+
}
243253
return &d
244254
}
245255

pkg/blob/blob_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ func TestNewDriver(t *testing.T) {
9292
fakedriver.Version = driverVersion
9393
fakedriver.accountSearchCache = driver.accountSearchCache
9494
fakedriver.dataPlaneAPIVolCache = driver.dataPlaneAPIVolCache
95+
fakedriver.volStatsCache = driver.volStatsCache
9596
assert.Equal(t, driver, fakedriver)
9697
}
9798

pkg/blob/nodeserver.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"time"
2929

3030
volumehelper "sigs.k8s.io/blob-csi-driver/pkg/util"
31+
azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
3132

3233
"github.com/Azure/azure-sdk-for-go/storage"
3334
"github.com/container-storage-interface/spec/lib/go/csi"
@@ -475,13 +476,26 @@ func (d *Driver) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeS
475476
return nil, status.Error(codes.InvalidArgument, "NodeGetVolumeStats volume path was empty")
476477
}
477478

479+
// check if the volume stats is cached
480+
cache, err := d.volStatsCache.Get(req.VolumeId, azcache.CacheReadTypeDefault)
481+
if err != nil {
482+
return nil, status.Errorf(codes.Internal, err.Error())
483+
}
484+
if cache != nil {
485+
resp := cache.(csi.NodeGetVolumeStatsResponse)
486+
klog.V(6).Infof("NodeGetVolumeStats: volume stats for volume %s path %s is cached", req.VolumeId, req.VolumePath)
487+
return &resp, nil
488+
}
489+
478490
if _, err := os.Lstat(req.VolumePath); err != nil {
479491
if os.IsNotExist(err) {
480492
return nil, status.Errorf(codes.NotFound, "path %s does not exist", req.VolumePath)
481493
}
482494
return nil, status.Errorf(codes.Internal, "failed to stat file %s: %v", req.VolumePath, err)
483495
}
484496

497+
klog.V(6).Infof("NodeGetVolumeStats: begin to get VolumeStats on volume %s path %s", req.VolumeId, req.VolumePath)
498+
485499
volumeMetrics, err := volume.NewMetricsStatFS(req.VolumePath).GetMetrics()
486500
if err != nil {
487501
return nil, status.Errorf(codes.Internal, "failed to get metrics: %v", err)
@@ -513,7 +527,7 @@ func (d *Driver) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeS
513527
return nil, status.Errorf(codes.Internal, "failed to transform disk inodes used(%v)", volumeMetrics.InodesUsed)
514528
}
515529

516-
return &csi.NodeGetVolumeStatsResponse{
530+
resp := &csi.NodeGetVolumeStatsResponse{
517531
Usage: []*csi.VolumeUsage{
518532
{
519533
Unit: csi.VolumeUsage_BYTES,
@@ -528,7 +542,12 @@ func (d *Driver) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeS
528542
Used: inodesUsed,
529543
},
530544
},
531-
}, nil
545+
}
546+
547+
klog.V(6).Infof("NodeGetVolumeStats: volume stats for volume %s path %s is %v", req.VolumeId, req.VolumePath, resp)
548+
// cache the volume stats per volume
549+
d.volStatsCache.Set(req.VolumeId, *resp)
550+
return resp, nil
532551
}
533552

534553
// ensureMountPoint: create mount point if not exists

0 commit comments

Comments
 (0)