diff options
author | Jakob Unterwurzacher | 2020-07-12 12:59:01 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2020-07-12 12:59:01 +0200 |
commit | 6196a5b5fe78f7a5b8e38c00e656f70c1592e1df (patch) | |
tree | 6bb2eb3058080f589a29d7104a09c2c6f3a1162e /internal/fusefrontend/file2.go | |
parent | d539a4c21474a5d45bb3b8432d7b6f07664e61bd (diff) |
v2api: File2: implement Release, Read, Write, Fsync, Flush, Allocate
Fortunately, this just means fixing up the function
signatures.
Diffstat (limited to 'internal/fusefrontend/file2.go')
-rw-r--r-- | internal/fusefrontend/file2.go | 78 |
1 files changed, 40 insertions, 38 deletions
diff --git a/internal/fusefrontend/file2.go b/internal/fusefrontend/file2.go index 7fe3d3a..0de325c 100644 --- a/internal/fusefrontend/file2.go +++ b/internal/fusefrontend/file2.go @@ -25,6 +25,7 @@ import ( "github.com/rfjakob/gocryptfs/internal/tlog" ) +// File2 implements the go-fuse v2 API (github.com/hanwen/go-fuse/v2/fs) type File2 struct { fd *os.File // Has Release() already been called on this file? This also means that the @@ -129,7 +130,7 @@ func (f *File2) createHeader() (fileID []byte, err error) { // // Called by Read() for normal reading, // by Write() and Truncate() via doWrite() for Read-Modify-Write. -func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Status) { +func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, syscall.Errno) { // Get the file ID, either from the open file table, or from disk. var fileID []byte f.fileTableEntry.IDLock.Lock() @@ -144,7 +145,7 @@ func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Stat f.fileTableEntry.IDLock.Unlock() if err == io.EOF { // Empty file - return nil, fuse.OK + return nil, 0 } buf := make([]byte, 100) n, _ := f.fd.ReadAt(buf, 0) @@ -152,7 +153,7 @@ func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Stat hexdump := hex.EncodeToString(buf) tlog.Warn.Printf("doRead %d: corrupt header: %v\nFile hexdump (%d bytes): %s", f.qIno.Ino, err, n, hexdump) - return nil, fuse.EIO + return nil, syscall.EIO } // Save into the file table f.fileTableEntry.ID = fileID @@ -173,12 +174,12 @@ func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Stat n, err := f.fd.ReadAt(ciphertext, int64(alignedOffset)) if err != nil && err != io.EOF { tlog.Warn.Printf("read: ReadAt: %s", err.Error()) - return nil, fuse.ToStatus(err) + return nil, fs.ToErrno(err) } // The ReadAt came back empty. We can skip all the decryption and return early. if n == 0 { f.rootNode.contentEnc.CReqPool.Put(ciphertext) - return dst, fuse.OK + return dst, 0 } // Truncate ciphertext buffer down to actually read bytes ciphertext = ciphertext[0:n] @@ -198,7 +199,7 @@ func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Stat } else { curruptBlockNo := firstBlockNo + f.contentEnc.PlainOffToBlockNo(uint64(len(plaintext))) tlog.Warn.Printf("doRead %d: corrupt block #%d: %v", f.qIno.Ino, curruptBlockNo, err) - return nil, fuse.EIO + return nil, syscall.EIO } } @@ -216,15 +217,15 @@ func (f *File2) doRead(dst []byte, off uint64, length uint64) ([]byte, fuse.Stat out = append(dst, out...) f.rootNode.contentEnc.PReqPool.Put(plaintext) - return out, fuse.OK + return out, 0 } // Read - FUSE call -func (f *File2) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fuse.Status) { +func (f *File2) Read(ctx context.Context, buf []byte, off int64) (resultData fuse.ReadResult, errno syscall.Errno) { if len(buf) > fuse.MAX_KERNEL_WRITE { // This would crash us due to our fixed-size buffer pool tlog.Warn.Printf("Read: rejecting oversized request with EMSGSIZE, len=%d", len(buf)) - return nil, fuse.Status(syscall.EMSGSIZE) + return nil, syscall.EMSGSIZE } f.fdLock.RLock() defer f.fdLock.RUnlock() @@ -236,15 +237,15 @@ func (f *File2) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fu if f.rootNode.args.SerializeReads { serialize_reads.Wait(off, len(buf)) } - out, status := f.doRead(buf[:0], uint64(off), uint64(len(buf))) + out, errno := f.doRead(buf[:0], uint64(off), uint64(len(buf))) if f.rootNode.args.SerializeReads { serialize_reads.Done() } - if status != fuse.OK { - return nil, status + if errno != 0 { + return nil, errno } - tlog.Debug.Printf("ino%d: Read: status %v, returning %d bytes", f.qIno.Ino, status, len(out)) - return fuse.ReadResultData(out), status + tlog.Debug.Printf("ino%d: Read: errno=%d, returning %d bytes", f.qIno.Ino, errno, len(out)) + return fuse.ReadResultData(out), errno } // doWrite - encrypt "data" and write it to plaintext offset "off" @@ -256,7 +257,7 @@ func (f *File2) Read(buf []byte, off int64) (resultData fuse.ReadResult, code fu // and by Truncate() to rewrite the last file block. // // Empty writes do nothing and are allowed. -func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) { +func (f *File2) doWrite(data []byte, off int64) (uint32, syscall.Errno) { fileWasEmpty := false // Get the file ID, create a new one if it does not exist yet. var fileID []byte @@ -274,7 +275,7 @@ func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) { fileWasEmpty = true } if err != nil { - return 0, fuse.ToStatus(err) + return 0, fs.ToErrno(err) } f.fileTableEntry.ID = fileID } @@ -287,10 +288,10 @@ func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) { // Incomplete block -> Read-Modify-Write if b.IsPartial() { // Read - oldData, status := f.doRead(nil, b.BlockPlainOff(), f.contentEnc.PlainBS()) - if status != fuse.OK { - tlog.Warn.Printf("ino%d fh%d: RMW read failed: %s", f.qIno.Ino, f.intFd(), status.String()) - return 0, status + oldData, errno := f.doRead(nil, b.BlockPlainOff(), f.contentEnc.PlainBS()) + if errno != 0 { + tlog.Warn.Printf("ino%d fh%d: RMW read failed: errno=%d", f.qIno.Ino, f.intFd(), errno) + return 0, errno } // Modify blockData = f.contentEnc.MergeBlocks(oldData, blockData, int(b.Skip)) @@ -321,7 +322,7 @@ func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) { tlog.Warn.Printf("ino%d fh%d: doWrite: rollback failed: %v", f.qIno.Ino, f.intFd(), err2) } } - return 0, fuse.ToStatus(err) + return 0, fs.ToErrno(err) } } // Write @@ -331,9 +332,9 @@ func (f *File2) doWrite(data []byte, off int64) (uint32, fuse.Status) { if err != nil { tlog.Warn.Printf("ino%d fh%d: doWrite: WriteAt off=%d len=%d failed: %v", f.qIno.Ino, f.intFd(), cOff, len(ciphertext), err) - return 0, fuse.ToStatus(err) + return 0, fs.ToErrno(err) } - return uint32(len(data)), fuse.OK + return uint32(len(data)), 0 } // isConsecutiveWrite returns true if the current write @@ -349,18 +350,18 @@ func (f *File2) isConsecutiveWrite(off int64) bool { // Write - FUSE call // // If the write creates a hole, pads the file to the next block boundary. -func (f *File2) Write(data []byte, off int64) (uint32, fuse.Status) { +func (f *File2) Write(ctx context.Context, data []byte, off int64) (uint32, syscall.Errno) { if len(data) > fuse.MAX_KERNEL_WRITE { // This would crash us due to our fixed-size buffer pool tlog.Warn.Printf("Write: rejecting oversized request with EMSGSIZE, len=%d", len(data)) - return 0, fuse.Status(syscall.EMSGSIZE) + return 0, syscall.EMSGSIZE } f.fdLock.RLock() defer f.fdLock.RUnlock() if f.released { // The file descriptor has been closed concurrently tlog.Warn.Printf("ino%d fh%d: Write on released file", f.qIno.Ino, f.intFd()) - return 0, fuse.EBADF + return 0, syscall.EBADF } f.fileTableEntry.ContentLock.Lock() defer f.fileTableEntry.ContentLock.Unlock() @@ -369,21 +370,21 @@ func (f *File2) Write(data []byte, off int64) (uint32, fuse.Status) { // But if the write directly follows an earlier write, it cannot create a // hole, and we can save one Stat() call. if !f.isConsecutiveWrite(off) { - status := f.writePadHole(off) - if !status.Ok() { - return 0, status + errno := f.writePadHole(off) + if errno != 0 { + return 0, errno } } - n, status := f.doWrite(data, off) - if status.Ok() { + n, errno := f.doWrite(data, off) + if errno != 0 { f.lastOpCount = openfiletable.WriteOpCount() f.lastWrittenOffset = off + int64(len(data)) - 1 } - return n, status + return n, errno } // Release - FUSE call, close file -func (f *File2) Release() { +func (f *File2) Release(ctx context.Context) syscall.Errno { f.fdLock.Lock() if f.released { log.Panicf("ino%d fh%d: double release", f.qIno.Ino, f.intFd()) @@ -392,10 +393,11 @@ func (f *File2) Release() { openfiletable.Unregister(f.qIno) f.fd.Close() f.fdLock.Unlock() + return 0 } // Flush - FUSE call -func (f *File2) Flush() fuse.Status { +func (f *File2) Flush(ctx context.Context) syscall.Errno { f.fdLock.RLock() defer f.fdLock.RUnlock() @@ -405,18 +407,18 @@ func (f *File2) Flush() fuse.Status { newFd, err := syscall.Dup(f.intFd()) if err != nil { - return fuse.ToStatus(err) + return fs.ToErrno(err) } err = syscall.Close(newFd) - return fuse.ToStatus(err) + return fs.ToErrno(err) } // Fsync FUSE call -func (f *File2) Fsync(flags int) (code fuse.Status) { +func (f *File2) Fsync(ctx context.Context, flags uint32) (errno syscall.Errno) { f.fdLock.RLock() defer f.fdLock.RUnlock() - return fuse.ToStatus(syscall.Fsync(f.intFd())) + return fs.ToErrno(syscall.Fsync(f.intFd())) } // Getattr FUSE call (like stat) |