add support for fallocate (#66)

* Fallocate support

* use fallocate wrapper that works on darwin
geesefs-0-30-9
Ka-Hing Cheung 2019-10-26 10:15:00 +02:00 committed by Michael Stapelberg
parent 081e9f4bc7
commit 4ee1cf7f62
9 changed files with 116 additions and 0 deletions

View File

@ -546,6 +546,21 @@ func convertInMessage(
Value: value,
Flags: in.Flags,
}
case fusekernel.OpFallocate:
type input fusekernel.FallocateIn
in := (*input)(inMsg.Consume(unsafe.Sizeof(input{})))
if in == nil {
err = errors.New("Corrupt OpFallocate")
return
}
o = &fuseops.FallocateOp{
Inode: fuseops.InodeID(inMsg.Header().Nodeid),
Handle: fuseops.HandleID(in.Fh),
Offset: in.Offset,
Length: in.Length,
Mode: in.Mode,
}
default:
o = &unknownOp{
@ -793,6 +808,9 @@ func (c *Connection) kernelResponseForOp(
case *fuseops.SetXattrOp:
// Empty response
case *fuseops.FallocateOp:
// Empty response
case *initOp:
out := (*fusekernel.InitOut)(m.Grow(int(unsafe.Sizeof(fusekernel.InitOut{}))))

View File

@ -98,6 +98,11 @@ func describeRequest(op interface{}) (s string) {
case *fuseops.SetXattrOp:
addComponent("name %s", typed.Name)
case *fuseops.FallocateOp:
addComponent("offset %d", typed.Offset)
addComponent("length %d", typed.Length)
addComponent("mode %d", typed.Mode)
}
// Use just the name if there is no extra info.

View File

@ -865,3 +865,22 @@ type SetXattrOp struct {
// simply replace the value if the attribute exists.
Flags uint32
}
type FallocateOp struct {
// The inode and handle we are fallocating
Inode InodeID
Handle HandleID
// Start of the byte range
Offset uint64
// Length of the byte range
Length uint64
// If Mode is 0x0, allocate disk space within the range specified
// If Mode has 0x1, allocate the space but don't increase the file size
// If Mode has 0x2, deallocate space within the range specified
// If Mode has 0x2, it sbould also have 0x1 (deallocate should not increase
// file size)
Mode uint32
}

View File

@ -61,6 +61,7 @@ type FileSystem interface {
GetXattr(context.Context, *fuseops.GetXattrOp) error
ListXattr(context.Context, *fuseops.ListXattrOp) error
SetXattr(context.Context, *fuseops.SetXattrOp) error
Fallocate(context.Context, *fuseops.FallocateOp) error
// Regard all inodes (including the root inode) as having their lookup counts
// decremented to zero, and clean up any resources associated with the file
@ -215,6 +216,9 @@ func (s *fileSystemServer) handleOp(
case *fuseops.SetXattrOp:
err = s.fs.SetXattr(ctx, typed)
case *fuseops.FallocateOp:
err = s.fs.Fallocate(ctx, typed)
}
c.Reply(ctx, err)

View File

@ -219,5 +219,12 @@ func (fs *NotImplementedFileSystem) SetXattr(
return
}
func (fs *NotImplementedFileSystem) Fallocate(
ctx context.Context,
op *fuseops.FallocateOp) (err error) {
err = fuse.ENOSYS
return
}
func (fs *NotImplementedFileSystem) Destroy() {
}

View File

@ -380,6 +380,7 @@ const (
OpDestroy = 38
OpIoctl = 39 // Linux?
OpPoll = 40 // Linux?
OpFallocate = 43
// OS X
OpSetvolname = 61
@ -665,6 +666,14 @@ type ListxattrIn struct {
Padding uint32
}
type FallocateIn struct {
Fh uint64
Offset uint64
Length uint64
Mode uint32
Padding uint32
}
type LkIn struct {
Fh uint64
Owner uint64

View File

@ -20,6 +20,7 @@ import (
"os"
"time"
"github.com/jacobsa/fuse"
"github.com/jacobsa/fuse/fuseops"
"github.com/jacobsa/fuse/fuseutil"
)
@ -382,3 +383,18 @@ func (in *inode) SetAttributes(
in.attrs.Mtime = *mtime
}
}
func (in *inode) Fallocate(mode uint32, offset uint64, length uint64) (
err error) {
if mode == 0 {
newSize := int(offset + length)
if newSize > len(in.contents) {
padding := make([]byte, newSize-len(in.contents))
in.contents = append(in.contents, padding...)
in.attrs.Size = offset + length
}
} else {
err = fuse.ENOSYS
}
return
}

View File

@ -753,3 +753,12 @@ func (fs *memFS) SetXattr(ctx context.Context,
return
}
func (fs *memFS) Fallocate(ctx context.Context,
op *fuseops.FallocateOp) (err error) {
fs.mu.Lock()
defer fs.mu.Unlock()
inode := fs.getInodeOrDie(op.Inode)
inode.Fallocate(op.Mode, op.Length, op.Length)
return
}

View File

@ -28,6 +28,7 @@ import (
"testing"
"time"
fallocate "github.com/detailyang/go-fallocate"
"github.com/jacobsa/fuse"
"github.com/jacobsa/fuse/fusetesting"
"github.com/jacobsa/fuse/samples"
@ -1955,3 +1956,31 @@ func (t *MknodTest) NonExistentParent() {
err = syscall.Mknod(p, syscall.S_IFREG|0600, 0)
ExpectEq(syscall.ENOENT, err)
}
func (t *MknodTest) Fallocate_Larger() {
var err error
fileName := path.Join(t.Dir, "foo")
// Create a file.
err = ioutil.WriteFile(fileName, []byte("taco"), 0600)
AssertEq(nil, err)
// Open it for modification.
f, err := os.OpenFile(fileName, os.O_RDWR, 0)
t.ToClose = append(t.ToClose, f)
AssertEq(nil, err)
// Truncate it.
err = fallocate.Fallocate(f, 5, 1)
AssertEq(nil, err)
// Stat it.
fi, err := f.Stat()
AssertEq(nil, err)
ExpectEq(6, fi.Size())
// Read the contents.
contents, err := ioutil.ReadFile(fileName)
AssertEq(nil, err)
ExpectEq("taco\x00\x00", string(contents))
}