Commit c1873abe authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

UnionFs: move the size update to File.Flush().

parent df9202b8
...@@ -282,15 +282,28 @@ func (me *UnionFs) Promote(name string, srcResult branchResult, context *fuse.Co ...@@ -282,15 +282,28 @@ func (me *UnionFs) Promote(name string, srcResult branchResult, context *fuse.Co
if srcResult.attr.IsRegular() { if srcResult.attr.IsRegular() {
code = fuse.CopyFile(sourceFs, writable, name, name, context) code = fuse.CopyFile(sourceFs, writable, name, name, context)
files := me.nodeFs.AllFiles(name, 0) files := me.nodeFs.AllFiles(name, 0)
for _, f := range files { for _, fileWrapper := range files {
if !code.Ok() { if !code.Ok() {
break break
} }
uf := f.File.(*UnionFsFile) var uf *unionFsFile
f := fileWrapper.File
for f != nil {
ok := false
uf, ok = f.(*unionFsFile)
if ok {
break
}
f = f.InnerFile()
}
if uf == nil {
panic("no unionFsFile found inside")
}
if uf.layer > 0 { if uf.layer > 0 {
uf.layer = 0 uf.layer = 0
uf.File.Release() uf.File.Release()
uf.File, code = me.fileSystems[0].Open(name, f.OpenFlags, context) uf.File, code = me.fileSystems[0].Open(name, fileWrapper.OpenFlags, context)
} }
} }
} else if srcResult.attr.IsSymlink() { } else if srcResult.attr.IsSymlink() {
...@@ -633,6 +646,7 @@ func (me *UnionFs) Create(name string, flags uint32, mode uint32, context *fuse. ...@@ -633,6 +646,7 @@ func (me *UnionFs) Create(name string, flags uint32, mode uint32, context *fuse.
} }
fuseFile, code = writable.Create(name, flags, mode, context) fuseFile, code = writable.Create(name, flags, mode, context)
if code.Ok() { if code.Ok() {
fuseFile = me.newUnionFsFile(fuseFile, 0)
me.removeDeletion(name) me.removeDeletion(name)
now := time.Nanoseconds() now := time.Nanoseconds()
...@@ -868,8 +882,8 @@ func (me *UnionFs) Rename(src string, dst string, context *fuse.Context) (code f ...@@ -868,8 +882,8 @@ func (me *UnionFs) Rename(src string, dst string, context *fuse.Context) (code f
if code.Ok() { if code.Ok() {
me.removeDeletion(dst) me.removeDeletion(dst)
srcResult.branch = 0 // Rename is racy; avoid racing with unionFsFile.Release().
me.branchCache.Set(dst, srcResult) me.branchCache.DropEntry(dst)
srcResult := me.branchCache.GetFresh(src) srcResult := me.branchCache.GetFresh(src)
if srcResult.(branchResult).branch > 0 { if srcResult.(branchResult).branch > 0 {
...@@ -928,17 +942,11 @@ func (me *UnionFs) Open(name string, flags uint32, context *fuse.Context) (fuseF ...@@ -928,17 +942,11 @@ func (me *UnionFs) Open(name string, flags uint32, context *fuse.Context) (fuseF
} }
fuseFile, status = me.fileSystems[r.branch].Open(name, uint32(flags), context) fuseFile, status = me.fileSystems[r.branch].Open(name, uint32(flags), context)
if fuseFile != nil { if fuseFile != nil {
fuseFile = &UnionFsFile{fuseFile, r.branch} fuseFile = me.newUnionFsFile(fuseFile, r.branch)
} }
return fuseFile, status return fuseFile, status
} }
func (me *UnionFs) Flush(name string) fuse.Status {
// Refresh timestamps and size field.
me.branchCache.GetFresh(name)
return fuse.OK
}
func (me *UnionFs) Name() string { func (me *UnionFs) Name() string {
names := []string{} names := []string{}
for _, fs := range me.fileSystems { for _, fs := range me.fileSystems {
...@@ -951,12 +959,39 @@ func (me *UnionFs) StatFs() *fuse.StatfsOut { ...@@ -951,12 +959,39 @@ func (me *UnionFs) StatFs() *fuse.StatfsOut {
return me.fileSystems[0].StatFs() return me.fileSystems[0].StatFs()
} }
type UnionFsFile struct { type unionFsFile struct {
fuse.File fuse.File
ufs *UnionFs
node *fuse.Inode
layer int layer int
} }
func (me *UnionFsFile) GetAttr() (*os.FileInfo, fuse.Status) { func (me *UnionFs) newUnionFsFile(f fuse.File, branch int) *unionFsFile {
return &unionFsFile{
File: f,
ufs: me,
layer: branch,
}
}
func (me *unionFsFile) InnerFile() (file fuse.File) {
return me.File
}
// We can't hook on Release. Release has no response, so it is not
// ordered wrt any following calls.
func (me *unionFsFile) Flush() (code fuse.Status) {
code = me.File.Flush()
path := me.ufs.nodeFs.Path(me.node)
me.ufs.branchCache.GetFresh(path)
return code
}
func (me *unionFsFile) SetInode(node *fuse.Inode) {
me.node = node
}
func (me *unionFsFile) GetAttr() (*os.FileInfo, fuse.Status) {
fi, code := me.File.GetAttr() fi, code := me.File.GetAttr()
if fi != nil { if fi != nil {
f := *fi f := *fi
......
...@@ -1001,3 +1001,51 @@ func TestStatFs(t *testing.T) { ...@@ -1001,3 +1001,51 @@ func TestStatFs(t *testing.T) {
t.Fatal("Expect blocksize > 0") t.Fatal("Expect blocksize > 0")
} }
} }
func TestFlushSize(t *testing.T) {
wd, clean := setupUfs(t)
defer clean()
fn := wd + "/mount/file"
f, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE, 0644)
CheckSuccess(err)
fi, err := f.Stat()
CheckSuccess(err)
n, err := f.Write([]byte("hello"))
CheckSuccess(err)
f.Close()
fi, err = os.Lstat(fn)
CheckSuccess(err)
if fi.Size != int64(n) {
t.Errorf("got %d from Stat().Size, want %d", fi.Size, n)
}
}
func TestFlushRename(t *testing.T) {
wd, clean := setupUfs(t)
defer clean()
err := ioutil.WriteFile(wd +"/mount/file", []byte("x"), 0644)
fn := wd + "/mount/tmp"
f, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE, 0644)
CheckSuccess(err)
fi, err := f.Stat()
CheckSuccess(err)
n, err := f.Write([]byte("hello"))
CheckSuccess(err)
f.Close()
dst := wd + "/mount/file"
err = os.Rename(fn, dst)
CheckSuccess(err)
fi, err = os.Lstat(dst)
CheckSuccess(err)
if fi.Size != int64(n) {
t.Errorf("got %d from Stat().Size, want %d", fi.Size, n)
}
}
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