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

MemUnionFs: garbage collect backing store.

parent 5fd3a354
......@@ -24,8 +24,6 @@ type MemUnionFs struct {
cond *sync.Cond
nextFree int
// TODO - should clear out backing every X file creations, to clean up unused files.
readonly fuse.FileSystem
openWritable int
......@@ -67,6 +65,34 @@ func (me *MemUnionFs) release() {
me.cond.Broadcast()
}
func (me *MemUnionFs) gc() {
f, err := os.Open(me.backingStore)
if err != nil {
return
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil {
return
}
me.mutex.Lock()
seen := map[string]bool{}
me.root.markUsed(seen)
del := []string{}
for _, n := range names {
full := filepath.Join(me.backingStore, n)
if !seen[full] {
del = append(del, full)
}
}
me.mutex.Unlock()
for _, n := range del {
os.Remove(n)
}
}
func (me *MemUnionFs) Reap() map[string]*Result {
me.mutex.Lock()
defer me.mutex.Unlock()
......@@ -164,6 +190,9 @@ func (me *MemUnionFs) Update(results map[string]*Result) {
func (me *MemUnionFs) getFilename() string {
id := me.nextFree
me.nextFree++
if me.nextFree % 1000 == 0 {
go me.gc()
}
return fmt.Sprintf("%s/%d", me.backingStore, id)
}
......@@ -582,6 +611,16 @@ func (me *memNode) Reap(path string, results map[string]*Result) {
}
}
func (me *memNode) markUsed(seen map[string]bool) {
if me.backing != "" {
seen[me.backing] = true
}
for _, ch := range me.Inode().FsChildren() {
ch.FsNode().(*memNode).markUsed(seen)
}
}
func (me *memNode) Clear(path string) {
me.original = path
me.changed = false
......@@ -592,3 +631,4 @@ func (me *memNode) Clear(path string) {
mn.Clear(p)
}
}
......@@ -775,3 +775,21 @@ func TestMemUnionFsRenameDirWithDeletions(t *testing.T) {
t.Fatalf("%s/mount/dir/subdir should have disappeared %#v", wd, fi)
}
}
func TestMemUnionGc(t *testing.T) {
wd, ufs, clean := setupMemUfs(t)
defer clean()
writeToFile(wd+"/mount/file1", "other-content")
writeToFile(wd+"/mount/file2", "other-content")
err := os.Remove(wd+"/mount/file1")
CheckSuccess(err)
ufs.gc()
entries, err := ioutil.ReadDir(wd+"/backing")
CheckSuccess(err)
if len(entries) != 1 {
t.Fatalf("should have 1 file after backing store gc: %v", entries)
}
}
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