lib/fs: Use file clone ioctl wrappers and types from golang.org/x/sys/unix (#7000)
Use the IoctlFileClone and IoctlFileCloneRange ioctl wrappers and the
FileCloneRange type provided by golang.org/x/sys/unix instead of
locally implementing them. This also allows to re-enable the code for
ppc/ppc64/ppc64le again (see commit 758a1a6a37 ("lib/fs: Disable ioctl
on ppc (fixes #6898) (#6901)")) since golang.org/x/sys/unix internally
uses the correct FICLONE and FICLONERANGE values depending on $GOARCH.
This commit is contained in:
@@ -4,40 +4,20 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
// +build linux,!ppc,!ppc64,!ppc64le
|
||||
// +build linux
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCopyRangeImplementation(CopyRangeMethodIoctl, copyRangeImplementationForBasicFile(copyRangeIoctl))
|
||||
}
|
||||
|
||||
const FICLONE = 0x40049409
|
||||
const FICLONERANGE = 0x4020940d
|
||||
|
||||
/*
|
||||
http://man7.org/linux/man-pages/man2/ioctl_ficlonerange.2.html
|
||||
|
||||
struct file_clone_range {
|
||||
__s64 src_fd;
|
||||
__u64 src_offset;
|
||||
__u64 src_length;
|
||||
__u64 dest_offset;
|
||||
};
|
||||
*/
|
||||
type fileCloneRange struct {
|
||||
srcFd int64
|
||||
srcOffset uint64
|
||||
srcLength uint64
|
||||
dstOffset uint64
|
||||
}
|
||||
|
||||
func copyRangeIoctl(src, dst basicFile, srcOffset, dstOffset, size int64) error {
|
||||
fi, err := src.Stat()
|
||||
if err != nil {
|
||||
@@ -56,38 +36,20 @@ func copyRangeIoctl(src, dst basicFile, srcOffset, dstOffset, size int64) error
|
||||
|
||||
if srcOffset == 0 && dstOffset == 0 && size == 0 {
|
||||
// Optimization for whole file copies.
|
||||
var errNo syscall.Errno
|
||||
_, err := withFileDescriptors(src, dst, func(srcFd, dstFd uintptr) (int, error) {
|
||||
_, _, errNo = syscall.Syscall(syscall.SYS_IOCTL, dstFd, FICLONE, srcFd)
|
||||
return 0, nil
|
||||
return 0, unix.IoctlFileClone(int(dstFd), int(srcFd))
|
||||
})
|
||||
// Failure in withFileDescriptors
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if errNo != 0 {
|
||||
return errNo
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var errNo syscall.Errno
|
||||
_, err = withFileDescriptors(src, dst, func(srcFd, dstFd uintptr) (int, error) {
|
||||
params := fileCloneRange{
|
||||
srcFd: int64(srcFd),
|
||||
srcOffset: uint64(srcOffset),
|
||||
srcLength: uint64(size),
|
||||
dstOffset: uint64(dstOffset),
|
||||
}
|
||||
_, _, errNo = syscall.Syscall(syscall.SYS_IOCTL, dstFd, FICLONERANGE, uintptr(unsafe.Pointer(¶ms)))
|
||||
return 0, nil
|
||||
})
|
||||
// Failure in withFileDescriptors
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if errNo != 0 {
|
||||
return errNo
|
||||
}
|
||||
return nil
|
||||
|
||||
_, err = withFileDescriptors(src, dst, func(srcFd, dstFd uintptr) (int, error) {
|
||||
params := unix.FileCloneRange{
|
||||
Src_fd: int64(srcFd),
|
||||
Src_offset: uint64(srcOffset),
|
||||
Src_length: uint64(size),
|
||||
Dest_offset: uint64(dstOffset),
|
||||
}
|
||||
return 0, unix.IoctlFileCloneRange(int(dstFd), ¶ms)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user