|
@@ -4,94 +4,28 @@
|
|
|
package overlay2 // import "github.com/docker/docker/daemon/graphdriver/overlay2"
|
|
|
|
|
|
import (
|
|
|
- "bytes"
|
|
|
- "encoding/json"
|
|
|
- "flag"
|
|
|
- "fmt"
|
|
|
- "os"
|
|
|
"runtime"
|
|
|
|
|
|
- "github.com/docker/docker/pkg/reexec"
|
|
|
"golang.org/x/sys/unix"
|
|
|
)
|
|
|
|
|
|
-func init() {
|
|
|
- reexec.Register("docker-mountfrom", mountFromMain)
|
|
|
-}
|
|
|
-
|
|
|
-func fatal(err error) {
|
|
|
- fmt.Fprint(os.Stderr, err)
|
|
|
- os.Exit(1)
|
|
|
-}
|
|
|
-
|
|
|
-type mountOptions struct {
|
|
|
- Device string
|
|
|
- Target string
|
|
|
- Type string
|
|
|
- Label string
|
|
|
- Flag uint32
|
|
|
-}
|
|
|
-
|
|
|
func mountFrom(dir, device, target, mType string, flags uintptr, label string) error {
|
|
|
- options := &mountOptions{
|
|
|
- Device: device,
|
|
|
- Target: target,
|
|
|
- Type: mType,
|
|
|
- Flag: uint32(flags),
|
|
|
- Label: label,
|
|
|
- }
|
|
|
-
|
|
|
- cmd := reexec.Command("docker-mountfrom", dir)
|
|
|
- w, err := cmd.StdinPipe()
|
|
|
- if err != nil {
|
|
|
- return fmt.Errorf("mountfrom error on pipe creation: %v", err)
|
|
|
- }
|
|
|
-
|
|
|
- output := bytes.NewBuffer(nil)
|
|
|
- cmd.Stdout = output
|
|
|
- cmd.Stderr = output
|
|
|
-
|
|
|
- // reexec.Command() sets cmd.SysProcAttr.Pdeathsig on Linux, which
|
|
|
- // causes the started process to be signaled when the creating OS thread
|
|
|
- // dies. Ensure that the reexec is not prematurely signaled. See
|
|
|
- // https://go.dev/issue/27505 for more information.
|
|
|
- runtime.LockOSThread()
|
|
|
- defer runtime.UnlockOSThread()
|
|
|
- if err := cmd.Start(); err != nil {
|
|
|
- w.Close()
|
|
|
- return fmt.Errorf("mountfrom error on re-exec cmd: %v", err)
|
|
|
- }
|
|
|
- // write the options to the pipe for the untar exec to read
|
|
|
- if err := json.NewEncoder(w).Encode(options); err != nil {
|
|
|
- w.Close()
|
|
|
- return fmt.Errorf("mountfrom json encode to pipe failed: %v", err)
|
|
|
- }
|
|
|
- w.Close()
|
|
|
-
|
|
|
- if err := cmd.Wait(); err != nil {
|
|
|
- return fmt.Errorf("mountfrom re-exec error: %v: output: %v", err, output)
|
|
|
- }
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-// mountfromMain is the entry-point for docker-mountfrom on re-exec.
|
|
|
-func mountFromMain() {
|
|
|
- runtime.LockOSThread()
|
|
|
- flag.Parse()
|
|
|
-
|
|
|
- var options *mountOptions
|
|
|
-
|
|
|
- if err := json.NewDecoder(os.Stdin).Decode(&options); err != nil {
|
|
|
- fatal(err)
|
|
|
- }
|
|
|
-
|
|
|
- if err := os.Chdir(flag.Arg(0)); err != nil {
|
|
|
- fatal(err)
|
|
|
- }
|
|
|
-
|
|
|
- if err := unix.Mount(options.Device, options.Target, options.Type, uintptr(options.Flag), options.Label); err != nil {
|
|
|
- fatal(err)
|
|
|
- }
|
|
|
-
|
|
|
- os.Exit(0)
|
|
|
+ chErr := make(chan error, 1)
|
|
|
+
|
|
|
+ go func() {
|
|
|
+ runtime.LockOSThread()
|
|
|
+ // Do not unlock this thread as the thread state cannot be restored
|
|
|
+ // We do not want go to re-use this thread for anything else.
|
|
|
+
|
|
|
+ if err := unix.Unshare(unix.CLONE_FS); err != nil {
|
|
|
+ chErr <- err
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if err := unix.Chdir(dir); err != nil {
|
|
|
+ chErr <- err
|
|
|
+ return
|
|
|
+ }
|
|
|
+ chErr <- unix.Mount(device, target, mType, flags, label)
|
|
|
+ }()
|
|
|
+ return <-chErr
|
|
|
}
|