diff options
Diffstat (limited to 'pkg/sentry/fsimpl/kernfs')
-rw-r--r-- | pkg/sentry/fsimpl/kernfs/dentry_refs.go | 42 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go | 9 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/kernfs/static_directory_refs.go | 42 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go | 42 |
4 files changed, 57 insertions, 78 deletions
diff --git a/pkg/sentry/fsimpl/kernfs/dentry_refs.go b/pkg/sentry/fsimpl/kernfs/dentry_refs.go index 79863b3bc..c2304939b 100644 --- a/pkg/sentry/fsimpl/kernfs/dentry_refs.go +++ b/pkg/sentry/fsimpl/kernfs/dentry_refs.go @@ -2,11 +2,9 @@ package kernfs import ( "fmt" - "runtime" "sync/atomic" - "gvisor.dev/gvisor/pkg/log" - refs_vfs1 "gvisor.dev/gvisor/pkg/refs" + "gvisor.dev/gvisor/pkg/refsvfs2" ) // ownerType is used to customize logging. Note that we use a pointer to T so @@ -19,11 +17,6 @@ var DentryownerType *Dentry // Note that the number of references is actually refCount + 1 so that a default // zero-value Refs object contains one reference. // -// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in -// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount. -// This will allow us to add stack trace information to the leak messages -// without growing the size of Refs. -// // +stateify savable type DentryRefs struct { // refCount is composed of two fields: @@ -36,24 +29,16 @@ type DentryRefs struct { refCount int64 } -func (r *DentryRefs) finalize() { - var note string - switch refs_vfs1.GetLeakMode() { - case refs_vfs1.NoLeakChecking: - return - case refs_vfs1.UninitializedLeakChecking: - note = "(Leak checker uninitialized): " - } - if n := r.ReadRefs(); n != 0 { - log.Warningf("%sRefs %p owned by %T garbage collected with ref count of %d (want 0)", note, r, DentryownerType, n) +// EnableLeakCheck enables reference leak checking on r. +func (r *DentryRefs) EnableLeakCheck() { + if refsvfs2.LeakCheckEnabled() { + refsvfs2.Register(r, fmt.Sprintf("%T", DentryownerType)) } } -// EnableLeakCheck checks for reference leaks when Refs gets garbage collected. -func (r *DentryRefs) EnableLeakCheck() { - if refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking { - runtime.SetFinalizer(r, (*DentryRefs).finalize) - } +// LeakMessage implements refsvfs2.CheckedObject.LeakMessage. +func (r *DentryRefs) LeakMessage() string { + return fmt.Sprintf("%T %p: reference count of %d instead of 0", DentryownerType, r, r.ReadRefs()) } // ReadRefs returns the current number of references. The returned count is @@ -68,7 +53,7 @@ func (r *DentryRefs) ReadRefs() int64 { //go:nosplit func (r *DentryRefs) IncRef() { if v := atomic.AddInt64(&r.refCount, 1); v <= 0 { - panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, DentryownerType)) + panic(fmt.Sprintf("Incrementing non-positive count %p on %T", r, DentryownerType)) } } @@ -110,9 +95,18 @@ func (r *DentryRefs) DecRef(destroy func()) { panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, DentryownerType)) case v == -1: + if refsvfs2.LeakCheckEnabled() { + refsvfs2.Unregister(r, fmt.Sprintf("%T", DentryownerType)) + } if destroy != nil { destroy() } } } + +func (r *DentryRefs) afterLoad() { + if refsvfs2.LeakCheckEnabled() && r.ReadRefs() > 0 { + r.EnableLeakCheck() + } +} diff --git a/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go b/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go index f87782ee1..5121f8225 100644 --- a/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go +++ b/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go @@ -23,10 +23,9 @@ func (r *DentryRefs) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(0, &r.refCount) } -func (r *DentryRefs) afterLoad() {} - func (r *DentryRefs) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &r.refCount) + stateSourceObject.AfterLoad(r.afterLoad) } func (f *DynamicBytesFile) StateTypeName() string { @@ -677,10 +676,9 @@ func (r *StaticDirectoryRefs) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(0, &r.refCount) } -func (r *StaticDirectoryRefs) afterLoad() {} - func (r *StaticDirectoryRefs) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &r.refCount) + stateSourceObject.AfterLoad(r.afterLoad) } func (s *StaticSymlink) StateTypeName() string { @@ -776,10 +774,9 @@ func (r *syntheticDirectoryRefs) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(0, &r.refCount) } -func (r *syntheticDirectoryRefs) afterLoad() {} - func (r *syntheticDirectoryRefs) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &r.refCount) + stateSourceObject.AfterLoad(r.afterLoad) } func init() { diff --git a/pkg/sentry/fsimpl/kernfs/static_directory_refs.go b/pkg/sentry/fsimpl/kernfs/static_directory_refs.go index 478b04bdd..9472a96b9 100644 --- a/pkg/sentry/fsimpl/kernfs/static_directory_refs.go +++ b/pkg/sentry/fsimpl/kernfs/static_directory_refs.go @@ -2,11 +2,9 @@ package kernfs import ( "fmt" - "runtime" "sync/atomic" - "gvisor.dev/gvisor/pkg/log" - refs_vfs1 "gvisor.dev/gvisor/pkg/refs" + "gvisor.dev/gvisor/pkg/refsvfs2" ) // ownerType is used to customize logging. Note that we use a pointer to T so @@ -19,11 +17,6 @@ var StaticDirectoryownerType *StaticDirectory // Note that the number of references is actually refCount + 1 so that a default // zero-value Refs object contains one reference. // -// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in -// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount. -// This will allow us to add stack trace information to the leak messages -// without growing the size of Refs. -// // +stateify savable type StaticDirectoryRefs struct { // refCount is composed of two fields: @@ -36,24 +29,16 @@ type StaticDirectoryRefs struct { refCount int64 } -func (r *StaticDirectoryRefs) finalize() { - var note string - switch refs_vfs1.GetLeakMode() { - case refs_vfs1.NoLeakChecking: - return - case refs_vfs1.UninitializedLeakChecking: - note = "(Leak checker uninitialized): " - } - if n := r.ReadRefs(); n != 0 { - log.Warningf("%sRefs %p owned by %T garbage collected with ref count of %d (want 0)", note, r, StaticDirectoryownerType, n) +// EnableLeakCheck enables reference leak checking on r. +func (r *StaticDirectoryRefs) EnableLeakCheck() { + if refsvfs2.LeakCheckEnabled() { + refsvfs2.Register(r, fmt.Sprintf("%T", StaticDirectoryownerType)) } } -// EnableLeakCheck checks for reference leaks when Refs gets garbage collected. -func (r *StaticDirectoryRefs) EnableLeakCheck() { - if refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking { - runtime.SetFinalizer(r, (*StaticDirectoryRefs).finalize) - } +// LeakMessage implements refsvfs2.CheckedObject.LeakMessage. +func (r *StaticDirectoryRefs) LeakMessage() string { + return fmt.Sprintf("%T %p: reference count of %d instead of 0", StaticDirectoryownerType, r, r.ReadRefs()) } // ReadRefs returns the current number of references. The returned count is @@ -68,7 +53,7 @@ func (r *StaticDirectoryRefs) ReadRefs() int64 { //go:nosplit func (r *StaticDirectoryRefs) IncRef() { if v := atomic.AddInt64(&r.refCount, 1); v <= 0 { - panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, StaticDirectoryownerType)) + panic(fmt.Sprintf("Incrementing non-positive count %p on %T", r, StaticDirectoryownerType)) } } @@ -110,9 +95,18 @@ func (r *StaticDirectoryRefs) DecRef(destroy func()) { panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, StaticDirectoryownerType)) case v == -1: + if refsvfs2.LeakCheckEnabled() { + refsvfs2.Unregister(r, fmt.Sprintf("%T", StaticDirectoryownerType)) + } if destroy != nil { destroy() } } } + +func (r *StaticDirectoryRefs) afterLoad() { + if refsvfs2.LeakCheckEnabled() && r.ReadRefs() > 0 { + r.EnableLeakCheck() + } +} diff --git a/pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go b/pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go index 28d556b42..7c4fde369 100644 --- a/pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go +++ b/pkg/sentry/fsimpl/kernfs/synthetic_directory_refs.go @@ -2,11 +2,9 @@ package kernfs import ( "fmt" - "runtime" "sync/atomic" - "gvisor.dev/gvisor/pkg/log" - refs_vfs1 "gvisor.dev/gvisor/pkg/refs" + "gvisor.dev/gvisor/pkg/refsvfs2" ) // ownerType is used to customize logging. Note that we use a pointer to T so @@ -19,11 +17,6 @@ var syntheticDirectoryownerType *syntheticDirectory // Note that the number of references is actually refCount + 1 so that a default // zero-value Refs object contains one reference. // -// TODO(gvisor.dev/issue/1486): Store stack traces when leak check is enabled in -// a map with 16-bit hashes, and store the hash in the top 16 bits of refCount. -// This will allow us to add stack trace information to the leak messages -// without growing the size of Refs. -// // +stateify savable type syntheticDirectoryRefs struct { // refCount is composed of two fields: @@ -36,24 +29,16 @@ type syntheticDirectoryRefs struct { refCount int64 } -func (r *syntheticDirectoryRefs) finalize() { - var note string - switch refs_vfs1.GetLeakMode() { - case refs_vfs1.NoLeakChecking: - return - case refs_vfs1.UninitializedLeakChecking: - note = "(Leak checker uninitialized): " - } - if n := r.ReadRefs(); n != 0 { - log.Warningf("%sRefs %p owned by %T garbage collected with ref count of %d (want 0)", note, r, syntheticDirectoryownerType, n) +// EnableLeakCheck enables reference leak checking on r. +func (r *syntheticDirectoryRefs) EnableLeakCheck() { + if refsvfs2.LeakCheckEnabled() { + refsvfs2.Register(r, fmt.Sprintf("%T", syntheticDirectoryownerType)) } } -// EnableLeakCheck checks for reference leaks when Refs gets garbage collected. -func (r *syntheticDirectoryRefs) EnableLeakCheck() { - if refs_vfs1.GetLeakMode() != refs_vfs1.NoLeakChecking { - runtime.SetFinalizer(r, (*syntheticDirectoryRefs).finalize) - } +// LeakMessage implements refsvfs2.CheckedObject.LeakMessage. +func (r *syntheticDirectoryRefs) LeakMessage() string { + return fmt.Sprintf("%T %p: reference count of %d instead of 0", syntheticDirectoryownerType, r, r.ReadRefs()) } // ReadRefs returns the current number of references. The returned count is @@ -68,7 +53,7 @@ func (r *syntheticDirectoryRefs) ReadRefs() int64 { //go:nosplit func (r *syntheticDirectoryRefs) IncRef() { if v := atomic.AddInt64(&r.refCount, 1); v <= 0 { - panic(fmt.Sprintf("Incrementing non-positive ref count %p owned by %T", r, syntheticDirectoryownerType)) + panic(fmt.Sprintf("Incrementing non-positive count %p on %T", r, syntheticDirectoryownerType)) } } @@ -110,9 +95,18 @@ func (r *syntheticDirectoryRefs) DecRef(destroy func()) { panic(fmt.Sprintf("Decrementing non-positive ref count %p, owned by %T", r, syntheticDirectoryownerType)) case v == -1: + if refsvfs2.LeakCheckEnabled() { + refsvfs2.Unregister(r, fmt.Sprintf("%T", syntheticDirectoryownerType)) + } if destroy != nil { destroy() } } } + +func (r *syntheticDirectoryRefs) afterLoad() { + if refsvfs2.LeakCheckEnabled() && r.ReadRefs() > 0 { + r.EnableLeakCheck() + } +} |