From 732dd9b848bec70a2ecb5b4998918886a0cec497 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Tue, 27 Feb 2018 19:02:05 -0800 Subject: [PATCH] devmapper/Remove(): use Rmdir, ignore errors 1. Replace EnsureRemoveAll() with Rmdir(), as here we are removing the container's mount point, which is already properly unmounted and is therefore an empty directory. 2. Ignore the Rmdir() error (but log it unless it's ENOENT). This is a mount point, currently unmounted (i.e. an empty directory), and an older kernel can return EBUSY if e.g. the mount was leaked to other mount namespaces. Signed-off-by: Kir Kolyshkin --- daemon/graphdriver/devmapper/driver.go | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/daemon/graphdriver/devmapper/driver.go b/daemon/graphdriver/devmapper/driver.go index 53e05c3b78..e27f3c85cc 100644 --- a/daemon/graphdriver/devmapper/driver.go +++ b/daemon/graphdriver/devmapper/driver.go @@ -9,16 +9,15 @@ import ( "path" "strconv" - "github.com/sirupsen/logrus" - "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/devicemapper" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/locker" "github.com/docker/docker/pkg/mount" - "github.com/docker/docker/pkg/system" units "github.com/docker/go-units" + "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" ) func init() { @@ -145,7 +144,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error { return d.DeviceSet.AddDevice(id, parent, storageOpt) } -// Remove removes a device with a given id, unmounts the filesystem. +// Remove removes a device with a given id, unmounts the filesystem, and removes the mount point. func (d *Driver) Remove(id string) error { d.locker.Lock(id) defer d.locker.Unlock(id) @@ -160,7 +159,21 @@ func (d *Driver) Remove(id string) error { if err := d.DeviceSet.DeleteDevice(id, false); err != nil { return fmt.Errorf("failed to remove device %s: %v", id, err) } - return system.EnsureRemoveAll(path.Join(d.home, "mnt", id)) + + // Most probably the mount point is already removed on Put() + // (see DeviceSet.UnmountDevice()), but just in case it was not + // let's try to remove it here as well, ignoring errors as + // an older kernel can return EBUSY if e.g. the mount was leaked + // to other mount namespaces. A failure to remove the container's + // mount point is not important and should not be treated + // as a failure to remove the container. + mp := path.Join(d.home, "mnt", id) + err := unix.Rmdir(mp) + if err != nil && !os.IsNotExist(err) { + logrus.WithField("storage-driver", "devicemapper").Warnf("unable to remove mount point %q: %s", mp, err) + } + + return nil } // Get mounts a device with given id into the root filesystem