gopkg.in/dotcloud/docker.v1@v1.13.1/daemon/graphdriver/overlay2/check.go (about) 1 // +build linux 2 3 package overlay2 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path" 10 "path/filepath" 11 "syscall" 12 13 "github.com/Sirupsen/logrus" 14 "github.com/docker/docker/pkg/system" 15 "github.com/pkg/errors" 16 ) 17 18 // hasOpaqueCopyUpBug checks whether the filesystem has a bug 19 // which copies up the opaque flag when copying up an opaque 20 // directory. When this bug exists naive diff should be used. 21 func hasOpaqueCopyUpBug(d string) error { 22 td, err := ioutil.TempDir(d, "opaque-bug-check") 23 if err != nil { 24 return err 25 } 26 defer func() { 27 if err := os.RemoveAll(td); err != nil { 28 logrus.Warnf("Failed to remove check directory %v: %v", td, err) 29 } 30 }() 31 32 // Make directories l1/d, l2/d, l3, work, merged 33 if err := os.MkdirAll(filepath.Join(td, "l1", "d"), 0755); err != nil { 34 return err 35 } 36 if err := os.MkdirAll(filepath.Join(td, "l2", "d"), 0755); err != nil { 37 return err 38 } 39 if err := os.Mkdir(filepath.Join(td, "l3"), 0755); err != nil { 40 return err 41 } 42 if err := os.Mkdir(filepath.Join(td, "work"), 0755); err != nil { 43 return err 44 } 45 if err := os.Mkdir(filepath.Join(td, "merged"), 0755); err != nil { 46 return err 47 } 48 49 // Mark l2/d as opaque 50 if err := system.Lsetxattr(filepath.Join(td, "l2", "d"), "trusted.overlay.opaque", []byte("y"), 0); err != nil { 51 return errors.Wrap(err, "failed to set opaque flag on middle layer") 52 } 53 54 opts := fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", path.Join(td, "l2"), path.Join(td, "l1"), path.Join(td, "l3"), path.Join(td, "work")) 55 if err := syscall.Mount("overlay", filepath.Join(td, "merged"), "overlay", 0, opts); err != nil { 56 return errors.Wrap(err, "failed to mount overlay") 57 } 58 defer func() { 59 if err := syscall.Unmount(filepath.Join(td, "merged"), 0); err != nil { 60 logrus.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err) 61 } 62 }() 63 64 // Touch file in d to force copy up of opaque directory "d" from "l2" to "l3" 65 if err := ioutil.WriteFile(filepath.Join(td, "merged", "d", "f"), []byte{}, 0644); err != nil { 66 return errors.Wrap(err, "failed to write to merged directory") 67 } 68 69 // Check l3/d does not have opaque flag 70 xattrOpaque, err := system.Lgetxattr(filepath.Join(td, "l3", "d"), "trusted.overlay.opaque") 71 if err != nil { 72 return errors.Wrap(err, "failed to read opaque flag on upper layer") 73 } 74 if string(xattrOpaque) == "y" { 75 return errors.New("opaque flag erroneously copied up, consider update to kernel 4.8 or later to fix") 76 } 77 78 return nil 79 }