mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
3ec4ec2857
This changeset allows Docker's VFS, and Overlay to take advantage of Linux's zerocopy APIs. The copy function first tries to use the ficlone ioctl. Reason being: - they do not allow partial success (aka short writes) - clones are expected to be a fast metadata operation See: http://oss.sgi.com/archives/xfs/2015-12/msg00356.html If the clone fails, we fall back to copy_file_range, which internally may fall back to splice, which has an upper limit on the size of copy it can perform. Given that, we have to loop until the copy is done. For a given dirCopy operation, if the clone fails, we will not try it again during any other file copy. Same is true with copy_file_range. If all else fails, we fall back to traditional copy. Signed-off-by: Sargun Dhillon <sargun@sargun.me>
67 lines
1.8 KiB
Go
67 lines
1.8 KiB
Go
// +build linux
|
|
|
|
package copy
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/docker/docker/pkg/parsers/kernel"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestIsCopyFileRangeSyscallAvailable(t *testing.T) {
|
|
// Verifies:
|
|
// 1. That copyFileRangeEnabled is being set to true when copy_file_range syscall is available
|
|
// 2. That isCopyFileRangeSyscallAvailable() works on "new" kernels
|
|
v, err := kernel.GetKernelVersion()
|
|
require.NoError(t, err)
|
|
|
|
copyWithFileRange := true
|
|
copyWithFileClone := false
|
|
doCopyTest(t, ©WithFileRange, ©WithFileClone)
|
|
|
|
if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 4, Major: 5, Minor: 0}) < 0 {
|
|
assert.False(t, copyWithFileRange)
|
|
} else {
|
|
assert.True(t, copyWithFileRange)
|
|
}
|
|
|
|
}
|
|
|
|
func TestCopy(t *testing.T) {
|
|
copyWithFileRange := true
|
|
copyWithFileClone := true
|
|
doCopyTest(t, ©WithFileRange, ©WithFileClone)
|
|
}
|
|
|
|
func TestCopyWithoutRange(t *testing.T) {
|
|
copyWithFileRange := false
|
|
copyWithFileClone := false
|
|
doCopyTest(t, ©WithFileRange, ©WithFileClone)
|
|
}
|
|
|
|
func doCopyTest(t *testing.T, copyWithFileRange, copyWithFileClone *bool) {
|
|
dir, err := ioutil.TempDir("", "docker-copy-check")
|
|
require.NoError(t, err)
|
|
defer os.RemoveAll(dir)
|
|
srcFilename := filepath.Join(dir, "srcFilename")
|
|
dstFilename := filepath.Join(dir, "dstilename")
|
|
|
|
r := rand.New(rand.NewSource(0))
|
|
buf := make([]byte, 1024)
|
|
_, err = r.Read(buf)
|
|
require.NoError(t, err)
|
|
require.NoError(t, ioutil.WriteFile(srcFilename, buf, 0777))
|
|
fileinfo, err := os.Stat(srcFilename)
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, copyRegular(srcFilename, dstFilename, fileinfo, copyWithFileRange, copyWithFileClone))
|
|
readBuf, err := ioutil.ReadFile(dstFilename)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, buf, readBuf)
|
|
}
|