@@ -3,6 +3,7 @@ package gceGCEDriver
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "math"
6
7
"regexp"
7
8
"strconv"
8
9
"strings"
@@ -16,10 +17,18 @@ import (
16
17
)
17
18
18
19
const (
19
- cacheSuffix = "csi-fast"
20
- mainLvSuffix = "csi-main"
21
- raidedLocalSsdName = "csi-driver-data-cache"
22
- raidMode = "0"
20
+ cacheSuffix = "csi-fast"
21
+ mainLvSuffix = "csi-main"
22
+ raidedLocalSsdName = "csi-driver-data-cache"
23
+ raidMode = "0"
24
+ maxAllowedChunks int64 = 1000000 // This is the max allowed chunks for LVM
25
+ GiB float64 = 1024 * 1024 * 1024
26
+ KiB float64 = 1024
27
+ )
28
+
29
+ var (
30
+ maxChunkSize float64 = 1 * GiB // Max allowed chunk size as per LVM documentation
31
+ minChunkSize float64 = 160 * KiB // This is randomly selected, we need a multiple of 32KiB, the default size would be too small for caching https://man7.org/linux/man-pages/man8/lvcreate.8.html (--chunksize)
23
32
)
24
33
25
34
func fetchRAIDedLocalSsdPath () (string , error ) {
@@ -84,7 +93,7 @@ func setupCaching(devicePath string, req *csi.NodeStageVolumeRequest, nodeId str
84
93
vgNameForPv := strings .TrimSpace (infoSlice [(len (infoSlice ) - 1 )])
85
94
klog .V (4 ).Infof ("Physical volume is part of Volume group: %v" , vgNameForPv )
86
95
if vgNameForPv == volumeGroupName {
87
- klog .V (4 ).Infof ("Physical Volume(PV) already exists in the Volume Group" )
96
+ klog .V (4 ).Infof ("Physical Volume(PV) already exists in the Volume Group %v" , volumeGroupName )
88
97
} else if vgNameForPv != "VG" && vgNameForPv != "" {
89
98
90
99
info , err = common .RunCommand ("" /* pipedCmd */ , nil /* pipedCmdArg */ , "vgchange" , []string {"-an" , vgNameForPv }... )
@@ -159,21 +168,30 @@ func setupCaching(devicePath string, req *csi.NodeStageVolumeRequest, nodeId str
159
168
// Validate that cache is setup for required size
160
169
klog .V (4 ).Infof ("Assuming valid data cache size and mode, resizing cache is not supported" )
161
170
} else {
162
- fastCacheSize := req .GetPublishContext ()[common .ContextDataCacheSize ]
163
- chunkSize := "960" // Cannot use default chunk size(64KiB) as it errors on maxChunksAllowed. Unit - KiB
164
- args = []string {
165
- "--yes" ,
166
- "-n" ,
167
- cacheLvName ,
168
- "-L" ,
169
- // ConvertGiStringToInt64 converts the input size to GiB so default to "g" for cache size - LVM g|G is GiB.
170
- fastCacheSize + "g" ,
171
- volumeGroupName ,
172
- raidedLocalSsdPath ,
173
- }
174
- info , err = common .RunCommand ("" /* pipedCmd */ , nil /* pipedCmdArg */ , "lvcreate" , args ... )
171
+ cacheSize := req .GetPublishContext ()[common .ContextDataCacheSize ]
172
+ chunkSize , err := fetchChunkSizeKiB (cacheSize )
175
173
if err != nil {
176
- return mainDevicePath , fmt .Errorf ("Errored while creating cache %w: %s" , err , info )
174
+ klog .Errorf ("Errored to fetch cache size, verify the data-cache-size is valid: got %v, error: %q" , cacheSize , err )
175
+ return mainDevicePath , err
176
+ }
177
+ // Check if LV exists
178
+ info , err = common .RunCommand ("" /* pipedCmd */ , nil /* pipedCmdArg */ , "lvs" , args ... )
179
+ lvExists := strings .Contains (string (info ), cacheLvName )
180
+ if ! lvExists {
181
+ args = []string {
182
+ "--yes" ,
183
+ "-n" ,
184
+ cacheLvName ,
185
+ "-L" ,
186
+ // ConvertGiStringToInt64 converts the input size to GiB so default to "g" for cache size - LVM g|G is GiB.
187
+ cacheSize + "g" ,
188
+ volumeGroupName ,
189
+ raidedLocalSsdPath ,
190
+ }
191
+ info , err = common .RunCommand ("" /* pipedCmd */ , nil /* pipedCmdArg */ , "lvcreate" , args ... )
192
+ if err != nil {
193
+ return mainDevicePath , fmt .Errorf ("Errored while creating cache %w: %s" , err , info )
194
+ }
177
195
}
178
196
179
197
// Once caching is setup, link the PD to cache
@@ -188,7 +206,7 @@ func setupCaching(devicePath string, req *csi.NodeStageVolumeRequest, nodeId str
188
206
req .GetPublishContext ()[common .ContextDataCacheMode ],
189
207
volumeGroupName + "/" + mainLvName ,
190
208
"--chunksize" ,
191
- string ( chunkSize ),
209
+ chunkSize , // default unit is KiB
192
210
"--force" ,
193
211
"-y" ,
194
212
}
@@ -357,11 +375,17 @@ func cleanupCache(volumeId string, nodeId string) error {
357
375
358
376
volumeGroupName := getVolumeGroupName (nodeId )
359
377
if ! checkVgExists (volumeGroupName ) {
378
+ klog .V (4 ).Infof ("Volume group %s not found, no cache clean up needed" , volumeGroupName )
360
379
// If volume group doesn't exist then there's nothing to uncache
361
380
return nil
362
381
}
363
382
reduceVolumeGroup (volumeGroupName , true )
364
383
mainLvName := getLvName (mainLvSuffix , volumeId )
384
+ if ! checkLvExists (mainLvName ) {
385
+ klog .V (4 ).Infof ("Logical volume %s not found, assuming caching wasn't setup for the PVC %s or is cleaned up" , mainLvName , volumeId )
386
+ // If logical volume doesn't exist then there's nothing to uncache
387
+ return nil
388
+ }
365
389
args := []string {
366
390
"-an" ,
367
391
"/dev/" + volumeGroupName + "/" + mainLvName ,
@@ -382,6 +406,17 @@ func cleanupCache(volumeId string, nodeId string) error {
382
406
return nil
383
407
}
384
408
409
+ func checkLvExists (lvName string ) bool {
410
+ args := []string {}
411
+ info , err := common .RunCommand ("" /* pipedCmd */ , nil /* pipedCmdArg */ , "lvscan" , args ... )
412
+ if err != nil {
413
+ klog .Errorf ("Errored while checking if logical volume exists for %s %v: %s" , lvName , err , info )
414
+ return false
415
+ }
416
+ // Check if the required logical volume already exists
417
+ return strings .Contains (string (info ), lvName )
418
+ }
419
+
385
420
func getVolumeGroupName (nodePath string ) string {
386
421
nodeSlice := strings .Split (nodePath , "/" )
387
422
nodeId := nodeSlice [len (nodeSlice )- 1 ]
@@ -497,3 +532,18 @@ func isCachingSetup(mainLvName string) (error, bool) {
497
532
}
498
533
return nil , false
499
534
}
535
+
536
+ func fetchChunkSizeKiB (cacheSize string ) (string , error ) {
537
+ var chunkSize float64
538
+
539
+ cacheSizeInt , err := common .ConvertGiStringToInt64 (cacheSize )
540
+ if err != nil {
541
+ return "0" , err
542
+ }
543
+ // Chunksize should be divisible by 32Kib so we need (chunksize/32*1024)*32*1024
544
+ chunkSize = (float64 (cacheSizeInt ) * GiB ) / float64 (maxAllowedChunks )
545
+ chunkSize = math .Round (chunkSize / (32 * KiB )) * (32 * KiB )
546
+ chunkSize = math .Min (math .Max (chunkSize , minChunkSize ), maxChunkSize ) / KiB
547
+ // default chunk size unit KiB
548
+ return strconv .FormatInt (int64 (chunkSize ), 10 ) + "KiB" , nil
549
+ }
0 commit comments