|
@@ -296,9 +296,6 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr
|
|
if err := idtools.MkdirAndChown(path.Join(dir, "work"), 0700, root); err != nil {
|
|
if err := idtools.MkdirAndChown(path.Join(dir, "work"), 0700, root); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
- if err := idtools.MkdirAndChown(path.Join(dir, "merged"), 0700, root); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
if err := ioutil.WriteFile(path.Join(dir, "lower-id"), []byte(parent), 0666); err != nil {
|
|
if err := ioutil.WriteFile(path.Join(dir, "lower-id"), []byte(parent), 0666); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
@@ -329,9 +326,6 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr
|
|
if err := idtools.MkdirAndChown(path.Join(dir, "work"), 0700, root); err != nil {
|
|
if err := idtools.MkdirAndChown(path.Join(dir, "work"), 0700, root); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
- if err := idtools.MkdirAndChown(path.Join(dir, "merged"), 0700, root); err != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
|
|
|
|
return copy.DirCopy(parentUpperDir, upperDir, copy.Content)
|
|
return copy.DirCopy(parentUpperDir, upperDir, copy.Content)
|
|
}
|
|
}
|
|
@@ -360,6 +354,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro
|
|
if _, err := os.Stat(rootDir); err == nil {
|
|
if _, err := os.Stat(rootDir); err == nil {
|
|
return containerfs.NewLocalContainerFS(rootDir), nil
|
|
return containerfs.NewLocalContainerFS(rootDir), nil
|
|
}
|
|
}
|
|
|
|
+
|
|
mergedDir := path.Join(dir, "merged")
|
|
mergedDir := path.Join(dir, "merged")
|
|
if count := d.ctr.Increment(mergedDir); count > 1 {
|
|
if count := d.ctr.Increment(mergedDir); count > 1 {
|
|
return containerfs.NewLocalContainerFS(mergedDir), nil
|
|
return containerfs.NewLocalContainerFS(mergedDir), nil
|
|
@@ -367,7 +362,13 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro
|
|
defer func() {
|
|
defer func() {
|
|
if err != nil {
|
|
if err != nil {
|
|
if c := d.ctr.Decrement(mergedDir); c <= 0 {
|
|
if c := d.ctr.Decrement(mergedDir); c <= 0 {
|
|
- unix.Unmount(mergedDir, 0)
|
|
|
|
|
|
+ if mntErr := unix.Unmount(mergedDir, 0); mntErr != nil {
|
|
|
|
+ logrus.Debugf("Failed to unmount %s: %v: %v", id, mntErr, err)
|
|
|
|
+ }
|
|
|
|
+ // Cleanup the created merged directory; see the comment in Put's rmdir
|
|
|
|
+ if rmErr := unix.Rmdir(mergedDir); rmErr != nil && !os.IsNotExist(rmErr) {
|
|
|
|
+ logrus.Warnf("Failed to remove %s: %v: %v", id, rmErr, err)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
}()
|
|
@@ -375,6 +376,13 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
+ rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+ if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.IDPair{rootUID, rootGID}); err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
var (
|
|
var (
|
|
lowerDir = path.Join(d.dir(string(lowerID)), "root")
|
|
lowerDir = path.Join(d.dir(string(lowerID)), "root")
|
|
upperDir = path.Join(dir, "upper")
|
|
upperDir = path.Join(dir, "upper")
|
|
@@ -386,10 +394,6 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro
|
|
}
|
|
}
|
|
// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
|
|
// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
|
|
// user namespace requires this to move a directory from lower to upper.
|
|
// user namespace requires this to move a directory from lower to upper.
|
|
- rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
|
|
|
|
- if err != nil {
|
|
|
|
- return nil, err
|
|
|
|
- }
|
|
|
|
if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
|
|
if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
@@ -397,6 +401,8 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro
|
|
}
|
|
}
|
|
|
|
|
|
// Put unmounts the mount path created for the give id.
|
|
// Put unmounts the mount path created for the give id.
|
|
|
|
+// It also removes the 'merged' directory to force the kernel to unmount the
|
|
|
|
+// overlay mount in other namespaces.
|
|
func (d *Driver) Put(id string) error {
|
|
func (d *Driver) Put(id string) error {
|
|
d.locker.Lock(id)
|
|
d.locker.Lock(id)
|
|
defer d.locker.Unlock(id)
|
|
defer d.locker.Unlock(id)
|
|
@@ -411,6 +417,17 @@ func (d *Driver) Put(id string) error {
|
|
if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil {
|
|
if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil {
|
|
logrus.Debugf("Failed to unmount %s overlay: %v", id, err)
|
|
logrus.Debugf("Failed to unmount %s overlay: %v", id, err)
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Remove the mountpoint here. Removing the mountpoint (in newer kernels)
|
|
|
|
+ // will cause all other instances of this mount in other mount namespaces
|
|
|
|
+ // to be unmounted. This is necessary to avoid cases where an overlay mount
|
|
|
|
+ // that is present in another namespace will cause subsequent mounts
|
|
|
|
+ // operations to fail with ebusy. We ignore any errors here because this may
|
|
|
|
+ // fail on older kernels which don't have
|
|
|
|
+ // torvalds/linux@8ed936b5671bfb33d89bc60bdcc7cf0470ba52fe applied.
|
|
|
|
+ if err := unix.Rmdir(mountpoint); err != nil {
|
|
|
|
+ logrus.Debugf("Failed to remove %s overlay: %v", id, err)
|
|
|
|
+ }
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|