diff --git a/file_system.go b/file_system.go index 815096b..cfe5bf9 100644 --- a/file_system.go +++ b/file_system.go @@ -211,7 +211,25 @@ type FileSystem interface { ctx context.Context, req *WriteFileRequest) (*WriteFileResponse, error) - // Flush the current state of an open file to storage. + // Synchronize the current contents of an open file to storage. + // + // vfs.txt documents this as being called for by the fsync(2) system call + // (cf. http://goo.gl/j9X8nB). Code walk for that case: + // + // * (http://goo.gl/IQkWZa) sys_fsync calls do_fsync, calls vfs_fsync, calls + // vfs_fsync_range. + // * (http://goo.gl/5L2SMy) vfs_fsync_range calls f_op->fsync. + // + // Note that this is also called by fdatasync(2) (cf. http://goo.gl/01R7rF). + // + // See also: FlushFile, which may perform a similar purpose when closing a + // file (but which is not used in "real" file systems). + SyncFile( + ctx context.Context, + req *SyncFileRequest) (*SyncFileResponse, error) + + // Flush the current state of an open file to storage upon closing a file + // descriptor. // // vfs.txt documents this as being called for each close(2) system call (cf. // http://goo.gl/FSkbrq). Code walk for that case: @@ -823,6 +841,17 @@ type WriteFileRequest struct { type WriteFileResponse struct { } +type SyncFileRequest struct { + Header RequestHeader + + // The file and handle being sync'd. + Inode InodeID + Handle HandleID +} + +type SyncFileResponse struct { +} + type FlushFileRequest struct { Header RequestHeader diff --git a/fuseutil/not_implemented_file_system.go b/fuseutil/not_implemented_file_system.go index 2bc4b11..9b21d95 100644 --- a/fuseutil/not_implemented_file_system.go +++ b/fuseutil/not_implemented_file_system.go @@ -118,6 +118,12 @@ func (fs *NotImplementedFileSystem) WriteFile( return nil, fuse.ENOSYS } +func (fs *NotImplementedFileSystem) SyncFile( + ctx context.Context, + req *fuse.SyncFileRequest) (*fuse.SyncFileResponse, error) { + return nil, fuse.ENOSYS +} + func (fs *NotImplementedFileSystem) FlushFile( ctx context.Context, req *fuse.FlushFileRequest) (*fuse.FlushFileResponse, error) { diff --git a/samples/flushfs/flush_fs.go b/samples/flushfs/flush_fs.go index 6bc61c2..c38c4e9 100644 --- a/samples/flushfs/flush_fs.go +++ b/samples/flushfs/flush_fs.go @@ -176,6 +176,19 @@ func (fs *flushFS) WriteFile( return } +func (fs *flushFS) SyncFile( + ctx context.Context, + req *fuse.SyncFileRequest) ( + resp *fuse.SyncFileResponse, err error) { + resp = &fuse.SyncFileResponse{} + + fs.mu.Lock() + defer fs.mu.Unlock() + + err = fs.reportFsync(string(fs.fooContents)) + return +} + func (fs *flushFS) FlushFile( ctx context.Context, req *fuse.FlushFileRequest) ( diff --git a/server.go b/server.go index c876361..91c05ca 100644 --- a/server.go +++ b/server.go @@ -427,6 +427,32 @@ func (s *server) handleFuseRequest(fuseReq bazilfuse.Request) { typed.Respond(fuseResp) } + case *bazilfuse.FsyncRequest: + // We don't currently support this for directories. + if typed.Dir { + s.logger.Println("fsyncdir not supported. Returning ENOSYS.") + typed.RespondError(ENOSYS) + return + } + + // Convert the request. + req := &SyncFileRequest{ + Header: convertHeader(typed.Header), + Inode: InodeID(typed.Header.Node), + Handle: HandleID(typed.Handle), + } + + // Call the file system. + _, err := s.fs.SyncFile(ctx, req) + if err != nil { + s.logger.Println("Responding:", err) + typed.RespondError(err) + return + } + + s.logger.Println("Responding OK.") + typed.Respond() + case *bazilfuse.FlushRequest: // Convert the request. req := &FlushFileRequest{