From d00ceca6f02fbef3a00a1bf98679b2c1c27387de Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Thu, 11 Oct 2018 23:37:28 -0700 Subject: [PATCH] btrfs: ensure graphdriver home is bind mount For some reason, shared mount propagation between the host and a container does not work for btrfs, unless container root directory (i.e. graphdriver home) is a bind mount. The above issue was reproduced on SLES 12sp3 + btrfs using the following script: #!/bin/bash set -eux -o pipefail # DIR should not be under a subvolume DIR=${DIR:-/lib} MNT=$DIR/my-mnt FILE=$MNT/file ID=$(docker run -d --privileged -v $DIR:$DIR:rshared ubuntu sleep 24h) docker exec $ID mkdir -p $MNT docker exec $ID mount -t tmpfs tmpfs $MNT docker exec $ID touch $FILE ls -l $FILE umount $MNT docker rm -f $ID which fails this way: + ls -l /lib/my-mnt/file ls: cannot access '/lib/my-mnt/file': No such file or directory meaning the mount performed inside a priviledged container is not propagated back to the host (even if all the mounts have "shared" propagation mode). The remedy to the above is to make graphdriver home a bind mount. Signed-off-by: Kir Kolyshkin (cherry picked from commit 16d822bba8ac5ab22c8697750f700403bca3dbf3) Upstream-commit: fa8ac946165b8004a15e85744e774ed6ba99fd38 Component: engine --- .../engine/daemon/graphdriver/btrfs/btrfs.go | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/components/engine/daemon/graphdriver/btrfs/btrfs.go b/components/engine/daemon/graphdriver/btrfs/btrfs.go index 4c14191d46..7ce7edef36 100644 --- a/components/engine/daemon/graphdriver/btrfs/btrfs.go +++ b/components/engine/daemon/graphdriver/btrfs/btrfs.go @@ -29,10 +29,12 @@ import ( "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/system" "github.com/docker/go-units" "github.com/opencontainers/selinux/go-selinux/label" + "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -81,6 +83,15 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, err } + // For some reason shared mount propagation between a container + // and the host does not work for btrfs, and a remedy is to bind + // mount graphdriver home to itself (even without changing the + // propagation mode). + err = mount.MakeMount(home) + if err != nil { + return nil, errors.Wrapf(err, "failed to make %s a mount", home) + } + driver := &Driver{ home: home, uidMaps: uidMaps, @@ -158,7 +169,19 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) { // Cleanup unmounts the home directory. func (d *Driver) Cleanup() error { - return d.subvolDisableQuota() + err := d.subvolDisableQuota() + umountErr := mount.Unmount(d.home) + + // in case we have two errors, prefer the one from disableQuota() + if err != nil { + return err + } + + if umountErr != nil { + return errors.Wrapf(umountErr, "error unmounting %s", d.home) + } + + return nil } func free(p *C.char) {