unix: add IoctlFile{Clone,CloneRange,DedupeRange} on linux

Add wrappers for the FICLONE, FICLONERANGE and FIDEDUPERANGE ioctl
operations on linux. See the ioctl_ficlone(2), ioctl_ficlonerange(2) and
ioctl_fideduperange(2) man pages for details.

Change-Id: If3bad98facc362d4f7524e8d7a128815e9e2f204
Reviewed-on: https://go-review.googlesource.com/c/sys/+/256000
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/linux/types.go b/unix/linux/types.go
index eb0fd3c..1888a49 100644
--- a/unix/linux/types.go
+++ b/unix/linux/types.go
@@ -465,6 +465,10 @@
 
 type Flock_t C.struct_flock
 
+type FileCloneRange C.struct_file_clone_range
+
+type FileDedupeRange C.struct_file_dedupe_range
+
 // Filesystem Encryption
 
 type FscryptPolicy C.struct_fscrypt_policy
diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh
index e7c51aa..1bef714 100755
--- a/unix/mkerrors.sh
+++ b/unix/mkerrors.sh
@@ -517,6 +517,7 @@
 		$2 ~ /^CP_/ ||
 		$2 ~ /^CPUSTATES$/ ||
 		$2 ~ /^ALG_/ ||
+		$2 ~ /^FI(CLONE|DEDUPERANGE)/ ||
 		$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ ||
 		$2 ~ /^FS_IOC_.*(ENCRYPTION|VERITY|[GS]ETFLAGS)/ ||
 		$2 ~ /^FS_VERITY_/ ||
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index ec7e4c4..94dafa4 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -112,6 +112,31 @@
 	return &value, err
 }
 
+// IoctlFileClone performs an FICLONERANGE ioctl operation to clone the range of
+// data conveyed in value to the file associated with the file descriptor
+// destFd. See the ioctl_ficlonerange(2) man page for details.
+func IoctlFileCloneRange(destFd int, value *FileCloneRange) error {
+	err := ioctl(destFd, FICLONERANGE, uintptr(unsafe.Pointer(value)))
+	runtime.KeepAlive(value)
+	return err
+}
+
+// IoctlFileClone performs an FICLONE ioctl operation to clone the entire file
+// associated with the file description srcFd to the file associated with the
+// file descriptor destFd. See the ioctl_ficlone(2) man page for details.
+func IoctlFileClone(destFd, srcFd int) error {
+	return ioctl(destFd, FICLONE, uintptr(srcFd))
+}
+
+// IoctlFileClone performs an FIDEDUPERANGE ioctl operation to share the range of
+// data conveyed in value with the file associated with the file descriptor
+// destFd. See the ioctl_fideduperange(2) man page for details.
+func IoctlFileDedupeRange(destFd int, value *FileDedupeRange) error {
+	err := ioctl(destFd, FIDEDUPERANGE, uintptr(unsafe.Pointer(value)))
+	runtime.KeepAlive(value)
+	return err
+}
+
 //sys	Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
 
 func Link(oldpath string, newpath string) (err error) {
diff --git a/unix/zerrors_linux.go b/unix/zerrors_linux.go
index 388050a..79e032f 100644
--- a/unix/zerrors_linux.go
+++ b/unix/zerrors_linux.go
@@ -686,6 +686,7 @@
 	FD_CLOEXEC                                  = 0x1
 	FD_SETSIZE                                  = 0x400
 	FF0                                         = 0x0
+	FIDEDUPERANGE                               = 0xc0189436
 	FSCRYPT_KEY_DESCRIPTOR_SIZE                 = 0x8
 	FSCRYPT_KEY_DESC_PREFIX                     = "fscrypt:"
 	FSCRYPT_KEY_DESC_PREFIX_SIZE                = 0x8
diff --git a/unix/zerrors_linux_386.go b/unix/zerrors_linux_386.go
index 11b25f6..dd282c0 100644
--- a/unix/zerrors_linux_386.go
+++ b/unix/zerrors_linux_386.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x40049409
+	FICLONERANGE                     = 0x4020940d
 	FLUSHO                           = 0x1000
 	FP_XSTATE_MAGIC2                 = 0x46505845
 	FS_IOC_ENABLE_VERITY             = 0x40806685
diff --git a/unix/zerrors_linux_amd64.go b/unix/zerrors_linux_amd64.go
index f92cff6..82fc93c 100644
--- a/unix/zerrors_linux_amd64.go
+++ b/unix/zerrors_linux_amd64.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x40049409
+	FICLONERANGE                     = 0x4020940d
 	FLUSHO                           = 0x1000
 	FP_XSTATE_MAGIC2                 = 0x46505845
 	FS_IOC_ENABLE_VERITY             = 0x40806685
diff --git a/unix/zerrors_linux_arm.go b/unix/zerrors_linux_arm.go
index 12bcbf8..fe7094f 100644
--- a/unix/zerrors_linux_arm.go
+++ b/unix/zerrors_linux_arm.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x40049409
+	FICLONERANGE                     = 0x4020940d
 	FLUSHO                           = 0x1000
 	FS_IOC_ENABLE_VERITY             = 0x40806685
 	FS_IOC_GETFLAGS                  = 0x80046601
diff --git a/unix/zerrors_linux_arm64.go b/unix/zerrors_linux_arm64.go
index 84f71e9..3b6cc58 100644
--- a/unix/zerrors_linux_arm64.go
+++ b/unix/zerrors_linux_arm64.go
@@ -73,6 +73,8 @@
 	EXTRA_MAGIC                      = 0x45585401
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x40049409
+	FICLONERANGE                     = 0x4020940d
 	FLUSHO                           = 0x1000
 	FPSIMD_MAGIC                     = 0x46508001
 	FS_IOC_ENABLE_VERITY             = 0x40806685
diff --git a/unix/zerrors_linux_mips.go b/unix/zerrors_linux_mips.go
index eeadea9..ce3d9ae 100644
--- a/unix/zerrors_linux_mips.go
+++ b/unix/zerrors_linux_mips.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x80049409
+	FICLONERANGE                     = 0x8020940d
 	FLUSHO                           = 0x2000
 	FS_IOC_ENABLE_VERITY             = 0x80806685
 	FS_IOC_GETFLAGS                  = 0x40046601
diff --git a/unix/zerrors_linux_mips64.go b/unix/zerrors_linux_mips64.go
index 0be6c4c..7a85215 100644
--- a/unix/zerrors_linux_mips64.go
+++ b/unix/zerrors_linux_mips64.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x80049409
+	FICLONERANGE                     = 0x8020940d
 	FLUSHO                           = 0x2000
 	FS_IOC_ENABLE_VERITY             = 0x80806685
 	FS_IOC_GETFLAGS                  = 0x40086601
diff --git a/unix/zerrors_linux_mips64le.go b/unix/zerrors_linux_mips64le.go
index 0880b74..07d4cc1 100644
--- a/unix/zerrors_linux_mips64le.go
+++ b/unix/zerrors_linux_mips64le.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x80049409
+	FICLONERANGE                     = 0x8020940d
 	FLUSHO                           = 0x2000
 	FS_IOC_ENABLE_VERITY             = 0x80806685
 	FS_IOC_GETFLAGS                  = 0x40086601
diff --git a/unix/zerrors_linux_mipsle.go b/unix/zerrors_linux_mipsle.go
index c8a6662..d4842ba 100644
--- a/unix/zerrors_linux_mipsle.go
+++ b/unix/zerrors_linux_mipsle.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x80049409
+	FICLONERANGE                     = 0x8020940d
 	FLUSHO                           = 0x2000
 	FS_IOC_ENABLE_VERITY             = 0x80806685
 	FS_IOC_GETFLAGS                  = 0x40046601
diff --git a/unix/zerrors_linux_ppc64.go b/unix/zerrors_linux_ppc64.go
index 97aae63..941e20d 100644
--- a/unix/zerrors_linux_ppc64.go
+++ b/unix/zerrors_linux_ppc64.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000000
 	FF1                              = 0x4000
 	FFDLY                            = 0x4000
+	FICLONE                          = 0x80049409
+	FICLONERANGE                     = 0x8020940d
 	FLUSHO                           = 0x800000
 	FS_IOC_ENABLE_VERITY             = 0x80806685
 	FS_IOC_GETFLAGS                  = 0x40086601
diff --git a/unix/zerrors_linux_ppc64le.go b/unix/zerrors_linux_ppc64le.go
index b0c3b06..63d3bc5 100644
--- a/unix/zerrors_linux_ppc64le.go
+++ b/unix/zerrors_linux_ppc64le.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000000
 	FF1                              = 0x4000
 	FFDLY                            = 0x4000
+	FICLONE                          = 0x80049409
+	FICLONERANGE                     = 0x8020940d
 	FLUSHO                           = 0x800000
 	FS_IOC_ENABLE_VERITY             = 0x80806685
 	FS_IOC_GETFLAGS                  = 0x40086601
diff --git a/unix/zerrors_linux_riscv64.go b/unix/zerrors_linux_riscv64.go
index 0c05181..490bee1 100644
--- a/unix/zerrors_linux_riscv64.go
+++ b/unix/zerrors_linux_riscv64.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x40049409
+	FICLONERANGE                     = 0x4020940d
 	FLUSHO                           = 0x1000
 	FS_IOC_ENABLE_VERITY             = 0x40806685
 	FS_IOC_GETFLAGS                  = 0x80086601
diff --git a/unix/zerrors_linux_s390x.go b/unix/zerrors_linux_s390x.go
index 0b96bd4..467b821 100644
--- a/unix/zerrors_linux_s390x.go
+++ b/unix/zerrors_linux_s390x.go
@@ -71,6 +71,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x40049409
+	FICLONERANGE                     = 0x4020940d
 	FLUSHO                           = 0x1000
 	FS_IOC_ENABLE_VERITY             = 0x40806685
 	FS_IOC_GETFLAGS                  = 0x80086601
diff --git a/unix/zerrors_linux_sparc64.go b/unix/zerrors_linux_sparc64.go
index bd5c305..79fbafb 100644
--- a/unix/zerrors_linux_sparc64.go
+++ b/unix/zerrors_linux_sparc64.go
@@ -75,6 +75,8 @@
 	EXTPROC                          = 0x10000
 	FF1                              = 0x8000
 	FFDLY                            = 0x8000
+	FICLONE                          = 0x80049409
+	FICLONERANGE                     = 0x8020940d
 	FLUSHO                           = 0x1000
 	FS_IOC_ENABLE_VERITY             = 0x80806685
 	FS_IOC_GETFLAGS                  = 0x40086601
diff --git a/unix/ztypes_linux.go b/unix/ztypes_linux.go
index 68e4974..a92a501 100644
--- a/unix/ztypes_linux.go
+++ b/unix/ztypes_linux.go
@@ -76,6 +76,21 @@
 	Val [2]int32
 }
 
+type FileCloneRange struct {
+	Src_fd      int64
+	Src_offset  uint64
+	Src_length  uint64
+	Dest_offset uint64
+}
+
+type FileDedupeRange struct {
+	Src_offset uint64
+	Src_length uint64
+	Dest_count uint16
+	Reserved1  uint16
+	Reserved2  uint32
+}
+
 type FscryptPolicy struct {
 	Version                   uint8
 	Contents_encryption_mode  uint8