Skip to content

Commit 76b8e4c

Browse files
committed
refactor: refactor device discovery process
Change logic in discoverDevices to increase chances of discovering multipath devices properly by retrying discovery multiple times if only non-multipath device is found. Refactor FindDiskById (and make it public) to not read the entire disk/by-id directory during device search
1 parent 037c85c commit 76b8e4c

File tree

2 files changed

+31
-34
lines changed

2 files changed

+31
-34
lines changed

sas/sas.go

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
66
You may obtain a copy of the License at
77
8-
http://www.apache.org/licenses/LICENSE-2.0
8+
http://www.apache.org/licenses/LICENSE-2.0
99
1010
Unless required by applicable law or agreed to in writing, software
1111
distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,6 +22,7 @@ import (
2222
"io/ioutil"
2323
"os"
2424
"os/exec"
25+
"time"
2526

2627
"path"
2728
"path/filepath"
@@ -30,6 +31,13 @@ import (
3031
"k8s.io/klog/v2"
3132
)
3233

34+
// Number of times to retry device discovery
35+
const discoveryRetries = 5
36+
37+
// sleep time in milliseconds between device discovery iterations.
38+
// May need to be adjusted to be longer if multipath discovery is not occuring quickly enough
39+
const discoverySleepTime = 500
40+
3341
type ioHandler interface {
3442
ReadDir(dirname string) ([]os.FileInfo, error)
3543
Lstat(name string) (os.FileInfo, error)
@@ -160,22 +168,22 @@ func ResizeMultipathDevice(ctx context.Context, devicePath string) error {
160168

161169
// PRIVATE
162170

163-
//ReadDir calls the ReadDir function from ioutil package
171+
// ReadDir calls the ReadDir function from ioutil package
164172
func (handler *OSioHandler) ReadDir(dirname string) ([]os.FileInfo, error) {
165173
return ioutil.ReadDir(dirname)
166174
}
167175

168-
//Lstat calls the Lstat function from os package
176+
// Lstat calls the Lstat function from os package
169177
func (handler *OSioHandler) Lstat(name string) (os.FileInfo, error) {
170178
return os.Lstat(name)
171179
}
172180

173-
//EvalSymlinks calls EvalSymlinks from filepath package
181+
// EvalSymlinks calls EvalSymlinks from filepath package
174182
func (handler *OSioHandler) EvalSymlinks(path string) (string, error) {
175183
return filepath.EvalSymlinks(path)
176184
}
177185

178-
//WriteFile calls WriteFile from ioutil package
186+
// WriteFile calls WriteFile from ioutil package
179187
func (handler *OSioHandler) WriteFile(filename string, data []byte, perm os.FileMode) error {
180188
return ioutil.WriteFile(filename, data, perm)
181189
}
@@ -201,15 +209,17 @@ func discoverDevices(logger klog.Logger, c *Connector, io ioHandler) error {
201209

202210
c.Multipath = false
203211
c.OSPathName = ""
204-
rescaned := false
212+
retries := 0
205213

206214
// two-phase search:
207215
// first phase, search existing device paths, if a multipath dm is found, exit loop
208216
// otherwise, in second phase, rescan scsi bus and search again, return with any findings
209-
for true {
217+
for retries < discoveryRetries {
210218

211219
// Find the multipath device using WWN
212-
dm, devices = findDiskById(logger, c.VolumeWWN, io)
220+
logger.V(5).Info("Sleeping 0.5 seconds before device discovery")
221+
time.Sleep(discoverySleepTime * time.Millisecond)
222+
dm, devices = FindDiskById(logger, c.VolumeWWN, io)
213223
logger.V(1).Info("find disk by id returned", "dm", dm, "devices", devices)
214224

215225
for _, device := range devices {
@@ -227,15 +237,9 @@ func discoverDevices(logger klog.Logger, c *Connector, io ioHandler) error {
227237
break
228238
}
229239

230-
// if a dm is found, exit loop
231-
if rescaned || dm != "" {
232-
break
233-
}
234-
235-
// rescan scsi hosts and search again
236240
logger.V(2).Info("scsi rescan host")
237241
scsiHostRescan(logger, io)
238-
rescaned = true
242+
retries++
239243
}
240244

241245
// if no disk matches input wwn, return error
@@ -249,8 +253,8 @@ func discoverDevices(logger klog.Logger, c *Connector, io ioHandler) error {
249253
return nil
250254
}
251255

252-
// findDiskById: given a wwn of the storage volume, find the multipath device and associated scsi devices
253-
func findDiskById(logger klog.Logger, wwn string, io ioHandler) (string, []string) {
256+
// FindDiskById: given a wwn of the storage volume, find the multipath device and associated scsi devices
257+
func FindDiskById(logger klog.Logger, wwn string, io ioHandler) (string, []string) {
254258

255259
// Example multipath device naming:
256260
// Under /dev/disk/by-id:
@@ -260,21 +264,14 @@ func findDiskById(logger klog.Logger, wwn string, io ioHandler) (string, []strin
260264
// wwn-0x600c0ff0005460670a4ae16201000000 -> ../../dm-5
261265

262266
var devices []string
263-
wwnPath := "wwn-0x" + wwn
264-
devPath := "/dev/disk/by-id/"
265-
logger.V(2).Info("find disk by id", "wwnPath", wwnPath, "devPath", devPath)
266-
267-
if dirs, err := io.ReadDir(devPath); err == nil {
268-
for _, f := range dirs {
269-
name := f.Name()
270-
logger.V(4).Info("checking", "contains", strings.Contains(name, wwnPath), "name", name)
271-
if strings.Contains(name, wwnPath) {
272-
logger.V(2).Info("found device, evaluate symbolic links", "devPath", devPath, "name", name)
273-
if dm, err1 := io.EvalSymlinks(devPath + name); err1 == nil {
274-
devices = FindLinkedDevicesOnMultipath(logger, dm, io)
275-
return dm, devices
276-
}
277-
}
267+
devPath := "/dev/disk/by-id/wwn-0x" + wwn
268+
logger.V(2).Info("find disk by id", "devPath", devPath)
269+
270+
if _, err := os.Stat(devPath); err == nil {
271+
logger.V(2).Info("found device, evaluate symbolic links", "devPath", devPath)
272+
if dm, err1 := io.EvalSymlinks(devPath); err1 == nil {
273+
devices = FindLinkedDevicesOnMultipath(logger, dm, io)
274+
return dm, devices
278275
}
279276
}
280277
return "", devices

sas/sas_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
66
You may obtain a copy of the License at
77
8-
http://www.apache.org/licenses/LICENSE-2.0
8+
http://www.apache.org/licenses/LICENSE-2.0
99
1010
Unless required by applicable law or agreed to in writing, software
1111
distributed under the License is distributed on an "AS IS" BASIS,
@@ -102,7 +102,7 @@ func TestSearchDisk(t *testing.T) {
102102
func TestInvalidWWN(t *testing.T) {
103103
logger, _ := ktesting.NewTestContext(t)
104104
testWwn := "INVALIDWWN"
105-
dm, devices := findDiskById(logger, testWwn, &fakeIOHandler{})
105+
dm, devices := FindDiskById(logger, testWwn, &fakeIOHandler{})
106106

107107
if len(devices) > 0 || dm != "" {
108108
t.Error("Found a disk with WWN that does not Exist")

0 commit comments

Comments
 (0)