Skip to content

Commit 43f1c17

Browse files
committed
fix: wait for blobfuse mount
1 parent c5d036f commit 43f1c17

File tree

3 files changed

+91
-11
lines changed

3 files changed

+91
-11
lines changed

pkg/blob/nodeserver.go

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ import (
4646
mount_azure_blob "sigs.k8s.io/blob-csi-driver/pkg/blobfuse-proxy/pb"
4747
)
4848

49+
const (
50+
waitForMountInterval = 20 * time.Millisecond
51+
waitForMountTimeout = 3 * time.Second
52+
)
53+
4954
type MountClient struct {
5055
service mount_azure_blob.MountServiceClient
5156
}
@@ -181,11 +186,7 @@ func (d *Driver) mountBlobfuseInsideDriver(args string, protocol string, authEnv
181186
cmd.Env = append(os.Environ(), authEnv...)
182187
output, err := cmd.CombinedOutput()
183188
klog.V(2).Infof("mount output: %s\n", string(output))
184-
if err == nil && protocol == Fuse2 {
185-
// todo: remove this when https://github.com/Azure/azure-storage-fuse/issues/1079 is fixed
186-
klog.V(2).Infof("sleep 2s, waiting for blobfuse2 mount complete")
187-
time.Sleep(2 * time.Second)
188-
}
189+
189190
return string(output), err
190191
}
191192

@@ -406,6 +407,12 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
406407
return nil, err
407408
}
408409

410+
// wait a few seconds to make sure blobfuse mount is successful
411+
// please refer to https://github.com/Azure/azure-storage-fuse/pull/1088 for more details
412+
if err := waitForMount(targetPath, waitForMountInterval, waitForMountTimeout); err != nil {
413+
return nil, fmt.Errorf("failed to wait for mount: %w", err)
414+
}
415+
409416
klog.V(2).Infof("volume(%s) mount on %q succeeded", volumeID, targetPath)
410417
return &csi.NodeStageVolumeResponse{}, nil
411418
}
@@ -575,3 +582,24 @@ func (d *Driver) ensureMountPoint(target string, perm os.FileMode) (bool, error)
575582
}
576583
return !notMnt, nil
577584
}
585+
586+
func waitForMount(path string, intervel, timeout time.Duration) error {
587+
timeAfter := time.After(timeout)
588+
timeTick := time.Tick(intervel)
589+
590+
for {
591+
select {
592+
case <-timeTick:
593+
notMount, err := mount.New("").IsLikelyNotMountPoint(path)
594+
if err != nil {
595+
return err
596+
}
597+
if !notMount {
598+
klog.V(2).Infof("blobfuse mount at %s success", path)
599+
return nil
600+
}
601+
case <-timeAfter:
602+
return fmt.Errorf("timeout waiting for mount %s", path)
603+
}
604+
}
605+
}

pkg/blob/nodeserver_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ import (
2424
"path/filepath"
2525
"reflect"
2626
"runtime"
27+
"strings"
2728
"syscall"
2829
"testing"
30+
"time"
2931

3032
"google.golang.org/grpc"
3133
"google.golang.org/grpc/codes"
@@ -754,3 +756,59 @@ func TestMountBlobfuseInsideDriver(t *testing.T) {
754756
// the error should be of type exec.ExitError
755757
assert.NotNil(t, err)
756758
}
759+
760+
func Test_waitForMount(t *testing.T) {
761+
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
762+
t.Skip("Skipping test on ", runtime.GOOS)
763+
}
764+
765+
tmpDir, err := os.MkdirTemp("", "")
766+
assert.NoError(t, err)
767+
defer os.RemoveAll(tmpDir)
768+
769+
type args struct {
770+
path string
771+
intervel time.Duration
772+
timeout time.Duration
773+
}
774+
775+
tests := []struct {
776+
name string
777+
args args
778+
wantErr bool
779+
subErrMsg string
780+
}{
781+
{
782+
name: "test error timeout",
783+
args: args{
784+
path: tmpDir,
785+
intervel: 1 * time.Millisecond,
786+
timeout: 10 * time.Millisecond,
787+
},
788+
wantErr: true,
789+
subErrMsg: "timeout",
790+
},
791+
{
792+
name: "test error no such file or directory",
793+
args: args{
794+
path: "/no/such/file/or/directory",
795+
intervel: 1 * time.Millisecond,
796+
timeout: 10 * time.Millisecond,
797+
},
798+
wantErr: true,
799+
subErrMsg: "no such file or directory",
800+
},
801+
}
802+
803+
for _, tt := range tests {
804+
t.Run(tt.name, func(t *testing.T) {
805+
err := waitForMount(tt.args.path, tt.args.intervel, tt.args.timeout)
806+
if (err != nil) != tt.wantErr {
807+
t.Errorf("waitForMount() error = %v, wantErr %v", err, tt.wantErr)
808+
}
809+
if err != nil && !strings.Contains(err.Error(), tt.subErrMsg) {
810+
t.Errorf("waitForMount() error = %v, wantErr %v", err, tt.subErrMsg)
811+
}
812+
})
813+
}
814+
}

pkg/blobfuse-proxy/server/server.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"os/exec"
2424
"strings"
2525
"sync"
26-
"time"
2726

2827
"google.golang.org/grpc"
2928
"k8s.io/klog/v2"
@@ -96,11 +95,6 @@ func (server *MountServer) MountAzureBlob(ctx context.Context,
9695
if err != nil {
9796
return &result, fmt.Errorf("%w %s", err, result.Output)
9897
}
99-
if protocol == blob.Fuse2 || server.blobfuseVersion == BlobfuseV2 {
100-
// todo: remove this when https://github.com/Azure/azure-storage-fuse/issues/1079 is fixed
101-
klog.V(2).Infof("sleep 2s, waiting for blobfuse2 mount complete\n")
102-
time.Sleep(2 * time.Second)
103-
}
10498
return &result, nil
10599
}
106100

0 commit comments

Comments
 (0)