fuse mount: speedup

This commit is contained in:
Tobias Klein 2017-10-08 17:47:10 +02:00
parent 8ceb22fe8a
commit 7e4ce0dacc
2 changed files with 101 additions and 70 deletions

View file

@ -27,6 +27,7 @@ type Root struct {
inode uint64 inode uint64
snapshots restic.Snapshots snapshots restic.Snapshots
blobSizeCache *BlobSizeCache blobSizeCache *BlobSizeCache
snCount int
*MetaDir *MetaDir
} }

View file

@ -19,33 +19,37 @@ import (
// SnapshotsDir is a fuse directory which contains snapshots named by timestamp. // SnapshotsDir is a fuse directory which contains snapshots named by timestamp.
type SnapshotsDir struct { type SnapshotsDir struct {
inode uint64 inode uint64
root *Root root *Root
names map[string]*restic.Snapshot names map[string]*restic.Snapshot
latest string latest string
tag string tag string
host string host string
snCount int
} }
// SnapshotsIDSDir is a fuse directory which contains snapshots named by ids. // SnapshotsIDSDir is a fuse directory which contains snapshots named by ids.
type SnapshotsIDSDir struct { type SnapshotsIDSDir struct {
inode uint64 inode uint64
root *Root root *Root
names map[string]*restic.Snapshot names map[string]*restic.Snapshot
snCount int
} }
// HostsDir is a fuse directory which contains hosts. // HostsDir is a fuse directory which contains hosts.
type HostsDir struct { type HostsDir struct {
inode uint64 inode uint64
root *Root root *Root
hosts map[string]bool hosts map[string]bool
snCount int
} }
// TagsDir is a fuse directory which contains tags. // TagsDir is a fuse directory which contains tags.
type TagsDir struct { type TagsDir struct {
inode uint64 inode uint64
root *Root root *Root
tags map[string]bool tags map[string]bool
snCount int
} }
// SnapshotLink // SnapshotLink
@ -68,28 +72,37 @@ var _ = fs.NodeStringLookuper(&HostsDir{})
var _ = fs.NodeReadlinker(&snapshotLink{}) var _ = fs.NodeReadlinker(&snapshotLink{})
// read tag names from the current repository-state. // read tag names from the current repository-state.
func getTagNames(d *TagsDir) { func updateTagNames(d *TagsDir) {
d.tags = make(map[string]bool, len(d.root.snapshots)) if d.snCount != d.root.snCount {
for _, snapshot := range d.root.snapshots { d.snCount = d.root.snCount
for _, tag := range snapshot.Tags { d.tags = make(map[string]bool, len(d.root.snapshots))
d.tags[tag] = true for _, snapshot := range d.root.snapshots {
for _, tag := range snapshot.Tags {
d.tags[tag] = true
}
} }
} }
} }
// read host names from the current repository-state. // read host names from the current repository-state.
func getHostsNames(d *HostsDir) { func updateHostsNames(d *HostsDir) {
d.hosts = make(map[string]bool, len(d.root.snapshots)) if d.snCount != d.root.snCount {
for _, snapshot := range d.root.snapshots { d.snCount = d.root.snCount
d.hosts[snapshot.Hostname] = true d.hosts = make(map[string]bool, len(d.root.snapshots))
for _, snapshot := range d.root.snapshots {
d.hosts[snapshot.Hostname] = true
}
} }
} }
// read snapshot id names from the current repository-state. // read snapshot id names from the current repository-state.
func getSnapshotIDSNames(d *SnapshotsIDSDir) { func updateSnapshotIDSNames(d *SnapshotsIDSDir) {
for _, sn := range d.root.snapshots { if d.snCount != d.root.snCount {
name := sn.ID().Str() d.snCount = d.root.snCount
d.names[name] = sn for _, sn := range d.root.snapshots {
name := sn.ID().Str()
d.names[name] = sn
}
} }
} }
@ -206,28 +219,41 @@ func isElem(e string, list []string) bool {
return false return false
} }
// update snapshots if repository has changed
func updateSnapshots(ctx context.Context, root *Root) {
snapshots := restic.FindFilteredSnapshots(ctx, root.repo, root.cfg.Host, root.cfg.Tags, root.cfg.Paths)
if root.snCount != len(snapshots) {
root.snCount = len(snapshots)
root.repo.LoadIndex(ctx)
root.snapshots = snapshots
}
}
// read snapshot timestamps from the current repository-state. // read snapshot timestamps from the current repository-state.
func getSnapshotNames(d *SnapshotsDir) { func updateSnapshotNames(d *SnapshotsDir) {
var latestTime time.Time if d.snCount != d.root.snCount {
d.latest = "" d.snCount = d.root.snCount
d.names = make(map[string]*restic.Snapshot, len(d.root.snapshots)) var latestTime time.Time
for _, sn := range d.root.snapshots { d.latest = ""
if d.tag == "" || isElem(d.tag, sn.Tags) { d.names = make(map[string]*restic.Snapshot, len(d.root.snapshots))
if d.host == "" || d.host == sn.Hostname { for _, sn := range d.root.snapshots {
name := sn.Time.Format(time.RFC3339) if d.tag == "" || isElem(d.tag, sn.Tags) {
if d.latest == "" || !sn.Time.Before(latestTime) { if d.host == "" || d.host == sn.Hostname {
latestTime = sn.Time name := sn.Time.Format(time.RFC3339)
d.latest = name if d.latest == "" || !sn.Time.Before(latestTime) {
} latestTime = sn.Time
for i := 1; ; i++ { d.latest = name
if _, ok := d.names[name]; !ok { }
break for i := 1; ; i++ {
if _, ok := d.names[name]; !ok {
break
}
name = fmt.Sprintf("%s-%d", sn.Time.Format(time.RFC3339), i)
} }
name = fmt.Sprintf("%s-%d", sn.Time.Format(time.RFC3339), i) d.names[name] = sn
} }
d.names[name] = sn
} }
} }
} }
@ -237,10 +263,11 @@ func getSnapshotNames(d *SnapshotsDir) {
func (d *SnapshotsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { func (d *SnapshotsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
debug.Log("ReadDirAll()") debug.Log("ReadDirAll()")
d.root.repo.LoadIndex(ctx) // update snapshots
d.root.snapshots = restic.FindFilteredSnapshots(ctx, d.root.repo, d.root.cfg.Host, d.root.cfg.Tags, d.root.cfg.Paths) updateSnapshots(ctx, d.root)
getSnapshotNames(d) // update snapshot names
updateSnapshotNames(d)
items := []fuse.Dirent{ items := []fuse.Dirent{
{ {
@ -278,10 +305,11 @@ func (d *SnapshotsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
func (d *SnapshotsIDSDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { func (d *SnapshotsIDSDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
debug.Log("ReadDirAll()") debug.Log("ReadDirAll()")
d.root.repo.LoadIndex(ctx) // update snapshots
d.root.snapshots = restic.FindFilteredSnapshots(ctx, d.root.repo, d.root.cfg.Host, d.root.cfg.Tags, d.root.cfg.Paths) updateSnapshots(ctx, d.root)
getSnapshotIDSNames(d) // update snapshot ids
updateSnapshotIDSNames(d)
items := []fuse.Dirent{ items := []fuse.Dirent{
{ {
@ -311,10 +339,11 @@ func (d *SnapshotsIDSDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error)
func (d *HostsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { func (d *HostsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
debug.Log("ReadDirAll()") debug.Log("ReadDirAll()")
d.root.repo.LoadIndex(ctx) // update snapshots
d.root.snapshots = restic.FindFilteredSnapshots(ctx, d.root.repo, d.root.cfg.Host, d.root.cfg.Tags, d.root.cfg.Paths) updateSnapshots(ctx, d.root)
getHostsNames(d) // update host names
updateHostsNames(d)
items := []fuse.Dirent{ items := []fuse.Dirent{
{ {
@ -344,10 +373,11 @@ func (d *HostsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
func (d *TagsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { func (d *TagsDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
debug.Log("ReadDirAll()") debug.Log("ReadDirAll()")
d.root.repo.LoadIndex(ctx) // update snapshots
d.root.snapshots = restic.FindFilteredSnapshots(ctx, d.root.repo, d.root.cfg.Host, d.root.cfg.Tags, d.root.cfg.Paths) updateSnapshots(ctx, d.root)
getTagNames(d) // update tag names
updateTagNames(d)
items := []fuse.Dirent{ items := []fuse.Dirent{
{ {
@ -408,10 +438,10 @@ func (d *SnapshotsDir) Lookup(ctx context.Context, name string) (fs.Node, error)
sn, ok := d.names[name] sn, ok := d.names[name]
if !ok { if !ok {
// could not find entry. Updating repository-state // could not find entry. Updating repository-state
d.root.repo.LoadIndex(ctx) updateSnapshots(ctx, d.root)
d.root.snapshots = restic.FindFilteredSnapshots(ctx, d.root.repo, d.root.cfg.Host, d.root.cfg.Tags, d.root.cfg.Paths)
getSnapshotNames(d) // update snapshot names
updateSnapshotNames(d)
sn, ok := d.names[name] sn, ok := d.names[name]
if ok { if ok {
@ -441,10 +471,10 @@ func (d *SnapshotsIDSDir) Lookup(ctx context.Context, name string) (fs.Node, err
sn, ok := d.names[name] sn, ok := d.names[name]
if !ok { if !ok {
// could not find entry. Updating repository-state // could not find entry. Updating repository-state
d.root.repo.LoadIndex(ctx) updateSnapshots(ctx, d.root)
d.root.snapshots = restic.FindFilteredSnapshots(ctx, d.root.repo, d.root.cfg.Host, d.root.cfg.Tags, d.root.cfg.Paths)
getSnapshotIDSNames(d) // update snapshot ids
updateSnapshotIDSNames(d)
sn, ok := d.names[name] sn, ok := d.names[name]
if ok { if ok {
@ -464,10 +494,10 @@ func (d *HostsDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
_, ok := d.hosts[name] _, ok := d.hosts[name]
if !ok { if !ok {
// could not find entry. Updating repository-state // could not find entry. Updating repository-state
d.root.repo.LoadIndex(ctx) updateSnapshots(ctx, d.root)
d.root.snapshots = restic.FindFilteredSnapshots(ctx, d.root.repo, d.root.cfg.Host, d.root.cfg.Tags, d.root.cfg.Paths)
getHostsNames(d) // update host names
updateHostsNames(d)
_, ok := d.hosts[name] _, ok := d.hosts[name]
if ok { if ok {
@ -487,10 +517,10 @@ func (d *TagsDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
_, ok := d.tags[name] _, ok := d.tags[name]
if !ok { if !ok {
// could not find entry. Updating repository-state // could not find entry. Updating repository-state
d.root.repo.LoadIndex(ctx) updateSnapshots(ctx, d.root)
d.root.snapshots = restic.FindFilteredSnapshots(ctx, d.root.repo, d.root.cfg.Host, d.root.cfg.Tags, d.root.cfg.Paths)
getTagNames(d) // update tag names
updateTagNames(d)
_, ok := d.tags[name] _, ok := d.tags[name]
if ok { if ok {