Updated documentation in light of the investigation in issue #8.

geesefs-0-30-9
Aaron Jacobs 2015-04-02 10:45:38 +11:00
parent dadff5d9b5
commit 7ed1d0689d
2 changed files with 14 additions and 30 deletions

View File

@ -707,7 +707,8 @@ func (o *ReadFileOp) Respond(err error) {
// * (http://goo.gl/RqYIxY) fuse_writepage_locked makes a write request to
// the userspace server.
//
// Note that writes *will* be received before a FlushOp when closing the file
// Note that the kernel *will* ensure that writes are received and acknowledged
// by the file system before sending a FlushFileOp when closing the file
// descriptor to which they were written:
//
// * (http://goo.gl/PheZjf) fuse_flush calls write_inode_now, which appears
@ -720,22 +721,8 @@ func (o *ReadFileOp) Respond(err error) {
// * (http://goo.gl/zzvxWv) Only then does fuse_flush finally send the
// flush request.
//
// Beware however that this is only the receipt of the write ops. fuse_flush
// doesn't actually wait for the responses to the write ops that it ensures it
// delivers:
//
// * (http://goo.gl/NdARvf) fuse_flush_writepages calls fuse_send_writepage.
//
// * (http://goo.gl/smVC67) fuse_send_writepage calls
// fuse_request_send_background_locked.
//
// * (http://goo.gl/WUqfFv) fuse_request_send_background_locked calls
// fuse_request_send_nowait_locked, which doesn't wait for a response.
//
// This package faithfully delivers requests in the order they were received
// from /dev/fuse, so this is not an issue unless the file system makes an
// effort to be parallel. In that case, it probably wants to ensure that write
// and flush ops are properly serialized.
// (See also http://goo.gl/ocdTdM, fuse-devel thread "Fuse guarantees on
// concurrent requests".)
type WriteFileOp struct {
commonOp
@ -805,11 +792,6 @@ func (o *WriteFileOp) Respond(err error) {
//
// See also: FlushFileOp, which may perform a similar function when closing a
// file (but which is not used in "real" file systems).
//
// In contrast to fuse_flush (see notes on FlushFileOp), fuse_fsync does appear
// to wait for write responses before sending the sync request (cf.
// http://goo.gl/grmAVH). However careful implementers would be well-advised to
// ensure the serialization themselves.
type SyncFileOp struct {
commonOp
@ -853,16 +835,16 @@ func (o *SyncFileOp) Respond(err error) {
//
// * However, even on OS X you can arrange for writes via a mapping to be
// flushed by calling msync(2) followed by close(2). On OS X msync(2)
// will cause a WriteFile to go through and close(2) will cause a
// will cause a WriteFileOps to go through and close(2) will cause a
// FlushFile as usual (cf. http://goo.gl/kVmNcx). On Linux, msync(2) does
// nothing unless you set the MS_SYNC flag, in which case it causes a
// SyncFile (cf. http://goo.gl/P3mErk).
// SyncFileOp to be sent (cf. http://goo.gl/P3mErk).
//
// In summary: if you make data durable in both FlushFile and SyncFile, then
// your users can get safe behavior from mapped files by calling msync(2)
// with MS_SYNC, followed by munmap(2), followed by close(2). On Linux, the
// msync(2) appears to be optional because close(2) implies dirty page
// writeback (cf. http://goo.gl/HyzLTT).
// your users can get safe behavior from mapped files on both operating systems
// by calling msync(2) with MS_SYNC, followed by munmap(2), followed by
// close(2). On Linux, the msync(2) is optional (cf. http://goo.gl/EIhAxv and
// the notes on WriteFileOp).
//
// Because of cases like dup2(2), FlushFileOps are not necessarily one to one
// with OpenFileOps. They should not be used for reference counting, and the

View File

@ -58,8 +58,10 @@ type FileSystem interface {
// FileSystem methods are called ine exactly the order of supported ops
// received by the connection, on a single goroutine. The methods should
// probably not block, instead continuing long-running operations in the
// background. Note however that there are subtleties here: for example, you
// probably want to serialize the order of write and flush operations.
// background. It is safe to naively do so, because the kernel guarantees to
// serialize operations that the user expects to happen in order (cf.
// http://goo.gl/jnkHPO, fuse-devel thread "Fuse guarantees on concurrent
// requests").
func NewFileSystemServer(fs FileSystem) fuse.Server {
return fileSystemServer{fs}
}