pkg/fsutils: deprecate in favor of containerd/continuity/fs
The pkg/fsutils package was forked in containerd, and later moved to
containerd/continuity/fs. As we're moving more bits to containerd, let's also
use the same implementation to reduce code-duplication and to prevent them from
diverging.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 5b6b42162b
)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
ff07aadeb0
commit
ac6624773e
|
@ -12,12 +12,12 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/continuity/fs"
|
||||||
"github.com/docker/docker/daemon/graphdriver"
|
"github.com/docker/docker/daemon/graphdriver"
|
||||||
"github.com/docker/docker/daemon/graphdriver/copy"
|
"github.com/docker/docker/daemon/graphdriver/copy"
|
||||||
"github.com/docker/docker/daemon/graphdriver/overlayutils"
|
"github.com/docker/docker/daemon/graphdriver/overlayutils"
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
"github.com/docker/docker/pkg/containerfs"
|
"github.com/docker/docker/pkg/containerfs"
|
||||||
"github.com/docker/docker/pkg/fsutils"
|
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/docker/docker/pkg/parsers"
|
"github.com/docker/docker/pkg/parsers"
|
||||||
"github.com/moby/locker"
|
"github.com/moby/locker"
|
||||||
|
@ -142,7 +142,7 @@ func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdr
|
||||||
backingFs = fsName
|
backingFs = fsName
|
||||||
}
|
}
|
||||||
|
|
||||||
supportsDType, err := fsutils.SupportsDType(testdir)
|
supportsDType, err := fs.SupportsDType(testdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/continuity/fs"
|
||||||
"github.com/docker/docker/daemon/graphdriver"
|
"github.com/docker/docker/daemon/graphdriver"
|
||||||
"github.com/docker/docker/daemon/graphdriver/overlayutils"
|
"github.com/docker/docker/daemon/graphdriver/overlayutils"
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
"github.com/docker/docker/pkg/chrootarchive"
|
"github.com/docker/docker/pkg/chrootarchive"
|
||||||
"github.com/docker/docker/pkg/containerfs"
|
"github.com/docker/docker/pkg/containerfs"
|
||||||
"github.com/docker/docker/pkg/directory"
|
"github.com/docker/docker/pkg/directory"
|
||||||
"github.com/docker/docker/pkg/fsutils"
|
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/docker/docker/pkg/parsers"
|
"github.com/docker/docker/pkg/parsers"
|
||||||
"github.com/docker/docker/quota"
|
"github.com/docker/docker/quota"
|
||||||
|
@ -152,7 +152,7 @@ func Init(home string, options []string, idMap idtools.IdentityMapping) (graphdr
|
||||||
backingFs = fsName
|
backingFs = fsName
|
||||||
}
|
}
|
||||||
|
|
||||||
supportsDType, err := fsutils.SupportsDType(testdir)
|
supportsDType, err := fs.SupportsDType(testdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,85 +1,8 @@
|
||||||
package fsutils // import "github.com/docker/docker/pkg/fsutils"
|
package fsutils // import "github.com/docker/docker/pkg/fsutils"
|
||||||
|
|
||||||
import (
|
import "github.com/containerd/continuity/fs"
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
// SupportsDType returns whether the filesystem mounted on path supports d_type.
|
||||||
)
|
//
|
||||||
|
// Deprecated: use github.com/containerd/continuity/fs.SupportsDType
|
||||||
func locateDummyIfEmpty(path string) (string, error) {
|
var SupportsDType = fs.SupportsDType
|
||||||
children, err := os.ReadDir(path)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if len(children) != 0 {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
dummyFile, err := os.CreateTemp(path, "fsutils-dummy")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
name := dummyFile.Name()
|
|
||||||
err = dummyFile.Close()
|
|
||||||
return name, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SupportsDType returns whether the filesystem mounted on path supports d_type
|
|
||||||
func SupportsDType(path string) (bool, error) {
|
|
||||||
// locate dummy so that we have at least one dirent
|
|
||||||
dummy, err := locateDummyIfEmpty(path)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if dummy != "" {
|
|
||||||
defer os.Remove(dummy)
|
|
||||||
}
|
|
||||||
|
|
||||||
visited := 0
|
|
||||||
supportsDType := true
|
|
||||||
fn := func(ent *unix.Dirent) bool {
|
|
||||||
visited++
|
|
||||||
if ent.Type == unix.DT_UNKNOWN {
|
|
||||||
supportsDType = false
|
|
||||||
// stop iteration
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// continue iteration
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if err = iterateReadDir(path, fn); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if visited == 0 {
|
|
||||||
return false, fmt.Errorf("did not hit any dirent during iteration %s", path)
|
|
||||||
}
|
|
||||||
return supportsDType, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func iterateReadDir(path string, fn func(*unix.Dirent) bool) error {
|
|
||||||
d, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer d.Close()
|
|
||||||
fd := int(d.Fd())
|
|
||||||
buf := make([]byte, 4096)
|
|
||||||
for {
|
|
||||||
nbytes, err := unix.ReadDirent(fd, buf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if nbytes == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
for off := 0; off < nbytes; {
|
|
||||||
ent := (*unix.Dirent)(unsafe.Pointer(&buf[off]))
|
|
||||||
if stop := fn(ent); stop {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
off += int(ent.Reclen)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
//go:build linux
|
|
||||||
// +build linux
|
|
||||||
|
|
||||||
package fsutils // import "github.com/docker/docker/pkg/fsutils"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testSupportsDType(t *testing.T, expected bool, mkfsCommand string, mkfsArg ...string) {
|
|
||||||
// check whether mkfs is installed
|
|
||||||
if _, err := exec.LookPath(mkfsCommand); err != nil {
|
|
||||||
t.Skipf("%s not installed: %v", mkfsCommand, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a sparse image
|
|
||||||
imageSize := int64(32 * 1024 * 1024)
|
|
||||||
imageFile, err := os.CreateTemp("", "fsutils-image")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
imageFileName := imageFile.Name()
|
|
||||||
defer os.Remove(imageFileName)
|
|
||||||
if _, err = imageFile.Seek(imageSize-1, 0); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if _, err = imageFile.Write([]byte{0}); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if err = imageFile.Close(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a mountpoint
|
|
||||||
mountpoint, err := os.MkdirTemp("", "fsutils-mountpoint")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(mountpoint)
|
|
||||||
|
|
||||||
// format the image
|
|
||||||
args := append(mkfsArg, imageFileName)
|
|
||||||
t.Logf("Executing `%s %v`", mkfsCommand, args)
|
|
||||||
out, err := exec.Command(mkfsCommand, args...).CombinedOutput()
|
|
||||||
if len(out) > 0 {
|
|
||||||
t.Log(string(out))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// loopback-mount the image.
|
|
||||||
// for ease of setting up loopback device, we use os/exec rather than unix.Mount
|
|
||||||
out, err = exec.Command("mount", "-o", "loop", imageFileName, mountpoint).CombinedOutput()
|
|
||||||
if len(out) > 0 {
|
|
||||||
t.Log(string(out))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Skip("skipping the test because mount failed")
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := unix.Unmount(mountpoint, 0); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// check whether it supports d_type
|
|
||||||
result, err := SupportsDType(mountpoint)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Logf("Supports d_type: %v", result)
|
|
||||||
if result != expected {
|
|
||||||
t.Fatalf("expected %v, got %v", expected, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSupportsDTypeWithFType0XFS(t *testing.T) {
|
|
||||||
testSupportsDType(t, false, "mkfs.xfs", "-m", "crc=0", "-n", "ftype=0")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSupportsDTypeWithFType1XFS(t *testing.T) {
|
|
||||||
testSupportsDType(t, true, "mkfs.xfs", "-m", "crc=0", "-n", "ftype=1")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSupportsDTypeWithExt4(t *testing.T) {
|
|
||||||
testSupportsDType(t, true, "mkfs.ext4")
|
|
||||||
}
|
|
Loading…
Reference in New Issue