@@ -1341,6 +1341,82 @@ var _ = Describe("GCE PD CSI Driver", func() {
13411341
13421342 Expect (err ).To (BeNil (), "no error expected when passed valid compute url" )
13431343 })
1344+
1345+ It ("Should block unstage if filesystem mounted" , func () {
1346+ testContext := getRandomTestContext ()
1347+
1348+ p , z , _ := testContext .Instance .GetIdentity ()
1349+ client := testContext .Client
1350+ instance := testContext .Instance
1351+
1352+ // Create Disk
1353+ volName , volID := createAndValidateUniqueZonalDisk (client , p , z , standardDiskType )
1354+
1355+ defer func () {
1356+ // Delete Disk
1357+ err := client .DeleteVolume (volID )
1358+ Expect (err ).To (BeNil (), "DeleteVolume failed" )
1359+
1360+ // Validate Disk Deleted
1361+ _ , err = computeService .Disks .Get (p , z , volName ).Do ()
1362+ Expect (gce .IsGCEError (err , "notFound" )).To (BeTrue (), "Expected disk to not be found" )
1363+ }()
1364+
1365+ // Attach Disk
1366+ err := client .ControllerPublishVolume (volID , instance .GetNodeID (), false /* forceAttach */ )
1367+ Expect (err ).To (BeNil (), "ControllerPublishVolume failed with error for disk %v on node %v: %v" , volID , instance .GetNodeID (), err )
1368+
1369+ defer func () {
1370+ // Detach Disk
1371+ err = client .ControllerUnpublishVolume (volID , instance .GetNodeID ())
1372+ if err != nil {
1373+ klog .Errorf ("Failed to detach disk: %v" , err )
1374+ }
1375+ }()
1376+
1377+ // Stage Disk
1378+ stageDir := filepath .Join ("/tmp/" , volName , "stage" )
1379+ err = client .NodeStageExt4Volume (volID , stageDir )
1380+ Expect (err ).To (BeNil (), "failed to stage volume: %v" , err )
1381+
1382+ // Create private bind mount
1383+ boundMountStageDir := filepath .Join ("/tmp/bindmount" , volName , "bindmount" )
1384+ boundMountStageMkdirOutput , err := instance .SSH ("mkdir" , "-p" , boundMountStageDir )
1385+ Expect (err ).To (BeNil (), "mkdir failed on instance %v: output: %v: %v" , instance .GetNodeID (), boundMountStageMkdirOutput , err )
1386+ bindMountOutput , err := instance .SSH ("mount" , "--rbind" , "--make-private" , stageDir , boundMountStageDir )
1387+ Expect (err ).To (BeNil (), "Bind mount failed on instance %v: output: %v: %v" , instance .GetNodeID (), bindMountOutput , err )
1388+
1389+ privateBindMountRemoved := false
1390+ unmountAndRmPrivateBindMount := func () {
1391+ if ! privateBindMountRemoved {
1392+ // Umount and delete private mount staging directory
1393+ bindUmountOutput , err := instance .SSH ("umount" , boundMountStageDir )
1394+ Expect (err ).To (BeNil (), "Bind mount failed on instance %v: output: %v: %v" , instance .GetNodeID (), bindUmountOutput , err )
1395+ err = testutils .RmAll (instance , boundMountStageDir )
1396+ Expect (err ).To (BeNil (), "Failed to rm mount stage dir %s: %v" , boundMountStageDir , err )
1397+ }
1398+ privateBindMountRemoved = true
1399+ }
1400+
1401+ defer func () {
1402+ unmountAndRmPrivateBindMount ()
1403+ }()
1404+
1405+ // Unstage Disk
1406+ err = client .NodeUnstageVolume (volID , stageDir )
1407+ Expect (err ).ToNot (BeNil (), "Expected failure during unstage" )
1408+ Expect (err ).To (MatchError (ContainSubstring (("is still in use" ))))
1409+
1410+ // Unmount private bind mount and try again
1411+ unmountAndRmPrivateBindMount ()
1412+
1413+ // Unstage Disk
1414+ err = client .NodeUnstageVolume (volID , stageDir )
1415+ Expect (err ).To (BeNil (), "Failed to unstage volume: %v" , err )
1416+ fp := filepath .Join ("/tmp/" , volName )
1417+ err = testutils .RmAll (instance , fp )
1418+ Expect (err ).To (BeNil (), "Failed to rm file path %s: %v" , fp , err )
1419+ })
13441420})
13451421
13461422func equalWithinEpsilon (a , b , epsiolon int64 ) bool {
0 commit comments