Merge pull request #33120 from cpuguy83/backport_lazy-unmount-volume
[17.03.x] Backport lazy unmount volume
This commit is contained in:
commit
4843bdced5
5 changed files with 53 additions and 7 deletions
|
@ -94,8 +94,8 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *check.C) {
|
|||
c.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil {
|
||||
c.Fatal(err)
|
||||
if out, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil {
|
||||
c.Fatal(err, out)
|
||||
}
|
||||
|
||||
if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil {
|
||||
|
|
|
@ -218,6 +218,14 @@ func (r *Root) Remove(v volume.Volume) error {
|
|||
return fmt.Errorf("unknown volume type %T", v)
|
||||
}
|
||||
|
||||
if lv.active.count > 0 {
|
||||
return fmt.Errorf("volume has active mounts")
|
||||
}
|
||||
|
||||
if err := lv.unmount(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
realPath, err := filepath.EvalSymlinks(lv.path)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
|
@ -306,6 +314,7 @@ func (v *localVolume) Path() string {
|
|||
}
|
||||
|
||||
// Mount implements the localVolume interface, returning the data location.
|
||||
// If there are any provided mount options, the resources will be mounted at this point
|
||||
func (v *localVolume) Mount(id string) (string, error) {
|
||||
v.m.Lock()
|
||||
defer v.m.Unlock()
|
||||
|
@ -321,19 +330,35 @@ func (v *localVolume) Mount(id string) (string, error) {
|
|||
return v.path, nil
|
||||
}
|
||||
|
||||
// Umount is for satisfying the localVolume interface and does not do anything in this driver.
|
||||
// Unmount dereferences the id, and if it is the last reference will unmount any resources
|
||||
// that were previously mounted.
|
||||
func (v *localVolume) Unmount(id string) error {
|
||||
v.m.Lock()
|
||||
defer v.m.Unlock()
|
||||
|
||||
// Always decrement the count, even if the unmount fails
|
||||
// Essentially docker doesn't care if this fails, it will send an error, but
|
||||
// ultimately there's nothing that can be done. If we don't decrement the count
|
||||
// this volume can never be removed until a daemon restart occurs.
|
||||
if v.opts != nil {
|
||||
v.active.count--
|
||||
if v.active.count == 0 {
|
||||
if err := mount.Unmount(v.path); err != nil {
|
||||
v.active.count++
|
||||
}
|
||||
|
||||
if v.active.count > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return v.unmount()
|
||||
}
|
||||
|
||||
func (v *localVolume) unmount() error {
|
||||
if v.opts != nil {
|
||||
if err := unmount(v.path); err != nil {
|
||||
if mounted, mErr := mount.Mounted(v.path); mounted || mErr != nil {
|
||||
return errors.Wrapf(err, "error while unmounting volume path '%s'", v.path)
|
||||
}
|
||||
v.active.mounted = false
|
||||
}
|
||||
v.active.mounted = false
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
7
volume/local/unmount_linux.go
Normal file
7
volume/local/unmount_linux.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package local
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
func unmount(path string) error {
|
||||
return unix.Unmount(path, unix.MNT_DETACH)
|
||||
}
|
9
volume/local/unmount_unix.go
Normal file
9
volume/local/unmount_unix.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
// +build !linux,!windows
|
||||
|
||||
package local
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
func unmount(path string) error {
|
||||
return unix.Unmount(path, 0)
|
||||
}
|
5
volume/local/unmount_windows.go
Normal file
5
volume/local/unmount_windows.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package local
|
||||
|
||||
func unmount(_ string) error {
|
||||
return nil
|
||||
}
|
Loading…
Reference in a new issue