From: Eric W. Biederman <ebiederm@xmission.com> - unquoted
Support is added for the .data.pernet section where all of
the variables who have a single instance in each network
namespace will live. Every architectures linker script
is modified so is should work.
Summarizing the functions:
net_ns_init creates a slab and allocates the template and
the initial network namespace.
pernet_modcopy keeps the network namespaces in sync with
the loaded modules. Initializing new data variables as
they are added.
The network namespace destruction because the last reference
can come from interrupt context queues itself for later with
schedule_work. Then we alert everyone the network namespace
is disappearing. If a buggy user is still holding a reference
to the network namespace we print a nasty message and leak
the network namespace.
The wrest are just light-weight wrapper functions to make things
more convinient.
A little should probably be said about net_head the variable
at the start of my network namespace structure. It is the only
variable with a location decided by the C code instead of the linker
and I string them together in a linked list so I can iterate.
Probably more interesting is that it looks like it is saner not
to directly use a pointer to my network namespace but instead to
use an offset. All of the references to data in my network namespace
are coming from per_net(...) which takes the address of the variable
in the .data.pernet section and then adds my magic offset. If I
used a pointer I would have to subract an additional value and
export an extra symbol. Not good for performance or maintenance :)
The expected usage of network namespace variables is to replace
sequences like: &loopback_dev with &per_net(loopback_dev, net)
where net is some network namespace reference. In my preliminary
tests the only a single additional addition is inserted so it
appears to be an efficient idiom. Hopefully it is also easy to
comprehend and use.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
arch/alpha/kernel/vmlinux.lds.S | 2 +
arch/arm/kernel/vmlinux.lds.S | 3 +
arch/arm26/kernel/vmlinux-arm26-xip.lds.in | 3 +
arch/arm26/kernel/vmlinux-arm26.lds.in | 3 +
arch/avr32/kernel/vmlinux.lds.c | 3 +
arch/cris/arch-v10/vmlinux.lds.S | 2 +
arch/cris/arch-v32/vmlinux.lds.S | 2 +
arch/frv/kernel/vmlinux.lds.S | 2 +
arch/h8300/kernel/vmlinux.lds.S | 3 +
arch/i386/kernel/vmlinux.lds.S | 3 +
arch/ia64/kernel/vmlinux.lds.S | 2 +
arch/m32r/kernel/vmlinux.lds.S | 3 +
arch/m68k/kernel/vmlinux-std.lds | 3 +
arch/m68k/kernel/vmlinux-sun3.lds | 3 +
arch/m68knommu/kernel/vmlinux.lds.S | 3 +
arch/mips/kernel/vmlinux.lds.S | 3 +
arch/parisc/kernel/vmlinux.lds.S | 3 +
arch/powerpc/kernel/vmlinux.lds.S | 2 +
arch/ppc/kernel/vmlinux.lds.S | 2 +
arch/s390/kernel/vmlinux.lds.S | 3 +
arch/sh/kernel/vmlinux.lds.S | 3 +
arch/sh64/kernel/vmlinux.lds.S | 3 +
arch/sparc/kernel/vmlinux.lds.S | 3 +
arch/sparc64/kernel/vmlinux.lds.S | 3 +
arch/v850/kernel/vmlinux.lds.S | 6 +-
arch/x86_64/kernel/vmlinux.lds.S | 3 +
arch/xtensa/kernel/vmlinux.lds.S | 2 +
include/asm-generic/vmlinux.lds.h | 8 +
include/asm-um/common.lds.S | 4 +-
include/linux/module.h | 3 +
include/linux/net_namespace_type.h | 63 ++++++++-
include/net/net_namespace.h | 49 ++++++-
kernel/module.c | 211 ++++++++++++++++++++++++-
net/core/net_namespace.c | 232 ++++++++++++++++++++++++++++
34 files changed, 631 insertions(+), 15 deletions(-)
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index 76bf071..ad20077 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -72,6 +72,8 @@ SECTIONS
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
+ DATA_PER_NET
+
. = ALIGN(2*8192);
__init_end = .;
/* Freed after init ends here */
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index a8fa75e..5b003f9 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -61,6 +61,9 @@ SECTIONS
__per_cpu_start = .;
*(.data.percpu)
__per_cpu_end = .;
+
+ DATA_PER_NET
+
#ifndef CONFIG_XIP_KERNEL
__init_begin = _stext;
*(.init.data)
diff --git a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
index ca61ec8..69d5772 100644
--- a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
+++ b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
@@ -50,6 +50,9 @@ SECTIONS
__initramfs_start = .;
usr/built-in.o(.init.ramfs)
__initramfs_end = .;
+
+ DATA_PER_NET
+
. = ALIGN(32768);
__init_end = .;
}
diff --git a/arch/arm26/kernel/vmlinux-arm26.lds.in b/arch/arm26/kernel/vmlinux-arm26.lds.in
index d1d3418..473a5b4 100644
--- a/arch/arm26/kernel/vmlinux-arm26.lds.in
+++ b/arch/arm26/kernel/vmlinux-arm26.lds.in
@@ -51,6 +51,9 @@ SECTIONS
__initramfs_start = .;
usr/built-in.o(.init.ramfs)
__initramfs_end = .;
+
+ DATA_PER_NET
+
. = ALIGN(32768);
__init_end = .;
}
diff --git a/arch/avr32/kernel/vmlinux.lds.c b/arch/avr32/kernel/vmlinux.lds.c
index 5c4424e..dee3715 100644
--- a/arch/avr32/kernel/vmlinux.lds.c
+++ b/arch/avr32/kernel/vmlinux.lds.c
@@ -50,6 +50,9 @@ SECTIONS
__initramfs_start = .;
*(.init.ramfs)
__initramfs_end = .;
+
+ DATA_PER_NET
+
. = ALIGN(4096);
__init_end = .;
}
diff --git a/arch/cris/arch-v10/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S
index 689729a..f1c890c 100644
--- a/arch/cris/arch-v10/vmlinux.lds.S
+++ b/arch/cris/arch-v10/vmlinux.lds.S
@@ -83,6 +83,8 @@ SECTIONS
}
SECURITY_INIT
+ DATA_PER_NET
+
.init.ramfs : {
__initramfs_start = .;
*(.init.ramfs)
diff --git a/arch/cris/arch-v32/vmlinux.lds.S b/arch/cris/arch-v32/vmlinux.lds.S
index 472d4b3..eb08771 100644
--- a/arch/cris/arch-v32/vmlinux.lds.S
+++ b/arch/cris/arch-v32/vmlinux.lds.S
@@ -95,6 +95,8 @@ SECTIONS
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
+ DATA_PER_NET
+
.init.ramfs : {
__initramfs_start = .;
*(.init.ramfs)
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index 9c1fb12..f383c83 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -61,6 +61,8 @@ SECTIONS
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
+ DATA_PER_NET
+
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
index f05288b..5d5fda5 100644
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ b/arch/h8300/kernel/vmlinux.lds.S
@@ -130,6 +130,9 @@ SECTIONS
___initramfs_start = .;
*(.init.ramfs)
___initramfs_end = .;
+
+ DATA_PER_NET
+
. = ALIGN(0x4) ;
___init_end = .;
__edata = . ;
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index a53c8b1..1aae8b4 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -193,6 +193,9 @@ SECTIONS
*(.data.percpu)
__per_cpu_end = .;
}
+
+ DATA_PER_NET
+
. = ALIGN(4096);
/* freed after init ends here */
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index d6083a0..28dd9eb 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -118,6 +118,8 @@ SECTIONS
__initramfs_end = .;
}
+ DATA_PER_NET
+
. = ALIGN(16);
.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET)
{
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
index 358b9ce..3e8c624 100644
--- a/arch/m32r/kernel/vmlinux.lds.S
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -107,6 +107,9 @@ SECTIONS
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
+
+ DATA_PER_NET
+
. = ALIGN(4096);
__init_end = .;
/* freed after init ends here */
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index d279445..d60cb7e 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -65,6 +65,9 @@ SECTIONS
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
+
+ DATA_PER_NET
+
. = ALIGN(8192);
__init_end = .;
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index 8c7eccb..101ec12 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -59,6 +59,9 @@ __init_begin = .;
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
+
+ DATA_PER_NET
+
. = ALIGN(8192);
__init_end = .;
.data.init.task : { *(.data.init_task) }
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 2b2a10d..e713614 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -153,6 +153,9 @@ SECTIONS {
__initramfs_start = .;
*(.init.ramfs)
__initramfs_end = .;
+
+ DATA_PER_NET
+
. = ALIGN(4096);
__init_end = .;
} > INIT
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index cecff24..a5cfeef 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -121,6 +121,9 @@ SECTIONS
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
+
+ DATA_PER_NET
+
. = ALIGN(_PAGE_SIZE);
__init_end = .;
/* freed after init ends here */
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 7b943b4..2cf241b 100644
--- a/arch/parisc/kernel/v
...