2020-06-18 06:15:47 +00:00
|
|
|
// Copyright (C) 2019 The Syncthing Authors.
|
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// 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/.
|
|
|
|
|
2020-09-24 08:29:32 +00:00
|
|
|
// +build linux
|
2020-06-18 06:15:47 +00:00
|
|
|
|
|
|
|
package fs
|
|
|
|
|
|
|
|
import (
|
2020-08-07 05:47:48 +00:00
|
|
|
"io"
|
2020-09-24 08:29:32 +00:00
|
|
|
|
|
|
|
"golang.org/x/sys/unix"
|
2020-06-18 06:15:47 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
registerCopyRangeImplementation(CopyRangeMethodIoctl, copyRangeImplementationForBasicFile(copyRangeIoctl))
|
|
|
|
}
|
|
|
|
|
|
|
|
func copyRangeIoctl(src, dst basicFile, srcOffset, dstOffset, size int64) error {
|
|
|
|
fi, err := src.Stat()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-08-07 05:47:48 +00:00
|
|
|
if srcOffset+size > fi.Size() {
|
|
|
|
return io.ErrUnexpectedEOF
|
|
|
|
}
|
|
|
|
|
2020-06-18 06:15:47 +00:00
|
|
|
// https://www.man7.org/linux/man-pages/man2/ioctl_ficlonerange.2.html
|
|
|
|
// If src_length is zero, the ioctl reflinks to the end of the source file.
|
|
|
|
if srcOffset+size == fi.Size() {
|
|
|
|
size = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
if srcOffset == 0 && dstOffset == 0 && size == 0 {
|
|
|
|
// Optimization for whole file copies.
|
2020-08-07 05:47:48 +00:00
|
|
|
_, err := withFileDescriptors(src, dst, func(srcFd, dstFd uintptr) (int, error) {
|
2020-09-24 08:29:32 +00:00
|
|
|
return 0, unix.IoctlFileClone(int(dstFd), int(srcFd))
|
2020-08-07 05:47:48 +00:00
|
|
|
})
|
2020-09-24 08:29:32 +00:00
|
|
|
return err
|
2020-06-18 06:15:47 +00:00
|
|
|
}
|
|
|
|
|
2020-08-07 05:47:48 +00:00
|
|
|
_, err = withFileDescriptors(src, dst, func(srcFd, dstFd uintptr) (int, error) {
|
2020-09-24 08:29:32 +00:00
|
|
|
params := unix.FileCloneRange{
|
|
|
|
Src_fd: int64(srcFd),
|
|
|
|
Src_offset: uint64(srcOffset),
|
|
|
|
Src_length: uint64(size),
|
|
|
|
Dest_offset: uint64(dstOffset),
|
2020-08-07 05:47:48 +00:00
|
|
|
}
|
2020-09-24 08:29:32 +00:00
|
|
|
return 0, unix.IoctlFileCloneRange(int(dstFd), ¶ms)
|
2020-08-07 05:47:48 +00:00
|
|
|
})
|
2020-09-24 08:29:32 +00:00
|
|
|
return err
|
2020-06-18 06:15:47 +00:00
|
|
|
}
|