From 22c6e605c0cd258c73c182c3b7dc7170f6348bc7 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 12:45:12 +1100 Subject: [PATCH 01/11] Added a test name for dup. --- samples/flushfs/flush_fs_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/samples/flushfs/flush_fs_test.go b/samples/flushfs/flush_fs_test.go index 4c6eda0..4663b46 100644 --- a/samples/flushfs/flush_fs_test.go +++ b/samples/flushfs/flush_fs_test.go @@ -340,6 +340,10 @@ func (t *FlushFSTest) CloseReports_MultipleTimes_OverlappingFileHandles() { AssertThat(t.getFsyncs(), ElementsAre()) } +func (t *FlushFSTest) CloseReports_DuplicatedFileDescriptor() { + AssertTrue(false, "TODO") +} + func (t *FlushFSTest) CloseError() { // Open the file. f, err := os.OpenFile(path.Join(t.Dir, "foo"), os.O_RDWR, 0) From bf6ff94688a03a2647dfb7a81141d41dd4fff10b Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:16:50 +1100 Subject: [PATCH 02/11] Added a FlushFile method. --- file_system.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/file_system.go b/file_system.go index 791c7c2..6572090 100644 --- a/file_system.go +++ b/file_system.go @@ -211,6 +211,34 @@ type FileSystem interface { ctx context.Context, req *WriteFileRequest) (*WriteFileResponse, error) + // Flush the current state of an open file to storage. + // + // vfs.txt documents this as being called for each close(2) system call (cf. + // http://goo.gl/FSkbrq). Code walk for that case: + // + // * (http://goo.gl/e3lv0e) sys_close calls __close_fd, calls filp_close. + // * (http://goo.gl/nI8fxD) filp_close calls f_op->flush (fuse_flush). + // + // But note that this is also called in other contexts where a file + // descriptor is closed, such as dup2(2) (cf. http://goo.gl/NQDvFS). In the + // case of close(2), a flush error is returned to the user. For dup2(2), it + // is not. + // + // Because of cases like dup2(2), calls to FlushFile are not necessarily one + // to one with calls to OpenFile. They should not be used for reference + // counting, and the handle must remain valid even after the method is called + // (use ReleaseFileHandle to dispose of it). + // + // Typical "real" file systems do not implement this, presumably relying on + // the kernel to write out the page cache to the block device eventually. + // They can get away with this because a later open(2) will see the same + // data. A file system that writes to remote storage however probably wants + // to at least schedule a real flush, and maybe do it immediately in order to + // return any errors that occur. + FlushFile( + ctx context.Context, + req *FlushFileRequest) (*FlushFileResponse, err) + // Release a previously-minted file handle. The kernel calls this when there // are no more references to an open file: all file descriptors are closed // and all memory mappings are unmapped. From 4a92165ab8a6f0d04aa44fba9cbc7c91191f5dc6 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:21:14 +1100 Subject: [PATCH 03/11] Added more flush test names. --- samples/flushfs/flush_fs_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/samples/flushfs/flush_fs_test.go b/samples/flushfs/flush_fs_test.go index 4663b46..71a0e26 100644 --- a/samples/flushfs/flush_fs_test.go +++ b/samples/flushfs/flush_fs_test.go @@ -431,3 +431,23 @@ func (t *FlushFSTest) FsyncError() { AssertNe(nil, err) ExpectThat(err, Error(HasSubstr("TODO"))) } + +func (t *FlushFSTest) Dup() { + AssertTrue(false, "TODO") +} + +func (t *FlushFSTest) Dup_CloseError() { + AssertTrue(false, "TODO") +} + +func (t *FlushFSTest) Dup2() { + AssertTrue(false, "TODO") +} + +func (t *FlushFSTest) Dup2_CloseError() { + AssertTrue(false, "TODO") +} + +func (t *FlushFSTest) Mmap() { + AssertTrue(false, "TODO") +} From 1ff10b144afe857aa4cd2fc305b25a85696c73b5 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:22:38 +1100 Subject: [PATCH 04/11] Defined FlushFile structs. --- file_system.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/file_system.go b/file_system.go index 6572090..834e172 100644 --- a/file_system.go +++ b/file_system.go @@ -823,6 +823,17 @@ type WriteFileRequest struct { type WriteFileResponse struct { } +type FlushFileRequest struct { + Header RequestHeader + + // The file and handle being flushed. + Inode InodeID + Handle HandleID +} + +type FlushFileResponse struct { +} + type ReleaseFileHandleRequest struct { Header RequestHeader From f285c2a51e947f9f23e7a56297a4e63e19911471 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:22:50 +1100 Subject: [PATCH 05/11] Fixed a build error. --- file_system.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file_system.go b/file_system.go index 834e172..815096b 100644 --- a/file_system.go +++ b/file_system.go @@ -237,7 +237,7 @@ type FileSystem interface { // return any errors that occur. FlushFile( ctx context.Context, - req *FlushFileRequest) (*FlushFileResponse, err) + req *FlushFileRequest) (*FlushFileResponse, error) // Release a previously-minted file handle. The kernel calls this when there // are no more references to an open file: all file descriptors are closed From 2fcd202d6692aa2a7430137f9580433e0ebbe53f Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:23:12 +1100 Subject: [PATCH 06/11] NotImplementedFileSystem.FlushFile --- fuseutil/not_implemented_file_system.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fuseutil/not_implemented_file_system.go b/fuseutil/not_implemented_file_system.go index e80ac99..2bc4b11 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) FlushFile( + ctx context.Context, + req *fuse.FlushFileRequest) (*fuse.FlushFileResponse, error) { + return nil, fuse.ENOSYS +} + func (fs *NotImplementedFileSystem) ReleaseFileHandle( ctx context.Context, req *fuse.ReleaseFileHandleRequest) (*fuse.ReleaseFileHandleResponse, error) { From 7af6c9300f0148556195f71758794d5866b30ccf Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:24:02 +1100 Subject: [PATCH 07/11] Declared a test for directories. --- samples/flushfs/flush_fs_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/samples/flushfs/flush_fs_test.go b/samples/flushfs/flush_fs_test.go index 71a0e26..fa6b628 100644 --- a/samples/flushfs/flush_fs_test.go +++ b/samples/flushfs/flush_fs_test.go @@ -451,3 +451,7 @@ func (t *FlushFSTest) Dup2_CloseError() { func (t *FlushFSTest) Mmap() { AssertTrue(false, "TODO") } + +func (t *FlushFSTest) Directory() { + AssertTrue(false, "TODO") +} From b0cb3df8c15bfdadaa666248fc7dac46966e99f1 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:26:04 +1100 Subject: [PATCH 08/11] Added server support. --- server.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/server.go b/server.go index 78df495..c876361 100644 --- a/server.go +++ b/server.go @@ -427,6 +427,25 @@ func (s *server) handleFuseRequest(fuseReq bazilfuse.Request) { typed.Respond(fuseResp) } + case *bazilfuse.FlushRequest: + // Convert the request. + req := &FlushFileRequest{ + Header: convertHeader(typed.Header), + Inode: InodeID(typed.Header.Node), + Handle: HandleID(typed.Handle), + } + + // Call the file system. + _, err := s.fs.FlushFile(ctx, req) + if err != nil { + s.logger.Println("Responding:", err) + typed.RespondError(err) + return + } + + s.logger.Println("Responding OK.") + typed.Respond() + case *bazilfuse.ReleaseRequest: // Directory or file? if typed.Dir { From 8ab34bc0e4f1feacc860ef3a6b0869a5c4f1e0a5 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:27:27 +1100 Subject: [PATCH 09/11] flushFS.FlushFile --- samples/flushfs/flush_fs.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/samples/flushfs/flush_fs.go b/samples/flushfs/flush_fs.go index 2cf3ecf..7d89734 100644 --- a/samples/flushfs/flush_fs.go +++ b/samples/flushfs/flush_fs.go @@ -32,7 +32,11 @@ import ( func NewFileSystem( reportFlush func(string) error, reportFsync func(string) error) (fs fuse.FileSystem, err error) { - fs = &flushFS{} + fs = &flushFS{ + reportFlush: reportFlush, + reportFsync: reportFsync, + } + return } @@ -40,6 +44,8 @@ const fooID = fuse.RootInodeID + 1 type flushFS struct { fuseutil.NotImplementedFileSystem + reportFlush func(string) error + reportFsync func(string) error mu sync.Mutex fooContents []byte // GUARDED_BY(mu) @@ -168,3 +174,16 @@ func (fs *flushFS) WriteFile( return } + +func (fs *flushFS) FlushFile( + ctx context.Context, + req *fuse.FlushFileRequest) ( + resp *fuse.FlushFileResponse, err error) { + resp = &fuse.FlushFileResponse{} + + fs.mu.Lock() + defer fs.mu.Unlock() + + err = fs.reportFlush(string(fs.fooContents)) + return +} From 4fba58178cf911f71ab9a59e22d1db1405666110 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:28:51 +1100 Subject: [PATCH 10/11] Fixed a file system bug. --- samples/flushfs/flush_fs.go | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/flushfs/flush_fs.go b/samples/flushfs/flush_fs.go index 7d89734..6bc61c2 100644 --- a/samples/flushfs/flush_fs.go +++ b/samples/flushfs/flush_fs.go @@ -68,6 +68,7 @@ func (fs *flushFS) fooAttributes() fuse.InodeAttributes { return fuse.InodeAttributes{ Nlink: 1, Mode: 0777, + Size: uint64(len(fs.fooContents)), } } From f1d36b3117bed8ebaff01a3e72c94a4deab1606b Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 20 Mar 2015 13:29:15 +1100 Subject: [PATCH 11/11] Filled in test TODOs. --- samples/flushfs/flush_fs_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/flushfs/flush_fs_test.go b/samples/flushfs/flush_fs_test.go index fa6b628..e5337ce 100644 --- a/samples/flushfs/flush_fs_test.go +++ b/samples/flushfs/flush_fs_test.go @@ -363,7 +363,7 @@ func (t *FlushFSTest) CloseError() { f = nil AssertNe(nil, err) - ExpectThat(err, Error(HasSubstr("TODO"))) + ExpectThat(err, Error(HasSubstr("no such file"))) } func (t *FlushFSTest) FsyncReports() { @@ -429,7 +429,7 @@ func (t *FlushFSTest) FsyncError() { err = f.Sync() AssertNe(nil, err) - ExpectThat(err, Error(HasSubstr("TODO"))) + ExpectThat(err, Error(HasSubstr("no such file"))) } func (t *FlushFSTest) Dup() {