mirror of
https://github.com/golang/sys.git
synced 2026-02-08 19:56:04 +03:00
Test for FIDEDUPERANGE, with fixes
Works for me in linux amd64 with /tmp in btrfs. Changing TMPDIR to a tmpfs the test says 'ok', but it goes through t.SkipNow().
This commit is contained in:
@@ -480,6 +480,8 @@ type RawFileDedupeRangeInfo C.struct_file_dedupe_range_info
|
||||
const (
|
||||
SizeofRawFileDedupeRange = C.sizeof_struct_file_dedupe_range
|
||||
SizeofRawFileDedupeRangeInfo = C.sizeof_struct_file_dedupe_range_info
|
||||
FILE_DEDUPE_RANGE_SAME = C.FILE_DEDUPE_RANGE_SAME
|
||||
FILE_DEDUPE_RANGE_DIFFERS = C.FILE_DEDUPE_RANGE_DIFFERS
|
||||
)
|
||||
|
||||
// Filesystem Encryption
|
||||
|
||||
@@ -140,7 +140,6 @@ func IoctlFileClone(destFd, srcFd int) error {
|
||||
type FileDedupeRange struct {
|
||||
Src_offset uint64
|
||||
Src_length uint64
|
||||
Dest_count uint16
|
||||
Reserved1 uint16
|
||||
Reserved2 uint32
|
||||
Info []FileDedupeRangeInfo
|
||||
@@ -155,12 +154,13 @@ type FileDedupeRangeInfo struct {
|
||||
}
|
||||
|
||||
// IoctlFileDedupeRange 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.
|
||||
// range of data conveyed in value from the file associated with the file
|
||||
// descriptor srcFd to the value.Info destinations. See the
|
||||
// ioctl_fideduperange(2) man page for details.
|
||||
func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
|
||||
buf := make([]byte, SizeofRawFileDedupeRange+
|
||||
len(value.Info)*SizeofRawFileDedupeRangeInfo)
|
||||
rawrange := (*FileDedupeRange)(unsafe.Pointer(&buf[0]))
|
||||
rawrange := (*RawFileDedupeRange)(unsafe.Pointer(&buf[0]))
|
||||
rawrange.Src_offset = value.Src_offset
|
||||
rawrange.Src_length = value.Src_length
|
||||
rawrange.Dest_count = uint16(len(value.Info))
|
||||
@@ -170,7 +170,7 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
|
||||
for i := range value.Info {
|
||||
rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer(
|
||||
uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) +
|
||||
uintptr(SizeofRawFileDedupeRangeInfo)))
|
||||
uintptr(i*SizeofRawFileDedupeRangeInfo)))
|
||||
rawinfo.Dest_fd = value.Info[i].Dest_fd
|
||||
rawinfo.Dest_offset = value.Info[i].Dest_offset
|
||||
rawinfo.Bytes_deduped = value.Info[i].Bytes_deduped
|
||||
@@ -179,7 +179,16 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
|
||||
}
|
||||
|
||||
err := ioctl(srcFd, FIDEDUPERANGE, uintptr(unsafe.Pointer(&buf[0])))
|
||||
runtime.KeepAlive(buf)
|
||||
|
||||
// Output
|
||||
for i := range value.Info {
|
||||
rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer(
|
||||
uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) +
|
||||
uintptr(i*SizeofRawFileDedupeRangeInfo)))
|
||||
value.Info[i].Bytes_deduped = rawinfo.Bytes_deduped
|
||||
value.Info[i].Status = rawinfo.Status
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -795,3 +795,90 @@ func TestOpenat2(t *testing.T) {
|
||||
t.Errorf("Openat2 should fail with EXDEV, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFideduperange(t *testing.T) {
|
||||
f1, err := ioutil.TempFile("", t.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f1.Close()
|
||||
|
||||
for i := 0; i < 2; i += 1 {
|
||||
_, err = f1.Write(make([]byte, 4096))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
f2, err := ioutil.TempFile("", t.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f2.Close()
|
||||
|
||||
for i := 0; i < 2; i += 1 {
|
||||
data := make([]byte, 4096)
|
||||
|
||||
// Make the 2nd block different
|
||||
if i == 1 {
|
||||
data[1] = 1
|
||||
}
|
||||
|
||||
_, err = f2.Write(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
dedupe := unix.FileDedupeRange{
|
||||
Src_offset: uint64(0),
|
||||
Src_length: uint64(4096),
|
||||
Info: []unix.FileDedupeRangeInfo{
|
||||
unix.FileDedupeRangeInfo{
|
||||
Dest_fd: int64(f2.Fd()),
|
||||
Dest_offset: uint64(0),
|
||||
Bytes_deduped: uint64(4096),
|
||||
},
|
||||
unix.FileDedupeRangeInfo{
|
||||
Dest_fd: int64(f2.Fd()),
|
||||
Dest_offset: uint64(4096),
|
||||
Bytes_deduped: uint64(4096),
|
||||
},
|
||||
}}
|
||||
|
||||
err = unix.IoctlFileDedupeRange(int(f1.Fd()), &dedupe)
|
||||
|
||||
if err != nil {
|
||||
if err == unix.EOPNOTSUPP {
|
||||
// We can't test if the fs doesn't support deduplication
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// The first Info should be equal
|
||||
if dedupe.Info[0].Status < 0 {
|
||||
// We expect status to be a negated errno
|
||||
t.Errorf("Unexpected error in FileDedupeRange: %s",
|
||||
unix.ErrnoName(unix.Errno(-dedupe.Info[0].Status)))
|
||||
} else if dedupe.Info[0].Status == unix.FILE_DEDUPE_RANGE_DIFFERS {
|
||||
t.Errorf("Unexpected different bytes in FileDedupeRange")
|
||||
}
|
||||
if dedupe.Info[0].Bytes_deduped != 4096 {
|
||||
t.Errorf("Unexpected amount of bytes deduped %v != %v",
|
||||
dedupe.Info[0].Bytes_deduped, 4096)
|
||||
}
|
||||
|
||||
// The second Info should be different
|
||||
if dedupe.Info[1].Status < 0 {
|
||||
// We expect status to be a negated errno
|
||||
t.Errorf("Unexpected error in FileDedupeRange: %s",
|
||||
unix.ErrnoName(unix.Errno(-dedupe.Info[1].Status)))
|
||||
} else if dedupe.Info[1].Status == unix.FILE_DEDUPE_RANGE_SAME {
|
||||
t.Errorf("Unexpected equal bytes in FileDedupeRange")
|
||||
}
|
||||
if dedupe.Info[1].Bytes_deduped != 0 {
|
||||
t.Errorf("Unexpected amount of bytes deduped %v != %v",
|
||||
dedupe.Info[1].Bytes_deduped, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,8 @@ type RawFileDedupeRangeInfo struct {
|
||||
const (
|
||||
SizeofRawFileDedupeRange = 0x18
|
||||
SizeofRawFileDedupeRangeInfo = 0x20
|
||||
FILE_DEDUPE_RANGE_SAME = 0x0
|
||||
FILE_DEDUPE_RANGE_DIFFERS = 0x1
|
||||
)
|
||||
|
||||
type FscryptPolicy struct {
|
||||
|
||||
Reference in New Issue
Block a user