overlayutils.go 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. //go:build linux
  2. // +build linux
  3. package overlayutils // import "github.com/docker/docker/daemon/graphdriver/overlayutils"
  4. import (
  5. "fmt"
  6. "io/ioutil"
  7. "os"
  8. "path"
  9. "path/filepath"
  10. "github.com/docker/docker/daemon/graphdriver"
  11. "github.com/pkg/errors"
  12. "github.com/sirupsen/logrus"
  13. "golang.org/x/sys/unix"
  14. )
  15. // ErrDTypeNotSupported denotes that the backing filesystem doesn't support d_type.
  16. func ErrDTypeNotSupported(driver, backingFs string) error {
  17. msg := fmt.Sprintf("%s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.", driver, backingFs)
  18. if backingFs == "xfs" {
  19. msg += " Reformat the filesystem with ftype=1 to enable d_type support."
  20. }
  21. if backingFs == "extfs" {
  22. msg += " Reformat the filesystem (or use tune2fs) with -O filetype flag to enable d_type support."
  23. }
  24. msg += " Backing filesystems without d_type support are not supported."
  25. return graphdriver.NotSupportedError(msg)
  26. }
  27. // SupportsOverlay checks if the system supports overlay filesystem
  28. // by performing an actual overlay mount.
  29. //
  30. // checkMultipleLowers parameter enables check for multiple lowerdirs,
  31. // which is required for the overlay2 driver.
  32. func SupportsOverlay(d string, checkMultipleLowers bool) error {
  33. // We can't rely on go-selinux.GetEnabled() to detect whether SELinux is enabled,
  34. // because RootlessKit doesn't mount /sys/fs/selinux in the child: https://github.com/rootless-containers/rootlesskit/issues/94
  35. // So we check $_DOCKERD_ROOTLESS_SELINUX, which is set by dockerd-rootless.sh .
  36. if os.Getenv("_DOCKERD_ROOTLESS_SELINUX") == "1" {
  37. // Kernel 5.11 introduced support for rootless overlayfs, but incompatible with SELinux,
  38. // so fallback to fuse-overlayfs.
  39. // https://github.com/moby/moby/issues/42333
  40. return errors.New("overlay is not supported for Rootless with SELinux")
  41. }
  42. td, err := ioutil.TempDir(d, "check-overlayfs-support")
  43. if err != nil {
  44. return err
  45. }
  46. defer func() {
  47. if err := os.RemoveAll(td); err != nil {
  48. logrus.Warnf("Failed to remove check directory %v: %v", td, err)
  49. }
  50. }()
  51. for _, dir := range []string{"lower1", "lower2", "upper", "work", "merged"} {
  52. if err := os.Mkdir(filepath.Join(td, dir), 0755); err != nil {
  53. return err
  54. }
  55. }
  56. mnt := filepath.Join(td, "merged")
  57. lowerDir := path.Join(td, "lower2")
  58. if checkMultipleLowers {
  59. lowerDir += ":" + path.Join(td, "lower1")
  60. }
  61. opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, path.Join(td, "upper"), path.Join(td, "work"))
  62. if err := unix.Mount("overlay", mnt, "overlay", 0, opts); err != nil {
  63. return errors.Wrap(err, "failed to mount overlay")
  64. }
  65. if err := unix.Unmount(mnt, 0); err != nil {
  66. logrus.Warnf("Failed to unmount check directory %v: %v", mnt, err)
  67. }
  68. return nil
  69. }