Expose some kernel hooks.

- Add Kernel.IsPaused() which indicates whether the kernel is currently paused.
- Add TaskSet.ForEachThreadGroup() which allows callers to iterate through all
  thread groups in the kernel.
- Export FDTable.ForEach() which allows other packages to iterate over all FDs.

PiperOrigin-RevId: 640760723
This commit is contained in:
Ayush Ranjan
2024-06-05 21:43:43 -07:00
committed by gVisor bot
parent 6b537e43eb
commit 448f894c70
4 changed files with 28 additions and 8 deletions
+6 -6
View File
@@ -93,7 +93,7 @@ func (f *FDTable) saveDescriptorTable() map[int32]descriptor {
m := make(map[int32]descriptor)
f.mu.Lock()
defer f.mu.Unlock()
f.forEach(context.Background(), func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
f.ForEach(context.Background(), func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
m[fd] = descriptor{
file: file,
flags: flags,
@@ -172,10 +172,10 @@ func (f *FDTable) forEachUpTo(ctx context.Context, maxFd int32, fn func(fd int32
})
}
// forEach iterates over all non-nil files upto maxFd in sorted order.
// ForEach iterates over all non-nil files upto maxFd in sorted order.
//
// It is the caller's responsibility to acquire an appropriate lock.
func (f *FDTable) forEach(ctx context.Context, fn func(fd int32, file *vfs.FileDescription, flags FDFlags) bool) {
func (f *FDTable) ForEach(ctx context.Context, fn func(fd int32, file *vfs.FileDescription, flags FDFlags) bool) {
f.forEachUpTo(ctx, MaxFdLimit, fn)
}
@@ -187,7 +187,7 @@ func (f *FDTable) String() string {
f.mu.Lock()
// Can't release f.mu from defer, because vfsObj.PathnameWithDeleted
// should not be called under the fdtable mutex.
f.forEach(ctx, func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
f.ForEach(ctx, func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
if file != nil {
file.IncRef()
files[fd] = file
@@ -424,7 +424,7 @@ func (f *FDTable) GetFDs(ctx context.Context) []int32 {
f.mu.Lock()
defer f.mu.Unlock()
fds := make([]int32, 0, int(f.fdBitmap.GetNumOnes()))
f.forEach(ctx, func(fd int32, _ *vfs.FileDescription, _ FDFlags) bool {
f.ForEach(ctx, func(fd int32, _ *vfs.FileDescription, _ FDFlags) bool {
fds = append(fds, fd)
return true
})
@@ -486,7 +486,7 @@ func (f *FDTable) RemoveIf(ctx context.Context, cond func(*vfs.FileDescription,
var files []*vfs.FileDescription
f.mu.Lock()
f.forEach(ctx, func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
f.ForEach(ctx, func(fd int32, file *vfs.FileDescription, flags FDFlags) bool {
if cond(file, flags) {
// Clear from table.
if df := f.set(fd, nil, FDFlags{}); df != nil {
+7 -2
View File
@@ -1215,7 +1215,7 @@ func (k *Kernel) pauseTimeLocked(ctx context.Context) {
// This means we'll iterate FDTables shared by multiple tasks repeatedly,
// but ktime.Timer.Pause is idempotent so this is harmless.
if t.fdTable != nil {
t.fdTable.forEach(ctx, func(_ int32, fd *vfs.FileDescription, _ FDFlags) bool {
t.fdTable.ForEach(ctx, func(_ int32, fd *vfs.FileDescription, _ FDFlags) bool {
if tfd, ok := fd.Impl().(*timerfd.TimerFileDescription); ok {
tfd.PauseTimer()
}
@@ -1246,7 +1246,7 @@ func (k *Kernel) resumeTimeLocked(ctx context.Context) {
}
}
if t.fdTable != nil {
t.fdTable.forEach(ctx, func(_ int32, fd *vfs.FileDescription, _ FDFlags) bool {
t.fdTable.ForEach(ctx, func(_ int32, fd *vfs.FileDescription, _ FDFlags) bool {
if tfd, ok := fd.Impl().(*timerfd.TimerFileDescription); ok {
tfd.ResumeTimer()
}
@@ -1354,6 +1354,11 @@ func (k *Kernel) Pause() {
k.tasks.aioGoroutines.Wait()
}
// IsPaused returns true if the kernel is currently paused.
func (k *Kernel) IsPaused() bool {
return k.tasks.isExternallyStopped()
}
// ReceiveTaskStates receives full states for all tasks.
func (k *Kernel) ReceiveTaskStates() {
k.extMu.Lock()
+8
View File
@@ -241,3 +241,11 @@ func (ts *TaskSet) EndExternalStop() {
t.tg.signalHandlers.mu.Unlock()
}
}
// isExternallyStopped returns true if BeginExternalStop() has been called on
// this TaskSet, without a corresponding call to EndExternalStop().
func (ts *TaskSet) isExternallyStopped() bool {
ts.mu.Lock()
defer ts.mu.Unlock()
return ts.stopCount > 0
}
+7
View File
@@ -106,6 +106,13 @@ func newTaskSet(pidns *PIDNamespace) *TaskSet {
return ts
}
// ForEachThreadGroup applies f to each thread group in ts.
func (ts *TaskSet) ForEachThreadGroup(f func(tg *ThreadGroup)) {
ts.mu.RLock()
defer ts.mu.RUnlock()
ts.forEachThreadGroupLocked(f)
}
// forEachThreadGroupLocked applies f to each thread group in ts.
//
// Preconditions: ts.mu must be locked (for reading or writing).