Skip to content

Commit

Permalink
iscsinl: introduce ScanTimeout
Browse files Browse the repository at this point in the history
The old loop would run for exactly 300ms, and then use the uevents
generated during that time. 300ms might not be long enough if it's on a
physical network link (our tests are VM only). However, we also need to
still support more than 1 LUN.

I'm not sure how to find out how many LUNs there are going to be
beforehand, so we don't know how many devices we are looking for.

So for now, we do the following: we keep looping to find matches, until
we're reasonably sure that no new ones are coming. We time out after 3
seconds, which any caller can change.

Signed-off-by: Chris Koch <[email protected]>
  • Loading branch information
hugelgupf committed Aug 11, 2020
1 parent 4ac55d2 commit bd38e9f
Showing 1 changed file with 28 additions and 6 deletions.
34 changes: 28 additions & 6 deletions initiator.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ type IscsiOptions struct {

// Scheduler to configure for the blockdev
Scheduler string

// ScanTimeout is the total time to wait for block devices to appear in
// the file system after initiating a scan.
ScanTimeout time.Duration
}

// IscsiTargetSession represents an iSCSI session and a single connection to a target
Expand Down Expand Up @@ -231,6 +235,7 @@ var defaultOpts = IscsiOptions{
DataPDUInOrder: true,
DataSequenceInOrder: true,
Scheduler: "noop",
ScanTimeout: 3 * time.Second,
}

// Option is a functional API for setting optional configuration.
Expand All @@ -244,6 +249,13 @@ func WithTarget(addr, volume string) Option {
}
}

// WithScanTimeout sets the timeout to wait for devices to appear after sending the scan event.
func WithScanTimeout(dur time.Duration) Option {
return func(i *IscsiOptions) {
i.ScanTimeout = dur
}
}

// WithInitiator adds the initiator name to the config.
func WithInitiator(initiatorName string) Option {
return func(i *IscsiOptions) {
Expand Down Expand Up @@ -428,16 +440,26 @@ func (s *IscsiTargetSession) ReScan() error {
}

var matches []string
for i := 0; i < 10; i++ {
var err error
start := time.Now()
// The kernel may add devices it finds through scanning at any time. If
// a scan yields multiple, kernel will not add them atomically. We wait
// until at least one device has appeared, and no new devices have
// appeared for 100ms. We also time out based on the user defined
// ScanTimeout.
for elapsed := time.Now().Sub(start); elapsed <= s.opts.ScanTimeout; {
log.Printf("Waiting for device...")
time.Sleep(30 * time.Millisecond)
matches, err = filepath.Glob(fmt.Sprintf(
time.Sleep(100 * time.Millisecond)
newMatches, err := filepath.Glob(fmt.Sprintf(
"/sys/class/iscsi_session/session%d/device/target*/*/block/*/uevent", s.sid))

if err != nil {
return err
}
if len(newMatches) > 0 {
if len(matches) == len(newMatches) {
break
}
matches = newMatches
}
}

found := false
Expand All @@ -458,7 +480,7 @@ func (s *IscsiTargetSession) ReScan() error {
}

if !found {
return errors.New("could not find DEVNAME")
return errors.New("could not find any device DEVNAMEs")
}
return nil

Expand Down

0 comments on commit bd38e9f

Please sign in to comment.