kernel: don't use atomic pointers for task.netns

task.netns is always changed from a task goroutine under task.mu.

It means that we can access it without any locks from a task goroutine
we don't need to increment a reference counter in such cases.

In all other cases, we need to take task.mu.

PiperOrigin-RevId: 552913323
This commit is contained in:
Andrei Vagin
2023-08-01 14:04:53 -07:00
committed by gVisor bot
parent fa9163e7a0
commit abe7cee096
6 changed files with 14 additions and 24 deletions
-12
View File
@@ -18,21 +18,9 @@ go_template_instance(
},
)
go_template_instance(
name = "atomicptr_netns",
out = "atomicptr_netns_unsafe.go",
package = "inet",
prefix = "Namespace",
template = "//pkg/sync/atomicptr:generic_atomicptr",
types = {
"Value": "Namespace",
},
)
go_library(
name = "inet",
srcs = [
"atomicptr_netns_unsafe.go",
"context.go",
"inet.go",
"namespace.go",
+2 -2
View File
@@ -508,8 +508,8 @@ type Task struct {
// netns is the task's network namespace. It has to be changed under mu
// so that GetNetworkNamespace can take a reference before it is
// released.
netns inet.NamespaceAtomicPtr
// released. It is changed only from the task goroutine.
netns *inet.Namespace
// If rseqPreempted is true, before the next call to p.Switch(),
// interrupt rseq critical regions as defined by rseqAddr and
+5 -4
View File
@@ -126,7 +126,7 @@ func (t *Task) Clone(args *linux.CloneArgs) (ThreadID, *SyscallControl, error) {
ipcns.DecRef(t)
})
netns := t.netns.Load()
netns := t.netns
if args.Flags&linux.CLONE_NEWNET != 0 {
netns = inet.NewNamespace(netns, userns)
inode := nsfs.NewInode(t, t.k.nsfsMount, netns)
@@ -444,7 +444,7 @@ func (t *Task) Setns(fd *vfs.FileDescription, flags int32) error {
oldNS := t.NetworkNamespace()
ns.IncRef()
t.mu.Lock()
t.netns.Store(ns)
t.netns = ns
t.mu.Unlock()
oldNS.DecRef(t)
return nil
@@ -570,9 +570,10 @@ func (t *Task) Unshare(flags int32) error {
netnsInode := nsfs.NewInode(t, t.k.nsfsMount, netns)
netns.SetInode(netnsInode)
t.mu.Lock()
netns = t.netns.Swap(netns)
oldNetns := t.netns
t.netns = netns
t.mu.Unlock()
netns.DecRef(t)
oldNetns.DecRef(t)
}
cu := cleanup.Cleanup{}
+2 -1
View File
@@ -288,7 +288,8 @@ func (*runExitMain) execute(t *Task) taskRunState {
mntns := t.mountNamespace
t.mountNamespace = nil
ipcns := t.ipcns
netns := t.netns.Swap(nil)
netns := t.netns
t.netns = nil
t.mu.Unlock()
if mntns != nil {
mntns.DecRef(t)
+4 -4
View File
@@ -20,7 +20,7 @@ import (
// IsNetworkNamespaced returns true if t is in a non-root network namespace.
func (t *Task) IsNetworkNamespaced() bool {
return !t.netns.Load().IsRoot()
return !t.netns.IsRoot()
}
// NetworkContext returns the network stack used by the task. NetworkContext
@@ -29,12 +29,12 @@ func (t *Task) IsNetworkNamespaced() bool {
// TODO(gvisor.dev/issue/1833): Migrate callers of this method to
// NetworkNamespace().
func (t *Task) NetworkContext() inet.Stack {
return t.netns.Load().Stack()
return t.netns.Stack()
}
// NetworkNamespace returns the network namespace observed by the task.
func (t *Task) NetworkNamespace() *inet.Namespace {
return t.netns.Load()
return t.netns
}
// GetNetworkNamespace takes a reference on the task network namespace and
@@ -43,7 +43,7 @@ func (t *Task) GetNetworkNamespace() *inet.Namespace {
// t.mu is required to be sure that the network namespace will not be
// released.
t.mu.Lock()
netns := t.netns.Load()
netns := t.netns
if netns != nil {
netns.IncRef()
}
+1 -1
View File
@@ -171,7 +171,7 @@ func (ts *TaskSet) newTask(ctx context.Context, cfg *TaskConfig) (*Task, error)
cgroups: make(map[Cgroup]struct{}),
userCounters: cfg.UserCounters,
}
t.netns.Store(cfg.NetworkNamespace)
t.netns = cfg.NetworkNamespace
t.creds.Store(cfg.Credentials)
t.endStopCond.L = &t.tg.signalHandlers.mu
t.ptraceTracer.Store((*Task)(nil))