@@ -23,6 +23,7 @@ import (
23
23
"path/filepath"
24
24
"regexp"
25
25
"strings"
26
+ "sync"
26
27
"time"
27
28
28
29
"k8s.io/klog/v2"
@@ -31,6 +32,7 @@ import (
31
32
var (
32
33
lastCleanExecuted time.Time
33
34
lastStaleCleanExecuted time.Time
35
+ scanLock = & sync.Mutex {}
34
36
)
35
37
36
38
type LinuxDevice interface {
@@ -81,7 +83,8 @@ func (d *Device) Populate(needActivePath bool) error {
81
83
tmpPathname := "dm-" + result ["Minor" ]
82
84
uuid , err := getUUID (tmpPathname )
83
85
if err != nil {
84
- return err
86
+ klog .Warning (err )
87
+ continue
85
88
}
86
89
tmpWWID := strings .TrimPrefix (uuid , "mpath-" )
87
90
tmpWWN := tmpWWID [1 :] // truncate scsi-id prefix
@@ -122,11 +125,6 @@ func (d *Device) DeleteDevice() (err error) {
122
125
123
126
// CreateDevice: attach and create linux devices to host
124
127
func (d * Device ) CreateDevice () (err error ) {
125
- if err = scsiHostRescan (); err != nil {
126
- return err
127
- }
128
- // wait for device to appear after rescan
129
- time .Sleep (time .Second * 1 )
130
128
131
129
if err = d .createLinuxDevice (); err != nil {
132
130
klog .Errorf ("unable to create device for wwn %v" , d .WWN )
@@ -139,6 +137,35 @@ func (d *Device) CreateDevice() (err error) {
139
137
return nil
140
138
}
141
139
140
+ // scsiHostRescanWithLock: scans all scsi hosts with locks
141
+ // This is calling scsiHostRescan
142
+ // which works in a way that only 1 scan will run at a time
143
+ // and other requests will wait till the scan is complete
144
+ // but will not scan again as it is already scanned.
145
+ func scsiHostRescanWithLock () (err error ) {
146
+ start := time .Now ()
147
+ var scan bool = true
148
+ defer scanLock .Unlock ()
149
+
150
+ for {
151
+ if scanLock .TryLock () {
152
+ if scan {
153
+ err = scsiHostRescan ()
154
+ }
155
+ return err
156
+ } else {
157
+ if time .Since (start ) > time .Minute {
158
+ // Scanning usually takes < 30s. If wait is more than a min then return.
159
+ return
160
+ }
161
+
162
+ // Already locked, wait for it to complete and don't scan again.
163
+ scan = false
164
+ time .Sleep (5 * time .Second )
165
+ }
166
+ }
167
+ }
168
+
142
169
// createLinuxDevice: attaches and creates a new linux device
143
170
// Try device discovery; retry every 5 sec if no device found or have 0 slaves
144
171
// In between checks we will try to cleanup:
@@ -151,6 +178,12 @@ func (d *Device) CreateDevice() (err error) {
151
178
func (d * Device ) createLinuxDevice () (err error ) {
152
179
// Start a Countdown ticker
153
180
for i := 0 ; i <= 10 ; i ++ {
181
+ if err = scsiHostRescanWithLock (); err != nil {
182
+ return err
183
+ }
184
+ // wait for device to appear after rescan
185
+ time .Sleep (time .Second * 1 )
186
+
154
187
err := d .Populate (true )
155
188
if err != nil {
156
189
return err
0 commit comments