Skip to content

Commit

Permalink
vfs: fix file length after fallocate & copyfilerange (#4427)
Browse files Browse the repository at this point in the history
Co-authored-by: Davies Liu <[email protected]>
  • Loading branch information
SandyXSD and davies authored Feb 28, 2024
1 parent bf669aa commit 4239270
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 43 deletions.
2 changes: 1 addition & 1 deletion pkg/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ func (fs *FileSystem) CopyFileRange(ctx meta.Context, src string, soff uint64, d
if err != 0 {
return
}
err = fs.m.CopyFileRange(ctx, sfi.inode, soff, dfi.inode, doff, size, 0, &written)
err = fs.m.CopyFileRange(ctx, sfi.inode, soff, dfi.inode, doff, size, 0, &written, nil)
return
}

Expand Down
32 changes: 16 additions & 16 deletions pkg/meta/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,25 +476,25 @@ func testMetaClient(t *testing.T, m Meta) {
if len(slices) != 2 || slices[0].Id != 0 || slices[0].Size != 100 || slices[1].Id != sliceId || slices[1].Size != 100 {
t.Fatalf("slices: %v", slices)
}
if st := m.Fallocate(ctx, inode, fallocPunchHole|fallocKeepSize, 100, 50); st != 0 {
if st := m.Fallocate(ctx, inode, fallocPunchHole|fallocKeepSize, 100, 50, nil); st != 0 {
t.Fatalf("fallocate: %s", st)
}
if st := m.Fallocate(ctx, inode, fallocPunchHole|fallocCollapesRange, 100, 50); st != syscall.EINVAL {
if st := m.Fallocate(ctx, inode, fallocPunchHole|fallocCollapesRange, 100, 50, nil); st != syscall.EINVAL {
t.Fatalf("fallocate: %s", st)
}
if st := m.Fallocate(ctx, inode, fallocPunchHole|fallocInsertRange, 100, 50); st != syscall.EINVAL {
if st := m.Fallocate(ctx, inode, fallocPunchHole|fallocInsertRange, 100, 50, nil); st != syscall.EINVAL {
t.Fatalf("fallocate: %s", st)
}
if st := m.Fallocate(ctx, inode, fallocCollapesRange, 100, 50); st != syscall.ENOTSUP {
if st := m.Fallocate(ctx, inode, fallocCollapesRange, 100, 50, nil); st != syscall.ENOTSUP {
t.Fatalf("fallocate: %s", st)
}
if st := m.Fallocate(ctx, inode, fallocPunchHole, 100, 50); st != syscall.EINVAL {
if st := m.Fallocate(ctx, inode, fallocPunchHole, 100, 50, nil); st != syscall.EINVAL {
t.Fatalf("fallocate: %s", st)
}
if st := m.Fallocate(ctx, inode, fallocPunchHole|fallocKeepSize, 0, 0); st != syscall.EINVAL {
if st := m.Fallocate(ctx, inode, fallocPunchHole|fallocKeepSize, 0, 0, nil); st != syscall.EINVAL {
t.Fatalf("fallocate: %s", st)
}
if st := m.Fallocate(ctx, parent, fallocPunchHole|fallocKeepSize, 100, 50); st != syscall.EPERM {
if st := m.Fallocate(ctx, parent, fallocPunchHole|fallocKeepSize, 100, 50, nil); st != syscall.EPERM {
t.Fatalf("fallocate dir: %s", st)
}
if st := m.Read(ctx, inode, 0, &slices); st != 0 {
Expand Down Expand Up @@ -1416,7 +1416,7 @@ func testCopyFileRange(t *testing.T, m Meta) {
m.Write(ctx, iin, 3, 0, Slice{12, 63 << 20, 10 << 20, 30 << 20}, time.Now())
m.Write(ctx, iout, 2, 10<<20, Slice{13, 50 << 20, 10 << 20, 30 << 20}, time.Now())
var copied uint64
if st := m.CopyFileRange(ctx, iin, 150, iout, 30<<20, 200<<20, 0, &copied); st != 0 {
if st := m.CopyFileRange(ctx, iin, 150, iout, 30<<20, 200<<20, 0, &copied, nil); st != 0 {
t.Fatalf("copy file range: %s", st)
}
var expected uint64 = 200 << 20
Expand Down Expand Up @@ -1967,17 +1967,17 @@ func testAttrFlags(t *testing.T, m Meta) {
if st := m.SetAttr(ctx, fallocFile, SetAttrFlag, 0, attr); st != 0 {
t.Fatalf("setattr f: %s", st)
}
if st := m.Fallocate(ctx, fallocFile, fallocKeepSize, 0, 1024); st != 0 {
if st := m.Fallocate(ctx, fallocFile, fallocKeepSize, 0, 1024, nil); st != 0 {
t.Fatalf("fallocate f: %s", st)
}
if st := m.Fallocate(ctx, fallocFile, fallocKeepSize|fallocZeroRange, 0, 1024); st != syscall.EPERM {
if st := m.Fallocate(ctx, fallocFile, fallocKeepSize|fallocZeroRange, 0, 1024, nil); st != syscall.EPERM {
t.Fatalf("fallocate f: %s", st)
}
attr.Flags = FlagImmutable
if st := m.SetAttr(ctx, fallocFile, SetAttrFlag, 0, attr); st != 0 {
t.Fatalf("setattr f: %s", st)
}
if st := m.Fallocate(ctx, fallocFile, fallocKeepSize, 0, 1024); st != syscall.EPERM {
if st := m.Fallocate(ctx, fallocFile, fallocKeepSize, 0, 1024, nil); st != syscall.EPERM {
t.Fatalf("fallocate f: %s", st)
}

Expand All @@ -1988,21 +1988,21 @@ func testAttrFlags(t *testing.T, m Meta) {
if st := m.Create(ctx, 1, "copydstfile", 0644, 022, 0, &copydstFile, nil); st != 0 {
t.Fatalf("create f: %s", st)
}
if st := m.Fallocate(ctx, copysrcFile, 0, 0, 1024); st != 0 {
if st := m.Fallocate(ctx, copysrcFile, 0, 0, 1024, nil); st != 0 {
t.Fatalf("fallocate f: %s", st)
}
attr.Flags = FlagAppend
if st := m.SetAttr(ctx, copydstFile, SetAttrFlag, 0, attr); st != 0 {
t.Fatalf("setattr f: %s", st)
}
if st := m.CopyFileRange(ctx, copysrcFile, 0, copydstFile, 0, 1024, 0, nil); st != syscall.EPERM {
if st := m.CopyFileRange(ctx, copysrcFile, 0, copydstFile, 0, 1024, 0, nil, nil); st != syscall.EPERM {
t.Fatalf("copy_file_range f: %s", st)
}
attr.Flags = FlagImmutable
if st := m.SetAttr(ctx, copydstFile, SetAttrFlag, 0, attr); st != 0 {
t.Fatalf("setattr f: %s", st)
}
if st := m.CopyFileRange(ctx, copysrcFile, 0, copydstFile, 0, 1024, 0, nil); st != syscall.EPERM {
if st := m.CopyFileRange(ctx, copysrcFile, 0, copydstFile, 0, 1024, 0, nil, nil); st != syscall.EPERM {
t.Fatalf("copy_file_range f: %s", st)
}
}
Expand Down Expand Up @@ -2185,7 +2185,7 @@ func testDirStat(t *testing.T, m Meta) {
checkResult(0, align4K(0), 1)

// test dir with file and fallocate
if st := m.Fallocate(Background, fileInode, 0, 0, 4097); st != 0 {
if st := m.Fallocate(Background, fileInode, 0, 0, 4097, nil); st != 0 {
t.Fatalf("fallocate: %s", st)
}
time.Sleep(500 * time.Millisecond)
Expand Down Expand Up @@ -2316,7 +2316,7 @@ func testClone(t *testing.T, m Meta) {
if eno := m.Mknod(Background, dir3, "file3", TypeFile, 0777, 022, 0, "", &file3, nil); eno != 0 {
t.Fatalf("mknod: %s", eno)
}
if eno := m.Fallocate(Background, file3, 0, 0, 67108864); eno != 0 {
if eno := m.Fallocate(Background, file3, 0, 0, 67108864, nil); eno != 0 {
t.Fatalf("fallocate: %s", eno)
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/meta/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ type Meta interface {
// Truncate changes the length for given file.
Truncate(ctx Context, inode Ino, flags uint8, attrlength uint64, attr *Attr, skipPermCheck bool) syscall.Errno
// Fallocate preallocate given space for given file.
Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size uint64) syscall.Errno
Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size uint64, length *uint64) syscall.Errno
// ReadLink returns the target of a symlink.
ReadLink(ctx Context, inode Ino, path *[]byte) syscall.Errno
// Symlink creates a symlink in a directory with given name.
Expand Down Expand Up @@ -412,7 +412,7 @@ type Meta interface {
// InvalidateChunkCache invalidate chunk cache
InvalidateChunkCache(ctx Context, inode Ino, indx uint32) syscall.Errno
// CopyFileRange copies part of a file to another one.
CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, offOut uint64, size uint64, flags uint32, copied *uint64) syscall.Errno
CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, offOut uint64, size uint64, flags uint32, copied, outLength *uint64) syscall.Errno
// GetParents returns a map of node parents (> 1 parents if hardlinked)
GetParents(ctx Context, inode Ino) map[Ino]int
// GetDirStat returns the space and inodes usage of a directory.
Expand Down
2 changes: 1 addition & 1 deletion pkg/meta/random_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1226,7 +1226,7 @@ func (m *fsMachine) Fallocate(t *rapid.T) {
inode := m.pickNode(t)
offset := rapid.Uint64Range(0, 500<<20).Draw(t, "offset")
length := rapid.Uint64Range(1, 500<<20).Draw(t, "length")
st := m.meta.Fallocate(m.ctx, inode, 0, offset, length)
st := m.meta.Fallocate(m.ctx, inode, 0, offset, length, nil)
st2 := m.fallocate(inode, 0, offset, length)
if st != st2 {
t.Fatalf("expect %s but got %s", st2, st)
Expand Down
18 changes: 14 additions & 4 deletions pkg/meta/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,7 @@ func (m *redisMeta) Truncate(ctx Context, inode Ino, flags uint8, length uint64,
return errno(err)
}

func (m *redisMeta) Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size uint64) syscall.Errno {
func (m *redisMeta) Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size uint64, flength *uint64) syscall.Errno {
if mode&fallocCollapesRange != 0 && mode != fallocCollapesRange {
return syscall.EINVAL
}
Expand Down Expand Up @@ -1090,6 +1090,9 @@ func (m *redisMeta) Fallocate(ctx Context, inode Ino, mode uint8, off uint64, si
if err := m.checkQuota(ctx, newSpace, 0, m.getParents(ctx, tx, inode, t.Parent)...); err != 0 {
return err
}
if flength != nil {
*flength = length
}
t.Length = length
now := time.Now()
t.Mtime = now.Unix()
Expand Down Expand Up @@ -2309,7 +2312,7 @@ func (m *redisMeta) Write(ctx Context, inode Ino, indx uint32, off uint32, slice
return errno(err)
}

func (m *redisMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, offOut uint64, size uint64, flags uint32, copied *uint64) syscall.Errno {
func (m *redisMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, offOut uint64, size uint64, flags uint32, copied, outLength *uint64) syscall.Errno {
defer m.timeit("CopyFileRange", time.Now())
f := m.of.find(fout)
if f != nil {
Expand All @@ -2334,7 +2337,9 @@ func (m *redisMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino,
return syscall.EINVAL
}
if offIn >= sattr.Length {
*copied = 0
if copied != nil {
*copied = 0
}
return nil
}
size := size
Expand Down Expand Up @@ -2364,6 +2369,9 @@ func (m *redisMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino,
attr.Mtimensec = uint32(now.Nanosecond())
attr.Ctime = now.Unix()
attr.Ctimensec = uint32(now.Nanosecond())
if outLength != nil {
*outLength = attr.Length
}

var vals [][]string
for i := offIn / ChunkSize; i <= (offIn+size)/ChunkSize; i++ {
Expand Down Expand Up @@ -2430,7 +2438,9 @@ func (m *redisMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino,
return nil
})
if err == nil {
*copied = size
if copied != nil {
*copied = size
}
}
return err
}, m.inodeKey(fout), m.inodeKey(fin))
Expand Down
18 changes: 14 additions & 4 deletions pkg/meta/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,7 @@ func (m *dbMeta) Truncate(ctx Context, inode Ino, flags uint8, length uint64, at
return errno(err)
}

func (m *dbMeta) Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size uint64) syscall.Errno {
func (m *dbMeta) Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size uint64, flength *uint64) syscall.Errno {
if mode&fallocCollapesRange != 0 && mode != fallocCollapesRange {
return syscall.EINVAL
}
Expand Down Expand Up @@ -1113,6 +1113,9 @@ func (m *dbMeta) Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size
if _, err := s.Cols("length", "mtime", "ctime", "mtimensec", "ctimensec").Update(&nodeAttr, &node{Inode: inode}); err != nil {
return err
}
if flength != nil {
*flength = length
}
if mode&(fallocZeroRange|fallocPunchHole) != 0 && off < old {
off, size := off, size
if off+size > old {
Expand Down Expand Up @@ -2313,7 +2316,7 @@ func (m *dbMeta) Write(ctx Context, inode Ino, indx uint32, off uint32, slice Sl
return errno(err)
}

func (m *dbMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, offOut uint64, size uint64, flags uint32, copied *uint64) syscall.Errno {
func (m *dbMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, offOut uint64, size uint64, flags uint32, copied, outLength *uint64) syscall.Errno {
defer m.timeit("CopyFileRange", time.Now())
f := m.of.find(fout)
if f != nil {
Expand All @@ -2335,7 +2338,9 @@ func (m *dbMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, off
return syscall.EINVAL
}
if offIn >= nin.Length {
*copied = 0
if copied != nil {
*copied = 0
}
return nil
}
size := size
Expand Down Expand Up @@ -2363,6 +2368,9 @@ func (m *dbMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, off
nout.Ctime = now / 1e3
nout.Mtimensec = int16(now % 1e3)
nout.Ctimensec = int16(now % 1e3)
if outLength != nil {
*outLength = nout.Length
}

var cs []chunk
err = s.Where("inode = ? AND indx >= ? AND indx <= ?", fin, offIn/ChunkSize, (offIn+size)/ChunkSize).ForUpdate().Find(&cs)
Expand Down Expand Up @@ -2433,7 +2441,9 @@ func (m *dbMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, off
if _, err := s.Cols("length", "mtime", "ctime", "mtimensec", "ctimensec").Update(&nout, &node{Inode: fout}); err != nil {
return err
}
*copied = size
if copied != nil {
*copied = size
}
return nil
}, fout)
if err == nil {
Expand Down
18 changes: 14 additions & 4 deletions pkg/meta/tkv.go
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ func (m *kvMeta) Truncate(ctx Context, inode Ino, flags uint8, length uint64, at
return errno(err)
}

func (m *kvMeta) Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size uint64) syscall.Errno {
func (m *kvMeta) Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size uint64, flength *uint64) syscall.Errno {
if mode&fallocCollapesRange != 0 && mode != fallocCollapesRange {
return syscall.EINVAL
}
Expand Down Expand Up @@ -1020,6 +1020,9 @@ func (m *kvMeta) Fallocate(ctx Context, inode Ino, mode uint8, off uint64, size
if err := m.checkQuota(ctx, newSpace, 0, m.getParents(tx, inode, t.Parent)...); err != 0 {
return err
}
if flength != nil {
*flength = length
}
t.Length = length
now := time.Now()
t.Mtime = now.Unix()
Expand Down Expand Up @@ -1995,7 +1998,7 @@ func (m *kvMeta) Write(ctx Context, inode Ino, indx uint32, off uint32, slice Sl
return errno(err)
}

func (m *kvMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, offOut uint64, size uint64, flags uint32, copied *uint64) syscall.Errno {
func (m *kvMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, offOut uint64, size uint64, flags uint32, copied, outLength *uint64) syscall.Errno {
defer m.timeit("CopyFileRange", time.Now())
var newLength, newSpace int64
f := m.of.find(fout)
Expand All @@ -2017,7 +2020,9 @@ func (m *kvMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, off
return syscall.EINVAL
}
if offIn >= sattr.Length {
*copied = 0
if copied != nil {
*copied = 0
}
return nil
}
size := size
Expand Down Expand Up @@ -2047,6 +2052,9 @@ func (m *kvMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, off
attr.Mtimensec = uint32(now.Nanosecond())
attr.Ctime = now.Unix()
attr.Ctimensec = uint32(now.Nanosecond())
if outLength != nil {
*outLength = attr.Length
}

vals := make(map[string][]byte)
tx.scan(m.chunkKey(fin, uint32(offIn/ChunkSize)), m.chunkKey(fin, uint32((offIn+size)/ChunkSize)+1),
Expand Down Expand Up @@ -2109,7 +2117,9 @@ func (m *kvMeta) CopyFileRange(ctx Context, fin Ino, offIn uint64, fout Ino, off
}
}
tx.set(m.inodeKey(fout), m.marshal(&attr))
*copied = size
if copied != nil {
*copied = size
}
return nil
}, fout)
if err == nil {
Expand Down
Loading

0 comments on commit 4239270

Please sign in to comment.