Skip to content

Commit d8cd841

Browse files
committed
fix(csi): ensure the bind mount point for block volume
longhorn-12006 Signed-off-by: Raphanus Lo <yunchang.lo@suse.com>
1 parent dd8dce6 commit d8cd841

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

csi/node_server.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,18 +364,27 @@ func (ns *NodeServer) nodePublishBlockVolume(volumeID, devicePath, targetPath st
364364

365365
// we ensure the parent directory exists and is valid
366366
if _, err := ensureDirectory(filepath.Dir(targetPath)); err != nil {
367-
return status.Errorf(codes.Internal, "failed to prepare mount point for block device %v: %v", devicePath, err)
367+
return status.Errorf(codes.Internal, "failed to prepare mount point directory for block device %v: %v", devicePath, err)
368+
}
369+
370+
// ensure the bind mount point is clear
371+
if err := ensureBindMountPoint(targetPath); err != nil {
372+
return status.Errorf(codes.Internal, "failed to prepare mount point file for block device %v: %v", devicePath, err)
368373
}
369374

370375
// create file where we can bind mount the device to
371376
if err := makeFile(targetPath); err != nil {
377+
if removeErr := unmountAndCleanupMountPoint(targetPath, mount.New("")); removeErr != nil {
378+
log.WithError(removeErr).Errorf("Failed to clean up the mount target %q for failed bind mount point", targetPath)
379+
}
372380
return status.Errorf(codes.Internal, "failed to create file %v: %v", targetPath, err)
373381
}
374382

375383
log.Infof("Bind mounting device %v at %v", devicePath, targetPath)
376384
if err := mounter.Mount(devicePath, targetPath, "", []string{"bind"}); err != nil {
377-
if removeErr := os.Remove(targetPath); removeErr != nil {
378-
log.WithError(removeErr).Errorf("Failed to remove failed mount target %q", targetPath)
385+
log.WithError(err).Infof("Clean up the mount target %s because of mount error", targetPath)
386+
if removeErr := unmountAndCleanupMountPoint(targetPath, mount.New("")); removeErr != nil {
387+
log.WithError(removeErr).Errorf("Failed to clean up the mount target %q for failed mounting", targetPath)
379388
}
380389
return status.Errorf(codes.Internal, "failed to bind mount %q at %q: %v", devicePath, targetPath, err)
381390
}

csi/util.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,31 @@ func ensureMountPoint(path string, mounter mount.Interface) (bool, error) {
338338
return isMnt, err
339339
}
340340

341+
// ensureBindMountPoint evaluates whether a path is a valid mount point for bind mount.
342+
// In case the path does not exists, it will create a regular file for bind mount.
343+
// In case where the mount point exists but is not a regular file, the mount point will be replaced by a regular file.
344+
func ensureBindMountPoint(path string) error {
345+
logrus.Infof("Trying to ensure bind mount point %v", path)
346+
info, statErr := os.Lstat(path)
347+
if statErr != nil {
348+
if !os.IsNotExist(statErr) {
349+
return errors.Wrapf(statErr, "failed to check bind mount at %s", path)
350+
}
351+
} else {
352+
if !info.Mode().IsRegular() {
353+
logrus.Infof("Bind mount point %v is not a regular file, clean up", path)
354+
if rmErr := os.Remove(path); rmErr != nil {
355+
return errors.Wrapf(rmErr, "failed to remove corrupt bind mount point at %s", path)
356+
}
357+
}
358+
}
359+
360+
if makeFileErr := makeFile(path); makeFileErr != nil {
361+
return errors.Wrapf(makeFileErr, "failed to create regular file for bind mount at %s", path)
362+
}
363+
return nil
364+
}
365+
341366
// ensureDirectory checks if a folder exists at the specified path.
342367
// If not, it creates the folder and returns true, otherwise returns false.
343368
// If the path exists but is not a folder, it returns an error.
@@ -439,7 +464,7 @@ func getFilesystemStatistics(volumePath string) (*volumeFilesystemStatistics, er
439464
return volStats, nil
440465
}
441466

442-
// makeFile creates an empty file.
467+
// makeFile creates an empty regular file.
443468
// If pathname already exists, whether a file or directory, no error is returned.
444469
func makeFile(pathname string) error {
445470
f, err := os.OpenFile(pathname, os.O_CREATE, os.FileMode(0644))

0 commit comments

Comments
 (0)