Skip to content

Commit

Permalink
Return ESTALE to all operations with stale inodes
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalif committed Sep 21, 2021
1 parent 5836cc7 commit ba7f5e4
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 3 deletions.
2 changes: 2 additions & 0 deletions internal/dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,13 +539,15 @@ func (dh *DirHandle) ReadDir(internalOffset int, offset fuseops.DirOffset) (en *
dh.inode.dir.listDone = false
dh.inode.dir.lastFromCloud = nil
// Remove unmodified stale inodes when we start listing
// FIXME: It's probably better to remove only inodes that don't exist in listing anymore
for i := 2; i < len(parent.dir.Children); i++ {
// Note on locking: See comments at Inode::AttrTime, Inode::Parent.
childTmp := parent.dir.Children[i]
if atomic.LoadInt32(&childTmp.fileHandles) == 0 &&
atomic.LoadInt32(&childTmp.CacheState) == ST_CACHED &&
(!childTmp.isDir() || atomic.LoadInt64(&childTmp.dir.ModifiedChildren) == 0) {
childTmp.mu.Lock()
atomic.StoreInt32(&childTmp.refreshed, -1)
if childTmp.isDir() {
childTmp.removeAllChildrenUnlocked()
}
Expand Down
86 changes: 83 additions & 3 deletions internal/goofys.go
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,11 @@ func (fs *Goofys) GetInodeAttributes(
inode := fs.getInodeOrDie(op.Inode)
fs.mu.RUnlock()

if atomic.LoadInt32(&inode.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

attr, err := inode.GetAttributes()
err = mapAwsError(err)
if err == nil {
Expand All @@ -690,6 +695,11 @@ func (fs *Goofys) GetXattr(ctx context.Context,
inode := fs.getInodeOrDie(op.Inode)
fs.mu.RUnlock()

if atomic.LoadInt32(&inode.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

value, err := inode.GetXattr(op.Name)
err = mapAwsError(err)
if err != nil {
Expand All @@ -714,6 +724,11 @@ func (fs *Goofys) ListXattr(ctx context.Context,
inode := fs.getInodeOrDie(op.Inode)
fs.mu.RUnlock()

if atomic.LoadInt32(&inode.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

xattrs, err := inode.ListXattr()
err = mapAwsError(err)

Expand Down Expand Up @@ -745,6 +760,11 @@ func (fs *Goofys) RemoveXattr(ctx context.Context,
inode := fs.getInodeOrDie(op.Inode)
fs.mu.RUnlock()

if atomic.LoadInt32(&inode.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

err = inode.RemoveXattr(op.Name)
err = mapAwsError(err)
if err == syscall.EPERM {
Expand All @@ -761,6 +781,11 @@ func (fs *Goofys) SetXattr(ctx context.Context,
inode := fs.getInodeOrDie(op.Inode)
fs.mu.RUnlock()

if atomic.LoadInt32(&inode.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

err = inode.SetXattr(op.Name, op.Value, op.Flags)
err = mapAwsError(err)
if err == syscall.EPERM {
Expand All @@ -776,6 +801,11 @@ func (fs *Goofys) CreateSymlink(ctx context.Context,
parent := fs.getInodeOrDie(op.Parent)
fs.mu.RUnlock()

if atomic.LoadInt32(&parent.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

inode := parent.CreateSymlink(op.Name, op.Target)
op.Entry.Child = inode.Id
op.Entry.Attributes = inode.InflateAttributes()
Expand All @@ -790,6 +820,11 @@ func (fs *Goofys) ReadSymlink(ctx context.Context,
inode := fs.getInodeOrDie(op.Inode)
fs.mu.RUnlock()

if atomic.LoadInt32(&inode.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

op.Target, err = inode.ReadSymlink()
err = mapAwsError(err)
return
Expand Down Expand Up @@ -1015,14 +1050,23 @@ func (fs *Goofys) ForgetInode(
func (fs *Goofys) OpenDir(
ctx context.Context,
op *fuseops.OpenDirOp) (err error) {
fs.mu.Lock()

fs.mu.Lock()
in := fs.getInodeOrDie(op.Inode)
if atomic.LoadInt32(&in.refreshed) == -1 {
// Stale inode
fs.mu.Unlock()
return syscall.ESTALE
}
handleID := fs.nextHandleID
fs.nextHandleID++

in := fs.getInodeOrDie(op.Inode)
fs.mu.Unlock()

if atomic.LoadInt32(&in.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

dh := in.OpenDir()

fs.mu.Lock()
Expand Down Expand Up @@ -1131,6 +1175,11 @@ func (fs *Goofys) OpenFile(
in := fs.getInodeOrDie(op.Inode)
fs.mu.RUnlock()

if atomic.LoadInt32(&in.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

fh, err := in.OpenFile()
if err != nil {
err = mapAwsError(err)
Expand Down Expand Up @@ -1233,6 +1282,11 @@ func (fs *Goofys) CreateFile(
parent := fs.getInodeOrDie(op.Parent)
fs.mu.RUnlock()

if atomic.LoadInt32(&parent.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

inode, fh := parent.Create(op.Name)

// Always take inode locks after fs lock if you need both...
Expand Down Expand Up @@ -1265,6 +1319,11 @@ func (fs *Goofys) MkDir(
parent := fs.getInodeOrDie(op.Parent)
fs.mu.RUnlock()

if atomic.LoadInt32(&parent.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

// ignore op.Mode for now
inode, err := parent.MkDir(op.Name)
if err != nil {
Expand All @@ -1288,6 +1347,11 @@ func (fs *Goofys) RmDir(
parent := fs.getInodeOrDie(op.Parent)
fs.mu.RUnlock()

if atomic.LoadInt32(&parent.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

err = parent.RmDir(op.Name)
err = mapAwsError(err)
parent.logFuse("<-- RmDir", op.Name, err)
Expand All @@ -1302,6 +1366,11 @@ func (fs *Goofys) SetInodeAttributes(
inode := fs.getInodeOrDie(op.Inode)
fs.mu.RUnlock()

if atomic.LoadInt32(&inode.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

if op.Size != nil {
inode.mu.Lock()
inode.ResizeUnlocked(*op.Size, true)
Expand Down Expand Up @@ -1351,6 +1420,11 @@ func (fs *Goofys) Unlink(
parent := fs.getInodeOrDie(op.Parent)
fs.mu.RUnlock()

if atomic.LoadInt32(&parent.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

err = parent.Unlink(op.Name)
err = mapAwsError(err)
return
Expand All @@ -1367,6 +1441,12 @@ func (fs *Goofys) Rename(
newParent := fs.getInodeOrDie(op.NewParent)
fs.mu.RUnlock()

if atomic.LoadInt32(&parent.refreshed) == -1 ||
atomic.LoadInt32(&newParent.refreshed) == -1 {
// Stale inode
return syscall.ESTALE
}

if op.OldParent == op.NewParent {
parent.mu.Lock()
defer parent.mu.Unlock()
Expand Down
1 change: 1 addition & 0 deletions internal/handles.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ type Inode struct {
dir *DirInodeData

ImplicitDir bool
refreshed int32

fileHandles int32
lastWriteEnd uint64
Expand Down

0 comments on commit ba7f5e4

Please sign in to comment.