|
5 | 5 | "os" |
6 | 6 | "os/exec" |
7 | 7 | "strings" |
| 8 | + "time" |
8 | 9 |
|
9 | 10 | "github.com/container-storage-interface/spec/lib/go/csi" |
10 | 11 | "google.golang.org/grpc/codes" |
@@ -55,10 +56,70 @@ func (ns *nodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStageVol |
55 | 56 |
|
56 | 57 | func formateAndMakeFS(device string, fstype string) error { |
57 | 58 | klog.Infof("formateAndMakeFS: called with args %s, %s", device, fstype) |
| 59 | + |
| 60 | + // Wait for device to be ready and check if filesystem exists |
| 61 | + // This prevents race condition where device is attached but not yet accessible |
| 62 | + const maxRetries = 10 |
| 63 | + const retryDelay = 500 * time.Millisecond |
| 64 | + |
| 65 | + var existingFS string |
| 66 | + var deviceReady bool |
| 67 | + |
| 68 | + for i := 0; i < maxRetries; i++ { |
| 69 | + // Check if device file exists |
| 70 | + if _, err := os.Stat(device); err != nil { |
| 71 | + if i < maxRetries-1 { |
| 72 | + klog.Infof("Device %s not ready (attempt %d/%d), waiting...", device, i+1, maxRetries) |
| 73 | + time.Sleep(retryDelay) |
| 74 | + continue |
| 75 | + } |
| 76 | + return fmt.Errorf("device %s not found after %d attempts: %v", device, maxRetries, err) |
| 77 | + } |
| 78 | + |
| 79 | + // Try to read filesystem type with blkid |
| 80 | + blkidCmd := exec.Command("blkid", "-o", "value", "-s", "TYPE", device) |
| 81 | + output, err := blkidCmd.CombinedOutput() |
| 82 | + existingFS = strings.TrimSpace(string(output)) |
| 83 | + |
| 84 | + if err == nil { |
| 85 | + // blkid succeeded - filesystem exists |
| 86 | + deviceReady = true |
| 87 | + break |
| 88 | + } |
| 89 | + |
| 90 | + // Check if error indicates device is not ready (vs no filesystem) |
| 91 | + exitErr, ok := err.(*exec.ExitError) |
| 92 | + if ok && exitErr.ExitCode() == 2 { |
| 93 | + // Exit code 2 means no filesystem found - device is ready but empty |
| 94 | + deviceReady = true |
| 95 | + break |
| 96 | + } |
| 97 | + |
| 98 | + // Other errors might indicate device not ready |
| 99 | + if i < maxRetries-1 { |
| 100 | + klog.Infof("Device %s not ready for blkid (attempt %d/%d): %v, waiting...", device, i+1, maxRetries, err) |
| 101 | + time.Sleep(retryDelay) |
| 102 | + continue |
| 103 | + } |
| 104 | + |
| 105 | + return fmt.Errorf("device %s not ready after %d attempts: %v", device, maxRetries, err) |
| 106 | + } |
| 107 | + |
| 108 | + if !deviceReady { |
| 109 | + return fmt.Errorf("device %s did not become ready", device) |
| 110 | + } |
| 111 | + |
| 112 | + if existingFS != "" { |
| 113 | + klog.Infof("Filesystem %s already exists on %s, skipping format", existingFS, device) |
| 114 | + return nil // Don't format if filesystem exists |
| 115 | + } |
| 116 | + |
| 117 | + klog.Infof("No filesystem detected on %s, creating %s filesystem", device, fstype) |
| 118 | + |
| 119 | + // Only format if no filesystem exists |
58 | 120 | mkfsCmd := fmt.Sprintf("mkfs.%s", fstype) |
59 | 121 |
|
60 | | - _, err := exec.LookPath(mkfsCmd) |
61 | | - if err != nil { |
| 122 | + if _, err := exec.LookPath(mkfsCmd); err != nil { |
62 | 123 | return fmt.Errorf("unable to find the mkfs (%s) utiltiy errors is %s", mkfsCmd, err.Error()) |
63 | 124 | } |
64 | 125 |
|
|
0 commit comments