More memfs fixes.
parent
05e62e432c
commit
0a06b97691
|
@ -25,7 +25,6 @@ import (
|
|||
"github.com/jacobsa/fuse/fuseops"
|
||||
"github.com/jacobsa/fuse/fuseutil"
|
||||
"github.com/jacobsa/gcloud/syncutil"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type memFS struct {
|
||||
|
@ -200,28 +199,26 @@ func (fs *memFS) deallocateInode(id fuseops.InodeID) {
|
|||
// FileSystem methods
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func (fs *memFS) Init(
|
||||
ctx context.Context,
|
||||
req *fuse.InitRequest) (resp *fuse.InitResponse, err error) {
|
||||
resp = &fuse.InitResponse{}
|
||||
func (fs *memFS) init(op *fuseops.InitOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) LookUpInode(
|
||||
ctx context.Context,
|
||||
req *fuse.LookUpInodeRequest) (resp *fuse.LookUpInodeResponse, err error) {
|
||||
resp = &fuse.LookUpInodeResponse{}
|
||||
func (fs *memFS) lookUpInode(op *fuseops.LookUpInodeOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
||||
// Grab the parent directory.
|
||||
inode := fs.getInodeForReadingOrDie(req.Parent)
|
||||
inode := fs.getInodeForReadingOrDie(op.Parent)
|
||||
defer inode.mu.RUnlock()
|
||||
|
||||
// Does the directory have an entry with the given name?
|
||||
childID, ok := inode.LookUpChild(req.Name)
|
||||
childID, ok := inode.LookUpChild(op.Name)
|
||||
if !ok {
|
||||
err = fuse.ENOENT
|
||||
return
|
||||
|
@ -232,85 +229,80 @@ func (fs *memFS) LookUpInode(
|
|||
defer child.mu.RUnlock()
|
||||
|
||||
// Fill in the response.
|
||||
resp.Entry.Child = childID
|
||||
resp.Entry.Attributes = child.attributes
|
||||
op.Entry.Child = childID
|
||||
op.Entry.Attributes = child.attributes
|
||||
|
||||
// We don't spontaneously mutate, so the kernel can cache as long as it wants
|
||||
// (since it also handles invalidation).
|
||||
resp.Entry.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
resp.Entry.EntryExpiration = resp.Entry.EntryExpiration
|
||||
op.Entry.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
op.Entry.EntryExpiration = op.Entry.EntryExpiration
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) GetInodeAttributes(
|
||||
ctx context.Context,
|
||||
req *fuse.GetInodeAttributesRequest) (
|
||||
resp *fuse.GetInodeAttributesResponse, err error) {
|
||||
resp = &fuse.GetInodeAttributesResponse{}
|
||||
func (fs *memFS) getInodeAttributes(op *fuseops.GetInodeAttributesOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
||||
// Grab the inode.
|
||||
inode := fs.getInodeForReadingOrDie(req.Inode)
|
||||
inode := fs.getInodeForReadingOrDie(op.Inode)
|
||||
defer inode.mu.RUnlock()
|
||||
|
||||
// Fill in the response.
|
||||
resp.Attributes = inode.attributes
|
||||
op.Attributes = inode.attributes
|
||||
|
||||
// We don't spontaneously mutate, so the kernel can cache as long as it wants
|
||||
// (since it also handles invalidation).
|
||||
resp.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
op.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) SetInodeAttributes(
|
||||
ctx context.Context,
|
||||
req *fuse.SetInodeAttributesRequest) (
|
||||
resp *fuse.SetInodeAttributesResponse, err error) {
|
||||
resp = &fuse.SetInodeAttributesResponse{}
|
||||
func (fs *memFS) setInodeAttributes(op *fuseops.SetInodeAttributesOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
||||
// Grab the inode.
|
||||
inode := fs.getInodeForModifyingOrDie(req.Inode)
|
||||
inode := fs.getInodeForModifyingOrDie(op.Inode)
|
||||
defer inode.mu.Unlock()
|
||||
|
||||
// Handle the request.
|
||||
inode.SetAttributes(req.Size, req.Mode, req.Mtime)
|
||||
inode.SetAttributes(op.Size, op.Mode, op.Mtime)
|
||||
|
||||
// Fill in the response.
|
||||
resp.Attributes = inode.attributes
|
||||
op.Attributes = inode.attributes
|
||||
|
||||
// We don't spontaneously mutate, so the kernel can cache as long as it wants
|
||||
// (since it also handles invalidation).
|
||||
resp.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
op.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) MkDir(
|
||||
ctx context.Context,
|
||||
req *fuse.MkDirRequest) (resp *fuse.MkDirResponse, err error) {
|
||||
resp = &fuse.MkDirResponse{}
|
||||
func (fs *memFS) mkDir(op *fuseops.MkDirOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
|
||||
// Grab the parent, which we will update shortly.
|
||||
parent := fs.getInodeForModifyingOrDie(req.Parent)
|
||||
parent := fs.getInodeForModifyingOrDie(op.Parent)
|
||||
defer parent.mu.Unlock()
|
||||
|
||||
// Set up attributes from the child, using the credentials of the calling
|
||||
// process as owner (matching inode_init_owner, cf. http://goo.gl/5qavg8).
|
||||
childAttrs := fuseops.InodeAttributes{
|
||||
Nlink: 1,
|
||||
Mode: req.Mode,
|
||||
Uid: req.Header.Uid,
|
||||
Gid: req.Header.Gid,
|
||||
Mode: op.Mode,
|
||||
Uid: op.Header().Uid,
|
||||
Gid: op.Header().Gid,
|
||||
}
|
||||
|
||||
// Allocate a child.
|
||||
|
@ -318,30 +310,29 @@ func (fs *memFS) MkDir(
|
|||
defer child.mu.Unlock()
|
||||
|
||||
// Add an entry in the parent.
|
||||
parent.AddChild(childID, req.Name, fuseutil.DT_Directory)
|
||||
parent.AddChild(childID, op.Name, fuseutil.DT_Directory)
|
||||
|
||||
// Fill in the response.
|
||||
resp.Entry.Child = childID
|
||||
resp.Entry.Attributes = child.attributes
|
||||
op.Entry.Child = childID
|
||||
op.Entry.Attributes = child.attributes
|
||||
|
||||
// We don't spontaneously mutate, so the kernel can cache as long as it wants
|
||||
// (since it also handles invalidation).
|
||||
resp.Entry.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
resp.Entry.EntryExpiration = resp.Entry.EntryExpiration
|
||||
op.Entry.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
op.Entry.EntryExpiration = op.Entry.EntryExpiration
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) CreateFile(
|
||||
ctx context.Context,
|
||||
req *fuse.CreateFileRequest) (resp *fuse.CreateFileResponse, err error) {
|
||||
resp = &fuse.CreateFileResponse{}
|
||||
func (fs *memFS) createFile(op *fuseops.CreateFileOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
|
||||
// Grab the parent, which we will update shortly.
|
||||
parent := fs.getInodeForModifyingOrDie(req.Parent)
|
||||
parent := fs.getInodeForModifyingOrDie(op.Parent)
|
||||
defer parent.mu.Unlock()
|
||||
|
||||
// Set up attributes from the child, using the credentials of the calling
|
||||
|
@ -349,13 +340,13 @@ func (fs *memFS) CreateFile(
|
|||
now := fs.clock.Now()
|
||||
childAttrs := fuseops.InodeAttributes{
|
||||
Nlink: 1,
|
||||
Mode: req.Mode,
|
||||
Mode: op.Mode,
|
||||
Atime: now,
|
||||
Mtime: now,
|
||||
Ctime: now,
|
||||
Crtime: now,
|
||||
Uid: req.Header.Uid,
|
||||
Gid: req.Header.Gid,
|
||||
Uid: op.Header().Uid,
|
||||
Gid: op.Header().Gid,
|
||||
}
|
||||
|
||||
// Allocate a child.
|
||||
|
@ -363,36 +354,35 @@ func (fs *memFS) CreateFile(
|
|||
defer child.mu.Unlock()
|
||||
|
||||
// Add an entry in the parent.
|
||||
parent.AddChild(childID, req.Name, fuseutil.DT_File)
|
||||
parent.AddChild(childID, op.Name, fuseutil.DT_File)
|
||||
|
||||
// Fill in the response entry.
|
||||
resp.Entry.Child = childID
|
||||
resp.Entry.Attributes = child.attributes
|
||||
op.Entry.Child = childID
|
||||
op.Entry.Attributes = child.attributes
|
||||
|
||||
// We don't spontaneously mutate, so the kernel can cache as long as it wants
|
||||
// (since it also handles invalidation).
|
||||
resp.Entry.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
resp.Entry.EntryExpiration = resp.Entry.EntryExpiration
|
||||
op.Entry.AttributesExpiration = fs.clock.Now().Add(365 * 24 * time.Hour)
|
||||
op.Entry.EntryExpiration = op.Entry.EntryExpiration
|
||||
|
||||
// We have nothing interesting to put in the Handle field.
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) RmDir(
|
||||
ctx context.Context,
|
||||
req *fuse.RmDirRequest) (resp *fuse.RmDirResponse, err error) {
|
||||
resp = &fuse.RmDirResponse{}
|
||||
func (fs *memFS) rmDir(op *fuseops.RmDirOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
|
||||
// Grab the parent, which we will update shortly.
|
||||
parent := fs.getInodeForModifyingOrDie(req.Parent)
|
||||
parent := fs.getInodeForModifyingOrDie(op.Parent)
|
||||
defer parent.mu.Unlock()
|
||||
|
||||
// Find the child within the parent.
|
||||
childID, ok := parent.LookUpChild(req.Name)
|
||||
childID, ok := parent.LookUpChild(op.Name)
|
||||
if !ok {
|
||||
err = fuse.ENOENT
|
||||
return
|
||||
|
@ -409,7 +399,7 @@ func (fs *memFS) RmDir(
|
|||
}
|
||||
|
||||
// Remove the entry within the parent.
|
||||
parent.RemoveChild(req.Name)
|
||||
parent.RemoveChild(op.Name)
|
||||
|
||||
// Mark the child as unlinked.
|
||||
child.attributes.Nlink--
|
||||
|
@ -417,20 +407,19 @@ func (fs *memFS) RmDir(
|
|||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) Unlink(
|
||||
ctx context.Context,
|
||||
req *fuse.UnlinkRequest) (resp *fuse.UnlinkResponse, err error) {
|
||||
resp = &fuse.UnlinkResponse{}
|
||||
func (fs *memFS) unlink(op *fuseops.UnlinkOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
|
||||
// Grab the parent, which we will update shortly.
|
||||
parent := fs.getInodeForModifyingOrDie(req.Parent)
|
||||
parent := fs.getInodeForModifyingOrDie(op.Parent)
|
||||
defer parent.mu.Unlock()
|
||||
|
||||
// Find the child within the parent.
|
||||
childID, ok := parent.LookUpChild(req.Name)
|
||||
childID, ok := parent.LookUpChild(op.Name)
|
||||
if !ok {
|
||||
err = fuse.ENOENT
|
||||
return
|
||||
|
@ -441,7 +430,7 @@ func (fs *memFS) Unlink(
|
|||
defer child.mu.Unlock()
|
||||
|
||||
// Remove the entry within the parent.
|
||||
parent.RemoveChild(req.Name)
|
||||
parent.RemoveChild(op.Name)
|
||||
|
||||
// Mark the child as unlinked.
|
||||
child.attributes.Nlink--
|
||||
|
@ -449,10 +438,9 @@ func (fs *memFS) Unlink(
|
|||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) OpenDir(
|
||||
ctx context.Context,
|
||||
req *fuse.OpenDirRequest) (resp *fuse.OpenDirResponse, err error) {
|
||||
resp = &fuse.OpenDirResponse{}
|
||||
func (fs *memFS) openDir(op *fuseops.OpenDirOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
@ -460,7 +448,7 @@ func (fs *memFS) OpenDir(
|
|||
// We don't mutate spontaneosuly, so if the VFS layer has asked for an
|
||||
// inode that doesn't exist, something screwed up earlier (a lookup, a
|
||||
// cache invalidation, etc.).
|
||||
inode := fs.getInodeForReadingOrDie(req.Inode)
|
||||
inode := fs.getInodeForReadingOrDie(op.Inode)
|
||||
defer inode.mu.RUnlock()
|
||||
|
||||
if !inode.dir {
|
||||
|
@ -470,20 +458,19 @@ func (fs *memFS) OpenDir(
|
|||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) ReadDir(
|
||||
ctx context.Context,
|
||||
req *fuse.ReadDirRequest) (resp *fuse.ReadDirResponse, err error) {
|
||||
resp = &fuse.ReadDirResponse{}
|
||||
func (fs *memFS) readDir(op *fuseops.ReadDirOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
||||
// Grab the directory.
|
||||
inode := fs.getInodeForReadingOrDie(req.Inode)
|
||||
inode := fs.getInodeForReadingOrDie(op.Inode)
|
||||
defer inode.mu.RUnlock()
|
||||
|
||||
// Serve the request.
|
||||
resp.Data, err = inode.ReadDir(int(req.Offset), req.Size)
|
||||
op.Data, err = inode.ReadDir(int(op.Offset), op.Size)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("inode.ReadDir: %v", err)
|
||||
return
|
||||
|
@ -492,10 +479,9 @@ func (fs *memFS) ReadDir(
|
|||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) OpenFile(
|
||||
ctx context.Context,
|
||||
req *fuse.OpenFileRequest) (resp *fuse.OpenFileResponse, err error) {
|
||||
resp = &fuse.OpenFileResponse{}
|
||||
func (fs *memFS) openFile(op *fuseops.OpenFileOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
@ -503,7 +489,7 @@ func (fs *memFS) OpenFile(
|
|||
// We don't mutate spontaneosuly, so if the VFS layer has asked for an
|
||||
// inode that doesn't exist, something screwed up earlier (a lookup, a
|
||||
// cache invalidation, etc.).
|
||||
inode := fs.getInodeForReadingOrDie(req.Inode)
|
||||
inode := fs.getInodeForReadingOrDie(op.Inode)
|
||||
defer inode.mu.RUnlock()
|
||||
|
||||
if inode.dir {
|
||||
|
@ -513,22 +499,21 @@ func (fs *memFS) OpenFile(
|
|||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) ReadFile(
|
||||
ctx context.Context,
|
||||
req *fuse.ReadFileRequest) (resp *fuse.ReadFileResponse, err error) {
|
||||
resp = &fuse.ReadFileResponse{}
|
||||
func (fs *memFS) readFile(op *fuseops.ReadFileOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
||||
// Find the inode in question.
|
||||
inode := fs.getInodeForReadingOrDie(req.Inode)
|
||||
inode := fs.getInodeForReadingOrDie(op.Inode)
|
||||
defer inode.mu.RUnlock()
|
||||
|
||||
// Serve the request.
|
||||
resp.Data = make([]byte, req.Size)
|
||||
n, err := inode.ReadAt(resp.Data, req.Offset)
|
||||
resp.Data = resp.Data[:n]
|
||||
op.Data = make([]byte, op.Size)
|
||||
n, err := inode.ReadAt(op.Data, op.Offset)
|
||||
op.Data = op.Data[:n]
|
||||
|
||||
// Don't return EOF errors; we just indicate EOF to fuse using a short read.
|
||||
if err == io.EOF {
|
||||
|
@ -538,20 +523,19 @@ func (fs *memFS) ReadFile(
|
|||
return
|
||||
}
|
||||
|
||||
func (fs *memFS) WriteFile(
|
||||
ctx context.Context,
|
||||
req *fuse.WriteFileRequest) (resp *fuse.WriteFileResponse, err error) {
|
||||
resp = &fuse.WriteFileResponse{}
|
||||
func (fs *memFS) writeFile(op *fuseops.WriteFileOp) {
|
||||
var err error
|
||||
defer func() { op.Respond(err) }()
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
||||
// Find the inode in question.
|
||||
inode := fs.getInodeForModifyingOrDie(req.Inode)
|
||||
inode := fs.getInodeForModifyingOrDie(op.Inode)
|
||||
defer inode.mu.Unlock()
|
||||
|
||||
// Serve the request.
|
||||
_, err = inode.WriteAt(req.Data, req.Offset)
|
||||
_, err = inode.WriteAt(op.Data, op.Offset)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/googlecloudplatform/gcsfuse/timeutil"
|
||||
"github.com/jacobsa/fuse"
|
||||
"github.com/jacobsa/fuse/fuseops"
|
||||
"github.com/jacobsa/fuse/fuseutil"
|
||||
"github.com/jacobsa/gcloud/syncutil"
|
||||
|
@ -123,7 +122,7 @@ func (inode *inode) checkInvariants() {
|
|||
|
||||
childNames := make(map[string]struct{})
|
||||
for i, e := range inode.entries {
|
||||
if e.Offset != fuse.DirOffset(i+1) {
|
||||
if e.Offset != fuseops.DirOffset(i+1) {
|
||||
panic(fmt.Sprintf("Unexpected offset: %v", e.Offset))
|
||||
}
|
||||
|
||||
|
@ -222,7 +221,7 @@ func (inode *inode) AddChild(
|
|||
// No matter where we place the entry, make sure it has the correct Offset
|
||||
// field.
|
||||
defer func() {
|
||||
inode.entries[index].Offset = fuse.DirOffset(index + 1)
|
||||
inode.entries[index].Offset = fuseops.DirOffset(index + 1)
|
||||
}()
|
||||
|
||||
// Set up the entry.
|
||||
|
@ -263,7 +262,7 @@ func (inode *inode) RemoveChild(name string) {
|
|||
// Mark it as unused.
|
||||
inode.entries[i] = fuseutil.Dirent{
|
||||
Type: fuseutil.DT_Unknown,
|
||||
Offset: fuse.DirOffset(i + 1),
|
||||
Offset: fuseops.DirOffset(i + 1),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue