Browse Source

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 <kolyshkin@gmail.com>
Kir Kolyshkin 7 năm trước cách đây
mục cha
commit
732dd9b848
1 tập tin đã thay đổi với 18 bổ sung5 xóa
  1. 18 5
      daemon/graphdriver/devmapper/driver.go

+ 18 - 5
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