Commit ae5da07e authored by Michael Stapelberg's avatar Michael Stapelberg Committed by GitHub

remove naked returns across the code base (#75)

fixes #73
parent 4898d792
......@@ -95,8 +95,8 @@ func newConnection(
cfg MountConfig,
debugLogger *log.Logger,
errorLogger *log.Logger,
dev *os.File) (c *Connection, err error) {
c = &Connection{
dev *os.File) (*Connection, error) {
c := &Connection{
cfg: cfg,
debugLogger: debugLogger,
errorLogger: errorLogger,
......@@ -105,30 +105,26 @@ func newConnection(
}
// Initialize.
err = c.Init()
if err != nil {
if err := c.Init(); err != nil {
c.close()
err = fmt.Errorf("Init: %v", err)
return
return nil, fmt.Errorf("Init: %v", err)
}
return
return c, nil
}
// Init performs the work necessary to cause the mount process to complete.
func (c *Connection) Init() (err error) {
func (c *Connection) Init() error {
// Read the init op.
ctx, op, err := c.ReadOp()
if err != nil {
err = fmt.Errorf("Reading init op: %v", err)
return
return fmt.Errorf("Reading init op: %v", err)
}
initOp, ok := op.(*initOp)
if !ok {
c.Reply(ctx, syscall.EPROTO)
err = fmt.Errorf("Expected *initOp, got %T", op)
return
return fmt.Errorf("Expected *initOp, got %T", op)
}
// Make sure the protocol version spoken by the kernel is new enough.
......@@ -139,8 +135,7 @@ func (c *Connection) Init() (err error) {
if initOp.Kernel.LT(min) {
c.Reply(ctx, syscall.EPROTO)
err = fmt.Errorf("Version too old: %v", initOp.Kernel)
return
return fmt.Errorf("Version too old: %v", initOp.Kernel)
}
// Downgrade our protocol if necessary.
......@@ -169,7 +164,7 @@ func (c *Connection) Init() (err error) {
}
c.Reply(ctx, nil)
return
return nil
}
// Log information for an operation with the given ID. calldepth is the depth
......@@ -228,9 +223,9 @@ func (c *Connection) recordCancelFunc(
// LOCKS_EXCLUDED(c.mu)
func (c *Connection) beginOp(
opCode uint32,
fuseID uint64) (ctx context.Context) {
fuseID uint64) context.Context {
// Start with the parent context.
ctx = c.cfg.OpContext
ctx := c.cfg.OpContext
// Set up a cancellation function.
//
......@@ -246,7 +241,7 @@ func (c *Connection) beginOp(
c.recordCancelFunc(fuseID, cancel)
}
return
return ctx
}
// Clean up all state associated with an op to which the user has responded,
......@@ -307,14 +302,14 @@ func (c *Connection) handleInterrupt(fuseID uint64) {
// Read the next message from the kernel. The message must later be destroyed
// using destroyInMessage.
func (c *Connection) readMessage() (m *buffer.InMessage, err error) {
func (c *Connection) readMessage() (*buffer.InMessage, error) {
// Allocate a message.
m = c.getInMessage()
m := c.getInMessage()
// Loop past transient errors.
for {
// Attempt a reaed.
err = m.Init(c.dev)
err := m.Init(c.dev)
// Special cases:
//
......@@ -336,28 +331,26 @@ func (c *Connection) readMessage() (m *buffer.InMessage, err error) {
if err != nil {
c.putInMessage(m)
m = nil
return
return nil, err
}
return
return m, nil
}
}
// Write the supplied message to the kernel.
func (c *Connection) writeMessage(msg []byte) (err error) {
func (c *Connection) writeMessage(msg []byte) error {
// Avoid the retry loop in os.File.Write.
n, err := syscall.Write(int(c.dev.Fd()), msg)
if err != nil {
return
return err
}
if n != len(msg) {
err = fmt.Errorf("Wrote %d bytes; expected %d", n, len(msg))
return
return fmt.Errorf("Wrote %d bytes; expected %d", n, len(msg))
}
return
return nil
}
// ReadOp consumes the next op from the kernel process, returning the op and a
......@@ -371,14 +364,13 @@ func (c *Connection) writeMessage(msg []byte) (err error) {
// /dev/fuse. It must not be called multiple times concurrently.
//
// LOCKS_EXCLUDED(c.mu)
func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
func (c *Connection) ReadOp() (_ context.Context, op interface{}, _ error) {
// Keep going until we find a request we know how to convert.
for {
// Read the next message from the kernel.
var inMsg *buffer.InMessage
inMsg, err = c.readMessage()
inMsg, err := c.readMessage()
if err != nil {
return
return nil, nil, err
}
// Convert the message to an op.
......@@ -386,8 +378,7 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
op, err = convertInMessage(inMsg, outMsg, c.protocol)
if err != nil {
c.putOutMessage(outMsg)
err = fmt.Errorf("convertInMessage: %v", err)
return
return nil, nil, fmt.Errorf("convertInMessage: %v", err)
}
// Choose an ID for this operation for the purposes of logging, and log it.
......@@ -402,11 +393,11 @@ func (c *Connection) ReadOp() (ctx context.Context, op interface{}, err error) {
}
// Set up a context that remembers information about this op.
ctx = c.beginOp(inMsg.Header().Opcode, inMsg.Header().Unique)
ctx := c.beginOp(inMsg.Header().Opcode, inMsg.Header().Unique)
ctx = context.WithValue(ctx, contextKey, opState{inMsg, outMsg, op})
// Return the op to the user.
return
return ctx, op, nil
}
}
......@@ -499,10 +490,9 @@ func (c *Connection) Reply(ctx context.Context, opErr error) {
// Close the connection. Must not be called until operations that were read
// from the connection have been responded to.
func (c *Connection) close() (err error) {
func (c *Connection) close() error {
// Posix doesn't say that close can be called concurrently with read or
// write, but luckily we exclude the possibility of a race by requiring the
// user to respond to all ops first.
err = c.dev.Close()
return
return c.dev.Close()
}
This diff is collapsed.
......@@ -25,16 +25,16 @@ import (
////////////////////////////////////////////////////////////////////////
// LOCKS_EXCLUDED(c.mu)
func (c *Connection) getInMessage() (x *buffer.InMessage) {
func (c *Connection) getInMessage() *buffer.InMessage {
c.mu.Lock()
x = (*buffer.InMessage)(c.inMessages.Get())
x := (*buffer.InMessage)(c.inMessages.Get())
c.mu.Unlock()
if x == nil {
x = new(buffer.InMessage)
}
return
return x
}
// LOCKS_EXCLUDED(c.mu)
......@@ -49,9 +49,9 @@ func (c *Connection) putInMessage(x *buffer.InMessage) {
////////////////////////////////////////////////////////////////////////
// LOCKS_EXCLUDED(c.mu)
func (c *Connection) getOutMessage() (x *buffer.OutMessage) {
func (c *Connection) getOutMessage() *buffer.OutMessage {
c.mu.Lock()
x = (*buffer.OutMessage)(c.outMessages.Get())
x := (*buffer.OutMessage)(c.outMessages.Get())
c.mu.Unlock()
if x == nil {
......@@ -59,7 +59,7 @@ func (c *Connection) getOutMessage() (x *buffer.OutMessage) {
}
x.Reset()
return
return x
}
// LOCKS_EXCLUDED(c.mu)
......
......@@ -28,25 +28,22 @@ import (
// Warning: this is not production-quality code, and should only be used for
// testing purposes. In particular, there is a race between creating and
// unlinking by name.
func AnonymousFile(dir string) (f *os.File, err error) {
func AnonymousFile(dir string) (*os.File, error) {
// Choose a prefix based on the binary name.
prefix := path.Base(os.Args[0])
// Create the file.
f, err = ioutil.TempFile(dir, prefix)
f, err := ioutil.TempFile(dir, prefix)
if err != nil {
err = fmt.Errorf("TempFile: %v", err)
return
return nil, fmt.Errorf("TempFile: %v", err)
}
// Unlink it.
err = os.Remove(f.Name())
if err != nil {
err = fmt.Errorf("Remove: %v", err)
return
if err := os.Remove(f.Name()); err != nil {
return nil, fmt.Errorf("Remove: %v", err)
}
return
return f, nil
}
// Call fdatasync on the supplied file.
......
......@@ -44,22 +44,18 @@ func RunCreateInParallelTest_NoTruncate(
// Set up a function that opens the file with O_CREATE and then appends a
// byte to it.
worker := func(id byte) (err error) {
worker := func(id byte) error {
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
if err != nil {
err = fmt.Errorf("Worker %d: Open: %v", id, err)
return
return fmt.Errorf("Worker %d: Open: %v", id, err)
}
defer f.Close()
_, err = f.Write([]byte{id})
if err != nil {
err = fmt.Errorf("Worker %d: Write: %v", id, err)
return
if _, err := f.Write([]byte{id}); err != nil {
return fmt.Errorf("Worker %d: Write: %v", id, err)
}
return
return nil
}
// Run several workers in parallel.
......@@ -67,9 +63,8 @@ func RunCreateInParallelTest_NoTruncate(
b := syncutil.NewBundle(ctx)
for i := 0; i < numWorkers; i++ {
id := byte(i)
b.Add(func(ctx context.Context) (err error) {
err = worker(id)
return
b.Add(func(ctx context.Context) error {
return worker(id)
})
}
......@@ -121,21 +116,16 @@ func RunCreateInParallelTest_Truncate(
filename,
os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_TRUNC,
0600)
if err != nil {
err = fmt.Errorf("Worker %d: Open: %v", id, err)
return
return fmt.Errorf("Worker %d: Open: %v", id, err)
}
defer f.Close()
_, err = f.Write([]byte{id})
if err != nil {
err = fmt.Errorf("Worker %d: Write: %v", id, err)
return
if _, err := f.Write([]byte{id}); err != nil {
return fmt.Errorf("Worker %d: Write: %v", id, err)
}
return
return nil
}
// Run several workers in parallel.
......@@ -143,9 +133,8 @@ func RunCreateInParallelTest_Truncate(
b := syncutil.NewBundle(ctx)
for i := 0; i < numWorkers; i++ {
id := byte(i)
b.Add(func(ctx context.Context) (err error) {
err = worker(id)
return
b.Add(func(ctx context.Context) error {
return worker(id)
})
}
......@@ -203,26 +192,22 @@ func RunCreateInParallelTest_Exclusive(
// If we failed to open due to the file already existing, just leave.
if os.IsExist(err) {
err = nil
return
return nil
}
// Propgate other errors.
if err != nil {
err = fmt.Errorf("Worker %d: Open: %v", id, err)
return
return fmt.Errorf("Worker %d: Open: %v", id, err)
}
atomic.AddUint64(&openCount, 1)
defer f.Close()
_, err = f.Write([]byte{id})
if err != nil {
err = fmt.Errorf("Worker %d: Write: %v", id, err)
return
if _, err := f.Write([]byte{id}); err != nil {
return fmt.Errorf("Worker %d: Write: %v", id, err)
}
return
return nil
}
// Run several workers in parallel.
......@@ -230,9 +215,8 @@ func RunCreateInParallelTest_Exclusive(
b := syncutil.NewBundle(ctx)
for i := 0; i < numWorkers; i++ {
id := byte(i)
b.Add(func(ctx context.Context) (err error) {
err = worker(id)
return
b.Add(func(ctx context.Context) error {
return worker(id)
})
}
......@@ -269,19 +253,16 @@ func RunMkdirInParallelTest(
filename := path.Join(dir, "foo")
// Set up a function that creates the directory, ignoring EEXIST errors.
worker := func(id byte) (err error) {
err = os.Mkdir(filename, 0700)
worker := func(id byte) error {
err := os.Mkdir(filename, 0700)
if os.IsExist(err) {
err = nil
return nil
}
if err != nil {
err = fmt.Errorf("Worker %d: Mkdir: %v", id, err)
return
return fmt.Errorf("Worker %d: Mkdir: %v", id, err)
}
return
return nil
}
// Run several workers in parallel.
......@@ -289,9 +270,8 @@ func RunMkdirInParallelTest(
b := syncutil.NewBundle(ctx)
for i := 0; i < numWorkers; i++ {
id := byte(i)
b.Add(func(ctx context.Context) (err error) {
err = worker(id)
return
b.Add(func(ctx context.Context) error {
return worker(id)
})
}
......@@ -325,19 +305,17 @@ func RunSymlinkInParallelTest(
filename := path.Join(dir, "foo")
// Set up a function that creates the symlink, ignoring EEXIST errors.
worker := func(id byte) (err error) {
err = os.Symlink("blah", filename)
worker := func(id byte) error {
err := os.Symlink("blah", filename)
if os.IsExist(err) {
err = nil
return nil
}
if err != nil {
err = fmt.Errorf("Worker %d: Symlink: %v", id, err)
return
return fmt.Errorf("Worker %d: Symlink: %v", id, err)
}
return
return nil
}
// Run several workers in parallel.
......@@ -345,9 +323,8 @@ func RunSymlinkInParallelTest(
b := syncutil.NewBundle(ctx)
for i := 0; i < numWorkers; i++ {
id := byte(i)
b.Add(func(ctx context.Context) (err error) {
err = worker(id)
return
b.Add(func(ctx context.Context) error {
return worker(id)
})
}
......@@ -388,19 +365,16 @@ func RunHardlinkInParallelTest(
filename := path.Join(dir, "foo")
// Set up a function that creates the symlink, ignoring EEXIST errors.
worker := func(id byte) (err error) {
err = os.Link(originalFile, filename)
worker := func(id byte) error {
err := os.Link(originalFile, filename)
if os.IsExist(err) {
err = nil
return nil
}
if err != nil {
err = fmt.Errorf("Worker %d: Link: %v", id, err)
return
return fmt.Errorf("Worker %d: Link: %v", id, err)
}
return
return nil
}
// Run several workers in parallel.
......@@ -408,9 +382,8 @@ func RunHardlinkInParallelTest(
b := syncutil.NewBundle(ctx)
for i := 0; i < numWorkers; i++ {
id := byte(i)
b.Add(func(ctx context.Context) (err error) {
err = worker(id)
return
b.Add(func(ctx context.Context) error {
return worker(id)
})
}
......
......@@ -37,8 +37,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
// Open the directory.
f, err := os.Open(dirname)
if err != nil {
err = fmt.Errorf("Open: %v", err)
return
return nil, fmt.Errorf("Open: %v", err)
}
// Don't forget to close it later.
......@@ -52,8 +51,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
// Read all of the names from the directory.
names, err := f.Readdirnames(-1)
if err != nil {
err = fmt.Errorf("Readdirnames: %v", err)
return
return nil, fmt.Errorf("Readdirnames: %v", err)
}
// Stat each one.
......@@ -62,8 +60,7 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
fi, err = os.Lstat(path.Join(dirname, name))
if err != nil {
err = fmt.Errorf("Lstat(%s): %v", name, err)
return
return nil, fmt.Errorf("Lstat(%s): %v", name, err)
}
entries = append(entries, fi)
......@@ -72,5 +69,5 @@ func ReadDirPicky(dirname string) (entries []os.FileInfo, err error) {
// Sort the entries by name.
sort.Sort(sortedEntries(entries))
return
return entries, nil
}
......@@ -20,26 +20,20 @@ import (
)
func extractMtime(sys interface{}) (mtime time.Time, ok bool) {
mtime = time.Unix(sys.(*syscall.Stat_t).Mtimespec.Unix())
ok = true
return
return time.Unix(sys.(*syscall.Stat_t).Mtimespec.Unix()), true
}
func extractBirthtime(sys interface{}) (birthtime time.Time, ok bool) {
birthtime = time.Unix(sys.(*syscall.Stat_t).Birthtimespec.Unix())
ok = true
return
return time.Unix(sys.(*syscall.Stat_t).Birthtimespec.Unix()), true
}
func extractNlink(sys interface{}) (nlink uint64, ok bool) {
nlink = uint64(sys.(*syscall.Stat_t).Nlink)
ok = true
return
return uint64(sys.(*syscall.Stat_t).Nlink), true
}
func getTimes(stat *syscall.Stat_t) (atime, ctime, mtime time.Time) {
atime = time.Unix(stat.Atimespec.Unix())
ctime = time.Unix(stat.Ctimespec.Unix())
mtime = time.Unix(stat.Mtimespec.Unix())
return
return atime, ctime, mtime
}
......@@ -20,24 +20,20 @@ import (
)
func extractMtime(sys interface{}) (mtime time.Time, ok bool) {
mtime = time.Unix(sys.(*syscall.Stat_t).Mtim.Unix())
ok = true
return
return time.Unix(sys.(*syscall.Stat_t).Mtim.Unix()), true
}
func extractBirthtime(sys interface{}) (birthtime time.Time, ok bool) {
return
return time.Time{}, false
}
func extractNlink(sys interface{}) (nlink uint64, ok bool) {
nlink = sys.(*syscall.Stat_t).Nlink
ok = true
return
return sys.(*syscall.Stat_t).Nlink, true
}
func getTimes(stat *syscall.Stat_t) (atime, ctime, mtime time.Time) {
atime = time.Unix(stat.Atim.Unix())
ctime = time.Unix(stat.Ctim.Unix())
mtime = time.Unix(stat.Mtim.Unix())
return
return atime, ctime, mtime
}
......@@ -79,7 +79,7 @@ func WriteDirent(buf []byte, d Dirent) (n int) {
// Do we have enough room?
totalLen := direntSize + len(d.Name) + padLen
if totalLen > len(buf) {
return
return n
}
// Write the header.
......@@ -101,5 +101,5 @@ func WriteDirent(buf []byte, d Dirent) (n int) {
n += copy(buf[n:], padding[:padLen])
}
return
return n
}
......@@ -32,198 +32,170 @@ var _ FileSystem = &NotImplementedFileSystem{}
func (fs *NotImplementedFileSystem) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.StatFSOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.LookUpInodeOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.GetInodeAttributesOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) SetInodeAttributes(
ctx context.Context,
op *fuseops.SetInodeAttributesOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.SetInodeAttributesOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) ForgetInode(
ctx context.Context,
op *fuseops.ForgetInodeOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.ForgetInodeOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) MkDir(
ctx context.Context,
op *fuseops.MkDirOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.MkDirOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) MkNode(
ctx context.Context,
op *fuseops.MkNodeOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.MkNodeOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) CreateFile(
ctx context.Context,
op *fuseops.CreateFileOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.CreateFileOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) CreateSymlink(
ctx context.Context,
op *fuseops.CreateSymlinkOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.CreateSymlinkOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) CreateLink(
ctx context.Context,
op *fuseops.CreateLinkOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.CreateLinkOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) Rename(
ctx context.Context,
op *fuseops.RenameOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.RenameOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) RmDir(
ctx context.Context,
op *fuseops.RmDirOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.RmDirOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) Unlink(
ctx context.Context,
op *fuseops.UnlinkOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.UnlinkOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) OpenDir(
ctx context.Context,
op *fuseops.OpenDirOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.OpenDirOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) ReadDir(
ctx context.Context,
op *fuseops.ReadDirOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.ReadDirOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) ReleaseDirHandle(
ctx context.Context,
op *fuseops.ReleaseDirHandleOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.ReleaseDirHandleOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.OpenFileOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) ReadFile(
ctx context.Context,
op *fuseops.ReadFileOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.ReadFileOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) WriteFile(
ctx context.Context,
op *fuseops.WriteFileOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.WriteFileOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) SyncFile(
ctx context.Context,
op *fuseops.SyncFileOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.SyncFileOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) FlushFile(
ctx context.Context,
op *fuseops.FlushFileOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.FlushFileOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) ReleaseFileHandle(
ctx context.Context,
op *fuseops.ReleaseFileHandleOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.ReleaseFileHandleOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) ReadSymlink(
ctx context.Context,
op *fuseops.ReadSymlinkOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.ReadSymlinkOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) RemoveXattr(
ctx context.Context,
op *fuseops.RemoveXattrOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.RemoveXattrOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) GetXattr(
ctx context.Context,
op *fuseops.GetXattrOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.GetXattrOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) ListXattr(
ctx context.Context,
op *fuseops.ListXattrOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.ListXattrOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) SetXattr(
ctx context.Context,
op *fuseops.SetXattrOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.SetXattrOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) Fallocate(
ctx context.Context,
op *fuseops.FallocateOp) (err error) {
err = fuse.ENOSYS
return
op *fuseops.FallocateOp) error {
return fuse.ENOSYS
}
func (fs *NotImplementedFileSystem) Destroy() {
......
......@@ -49,38 +49,34 @@ type InMessage struct {
// Initialize with the data read by a single call to r.Read. The first call to
// Consume will consume the bytes directly after the fusekernel.InHeader
// struct.
func (m *InMessage) Init(r io.Reader) (err error) {
func (m *InMessage) Init(r io.Reader) error {
n, err := r.Read(m.storage[:])
if err != nil {
return
return err
}
// Make sure the message is long enough.
const headerSize = unsafe.Sizeof(fusekernel.InHeader{})
if uintptr(n) < headerSize {
err = fmt.Errorf("Unexpectedly read only %d bytes.", n)
return
return fmt.Errorf("Unexpectedly read only %d bytes.", n)
}
m.remaining = m.storage[headerSize:n]
// Check the header's length.
if int(m.Header().Len) != n {
err = fmt.Errorf(
return fmt.Errorf(
"Header says %d bytes, but we read %d",
m.Header().Len,
n)
return
}
return
return nil
}
// Return a reference to the header read in the most recent call to Init.
func (m *InMessage) Header() (h *fusekernel.InHeader) {
h = (*fusekernel.InHeader)(unsafe.Pointer(&m.storage[0]))
return
func (m *InMessage) Header() *fusekernel.InHeader {
return (*fusekernel.InHeader)(unsafe.Pointer(&m.storage[0]))
}
// Return the number of bytes left to consume.
......@@ -90,26 +86,26 @@ func (m *InMessage) Len() uintptr {
// Consume the next n bytes from the message, returning a nil pointer if there
// are fewer than n bytes available.
func (m *InMessage) Consume(n uintptr) (p unsafe.Pointer) {
func (m *InMessage) Consume(n uintptr) unsafe.Pointer {
if m.Len() == 0 || n > m.Len() {
return
return nil
}
p = unsafe.Pointer(&m.remaining[0])
p := unsafe.Pointer(&m.remaining[0])
m.remaining = m.remaining[n:]
return
return p
}
// Equivalent to Consume, except returns a slice of bytes. The result will be
// nil if Consume would fail.
func (m *InMessage) ConsumeBytes(n uintptr) (b []byte) {
func (m *InMessage) ConsumeBytes(n uintptr) []byte {
if n > m.Len() {
return
return nil
}
b = m.remaining[:n]
b := m.remaining[:n]
m.remaining = m.remaining[n:]
return
return b
}
......@@ -81,28 +81,28 @@ func (m *OutMessage) OutHeader() *fusekernel.OutHeader {
// Grow grows m's buffer by the given number of bytes, returning a pointer to
// the start of the new segment, which is guaranteed to be zeroed. If there is
// insufficient space, it returns nil.
func (m *OutMessage) Grow(n int) (p unsafe.Pointer) {
p = m.GrowNoZero(n)
func (m *OutMessage) Grow(n int) unsafe.Pointer {
p := m.GrowNoZero(n)
if p != nil {
memclr(p, uintptr(n))
}
return
return p
}
// GrowNoZero is equivalent to Grow, except the new segment is not zeroed. Use
// with caution!
func (m *OutMessage) GrowNoZero(n int) (p unsafe.Pointer) {
func (m *OutMessage) GrowNoZero(n int) unsafe.Pointer {
// Will we overflow the buffer?
o := m.payloadOffset
if len(m.payload)-o < n {
return
return nil
}
p = unsafe.Pointer(uintptr(unsafe.Pointer(&m.payload)) + uintptr(o))
p := unsafe.Pointer(uintptr(unsafe.Pointer(&m.payload)) + uintptr(o))
m.payloadOffset = o + n
return
return p
}
// ShrinkTo shrinks m to the given size. It panics if the size is greater than
......
......@@ -24,16 +24,16 @@ func toByteSlice(p unsafe.Pointer, n int) []byte {
}
// fillWithGarbage writes random data to [p, p+n).
func fillWithGarbage(p unsafe.Pointer, n int) (err error) {
func fillWithGarbage(p unsafe.Pointer, n int) error {
b := toByteSlice(p, n)
_, err = io.ReadFull(rand.Reader, b)
return
_, err := io.ReadFull(rand.Reader, b)
return err
}
func randBytes(n int) (b []byte, err error) {
b = make([]byte, n)
_, err = io.ReadFull(rand.Reader, b)
return
func randBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := io.ReadFull(rand.Reader, b)
return b, err
}
// findNonZero finds the offset of the first non-zero byte in [p, p+n). If
......
......@@ -22,16 +22,16 @@ type Freelist struct {
}
// Get an element from the freelist, returning nil if empty.
func (fl *Freelist) Get() (p unsafe.Pointer) {
func (fl *Freelist) Get() unsafe.Pointer {
l := len(fl.list)
if l == 0 {
return
return nil
}
p = fl.list[l-1]
p := fl.list[l-1]
fl.list = fl.list[:l-1]
return
return p
}
// Contribute an element back to the freelist.
......
......@@ -35,25 +35,23 @@ type Server interface {
func Mount(
dir string,
server Server,
config *MountConfig) (mfs *MountedFileSystem, err error) {
config *MountConfig) (*MountedFileSystem, error) {
// Sanity check: make sure the mount point exists and is a directory. This
// saves us from some confusing errors later on OS X.
fi, err := os.Stat(dir)
switch {
case os.IsNotExist(err):
return
return nil, err
case err != nil:
err = fmt.Errorf("Statting mount point: %v", err)
return
return nil, fmt.Errorf("Statting mount point: %v", err)
case !fi.IsDir():
err = fmt.Errorf("Mount point %s is not a directory", dir)
return
return nil, fmt.Errorf("Mount point %s is not a directory", dir)
}
// Initialize the struct.
mfs = &MountedFileSystem{
mfs := &MountedFileSystem{
dir: dir,
joinStatusAvailable: make(chan struct{}),
}
......@@ -62,8 +60,7 @@ func Mount(
ready := make(chan error, 1)
dev, err := mount(dir, config, ready)
if err != nil {
err = fmt.Errorf("mount: %v", err)
return
return nil, fmt.Errorf("mount: %v", err)
}
// Choose a parent context for ops.
......@@ -78,10 +75,8 @@ func Mount(
config.DebugLogger,
config.ErrorLogger,
dev)
if err != nil {
err = fmt.Errorf("newConnection: %v", err)
return
return nil, fmt.Errorf("newConnection: %v", err)
}
// Serve the connection in the background. When done, set the join status.
......@@ -92,10 +87,9 @@ func Mount(
}()
// Wait for the mount process to complete.
if err = <-ready; err != nil {
err = fmt.Errorf("mount (background): %v", err)
return
if err := <-ready; err != nil {
return nil, fmt.Errorf("mount (background): %v", err)
}
return
return mfs, nil
}
......@@ -213,14 +213,14 @@ func (c *MountConfig) toMap() (opts map[string]string) {
opts[k] = v
}
return
return opts
}
func escapeOptionsKey(s string) (res string) {
res = s
res = strings.Replace(res, `\`, `\\`, -1)
res = strings.Replace(res, `,`, `\,`, -1)
return
return res
}
func mapToOptionsString(opts map[string]string) string {
......
......@@ -76,13 +76,11 @@ func openOSXFUSEDev(devPrefix string) (dev *os.File, err error) {
if os.IsNotExist(err) {
if i == 0 {
// Not even the first device was found. Fuse must not be loaded.
err = errNotLoaded
return
return nil, errNotLoaded
}
// Otherwise we've run out of kernel-provided devices
err = errNoAvail
return
return nil, errNoAvail
}
if err2, ok := err.(*os.PathError); ok && err2.Err == syscall.EBUSY {
......@@ -90,7 +88,7 @@ func openOSXFUSEDev(devPrefix string) (dev *os.File, err error) {
continue
}
return
return dev, nil
}
}
......@@ -100,7 +98,7 @@ func callMount(
dir string,
cfg *MountConfig,
dev *os.File,
ready chan<- error) (err error) {
ready chan<- error) error {
// The mount helper doesn't understand any escaping.
for k, v := range cfg.toMap() {
......@@ -143,9 +141,8 @@ func callMount(
cmd.Stdout = &buf
cmd.Stderr = &buf
err = cmd.Start()
if err != nil {
return
if err := cmd.Start(); err != nil {
return err
}
// In the background, wait for the command to complete.
......@@ -162,7 +159,7 @@ func callMount(
ready <- err
}()
return
return nil
}
// Begin the process of mounting at the given directory, returning a connection
......@@ -188,8 +185,7 @@ func mount(
if err == errNotLoaded {
err = loadOSXFUSE(loc.Load)
if err != nil {
err = fmt.Errorf("loadOSXFUSE: %v", err)
return
return nil, fmt.Errorf("loadOSXFUSE: %v", err)
}
dev, err = openOSXFUSEDev(loc.DevicePrefix)
......@@ -197,21 +193,17 @@ func mount(
// Propagate errors.
if err != nil {
err = fmt.Errorf("openOSXFUSEDev: %v", err)
return
return nil, fmt.Errorf("openOSXFUSEDev: %v", err)
}
// Call the mount binary with the device.
err = callMount(loc.Mount, loc.DaemonVar, dir, cfg, dev, ready)
if err != nil {
if err := callMount(loc.Mount, loc.DaemonVar, dir, cfg, dev, ready); err != nil {
dev.Close()
err = fmt.Errorf("callMount: %v", err)
return
return nil, fmt.Errorf("callMount: %v", err)
}
return
return dev, nil
}
err = errOSXFUSENotFound
return
return nil, errOSXFUSENotFound
}
......@@ -26,8 +26,8 @@ type minimalFS struct {
func (fs *minimalFS) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) (err error) {
return
op *fuseops.StatFSOp) error {
return nil
}
////////////////////////////////////////////////////////////////////////
......
......@@ -82,7 +82,7 @@ type CachingFS interface {
//
func NewCachingFS(
lookupEntryTimeout time.Duration,
getattrTimeout time.Duration) (fs CachingFS, err error) {
getattrTimeout time.Duration) (CachingFS, error) {
roundUp := func(n fuseops.InodeID) fuseops.InodeID {
return numInodes * ((n + numInodes - 1) / numInodes)
}
......@@ -96,8 +96,7 @@ func NewCachingFS(
cfs.mu = syncutil.NewInvariantMutex(cfs.checkInvariants)
fs = cfs
return
return cfs, nil
}
const (
......@@ -262,14 +261,14 @@ func (fs *cachingFS) SetKeepCache(keep bool) {
func (fs *cachingFS) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) (err error) {
return
op *fuseops.StatFSOp) error {
return nil
}
// LOCKS_EXCLUDED(fs.mu)
func (fs *cachingFS) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) (err error) {
op *fuseops.LookUpInodeOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -281,8 +280,7 @@ func (fs *cachingFS) LookUpInode(
case "foo":
// Parent must be the root.
if op.Parent != fuseops.RootInodeID {
err = fuse.ENOENT
return
return fuse.ENOENT
}
id = fs.fooID()
......@@ -291,8 +289,7 @@ func (fs *cachingFS) LookUpInode(
case "dir":
// Parent must be the root.
if op.Parent != fuseops.RootInodeID {
err = fuse.ENOENT
return
return fuse.ENOENT
}
id = fs.dirID()
......@@ -301,16 +298,14 @@ func (fs *cachingFS) LookUpInode(
case "bar":
// Parent must be dir.
if op.Parent == fuseops.RootInodeID || op.Parent%numInodes != dirOffset {
err = fuse.ENOENT
return
return fuse.ENOENT
}
id = fs.barID()
attrs = fs.barAttrs()
default:
err = fuse.ENOENT
return
return fuse.ENOENT
}
// Fill in the response.
......@@ -318,13 +313,13 @@ func (fs *cachingFS) LookUpInode(
op.Entry.Attributes = attrs
op.Entry.EntryExpiration = time.Now().Add(fs.lookupEntryTimeout)
return
return nil
}
// LOCKS_EXCLUDED(fs.mu)
func (fs *cachingFS) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) (err error) {
op *fuseops.GetInodeAttributesOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -349,29 +344,30 @@ func (fs *cachingFS) GetInodeAttributes(
op.Attributes = attrs
op.AttributesExpiration = time.Now().Add(fs.getattrTimeout)
return
return nil
}
func (fs *cachingFS) OpenDir(
ctx context.Context,
op *fuseops.OpenDirOp) (err error) {
return
op *fuseops.OpenDirOp) error {
return nil
}
func (fs *cachingFS) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) (err error) {
op *fuseops.OpenFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
op.KeepPageCache = fs.keepPageCache
return
return nil
}
func (fs *cachingFS) ReadFile(
ctx context.Context,
op *fuseops.ReadFileOp) (err error) {
op *fuseops.ReadFileOp) error {
var err error
op.BytesRead, err = io.ReadFull(rand.Reader, op.Dst)
return
return err
}
......@@ -83,7 +83,7 @@ func (t *cachingFSTest) statAll() (foo, dir, bar os.FileInfo) {
bar, err = os.Stat(path.Join(t.Dir, "dir/bar"))
AssertEq(nil, err)
return
return foo, dir, bar
}
func (t *cachingFSTest) openFiles() (foo, dir, bar *os.File) {
......@@ -98,7 +98,7 @@ func (t *cachingFSTest) openFiles() (foo, dir, bar *os.File) {
bar, err = os.Open(path.Join(t.Dir, "dir/bar"))
AssertEq(nil, err)
return
return foo, dir, bar
}
func (t *cachingFSTest) statFiles(
......@@ -114,7 +114,7 @@ func (t *cachingFSTest) statFiles(
bar, err = h.Stat()
AssertEq(nil, err)
return
return foo, dir, bar
}
func getInodeID(fi os.FileInfo) uint64 {
......
......@@ -33,15 +33,14 @@ import (
// This implementation depends on direct IO in fuse. Without it, all read
// operations are suppressed because the kernel detects that they read beyond
// the end of the files.
func NewDynamicFS(clock timeutil.Clock) (server fuse.Server, err error) {
func NewDynamicFS(clock timeutil.Clock) (fuse.Server, error) {
createTime := clock.Now()
fs := &dynamicFS{
clock: clock,
createTime: createTime,
fileHandles: make(map[fuseops.HandleID]string),
}
server = fuseutil.NewFileSystemServer(fs)
return
return fuseutil.NewFileSystemServer(fs), nil
}
type dynamicFS struct {
......@@ -114,16 +113,14 @@ var gInodeInfo = map[fuseops.InodeID]inodeInfo{
func findChildInode(
name string,
children []fuseutil.Dirent) (inode fuseops.InodeID, err error) {
children []fuseutil.Dirent) (fuseops.InodeID, error) {
for _, e := range children {
if e.Name == name {
inode = e.Inode
return
return e.Inode, nil
}
}
err = fuse.ENOENT
return
return 0, fuse.ENOENT
}
func (fs *dynamicFS) findUnusedHandle() fuseops.HandleID {
......@@ -138,69 +135,64 @@ func (fs *dynamicFS) findUnusedHandle() fuseops.HandleID {
func (fs *dynamicFS) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) (err error) {
op *fuseops.GetInodeAttributesOp) error {
// Find the info for this inode.
info, ok := gInodeInfo[op.Inode]
if !ok {
err = fuse.ENOENT
return
return fuse.ENOENT
}
// Copy over its attributes.
op.Attributes = info.attributes
return
return nil
}
func (fs *dynamicFS) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) (err error) {
op *fuseops.LookUpInodeOp) error {
// Find the info for the parent.
parentInfo, ok := gInodeInfo[op.Parent]
if !ok {
err = fuse.ENOENT
return
return fuse.ENOENT
}
// Find the child within the parent.
childInode, err := findChildInode(op.Name, parentInfo.children)
if err != nil {
return
return err
}
// Copy over information.
op.Entry.Child = childInode
op.Entry.Attributes = gInodeInfo[childInode].attributes
return
return nil
}
func (fs *dynamicFS) OpenDir(
ctx context.Context,
op *fuseops.OpenDirOp) (err error) {
op *fuseops.OpenDirOp) error {
// Allow opening directory.
return
return nil
}
func (fs *dynamicFS) ReadDir(
ctx context.Context,
op *fuseops.ReadDirOp) (err error) {
op *fuseops.ReadDirOp) error {
// Find the info for this inode.
info, ok := gInodeInfo[op.Inode]
if !ok {
err = fuse.ENOENT
return
return fuse.ENOENT
}
if !info.dir {
err = fuse.EIO
return
return fuse.EIO
}
entries := info.children
// Grab the range of interest.
if op.Offset > fuseops.DirOffset(len(entries)) {
err = fuse.EIO
return
return fuse.EIO
}
entries = entries[op.Offset:]
......@@ -215,12 +207,12 @@ func (fs *dynamicFS) ReadDir(
op.BytesRead += n
}
return
return nil
}
func (fs *dynamicFS) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) (err error) {
op *fuseops.OpenFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
var contents string
......@@ -233,51 +225,49 @@ func (fs *dynamicFS) OpenFile(
case weekdayInode:
contents = fmt.Sprintf("Today is %s.", fs.clock.Now().Weekday())
default:
err = fuse.EINVAL
return
return fuse.EINVAL
}
handle := fs.findUnusedHandle()
fs.fileHandles[handle] = contents
op.UseDirectIO = true
op.Handle = handle
return
return nil
}
func (fs *dynamicFS) ReadFile(
ctx context.Context,
op *fuseops.ReadFileOp) (err error) {
op *fuseops.ReadFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
contents, ok := fs.fileHandles[op.Handle]
if !ok {
log.Printf("ReadFile: no open file handle: %d", op.Handle)
err = fuse.EIO
return
return fuse.EIO
}
reader := strings.NewReader(contents)
var err error
op.BytesRead, err = reader.ReadAt(op.Dst, op.Offset)
if err == io.EOF {
err = nil
return nil
}
return
return err
}
func (fs *dynamicFS) ReleaseFileHandle(
ctx context.Context,
op *fuseops.ReleaseFileHandleOp) (err error) {
op *fuseops.ReleaseFileHandleOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
_, ok := fs.fileHandles[op.Handle]
if !ok {
log.Printf("ReleaseFileHandle: bad handle: %d", op.Handle)
err = fuse.EIO
return
return fuse.EIO
}
delete(fs.fileHandles, op.Handle)
return
return nil
}
func (fs *dynamicFS) StatFS(ctx context.Context,
op *fuseops.StatFSOp) (err error) {
return
op *fuseops.StatFSOp) error {
return nil
}
......@@ -49,12 +49,10 @@ type FS interface {
SetError(t reflect.Type, err syscall.Errno)
}
func New() (fs FS, err error) {
fs = &errorFS{
func New() (FS, error) {
return &errorFS{
errors: make(map[reflect.Type]syscall.Errno),
}
return
}, nil
}
type errorFS struct {
......@@ -95,9 +93,10 @@ func (fs *errorFS) transformError(op interface{}, err *error) bool {
// LOCKS_EXCLUDED(fs.mu)
func (fs *errorFS) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) (err error) {
op *fuseops.GetInodeAttributesOp) error {
var err error
if fs.transformError(op, &err) {
return
return err
}
// Figure out which inode the request is for.
......@@ -111,100 +110,99 @@ func (fs *errorFS) GetInodeAttributes(
op.Attributes = fooAttrs
default:
err = fmt.Errorf("Unknown inode: %d", op.Inode)
return
return fmt.Errorf("Unknown inode: %d", op.Inode)
}
return
return nil
}
func (fs *errorFS) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) (err error) {
return
op *fuseops.StatFSOp) error {
return nil
}
// LOCKS_EXCLUDED(fs.mu)
func (fs *errorFS) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) (err error) {
op *fuseops.LookUpInodeOp) error {
var err error
if fs.transformError(op, &err) {
return
return err
}
// Is this a known inode?
if !(op.Parent == fuseops.RootInodeID && op.Name == "foo") {
err = syscall.ENOENT
return
return syscall.ENOENT
}
op.Entry.Child = fooInodeID
op.Entry.Attributes = fooAttrs
return
return nil
}
// LOCKS_EXCLUDED(fs.mu)
func (fs *errorFS) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) (err error) {
op *fuseops.OpenFileOp) error {
var err error
if fs.transformError(op, &err) {
return
return err
}
if op.Inode != fooInodeID {
err = fmt.Errorf("Unsupported inode ID: %d", op.Inode)
return
return fmt.Errorf("Unsupported inode ID: %d", op.Inode)
}
return
return nil
}
// LOCKS_EXCLUDED(fs.mu)
func (fs *errorFS) ReadFile(
ctx context.Context,
op *fuseops.ReadFileOp) (err error) {
op *fuseops.ReadFileOp) error {
var err error
if fs.transformError(op, &err) {
return
return err
}
if op.Inode != fooInodeID || op.Offset != 0 {
err = fmt.Errorf("Unexpected request: %#v", op)
return
return fmt.Errorf("Unexpected request: %#v", op)
}
op.BytesRead = copy(op.Dst, FooContents)
return
return nil
}
// LOCKS_EXCLUDED(fs.mu)
func (fs *errorFS) OpenDir(
ctx context.Context,
op *fuseops.OpenDirOp) (err error) {
op *fuseops.OpenDirOp) error {
var err error
if fs.transformError(op, &err) {
return
return err
}
if op.Inode != fuseops.RootInodeID {
err = fmt.Errorf("Unsupported inode ID: %d", op.Inode)
return
return fmt.Errorf("Unsupported inode ID: %d", op.Inode)
}
return
return nil
}
// LOCKS_EXCLUDED(fs.mu)
func (fs *errorFS) ReadDir(
ctx context.Context,
op *fuseops.ReadDirOp) (err error) {
op *fuseops.ReadDirOp) error {
var err error
if fs.transformError(op, &err) {
return
return err
}
if op.Inode != fuseops.RootInodeID || op.Offset != 0 {
err = fmt.Errorf("Unexpected request: %#v", op)
return
return fmt.Errorf("Unexpected request: %#v", op)
}
op.BytesRead = fuseutil.WriteDirent(
......@@ -216,5 +214,5 @@ func (fs *errorFS) ReadDir(
Type: fuseutil.DT_File,
})
return
return nil
}
......@@ -35,14 +35,13 @@ import (
// The directory cannot be modified.
func NewFileSystem(
reportFlush func(string) error,
reportFsync func(string) error) (server fuse.Server, err error) {
reportFsync func(string) error) (fuse.Server, error) {
fs := &flushFS{
reportFlush: reportFlush,
reportFsync: reportFsync,
}
server = fuseutil.NewFileSystemServer(fs)
return
return fuseutil.NewFileSystemServer(fs), nil
}
const (
......@@ -90,25 +89,19 @@ func (fs *flushFS) barAttributes() fuseops.InodeAttributes {
}
// LOCKS_REQUIRED(fs.mu)
func (fs *flushFS) getAttributes(id fuseops.InodeID) (
attrs fuseops.InodeAttributes,
err error) {
func (fs *flushFS) getAttributes(id fuseops.InodeID) (fuseops.InodeAttributes, error) {
switch id {
case fuseops.RootInodeID:
attrs = fs.rootAttributes()
return
return fs.rootAttributes(), nil
case fooID:
attrs = fs.fooAttributes()
return
return fs.fooAttributes(), nil
case barID:
attrs = fs.barAttributes()
return
return fs.barAttributes(), nil
default:
err = fuse.ENOENT
return
return fuseops.InodeAttributes{}, fuse.ENOENT
}
}
......@@ -118,20 +111,19 @@ func (fs *flushFS) getAttributes(id fuseops.InodeID) (
func (fs *flushFS) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) (err error) {
return
op *fuseops.StatFSOp) error {
return nil
}
func (fs *flushFS) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) (err error) {
op *fuseops.LookUpInodeOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
// Sanity check.
if op.Parent != fuseops.RootInodeID {
err = fuse.ENOENT
return
return fuse.ENOENT
}
// Set up the entry.
......@@ -149,70 +141,69 @@ func (fs *flushFS) LookUpInode(
}
default:
err = fuse.ENOENT
return
return fuse.ENOENT
}
return
return nil
}
func (fs *flushFS) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) (err error) {
op *fuseops.GetInodeAttributesOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
var err error
op.Attributes, err = fs.getAttributes(op.Inode)
return
return err
}
func (fs *flushFS) SetInodeAttributes(
ctx context.Context,
op *fuseops.SetInodeAttributesOp) (err error) {
op *fuseops.SetInodeAttributesOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
// Ignore any changes and simply return existing attributes.
var err error
op.Attributes, err = fs.getAttributes(op.Inode)
return
return err
}
func (fs *flushFS) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) (err error) {
op *fuseops.OpenFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
// Sanity check.
if op.Inode != fooID {
err = fuse.ENOSYS
return
return fuse.ENOSYS
}
return
return nil
}
func (fs *flushFS) ReadFile(
ctx context.Context,
op *fuseops.ReadFileOp) (err error) {
op *fuseops.ReadFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
// Ensure the offset is in range.
if op.Offset > int64(len(fs.fooContents)) {
return
return nil
}
// Read what we can.
op.BytesRead = copy(op.Dst, fs.fooContents[op.Offset:])
return
return nil
}
func (fs *flushFS) WriteFile(
ctx context.Context,
op *fuseops.WriteFileOp) (err error) {
op *fuseops.WriteFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -231,32 +222,30 @@ func (fs *flushFS) WriteFile(
panic(fmt.Sprintf("Unexpected short copy: %v", n))
}
return
return nil
}
func (fs *flushFS) SyncFile(
ctx context.Context,
op *fuseops.SyncFileOp) (err error) {
op *fuseops.SyncFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
err = fs.reportFsync(string(fs.fooContents))
return
return fs.reportFsync(string(fs.fooContents))
}
func (fs *flushFS) FlushFile(
ctx context.Context,
op *fuseops.FlushFileOp) (err error) {
op *fuseops.FlushFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
err = fs.reportFlush(string(fs.fooContents))
return
return fs.reportFlush(string(fs.fooContents))
}
func (fs *flushFS) OpenDir(
ctx context.Context,
op *fuseops.OpenDirOp) (err error) {
op *fuseops.OpenDirOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -266,16 +255,15 @@ func (fs *flushFS) OpenDir(
case barID:
default:
err = fuse.ENOENT
return
return fuse.ENOENT
}
return
return nil
}
func (fs *flushFS) ReadDir(
ctx context.Context,
op *fuseops.ReadDirOp) (err error) {
op *fuseops.ReadDirOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -303,21 +291,19 @@ func (fs *flushFS) ReadDir(
case barID:
default:
err = fmt.Errorf("Unexpected inode: %v", op.Inode)
return
return fmt.Errorf("Unexpected inode: %v", op.Inode)
}
// If the offset is for the end of the listing, we're done. Otherwise we
// expect it to be for the start.
switch op.Offset {
case fuseops.DirOffset(len(dirents)):
return
return nil
case 0:
default:
err = fmt.Errorf("Unexpected offset: %v", op.Offset)
return
return fmt.Errorf("Unexpected offset: %v", op.Offset)
}
// Fill in the listing.
......@@ -326,12 +312,11 @@ func (fs *flushFS) ReadDir(
// We don't support doing this in anything more than one shot.
if n == 0 {
err = fmt.Errorf("Couldn't fit listing in %v bytes", len(op.Dst))
return
return fmt.Errorf("Couldn't fit listing in %v bytes", len(op.Dst))
}
op.BytesRead += n
}
return
return nil
}
......@@ -121,30 +121,24 @@ var isDarwin = runtime.GOOS == "darwin"
func readReports(f *os.File) (reports []string, err error) {
// Seek the file to the start.
_, err = f.Seek(0, 0)
if err != nil {
err = fmt.Errorf("Seek: %v", err)
return
if _, err := f.Seek(0, 0); err != nil {
return nil, fmt.Errorf("Seek: %v", err)
}
// We expect reports to end in a newline (including the final one).
reader := bufio.NewReader(f)
for {
var record []byte
record, err = reader.ReadBytes('\n')
record, err := reader.ReadBytes('\n')
if err == io.EOF {
if len(record) != 0 {
err = fmt.Errorf("Unexpected record:\n%s", hex.Dump(record))
return
return nil, fmt.Errorf("Unexpected record:\n%s", hex.Dump(record))
}
err = nil
return
return reports, nil
}
if err != nil {
err = fmt.Errorf("ReadBytes: %v", err)
return
return nil, fmt.Errorf("ReadBytes: %v", err)
}
// Strip the newline.
......@@ -153,41 +147,39 @@ func readReports(f *os.File) (reports []string, err error) {
}
// Return a copy of the current contents of t.flushes.
func (t *flushFSTest) getFlushes() (p []string) {
var err error
if p, err = readReports(t.flushes); err != nil {
func (t *flushFSTest) getFlushes() []string {
p, err := readReports(t.flushes)
if err != nil {
panic(err)
}
return
return p
}
// Return a copy of the current contents of t.fsyncs.
func (t *flushFSTest) getFsyncs() (p []string) {
var err error
if p, err = readReports(t.fsyncs); err != nil {
func (t *flushFSTest) getFsyncs() []string {
p, err := readReports(t.fsyncs)
if err != nil {
panic(err)
}
return
return p
}
// Like syscall.Dup2, but correctly annotates the syscall as blocking. See here
// for more info: https://github.com/golang/go/issues/10202
func dup2(oldfd int, newfd int) (err error) {
func dup2(oldfd int, newfd int) error {
_, _, e1 := syscall.Syscall(
syscall.SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
if e1 != 0 {
err = e1
return e1
}
return
return nil
}
// Call msync(2) with the MS_SYNC flag on a slice previously returned by
// mmap(2).
func msync(p []byte) (err error) {
func msync(p []byte) error {
_, _, errno := unix.Syscall(
unix.SYS_MSYNC,
uintptr(unsafe.Pointer(&p[0])),
......@@ -195,11 +187,10 @@ func msync(p []byte) (err error) {
unix.MS_SYNC)
if errno != 0 {
err = errno
return
return errno
}
return
return nil
}
////////////////////////////////////////////////////////////////////////
......
......@@ -38,7 +38,7 @@ import (
// after we expect it to be dead. Its Check method may be used to check that
// there are no inodes with unexpected reference counts remaining, after
// unmounting.
func NewFileSystem() (fs *ForgetFS) {
func NewFileSystem() *ForgetFS {
// Set up the actual file system.
impl := &fsImpl{
inodes: map[fuseops.InodeID]*inode{
......@@ -78,12 +78,10 @@ func NewFileSystem() (fs *ForgetFS) {
impl.mu = syncutil.NewInvariantMutex(impl.checkInvariants)
// Set up a wrapper that exposes only certain methods.
fs = &ForgetFS{
return &ForgetFS{
impl: impl,
server: fuseutil.NewFileSystemServer(impl),
}
return
}
////////////////////////////////////////////////////////////////////////
......@@ -206,8 +204,8 @@ func (fs *fsImpl) Check() {
// Look up the inode and verify it hasn't been forgotten.
//
// LOCKS_REQUIRED(fs.mu)
func (fs *fsImpl) findInodeByID(id fuseops.InodeID) (in *inode) {
in = fs.inodes[id]
func (fs *fsImpl) findInodeByID(id fuseops.InodeID) *inode {
in := fs.inodes[id]
if in == nil {
panic(fmt.Sprintf("Unknown inode: %v", id))
}
......@@ -216,7 +214,7 @@ func (fs *fsImpl) findInodeByID(id fuseops.InodeID) (in *inode) {
panic(fmt.Sprintf("Forgotten inode: %v", id))
}
return
return in
}
////////////////////////////////////////////////////////////////////////
......@@ -225,13 +223,13 @@ func (fs *fsImpl) findInodeByID(id fuseops.InodeID) (in *inode) {
func (fs *fsImpl) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) (err error) {
return
op *fuseops.StatFSOp) error {
return nil
}
func (fs *fsImpl) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) (err error) {
op *fuseops.LookUpInodeOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -248,8 +246,7 @@ func (fs *fsImpl) LookUpInode(
childID = cannedID_Bar
default:
err = fuse.ENOENT
return
return fuse.ENOENT
}
// Look up the child.
......@@ -262,12 +259,12 @@ func (fs *fsImpl) LookUpInode(
Attributes: child.attributes,
}
return
return nil
}
func (fs *fsImpl) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) (err error) {
op *fuseops.GetInodeAttributesOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -277,12 +274,12 @@ func (fs *fsImpl) GetInodeAttributes(
// Return appropriate attributes.
op.Attributes = in.attributes
return
return nil
}
func (fs *fsImpl) ForgetInode(
ctx context.Context,
op *fuseops.ForgetInodeOp) (err error) {
op *fuseops.ForgetInodeOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -290,12 +287,12 @@ func (fs *fsImpl) ForgetInode(
in := fs.findInodeByID(op.Inode)
in.DecrementLookupCount(op.N)
return
return nil
}
func (fs *fsImpl) MkDir(
ctx context.Context,
op *fuseops.MkDirOp) (err error) {
op *fuseops.MkDirOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -322,12 +319,12 @@ func (fs *fsImpl) MkDir(
Attributes: child.attributes,
}
return
return nil
}
func (fs *fsImpl) CreateFile(
ctx context.Context,
op *fuseops.CreateFileOp) (err error) {
op *fuseops.CreateFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
......@@ -354,31 +351,31 @@ func (fs *fsImpl) CreateFile(
Attributes: child.attributes,
}
return
return nil
}
func (fs *fsImpl) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) (err error) {
op *fuseops.OpenFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
// Verify that the inode has not been forgotten.
_ = fs.findInodeByID(op.Inode)
return
return nil
}
func (fs *fsImpl) OpenDir(
ctx context.Context,
op *fuseops.OpenDirOp) (err error) {
op *fuseops.OpenDirOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
// Verify that the inode has not been forgotten.
_ = fs.findInodeByID(op.Inode)
return
return nil
}
func (fs *fsImpl) Destroy() {
......
......@@ -33,13 +33,12 @@ import (
// world
//
// Each file contains the string "Hello, world!".
func NewHelloFS(clock timeutil.Clock) (server fuse.Server, err error) {
func NewHelloFS(clock timeutil.Clock) (fuse.Server, error) {
fs := &helloFS{
Clock: clock,
}
server = fuseutil.NewFileSystemServer(fs)
return
return fuseutil.NewFileSystemServer(fs), nil
}
type helloFS struct {
......@@ -128,16 +127,14 @@ var gInodeInfo = map[fuseops.InodeID]inodeInfo{
func findChildInode(
name string,
children []fuseutil.Dirent) (inode fuseops.InodeID, err error) {
children []fuseutil.Dirent) (fuseops.InodeID, error) {
for _, e := range children {
if e.Name == name {
inode = e.Inode
return
return e.Inode, nil
}
}
err = fuse.ENOENT
return
return 0, fuse.ENOENT
}
func (fs *helloFS) patchAttributes(
......@@ -150,24 +147,23 @@ func (fs *helloFS) patchAttributes(
func (fs *helloFS) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) (err error) {
return
op *fuseops.StatFSOp) error {
return nil
}
func (fs *helloFS) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) (err error) {
op *fuseops.LookUpInodeOp) error {
// Find the info for the parent.
parentInfo, ok := gInodeInfo[op.Parent]
if !ok {
err = fuse.ENOENT
return
return fuse.ENOENT
}
// Find the child within the parent.
childInode, err := findChildInode(op.Name, parentInfo.children)
if err != nil {
return
return err
}
// Copy over information.
......@@ -177,17 +173,16 @@ func (fs *helloFS) LookUpInode(
// Patch attributes.
fs.patchAttributes(&op.Entry.Attributes)
return
return nil
}
func (fs *helloFS) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) (err error) {
op *fuseops.GetInodeAttributesOp) error {
// Find the info for this inode.
info, ok := gInodeInfo[op.Inode]
if !ok {
err = fuse.ENOENT
return
return fuse.ENOENT
}
// Copy over its attributes.
......@@ -196,37 +191,34 @@ func (fs *helloFS) GetInodeAttributes(
// Patch attributes.
fs.patchAttributes(&op.Attributes)
return
return nil
}
func (fs *helloFS) OpenDir(
ctx context.Context,
op *fuseops.OpenDirOp) (err error) {
op *fuseops.OpenDirOp) error {
// Allow opening any directory.
return
return nil
}
func (fs *helloFS) ReadDir(
ctx context.Context,
op *fuseops.ReadDirOp) (err error) {
op *fuseops.ReadDirOp) error {
// Find the info for this inode.
info, ok := gInodeInfo[op.Inode]
if !ok {
err = fuse.ENOENT
return
return fuse.ENOENT
}
if !info.dir {
err = fuse.EIO
return
return fuse.EIO
}
entries := info.children
// Grab the range of interest.
if op.Offset > fuseops.DirOffset(len(entries)) {
err = fuse.EIO
return
return fuse.EIO
}
entries = entries[op.Offset:]
......@@ -241,28 +233,29 @@ func (fs *helloFS) ReadDir(
op.BytesRead += n
}
return
return nil
}
func (fs *helloFS) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) (err error) {
op *fuseops.OpenFileOp) error {
// Allow opening any file.
return
return nil
}
func (fs *helloFS) ReadFile(
ctx context.Context,
op *fuseops.ReadFileOp) (err error) {
op *fuseops.ReadFileOp) error {
// Let io.ReaderAt deal with the semantics.
reader := strings.NewReader("Hello, world!")
var err error
op.BytesRead, err = reader.ReadAt(op.Dst, op.Offset)
// Special case: FUSE doesn't expect us to return io.EOF.
if err == io.EOF {
err = nil
return nil
}
return
return err
}
......@@ -75,7 +75,7 @@ func (t *SampleTest) SetUp(ti *ogletest.TestInfo) {
func (t *SampleTest) initialize(
ctx context.Context,
server fuse.Server,
config *fuse.MountConfig) (err error) {
config *fuse.MountConfig) error {
// Initialize the context used by the test.
t.Ctx = ctx
......@@ -89,20 +89,19 @@ func (t *SampleTest) initialize(
t.Clock.SetTime(time.Date(2012, 8, 15, 22, 56, 0, 0, time.Local))
// Set up a temporary directory.
var err error
t.Dir, err = ioutil.TempDir("", "sample_test")
if err != nil {
err = fmt.Errorf("TempDir: %v", err)
return
return fmt.Errorf("TempDir: %v", err)
}
// Mount the file system.
t.mfs, err = fuse.Mount(t.Dir, server, config)
if err != nil {
err = fmt.Errorf("Mount: %v", err)
return
return fmt.Errorf("Mount: %v", err)
}
return
return nil
}
// Unmount the file system and clean up. Panics on error.
......@@ -126,28 +125,23 @@ func (t *SampleTest) destroy() (err error) {
// Was the file system mounted?
if t.mfs == nil {
return
return nil
}
// Unmount the file system.
err = unmount(t.Dir)
if err != nil {
err = fmt.Errorf("unmount: %v", err)
return
if err := unmount(t.Dir); err != nil {
return fmt.Errorf("unmount: %v", err)
}
// Unlink the mount point.
if err = os.Remove(t.Dir); err != nil {
err = fmt.Errorf("Unlinking mount point: %v", err)
return
if err := os.Remove(t.Dir); err != nil {
return fmt.Errorf("Unlinking mount point: %v", err)
}
// Join the file system.
err = t.mfs.Join(t.Ctx)
if err != nil {
err = fmt.Errorf("mfs.Join: %v", err)
return
if err := t.mfs.Join(t.Ctx); err != nil {
return fmt.Errorf("mfs.Join: %v", err)
}
return
return nil
}
......@@ -56,13 +56,11 @@ type InterruptFS struct {
flushReceived chan struct{}
}
func New() (fs *InterruptFS) {
fs = &InterruptFS{
func New() *InterruptFS {
return &InterruptFS{
readReceived: make(chan struct{}),
flushReceived: make(chan struct{}),
}
return
}
////////////////////////////////////////////////////////////////////////
......@@ -101,35 +99,33 @@ func (fs *InterruptFS) EnableFlushBlocking() {
func (fs *InterruptFS) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) (err error) {
return
op *fuseops.StatFSOp) error {
return nil
}
func (fs *InterruptFS) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) (err error) {
op *fuseops.LookUpInodeOp) error {
// We support only one parent.
if op.Parent != fuseops.RootInodeID {
err = fmt.Errorf("Unexpected parent: %v", op.Parent)
return
return fmt.Errorf("Unexpected parent: %v", op.Parent)
}
// We support only one name.
if op.Name != "foo" {
err = fuse.ENOENT
return
return fuse.ENOENT
}
// Fill in the response.
op.Entry.Child = fooID
op.Entry.Attributes = fooAttrs
return
return nil
}
func (fs *InterruptFS) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) (err error) {
op *fuseops.GetInodeAttributesOp) error {
switch op.Inode {
case fuseops.RootInodeID:
op.Attributes = rootAttrs
......@@ -138,22 +134,21 @@ func (fs *InterruptFS) GetInodeAttributes(
op.Attributes = fooAttrs
default:
err = fmt.Errorf("Unexpected inode ID: %v", op.Inode)
return
return fmt.Errorf("Unexpected inode ID: %v", op.Inode)
}
return
return nil
}
func (fs *InterruptFS) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) (err error) {
return
op *fuseops.OpenFileOp) error {
return nil
}
func (fs *InterruptFS) ReadFile(
ctx context.Context,
op *fuseops.ReadFileOp) (err error) {
op *fuseops.ReadFileOp) error {
fs.mu.Lock()
shouldBlock := fs.blockForReads
......@@ -173,15 +168,15 @@ func (fs *InterruptFS) ReadFile(
}
<-done
err = ctx.Err()
return ctx.Err()
}
return
return nil
}
func (fs *InterruptFS) FlushFile(
ctx context.Context,
op *fuseops.FlushFileOp) (err error) {
op *fuseops.FlushFileOp) error {
fs.mu.Lock()
shouldBlock := fs.blockForFlushes
......@@ -201,8 +196,8 @@ func (fs *InterruptFS) FlushFile(
}
<-done
err = ctx.Err()
return ctx.Err()
}
return
return nil
}
......@@ -73,20 +73,17 @@ type inode struct {
// Create a new inode with the supplied attributes, which need not contain
// time-related information (the inode object will take care of that).
func newInode(
attrs fuseops.InodeAttributes) (in *inode) {
func newInode(attrs fuseops.InodeAttributes) *inode {
// Update time info.
now := time.Now()
attrs.Mtime = now
attrs.Crtime = now
// Create the object.
in = &inode{
return &inode{
attrs: attrs,
xattrs: make(map[string][]byte),
}
return
}
func (in *inode) CheckInvariants() {
......@@ -168,12 +165,11 @@ func (in *inode) findChild(name string) (i int, ok bool) {
var e fuseutil.Dirent
for i, e = range in.entries {
if e.Name == name {
ok = true
return
return i, true
}
}
return
return 0, false
}
////////////////////////////////////////////////////////////////////////
......@@ -183,14 +179,15 @@ func (in *inode) findChild(name string) (i int, ok bool) {
// Return the number of children of the directory.
//
// REQUIRES: in.isDir()
func (in *inode) Len() (n int) {
func (in *inode) Len() int {
var n int
for _, e := range in.entries {
if e.Type != fuseutil.DT_Unknown {
n++
}
}
return
return n
}
// Find an entry for the given child name and return its inode ID.
......@@ -206,7 +203,7 @@ func (in *inode) LookUpChild(name string) (
typ = in.entries[index].Type
}
return
return id, typ, ok
}
// Add an entry for a child.
......@@ -272,11 +269,12 @@ func (in *inode) RemoveChild(name string) {
// Serve a ReadDir request.
//
// REQUIRES: in.isDir()
func (in *inode) ReadDir(p []byte, offset int) (n int) {
func (in *inode) ReadDir(p []byte, offset int) int {
if !in.isDir() {
panic("ReadDir called on non-directory.")
}
var n int
for i := offset; i < len(in.entries); i++ {
e := in.entries[i]
......@@ -293,36 +291,35 @@ func (in *inode) ReadDir(p []byte, offset int) (n int) {
n += tmp
}
return
return n
}
// Read from the file's contents. See documentation for ioutil.ReaderAt.
//
// REQUIRES: in.isFile()
func (in *inode) ReadAt(p []byte, off int64) (n int, err error) {
func (in *inode) ReadAt(p []byte, off int64) (int, error) {
if !in.isFile() {
panic("ReadAt called on non-file.")
}
// Ensure the offset is in range.
if off > int64(len(in.contents)) {
err = io.EOF
return
return 0, io.EOF
}
// Read what we can.
n = copy(p, in.contents[off:])
n := copy(p, in.contents[off:])
if n < len(p) {
err = io.EOF
return n, io.EOF
}
return
return n, nil
}
// Write to the file's contents. See documentation for ioutil.WriterAt.
//
// REQUIRES: in.isFile()
func (in *inode) WriteAt(p []byte, off int64) (n int, err error) {
func (in *inode) WriteAt(p []byte, off int64) (int, error) {
if !in.isFile() {
panic("WriteAt called on non-file.")
}
......@@ -339,14 +336,14 @@ func (in *inode) WriteAt(p []byte, off int64) (n int, err error) {
}
// Copy in the data.
n = copy(in.contents[off:], p)
n := copy(in.contents[off:], p)
// Sanity check.
if n != len(p) {
panic(fmt.Sprintf("Unexpected short copy: %v", n))
}
return
return n, nil
}
// Update attributes from non-nil parameters.
......@@ -384,17 +381,15 @@ func (in *inode) SetAttributes(
}
}
func (in *inode) Fallocate(mode uint32, offset uint64, length uint64) (
err error) {
if mode == 0 {
func (in *inode) Fallocate(mode uint32, offset uint64, length uint64) error {
if mode != 0 {
return fuse.ENOSYS
}
newSize := int(offset + length)
if newSize > len(in.contents) {
padding := make([]byte, newSize-len(in.contents))
in.contents = append(in.contents, padding...)
in.attrs.Size = offset + length
}
} else {
err = fuse.ENOSYS
}
return
return nil
}
This diff is collapsed.
......@@ -39,8 +39,7 @@ func TestPosix(t *testing.T) { RunTests(t) }
func getFileOffset(f *os.File) (offset int64, err error) {
const relativeToCurrent = 1
offset, err = f.Seek(0, relativeToCurrent)
return
return f.Seek(0, relativeToCurrent)
}
////////////////////////////////////////////////////////////////////////
......
......@@ -42,11 +42,10 @@ var fFsyncError = flag.Int("flushfs.fsync_error", 0, "")
var fReadOnly = flag.Bool("read_only", false, "Mount in read-only mode.")
var fDebug = flag.Bool("debug", false, "Enable debug logging.")
func makeFlushFS() (server fuse.Server, err error) {
func makeFlushFS() (fuse.Server, error) {
// Check the flags.
if *fFlushesFile == 0 || *fFsyncsFile == 0 {
err = fmt.Errorf("You must set the flushfs flags.")
return
return nil, fmt.Errorf("You must set the flushfs flags.")
}
// Set up the files.
......@@ -67,18 +66,15 @@ func makeFlushFS() (server fuse.Server, err error) {
// Report flushes and fsyncs by writing the contents followed by a newline.
report := func(f *os.File, outErr error) func(string) error {
return func(s string) (err error) {
return func(s string) error {
buf := []byte(s)
buf = append(buf, '\n')
_, err = f.Write(buf)
if err != nil {
err = fmt.Errorf("Write: %v", err)
return
if _, err := f.Write(buf); err != nil {
return fmt.Errorf("Write: %v", err)
}
err = outErr
return
return outErr
}
}
......@@ -86,31 +82,25 @@ func makeFlushFS() (server fuse.Server, err error) {
reportFsync := report(fsyncs, fsyncErr)
// Create the file system.
server, err = flushfs.NewFileSystem(reportFlush, reportFsync)
return
return flushfs.NewFileSystem(reportFlush, reportFsync)
}
func makeFS() (server fuse.Server, err error) {
func makeFS() (fuse.Server, error) {
switch *fType {
default:
err = fmt.Errorf("Unknown FS type: %v", *fType)
return nil, fmt.Errorf("Unknown FS type: %v", *fType)
case "flushfs":
server, err = makeFlushFS()
return makeFlushFS()
}
return
}
func getReadyFile() (f *os.File, err error) {
func getReadyFile() (*os.File, error) {
if *fReadyFile == 0 {
err = errors.New("You must set --ready_file.")
return
return nil, errors.New("You must set --ready_file.")
}
f = os.NewFile(uintptr(*fReadyFile), "(ready file)")
return
return os.NewFile(uintptr(*fReadyFile), "(ready file)"), nil
}
func main() {
......
......@@ -47,15 +47,13 @@ type FS interface {
MostRecentWriteSize() int
}
func New() (fs FS) {
fs = &statFS{
func New() FS {
return &statFS{
cannedStatResponse: fuseops.InodeAttributes{
Mode: 0666,
},
mostRecentWriteSize: -1,
}
return
}
const childInodeID = fuseops.RootInodeID + 1
......@@ -118,32 +116,31 @@ func (fs *statFS) MostRecentWriteSize() int {
// LOCKS_EXCLUDED(fs.mu)
func (fs *statFS) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) (err error) {
op *fuseops.StatFSOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
*op = fs.cannedResponse
return
return nil
}
func (fs *statFS) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) (err error) {
op *fuseops.LookUpInodeOp) error {
// Only the root has children.
if op.Parent != fuseops.RootInodeID {
err = fuse.ENOENT
return
return fuse.ENOENT
}
op.Entry.Child = childInodeID
op.Entry.Attributes = fs.fileAttrs()
return
return nil
}
func (fs *statFS) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) (err error) {
op *fuseops.GetInodeAttributesOp) error {
switch op.Inode {
case fuseops.RootInodeID:
op.Attributes = dirAttrs()
......@@ -152,32 +149,32 @@ func (fs *statFS) GetInodeAttributes(
op.Attributes = fs.fileAttrs()
default:
err = fuse.ENOENT
return fuse.ENOENT
}
return
return nil
}
func (fs *statFS) SetInodeAttributes(
ctx context.Context,
op *fuseops.SetInodeAttributesOp) (err error) {
op *fuseops.SetInodeAttributesOp) error {
// Ignore calls to truncate existing files when opening.
return
return nil
}
func (fs *statFS) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) (err error) {
return
op *fuseops.OpenFileOp) error {
return nil
}
// LOCKS_EXCLUDED(fs.mu)
func (fs *statFS) WriteFile(
ctx context.Context,
op *fuseops.WriteFileOp) (err error) {
op *fuseops.WriteFileOp) error {
fs.mu.Lock()
defer fs.mu.Unlock()
fs.mostRecentWriteSize = len(op.Data)
return
return nil
}
......@@ -35,7 +35,7 @@ var gDfOutputRegexp = regexp.MustCompile(`^\S+\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+%\s+
// Helpers
////////////////////////////////////////////////////////////////////////
func convertName(in []int8) (s string) {
func convertName(in []int8) string {
var tmp []byte
for _, v := range in {
if v == 0 {
......@@ -45,8 +45,7 @@ func convertName(in []int8) (s string) {
tmp = append(tmp, byte(v))
}
s = string(tmp)
return
return string(tmp)
}
////////////////////////////////////////////////////////////////////////
......
......@@ -53,7 +53,7 @@ func df(dir string) (capacity, used, available uint64, err error) {
output, err := cmd.CombinedOutput()
if err != nil {
return
return 0, 0, 0, err
}
// Scrape it.
......@@ -65,23 +65,22 @@ func df(dir string) (capacity, used, available uint64, err error) {
submatches := gDfOutputRegexp.FindSubmatch(line)
if submatches == nil {
err = fmt.Errorf("Unable to parse line: %q", line)
return
return 0, 0, 0, fmt.Errorf("Unable to parse line: %q", line)
}
capacity, err = strconv.ParseUint(string(submatches[1]), 10, 64)
if err != nil {
return
return 0, 0, 0, err
}
used, err = strconv.ParseUint(string(submatches[2]), 10, 64)
if err != nil {
return
return 0, 0, 0, err
}
available, err = strconv.ParseUint(string(submatches[3]), 10, 64)
if err != nil {
return
return 0, 0, 0, err
}
// Scale appropriately based on the BLOCKSIZE set above.
......@@ -89,11 +88,10 @@ func df(dir string) (capacity, used, available uint64, err error) {
used *= 1024
available *= 1024
return
return capacity, used, available, nil
}
err = fmt.Errorf("Unable to parse df output:\n%s", output)
return
return 0, 0, 0, fmt.Errorf("Unable to parse df output:\n%s", output)
}
////////////////////////////////////////////////////////////////////////
......
......@@ -80,23 +80,21 @@ var getToolContents_Err error
var getToolContents_Once sync.Once
// Implementation detail of getToolPath.
func getToolContentsImpl() (contents []byte, err error) {
func getToolContentsImpl() ([]byte, error) {
// Fast path: has the user set the flag?
if *fToolPath != "" {
contents, err = ioutil.ReadFile(*fToolPath)
contents, err := ioutil.ReadFile(*fToolPath)
if err != nil {
err = fmt.Errorf("Reading mount_sample contents: %v", err)
return
return nil, fmt.Errorf("Reading mount_sample contents: %v", err)
}
return
return contents, err
}
// Create a temporary directory into which we will compile the tool.
tempDir, err := ioutil.TempDir("", "sample_test")
if err != nil {
err = fmt.Errorf("TempDir: %v", err)
return
return nil, fmt.Errorf("TempDir: %v", err)
}
toolPath := path.Join(tempDir, "mount_sample")
......@@ -114,34 +112,30 @@ func getToolContentsImpl() (contents []byte, err error) {
output, err := cmd.CombinedOutput()
if err != nil {
err = fmt.Errorf(
return nil, fmt.Errorf(
"mount_sample exited with %v, output:\n%s",
err,
string(output))
return
}
// Slurp the tool contents.
contents, err = ioutil.ReadFile(toolPath)
contents, err := ioutil.ReadFile(toolPath)
if err != nil {
err = fmt.Errorf("ReadFile: %v", err)
return
return nil, fmt.Errorf("ReadFile: %v", err)
}
return
return contents, nil
}
// Build the mount_sample tool if it has not yet been built for this process.
// Return its contents.
func getToolContents() (contents []byte, err error) {
func getToolContents() ([]byte, error) {
// Get hold of the binary contents, if we haven't yet.
getToolContents_Once.Do(func() {
getToolContents_Contents, getToolContents_Err = getToolContentsImpl()
})
contents, err = getToolContents_Contents, getToolContents_Err
return
return getToolContents_Contents, getToolContents_Err
}
func waitForMountSample(
......@@ -184,29 +178,27 @@ func waitForReady(readyReader *os.File, c chan<- struct{}) {
}
// Like SetUp, but doens't panic.
func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
func (t *SubprocessTest) initialize(ctx context.Context) error {
// Initialize the context.
t.Ctx = ctx
// Set up a temporary directory.
var err error
t.Dir, err = ioutil.TempDir("", "sample_test")
if err != nil {
err = fmt.Errorf("TempDir: %v", err)
return
return fmt.Errorf("TempDir: %v", err)
}
// Build/read the mount_sample tool.
toolContents, err := getToolContents()
if err != nil {
err = fmt.Errorf("getTooltoolContents: %v", err)
return
return fmt.Errorf("getTooltoolContents: %v", err)
}
// Create a temporary file to hold the contents of the tool.
toolFile, err := ioutil.TempFile("", "sample_test")
if err != nil {
err = fmt.Errorf("TempFile: %v", err)
return
return fmt.Errorf("TempFile: %v", err)
}
defer toolFile.Close()
......@@ -217,21 +209,18 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
// Write out the tool contents and make them executable.
if _, err = toolFile.Write(toolContents); err != nil {
err = fmt.Errorf("toolFile.Write: %v", err)
return
return fmt.Errorf("toolFile.Write: %v", err)
}
if err = toolFile.Chmod(0500); err != nil {
err = fmt.Errorf("toolFile.Chmod: %v", err)
return
return fmt.Errorf("toolFile.Chmod: %v", err)
}
// Close the tool file to prevent "text file busy" errors below.
err = toolFile.Close()
toolFile = nil
if err != nil {
err = fmt.Errorf("toolFile.Close: %v", err)
return
return fmt.Errorf("toolFile.Close: %v", err)
}
// Set up basic args for the subprocess.
......@@ -247,8 +236,7 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
// Set up a pipe for the "ready" status.
readyReader, readyWriter, err := os.Pipe()
if err != nil {
err = fmt.Errorf("Pipe: %v", err)
return
return fmt.Errorf("Pipe: %v", err)
}
defer readyReader.Close()
......@@ -280,9 +268,8 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
}
// Start the command.
if err = mountCmd.Start(); err != nil {
err = fmt.Errorf("mountCmd.Start: %v", err)
return
if err := mountCmd.Start(); err != nil {
return fmt.Errorf("mountCmd.Start: %v", err)
}
// Launch a goroutine that waits for it and returns its status.
......@@ -296,14 +283,14 @@ func (t *SubprocessTest) initialize(ctx context.Context) (err error) {
select {
case <-readyChan:
case err = <-mountSampleErr:
return
case err := <-mountSampleErr:
return err
}
// TearDown is no responsible for joining.
t.mountSampleErr = mountSampleErr
return
return nil
}
// Unmount the file system and clean up. Panics on error.
......@@ -329,7 +316,7 @@ func (t *SubprocessTest) destroy() (err error) {
// If we didn't try to mount the file system, there's nothing further to do.
if t.mountSampleErr == nil {
return
return nil
}
// In the background, initiate an unmount.
......@@ -358,9 +345,9 @@ func (t *SubprocessTest) destroy() (err error) {
}()
// Wait for the subprocess.
if err = <-t.mountSampleErr; err != nil {
return
if err := <-t.mountSampleErr; err != nil {
return err
}
return
return nil
}
......@@ -27,12 +27,12 @@ import (
// "resource busy" errors, which happen from time to time on OS X (due to weird
// requests from the Finder) and when tests don't or can't synchronize all
// events.
func unmount(dir string) (err error) {
func unmount(dir string) error {
delay := 10 * time.Millisecond
for {
err = fuse.Unmount(dir)
err := fuse.Unmount(dir)
if err == nil {
return
return err
}
if strings.Contains(err.Error(), "resource busy") {
......@@ -42,7 +42,6 @@ func unmount(dir string) (err error) {
continue
}
err = fmt.Errorf("Unmount: %v", err)
return
return fmt.Errorf("Unmount: %v", err)
}
}
......@@ -6,18 +6,17 @@ import (
"os/exec"
)
func unmount(dir string) (err error) {
func unmount(dir string) error {
// Call fusermount.
cmd := exec.Command("fusermount", "-u", dir)
output, err := cmd.CombinedOutput()
if err != nil {
if len(output) > 0 {
output = bytes.TrimRight(output, "\n")
err = fmt.Errorf("%v: %s", err, output)
return fmt.Errorf("%v: %s", err, output)
}
return
return err
}
return
return nil
}
......@@ -7,12 +7,10 @@ import (
"syscall"
)
func unmount(dir string) (err error) {
err = syscall.Unmount(dir, 0)
if err != nil {
err = &os.PathError{Op: "unmount", Path: dir, Err: err}
return
func unmount(dir string) error {
if err := syscall.Unmount(dir, 0); err != nil {
return &os.PathError{Op: "unmount", Path: dir, Err: err}
}
return
return nil
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment