diff --git a/conversions.go b/conversions.go index 4416412..c330f8a 100644 --- a/conversions.go +++ b/conversions.go @@ -113,6 +113,32 @@ func convertInMessage( OpContext: fuseops.OpContext{Pid: inMsg.Header().Pid}, } + case fusekernel.OpBatchForget: + type input fusekernel.BatchForgetCountIn + in := (*input)(inMsg.Consume(unsafe.Sizeof(input{}))) + if in == nil { + return nil, errors.New("Corrupt OpBatchForget") + } + + entries := make([]fuseops.BatchForgetEntry, 0, in.Count) + for i := uint32(0); i < in.Count; i++ { + type entry fusekernel.BatchForgetEntryIn + ein := (*entry)(inMsg.Consume(unsafe.Sizeof(entry{}))) + if ein == nil { + return nil, errors.New("Corrupt OpBatchForget") + } + + entries = append(entries, fuseops.BatchForgetEntry{ + Inode: fuseops.InodeID(ein.Inode), + N: ein.Nlookup, + }) + } + + o = &fuseops.BatchForgetOp{ + Entries: entries, + OpContext: fuseops.OpContext{Pid: inMsg.Header().Pid}, + } + case fusekernel.OpMkdir: in := (*fusekernel.MkdirIn)(inMsg.Consume(fusekernel.MkdirInSize(protocol))) if in == nil { @@ -595,6 +621,9 @@ func (c *Connection) kernelResponse( case *fuseops.ForgetInodeOp: return true + case *fuseops.BatchForgetOp: + return true + case *interruptOp: return true } diff --git a/fuseops/ops.go b/fuseops/ops.go index 9a0b8c5..06537d9 100644 --- a/fuseops/ops.go +++ b/fuseops/ops.go @@ -220,6 +220,32 @@ type ForgetInodeOp struct { OpContext OpContext } +// BatchForgetEntry represents one Inode entry to forget in the BatchForgetOp. +// +// Everything written in the ForgetInodeOp docs applies for the BatchForgetEntry +// too. +type BatchForgetEntry struct { + // The inode whose reference count should be decremented. + Inode InodeID + + // The amount to decrement the reference count. + N uint64 +} + +// Decrement the reference counts for a list of inode IDs previously issued by the file +// system. +// +// This operation is a batch of ForgetInodeOp operations. Every entry in +// Entries is one ForgetInodeOp operation. See the docs of ForgetInodeOp +// for further details. +type BatchForgetOp struct { + // Entries is a list of Forget operations. One could treat every entry in the + // list as a single ForgetInodeOp operation. + Entries []BatchForgetEntry + + OpContext OpContext +} + //////////////////////////////////////////////////////////////////////// // Inode creation //////////////////////////////////////////////////////////////////////// diff --git a/fuseutil/file_system.go b/fuseutil/file_system.go index 5eb8bca..b0e633a 100644 --- a/fuseutil/file_system.go +++ b/fuseutil/file_system.go @@ -39,6 +39,7 @@ type FileSystem interface { GetInodeAttributes(context.Context, *fuseops.GetInodeAttributesOp) error SetInodeAttributes(context.Context, *fuseops.SetInodeAttributesOp) error ForgetInode(context.Context, *fuseops.ForgetInodeOp) error + BatchForget(context.Context, *fuseops.BatchForgetOp) error MkDir(context.Context, *fuseops.MkDirOp) error MkNode(context.Context, *fuseops.MkNodeOp) error CreateFile(context.Context, *fuseops.CreateFileOp) error @@ -151,6 +152,9 @@ func (s *fileSystemServer) handleOp( case *fuseops.ForgetInodeOp: err = s.fs.ForgetInode(ctx, typed) + case *fuseops.BatchForgetOp: + err = s.fs.BatchForget(ctx, typed) + case *fuseops.MkDirOp: err = s.fs.MkDir(ctx, typed) diff --git a/fuseutil/not_implemented_file_system.go b/fuseutil/not_implemented_file_system.go index 4d29cfa..cfb116c 100644 --- a/fuseutil/not_implemented_file_system.go +++ b/fuseutil/not_implemented_file_system.go @@ -60,6 +60,12 @@ func (fs *NotImplementedFileSystem) ForgetInode( return fuse.ENOSYS } +func (fs *NotImplementedFileSystem) BatchForget( + ctx context.Context, + op *fuseops.BatchForgetOp) error { + return fuse.ENOSYS +} + func (fs *NotImplementedFileSystem) MkDir( ctx context.Context, op *fuseops.MkDirOp) error { diff --git a/internal/fusekernel/fuse_kernel.go b/internal/fusekernel/fuse_kernel.go index e2d55ec..c1aded9 100644 --- a/internal/fusekernel/fuse_kernel.go +++ b/internal/fusekernel/fuse_kernel.go @@ -386,6 +386,7 @@ const ( OpDestroy = 38 OpIoctl = 39 // Linux? OpPoll = 40 // Linux? + OpBatchForget = 42 OpFallocate = 43 // OS X @@ -417,6 +418,16 @@ type ForgetIn struct { Nlookup uint64 } +type BatchForgetCountIn struct { + Count uint32 + dummy uint32 +} + +type BatchForgetEntryIn struct { + Inode int64 + Nlookup uint64 +} + type GetattrIn struct { GetattrFlags uint32 dummy uint32