Skip to content

Commit 3d4721a

Browse files
authored
Merge pull request #862 from umagnus/use_util_wait_func
fix: mount stuck issue
2 parents c1087f1 + 4ac586c commit 3d4721a

File tree

3 files changed

+128
-10
lines changed

3 files changed

+128
-10
lines changed

pkg/smb/nodeserver.go

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828

2929
"github.com/container-storage-interface/spec/lib/go/csi"
3030

31-
"k8s.io/apimachinery/pkg/util/wait"
3231
"k8s.io/klog/v2"
3332
"k8s.io/kubernetes/pkg/volume"
3433

@@ -37,6 +36,7 @@ import (
3736

3837
"golang.org/x/net/context"
3938

39+
volumehelper "github.com/kubernetes-csi/csi-driver-smb/pkg/util"
4040
azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
4141
)
4242

@@ -232,16 +232,11 @@ func (d *Driver) NodeStageVolume(_ context.Context, req *csi.NodeStageVolumeRequ
232232
source = strings.TrimRight(source, "/")
233233
source = fmt.Sprintf("%s/%s", source, subDir)
234234
}
235-
mountComplete := false
236-
err = wait.PollImmediate(1*time.Second, 2*time.Minute, func() (bool, error) {
237-
err := Mount(d.mounter, source, targetPath, "cifs", mountOptions, sensitiveMountOptions, volumeID)
238-
mountComplete = true
239-
return true, err
240-
})
241-
if !mountComplete {
242-
return nil, status.Error(codes.Internal, fmt.Sprintf("volume(%s) mount %q on %q failed with timeout(10m)", volumeID, source, targetPath))
235+
execFunc := func() error {
236+
return Mount(d.mounter, source, targetPath, "cifs", mountOptions, sensitiveMountOptions, volumeID)
243237
}
244-
if err != nil {
238+
timeoutFunc := func() error { return fmt.Errorf("time out") }
239+
if err := volumehelper.WaitUntilTimeout(90*time.Second, execFunc, timeoutFunc); err != nil {
245240
return nil, status.Error(codes.Internal, fmt.Sprintf("volume(%s) mount %q on %q failed with %v", volumeID, source, targetPath, err))
246241
}
247242
klog.V(2).Infof("volume(%s) mount %q on %q succeeded", volumeID, source, targetPath)

pkg/util/util.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package util
18+
19+
import (
20+
"time"
21+
)
22+
23+
// ExecFunc returns a exec function's output and error
24+
type ExecFunc func() (err error)
25+
26+
// TimeoutFunc returns output and error if an ExecFunc timeout
27+
type TimeoutFunc func() (err error)
28+
29+
// WaitUntilTimeout waits for the exec function to complete or return timeout error
30+
func WaitUntilTimeout(timeout time.Duration, execFunc ExecFunc, timeoutFunc TimeoutFunc) error {
31+
// Create a channel to receive the result of the exec function
32+
done := make(chan bool)
33+
var err error
34+
35+
// Start the exec function in a goroutine
36+
go func() {
37+
err = execFunc()
38+
done <- true
39+
}()
40+
41+
// Wait for the function to complete or time out
42+
select {
43+
case <-done:
44+
return err
45+
case <-time.After(timeout):
46+
return timeoutFunc()
47+
}
48+
}

pkg/util/util_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package util
18+
19+
import (
20+
"fmt"
21+
"testing"
22+
"time"
23+
)
24+
25+
func TestWaitUntilTimeout(t *testing.T) {
26+
tests := []struct {
27+
desc string
28+
timeout time.Duration
29+
execFunc ExecFunc
30+
timeoutFunc TimeoutFunc
31+
expectedErr error
32+
}{
33+
{
34+
desc: "execFunc returns error",
35+
timeout: 1 * time.Second,
36+
execFunc: func() error {
37+
return fmt.Errorf("execFunc error")
38+
},
39+
timeoutFunc: func() error {
40+
return fmt.Errorf("timeout error")
41+
},
42+
expectedErr: fmt.Errorf("execFunc error"),
43+
},
44+
{
45+
desc: "execFunc timeout",
46+
timeout: 1 * time.Second,
47+
execFunc: func() error {
48+
time.Sleep(2 * time.Second)
49+
return nil
50+
},
51+
timeoutFunc: func() error {
52+
return fmt.Errorf("timeout error")
53+
},
54+
expectedErr: fmt.Errorf("timeout error"),
55+
},
56+
{
57+
desc: "execFunc completed successfully",
58+
timeout: 1 * time.Second,
59+
execFunc: func() error {
60+
return nil
61+
},
62+
timeoutFunc: func() error {
63+
return fmt.Errorf("timeout error")
64+
},
65+
expectedErr: nil,
66+
},
67+
}
68+
69+
for _, test := range tests {
70+
err := WaitUntilTimeout(test.timeout, test.execFunc, test.timeoutFunc)
71+
if err != nil && (err.Error() != test.expectedErr.Error()) {
72+
t.Errorf("unexpected error: %v, expected error: %v", err, test.expectedErr)
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)