|
@@ -446,6 +446,10 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if err := ioutil.WriteFile(path.Join(d.dir(parent), "committed"), []byte{}, 0600); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+
|
|
lower, err := d.getLower(parent)
|
|
lower, err := d.getLower(parent)
|
|
if err != nil {
|
|
if err != nil {
|
|
return err
|
|
return err
|
|
@@ -592,7 +596,20 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
|
|
for i, s := range splitLowers {
|
|
for i, s := range splitLowers {
|
|
absLowers[i] = path.Join(d.home, s)
|
|
absLowers[i] = path.Join(d.home, s)
|
|
}
|
|
}
|
|
- opts := indexOff + "lowerdir=" + strings.Join(absLowers, ":") + ",upperdir=" + diffDir + ",workdir=" + workDir
|
|
|
|
|
|
+ var readonly bool
|
|
|
|
+ if _, err := os.Stat(path.Join(dir, "committed")); err == nil {
|
|
|
|
+ readonly = true
|
|
|
|
+ } else if !os.IsNotExist(err) {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var opts string
|
|
|
|
+ if readonly {
|
|
|
|
+ opts = indexOff + "lowerdir=" + diffDir + ":" + strings.Join(absLowers, ":")
|
|
|
|
+ } else {
|
|
|
|
+ opts = indexOff + "lowerdir=" + strings.Join(absLowers, ":") + ",upperdir=" + diffDir + ",workdir=" + workDir
|
|
|
|
+ }
|
|
|
|
+
|
|
mountData := label.FormatMountLabel(opts, mountLabel)
|
|
mountData := label.FormatMountLabel(opts, mountLabel)
|
|
mount := unix.Mount
|
|
mount := unix.Mount
|
|
mountTarget := mergedDir
|
|
mountTarget := mergedDir
|
|
@@ -612,7 +629,11 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
|
|
// fit within a page and relative links make the mount data much
|
|
// fit within a page and relative links make the mount data much
|
|
// smaller at the expense of requiring a fork exec to chroot.
|
|
// smaller at the expense of requiring a fork exec to chroot.
|
|
if len(mountData) > pageSize {
|
|
if len(mountData) > pageSize {
|
|
- opts = indexOff + "lowerdir=" + string(lowers) + ",upperdir=" + path.Join(id, diffDirName) + ",workdir=" + path.Join(id, workDirName)
|
|
|
|
|
|
+ if readonly {
|
|
|
|
+ opts = indexOff + "lowerdir=" + path.Join(id, diffDirName) + ":" + string(lowers)
|
|
|
|
+ } else {
|
|
|
|
+ opts = indexOff + "lowerdir=" + string(lowers) + ",upperdir=" + path.Join(id, diffDirName) + ",workdir=" + path.Join(id, workDirName)
|
|
|
|
+ }
|
|
mountData = label.FormatMountLabel(opts, mountLabel)
|
|
mountData = label.FormatMountLabel(opts, mountLabel)
|
|
if len(mountData) > pageSize {
|
|
if len(mountData) > pageSize {
|
|
return nil, fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
|
|
return nil, fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
|
|
@@ -628,10 +649,12 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
|
|
return nil, fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
|
|
return nil, fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
|
|
}
|
|
}
|
|
|
|
|
|
- // 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.
|
|
|
|
- if err := os.Chown(path.Join(workDir, workDirName), rootUID, rootGID); err != nil {
|
|
|
|
- return nil, err
|
|
|
|
|
|
+ if !readonly {
|
|
|
|
+ // 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.
|
|
|
|
+ if err := os.Chown(path.Join(workDir, workDirName), rootUID, rootGID); err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
return containerfs.NewLocalContainerFS(mergedDir), nil
|
|
return containerfs.NewLocalContainerFS(mergedDir), nil
|