summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorZhaozhong Ni <nzz@google.com>2018-08-28 13:20:54 -0700
committerShentubot <shentubot@google.com>2018-08-28 13:22:07 -0700
commitd724863a313f5e08a043c8f2ccb4969e8ea23de1 (patch)
tree16d082c77daa0d3384e89a9984a2569e739f0bb7
parentea113a4380543080f7ad92f536e71706e71d9285 (diff)
sentry: optimize dirent weakref map save / restore.
Weak references save / restore involves multiple interface indirection and cause material latency overhead when there are lots of dirents, each containing a weak reference map. The nil entries in the map should also be purged. PiperOrigin-RevId: 210593727 Change-Id: Ied6f4c3c0726fcc53a24b983d9b3a79121b6b758
-rw-r--r--pkg/sentry/fs/dirent.go2
-rw-r--r--pkg/sentry/fs/dirent_state.go23
2 files changed, 24 insertions, 1 deletions
diff --git a/pkg/sentry/fs/dirent.go b/pkg/sentry/fs/dirent.go
index 5587582b5..9417e808f 100644
--- a/pkg/sentry/fs/dirent.go
+++ b/pkg/sentry/fs/dirent.go
@@ -201,7 +201,7 @@ type Dirent struct {
mu sync.Mutex `state:"nosave"`
// children are cached via weak references.
- children map[string]*refs.WeakRef
+ children map[string]*refs.WeakRef `state:".(map[string]*Dirent)"`
}
// NewDirent returns a new root Dirent, taking the caller's reference on inode. The caller
diff --git a/pkg/sentry/fs/dirent_state.go b/pkg/sentry/fs/dirent_state.go
index c6a1b5e38..fb81e7d54 100644
--- a/pkg/sentry/fs/dirent_state.go
+++ b/pkg/sentry/fs/dirent_state.go
@@ -17,6 +17,8 @@ package fs
import (
"fmt"
"sync/atomic"
+
+ "gvisor.googlesource.com/gvisor/pkg/refs"
)
// beforeSave is invoked by stateify.
@@ -36,6 +38,27 @@ func (d *Dirent) beforeSave() {
}
}
+// saveChildren is invoked by stateify.
+func (d *Dirent) saveChildren() map[string]*Dirent {
+ c := make(map[string]*Dirent)
+ for name, w := range d.children {
+ if rc := w.Get(); rc != nil {
+ // Drop the reference count obtain in w.Get()
+ rc.DecRef()
+ c[name] = rc.(*Dirent)
+ }
+ }
+ return c
+}
+
+// loadChildren is invoked by stateify.
+func (d *Dirent) loadChildren(children map[string]*Dirent) {
+ d.children = make(map[string]*refs.WeakRef)
+ for name, c := range children {
+ d.children[name] = refs.NewWeakRef(c, nil)
+ }
+}
+
// afterLoad is invoked by stateify.
func (d *Dirent) afterLoad() {
if d.userVisible {