From 0d87959d8c54875bbedbef81c11c0ded858c1b5e Mon Sep 17 00:00:00 2001 From: David Michael Date: Thu, 21 Sep 2017 14:07:16 -0700 Subject: [PATCH] app-emulation/rkt: Backport overlay mount patch https://github.com/rkt/rkt/issues/3805 --- ...t-1.28.1-avoid-double-overlay-mounts.patch | 109 ++++++++++++++++++ ...rkt-1.28.1.ebuild => rkt-1.28.1-r1.ebuild} | 0 .../app-emulation/rkt/rkt-9999.ebuild | 2 + 3 files changed, 111 insertions(+) create mode 100644 sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/files/rkt-1.28.1-avoid-double-overlay-mounts.patch rename sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/{rkt-1.28.1.ebuild => rkt-1.28.1-r1.ebuild} (100%) diff --git a/sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/files/rkt-1.28.1-avoid-double-overlay-mounts.patch b/sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/files/rkt-1.28.1-avoid-double-overlay-mounts.patch new file mode 100644 index 0000000000..736b49738b --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/files/rkt-1.28.1-avoid-double-overlay-mounts.patch @@ -0,0 +1,109 @@ +From a778cd1b33d191e83178879cd23732f1c106a0ef Mon Sep 17 00:00:00 2001 +From: Luca Bruno +Date: Wed, 20 Sep 2017 10:10:37 +0000 +Subject: [PATCH] stage0/gc: try to avoid double overlay mounts + +Before Linux 4.13, it used to be possible to perform double overlayfs +mounts in place. This now fails at mount() with EBUSY. +We were abusing this feature to unconditionally ensure that the stage1 +image overlay mount was present before calling gc entrypoint. +This improves stage0 logic to perform the stage1 image overlay mount +only if it doesn't already exist. +--- + rkt/gc.go | 50 ++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 36 insertions(+), 14 deletions(-) + +diff --git a/rkt/gc.go b/rkt/gc.go +index 5e025bb96..1ecdd8faf 100644 +--- a/rkt/gc.go ++++ b/rkt/gc.go +@@ -26,6 +26,7 @@ import ( + + "github.com/hashicorp/errwrap" + "github.com/rkt/rkt/common" ++ "github.com/rkt/rkt/pkg/mountinfo" + pkgPod "github.com/rkt/rkt/pkg/pod" + "github.com/rkt/rkt/stage0" + "github.com/rkt/rkt/store/imagestore" +@@ -197,29 +198,51 @@ func emptyGarbage() error { + return nil + } + +-func mountPodStage1(ts *treestore.Store, p *pkgPod.Pod) error { ++// mountPodStage1 tries to remount stage1 image overlay in case ++// it is not anymore available in place (e.g. a reboot happened ++// in-between). If an overlay mount is already there, we assume ++// stage1 image is properly in place and we don't perform any ++// further actions. A boolean is returned to signal whether a ++// a new mount was performed. ++func mountPodStage1(ts *treestore.Store, p *pkgPod.Pod) (bool, error) { + if !p.UsesOverlay() { +- return nil ++ return false, nil + } + + s1Id, err := p.GetStage1TreeStoreID() + if err != nil { +- return errwrap.Wrap(errors.New("error getting stage1 treeStoreID"), err) ++ return false, errwrap.Wrap(errors.New("error getting stage1 treeStoreID"), err) + } + s1rootfs := ts.GetRootFS(s1Id) +- + stage1Dir := common.Stage1RootfsPath(p.Path()) ++ ++ if mounts, err := mountinfo.ParseMounts(0); err == nil { ++ for _, m := range mounts { ++ if m.MountPoint == stage1Dir { ++ // stage1 image overlay already in place ++ return false, nil ++ } ++ } ++ } ++ + overlayDir := filepath.Join(p.Path(), "overlay") + imgDir := filepath.Join(overlayDir, s1Id) + upperDir := filepath.Join(imgDir, "upper") + workDir := filepath.Join(imgDir, "work") + + opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", s1rootfs, upperDir, workDir) +- if err := syscall.Mount("overlay", stage1Dir, "overlay", 0, opts); err != nil { +- return errwrap.Wrap(errors.New("error mounting stage1"), err) ++ err = syscall.Mount("overlay", stage1Dir, "overlay", 0, opts) ++ if err != nil { ++ // -EBUSY means the overlay mount is already present. ++ // This behavior was introduced in Linux 4.13, double-mounts were allowed ++ // in older kernels. ++ if err == syscall.EBUSY { ++ stderr.Println("mount detected on stage1 target, skipping overlay mount") ++ return false, nil ++ } ++ return false, errwrap.Wrap(errors.New("error mounting stage1"), err) + } +- +- return nil ++ return true, nil + } + + // deletePod cleans up files and resource associated with the pod +@@ -250,16 +273,15 @@ func deletePod(p *pkgPod.Pod) bool { + stage0.InitDebug() + } + +- if err := mountPodStage1(ts, p); err == nil { ++ if newMount, err := mountPodStage1(ts, p); err == nil { + if err = stage0.GC(p.Path(), p.UUID, globalFlags.LocalConfigDir); err != nil { + stderr.PrintE(fmt.Sprintf("problem performing stage1 GC on %q", p.UUID), err) + } +- // an overlay fs can be mounted over itself, let's unmount it here +- // if we mounted it before to avoid problems when running +- // stage0.MountGC +- if p.UsesOverlay() { ++ // Linux <4.13 allows an overlay fs to be mounted over itself, so let's ++ // unmount it here to avoid problems when running stage0.MountGC ++ if p.UsesOverlay() && newMount { + stage1Mnt := common.Stage1RootfsPath(p.Path()) +- if err := syscall.Unmount(stage1Mnt, 0); err != nil { ++ if err := syscall.Unmount(stage1Mnt, 0); err != nil && err != syscall.EBUSY { + stderr.PrintE("error unmounting stage1", err) + } + } diff --git a/sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/rkt-1.28.1.ebuild b/sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/rkt-1.28.1-r1.ebuild similarity index 100% rename from sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/rkt-1.28.1.ebuild rename to sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/rkt-1.28.1-r1.ebuild diff --git a/sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/rkt-9999.ebuild b/sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/rkt-9999.ebuild index 138b9731e4..2866396416 100644 --- a/sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/rkt-9999.ebuild +++ b/sdk_container/src/third_party/coreos-overlay/app-emulation/rkt/rkt-9999.ebuild @@ -76,6 +76,8 @@ function add_stage1() { } src_prepare() { + epatch "${FILESDIR}/${PN}-1.28.1-avoid-double-overlay-mounts.patch" + # ensure we use a CoreOS PXE image version that matches rkt's expectations. local rkt_coreos_version