overlayutils.go 2.7 KB

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