Skip to content

Commit a59b8a2

Browse files
authored
[cinder-csi-plugin] retry mount operation with rescan (kubernetes#2610)
If the initial formatting and mounting fails in NodeStageVolume try to rescan the device and retry the operation. This prevents failures if the device information is reported wrongly which would otherwise be blocking the mounting. Signed-off-by: NymanRobin <[email protected]>
1 parent 76d7608 commit a59b8a2

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

pkg/csi/cinder/nodeserver.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVol
398398
options = append(options, collectMountOptions(fsType, mountFlags)...)
399399
}
400400
// Mount
401-
err = m.Mounter().FormatAndMount(devicePath, stagingTarget, fsType, options)
401+
err = ns.formatAndMountRetry(devicePath, stagingTarget, fsType, options)
402402
if err != nil {
403403
return nil, status.Error(codes.Internal, err.Error())
404404
}
@@ -426,6 +426,25 @@ func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVol
426426
return &csi.NodeStageVolumeResponse{}, nil
427427
}
428428

429+
// formatAndMountRetry attempts to format and mount a device at the given path.
430+
// If the initial mount fails, it rescans the device and retries the mount operation.
431+
func (ns *nodeServer) formatAndMountRetry(devicePath, stagingTarget, fsType string, options []string) error {
432+
m := ns.Mount
433+
err := m.Mounter().FormatAndMount(devicePath, stagingTarget, fsType, options)
434+
if err != nil {
435+
klog.Infof("Initial format and mount failed: %v. Attempting rescan.", err)
436+
// Attempting rescan if the initial mount fails
437+
rescanErr := blockdevice.RescanDevice(devicePath)
438+
if rescanErr != nil {
439+
klog.Infof("Rescan failed: %v. Returning original mount error.", rescanErr)
440+
return err
441+
}
442+
klog.Infof("Rescan succeeded, retrying format and mount")
443+
err = m.Mounter().FormatAndMount(devicePath, stagingTarget, fsType, options)
444+
}
445+
return err
446+
}
447+
429448
func (ns *nodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) {
430449
klog.V(4).Infof("NodeUnstageVolume: called with args %+v", protosanitizer.StripSecrets(*req))
431450

pkg/util/blockdevice/blockdevice_linux.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@ func checkBlockDeviceSize(devicePath string, deviceMountPath string, newSize int
8585
return nil
8686
}
8787

88+
func triggerRescan(blockDeviceRescanPath string) error {
89+
klog.V(4).Infof("Rescanning %q block device geometry", blockDeviceRescanPath)
90+
err := os.WriteFile(blockDeviceRescanPath, []byte{'1'}, 0666)
91+
if err != nil {
92+
klog.Errorf("Error rescanning new block device geometry: %v", err)
93+
return err
94+
}
95+
return nil
96+
}
97+
8898
func RescanBlockDeviceGeometry(devicePath string, deviceMountPath string, newSize int64) error {
8999
if newSize == 0 {
90100
klog.Error("newSize is empty, skipping the block device rescan")
@@ -106,13 +116,25 @@ func RescanBlockDeviceGeometry(devicePath string, deviceMountPath string, newSiz
106116
}
107117

108118
klog.V(3).Infof("Resolved block device path from %q to %q", devicePath, blockDeviceRescanPath)
109-
klog.V(4).Infof("Rescanning %q block device geometry", devicePath)
110-
err = os.WriteFile(blockDeviceRescanPath, []byte{'1'}, 0666)
119+
err = triggerRescan(blockDeviceRescanPath)
111120
if err != nil {
112-
klog.Errorf("Error rescanning new block device geometry: %v", err)
113121
// no need to run checkBlockDeviceSize second time here, return the saved error
114122
return bdSizeErr
115123
}
116124

117125
return checkBlockDeviceSize(devicePath, deviceMountPath, newSize)
118126
}
127+
128+
func RescanDevice(devicePath string) error {
129+
blockDeviceRescanPath, err := findBlockDeviceRescanPath(devicePath)
130+
if err != nil {
131+
return fmt.Errorf("Device does not have rescan path " + devicePath)
132+
}
133+
134+
klog.V(3).Infof("Resolved block device path from %q to %q", devicePath, blockDeviceRescanPath)
135+
err = triggerRescan(blockDeviceRescanPath)
136+
if err != nil {
137+
return fmt.Errorf("Error rescanning new block device geometry " + devicePath)
138+
}
139+
return nil
140+
}

0 commit comments

Comments
 (0)