From 70c4d5d4786a6113904858bf452f0af7906eb9f6 Mon Sep 17 00:00:00 2001 From: Alex Suraci Date: Fri, 27 Nov 2020 16:30:44 -0500 Subject: [PATCH] fix nesting volumes even more deeply the previous fix actually only made it work slightly more deeply; this should fix it all the way. the problem was that the grandparent was found using its logical parent, rather than the 'actual' parent, which must be found by recursively walking through the hierarchy all the way to the bottom. * test up to depth 10 * assert that file updates and deletions are preserved at each depth, just to be sure Signed-off-by: Alex Suraci --- volume/driver/overlay_linux.go | 16 +++++- volume/driver/overlay_linux_test.go | 79 ++++++++++++++--------------- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/volume/driver/overlay_linux.go b/volume/driver/overlay_linux.go index 1c19fa0..df52bd6 100644 --- a/volume/driver/overlay_linux.go +++ b/volume/driver/overlay_linux.go @@ -69,8 +69,8 @@ func (driver *OverlayDriver) CreateCopyOnWriteLayer( return err } - childDir := driver.layerDir(child) if hasGrandparent { + childDir := driver.layerDir(child) parentDir := driver.layerDir(parent) err := copy.Cp(false, parentDir, childDir) if err != nil { @@ -78,6 +78,20 @@ func (driver *OverlayDriver) CreateCopyOnWriteLayer( } parent = grandparent + + // resolve to root volume + for { + grandparent, hasGrandparent, err := parent.Parent() + if err != nil { + return err + } + + if !hasGrandparent { + break + } + + parent = grandparent + } } return driver.overlayMount(child, parent) diff --git a/volume/driver/overlay_linux_test.go b/volume/driver/overlay_linux_test.go index db9e79c..750b09c 100644 --- a/volume/driver/overlay_linux_test.go +++ b/volume/driver/overlay_linux_test.go @@ -1,6 +1,7 @@ package driver_test import ( + "fmt" "io/ioutil" "os" "path/filepath" @@ -39,13 +40,15 @@ var _ = Describe("Overlay", func() { Expect(err).ToNot(HaveOccurred()) // write to file under rootVolData - rootFile := filepath.Join(rootVolInit.DataPath(), "rootFile") - err = ioutil.WriteFile(rootFile, []byte("root"), 0644) + rootFile := filepath.Join(rootVolInit.DataPath(), "updated-file") + err = ioutil.WriteFile(rootFile, []byte("depth-0"), 0644) Expect(err).ToNot(HaveOccurred()) - doomedFile := filepath.Join(rootVolInit.DataPath(), "doomedFile") - err = ioutil.WriteFile(doomedFile, []byte("im doomed"), 0644) - Expect(err).ToNot(HaveOccurred()) + for depth := 1; depth <= 10; depth++ { + doomedFile := filepath.Join(rootVolInit.DataPath(), fmt.Sprintf("doomed-file-%d", depth)) + err := ioutil.WriteFile(doomedFile, []byte(fmt.Sprintf("i will be removed at depth %d", depth)), 0644) + Expect(err).ToNot(HaveOccurred()) + } rootVolLive, err := rootVolInit.Initialize() Expect(err).ToNot(HaveOccurred()) @@ -55,53 +58,47 @@ var _ = Describe("Overlay", func() { Expect(err).ToNot(HaveOccurred()) }() - childVolInit, err := rootVolLive.NewSubvolume("child-vol") - Expect(err).ToNot(HaveOccurred()) - - // write to file under rootVolData - chileFilePath := filepath.Join(childVolInit.DataPath(), "rootFile") - err = ioutil.WriteFile(chileFilePath, []byte("child"), 0644) - Expect(err).ToNot(HaveOccurred()) - - err = os.Remove(filepath.Join(childVolInit.DataPath(), "doomedFile")) - Expect(err).ToNot(HaveOccurred()) + nest := rootVolLive + for depth := 1; depth <= 10; depth++ { + By(fmt.Sprintf("creating a child nested %d levels deep", depth)) - childVolLive, err := childVolInit.Initialize() - Expect(err).ToNot(HaveOccurred()) + childInit, err := nest.NewSubvolume(fmt.Sprintf("child-vol-%d", depth)) + Expect(err).ToNot(HaveOccurred()) - defer func() { - err := childVolLive.Destroy() + childLive, err := childInit.Initialize() Expect(err).ToNot(HaveOccurred()) - }() - childVol2Init, err := childVolLive.NewSubvolume("child-vol-2") - Expect(err).ToNot(HaveOccurred()) + defer func() { + err := childLive.Destroy() + Expect(err).ToNot(HaveOccurred()) + }() - childVol2Live, err := childVol2Init.Initialize() - Expect(err).ToNot(HaveOccurred()) + for i := 1; i <= 10; i++ { + doomedFilePath := filepath.Join(childLive.DataPath(), fmt.Sprintf("doomed-file-%d", i)) - defer func() { - err := childVol2Live.Destroy() - Expect(err).ToNot(HaveOccurred()) - }() + _, statErr := os.Stat(doomedFilePath) + if i < depth { + Expect(statErr).To(HaveOccurred()) + } else { + Expect(statErr).ToNot(HaveOccurred()) - childVol3Init, err := childVol2Live.NewSubvolume("child-vol-3") - Expect(err).ToNot(HaveOccurred()) + if i == depth { + err := os.Remove(doomedFilePath) + Expect(err).ToNot(HaveOccurred()) + } + } + } - childVol3Live, err := childVol3Init.Initialize() - Expect(err).ToNot(HaveOccurred()) + updateFilePath := filepath.Join(childLive.DataPath(), "updated-file") - defer func() { - err := childVol3Live.Destroy() - Expect(err).ToNot(HaveOccurred()) - }() + content, err := ioutil.ReadFile(updateFilePath) + Expect(string(content)).To(Equal(fmt.Sprintf("depth-%d", depth-1))) - child3FilePath := filepath.Join(childVol3Live.DataPath(), "rootFile") - content, err := ioutil.ReadFile(child3FilePath) - Expect(string(content)).To(Equal("child")) + err = ioutil.WriteFile(updateFilePath, []byte(fmt.Sprintf("depth-%d", depth)), 0644) + Expect(err).ToNot(HaveOccurred()) - _, err = os.Stat(filepath.Join(childVol3Live.DataPath(), "doomedFile")) - Expect(err).To(HaveOccurred()) + nest = childLive + } }) }) })