Skip to content

Commit 16d822b

Browse files
committed
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 <kolyshkin@gmail.com>
1 parent 8abadb3 commit 16d822b

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

‎daemon/graphdriver/btrfs/btrfs.go‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ import (
2929
"github.com/docker/docker/daemon/graphdriver"
3030
"github.com/docker/docker/pkg/containerfs"
3131
"github.com/docker/docker/pkg/idtools"
32+
"github.com/docker/docker/pkg/mount"
3233
"github.com/docker/docker/pkg/parsers"
3334
"github.com/docker/docker/pkg/system"
3435
"github.com/docker/go-units"
3536
"github.com/opencontainers/selinux/go-selinux/label"
37+
"github.com/pkg/errors"
3638
"github.com/sirupsen/logrus"
3739
"golang.org/x/sys/unix"
3840
)
@@ -81,6 +83,15 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
8183
return nil, err
8284
}
8385

86+
// For some reason shared mount propagation between a container
87+
// and the host does not work for btrfs, and a remedy is to bind
88+
// mount graphdriver home to itself (even without changing the
89+
// propagation mode).
90+
err = mount.MakeMount(home)
91+
if err != nil {
92+
return nil, errors.Wrapf(err, "failed to make %s a mount", home)
93+
}
94+
8495
driver := &Driver{
8596
home: home,
8697
uidMaps: uidMaps,
@@ -158,7 +169,19 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) {
158169

159170
// Cleanup unmounts the home directory.
160171
func (d *Driver) Cleanup() error {
161-
return d.subvolDisableQuota()
172+
err := d.subvolDisableQuota()
173+
umountErr := mount.Unmount(d.home)
174+
175+
// in case we have two errors, prefer the one from disableQuota()
176+
if err != nil {
177+
return err
178+
}
179+
180+
if umountErr != nil {
181+
return errors.Wrapf(umountErr, "error unmounting %s", d.home)
182+
}
183+
184+
return nil
162185
}
163186

164187
func free(p *C.char) {

0 commit comments

Comments
 (0)