Home » Mailing lists » Devel » [PATCH 4/7] uts namespaces: implement utsname namespaces  
	
		
		
			| [PATCH 4/7] uts namespaces: implement utsname namespaces [message #2507] | 
			Sat, 08 April 2006 04:52   | 
		 
		
			
				
				
				
					
						  
						serue
						 Messages: 750 Registered: February 2006 
						
					 | 
					Senior Member  | 
					 | 
		 
		 
	 | 
 
	
		This patch defines the uts namespace and some manipulators. 
Adds the uts namespace to task_struct, and initializes a 
system-wide init namespace. 
 
It leaves a #define for system_utsname so sysctl will compile. 
This define will be removed in a separate patch. 
 
Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> 
 
--- 
 
 include/linux/init_task.h |    2 + 
 include/linux/sched.h     |    2 + 
 include/linux/utsname.h   |   43 ++++++++++++++++++++++++++-- 
 init/Kconfig              |    8 +++++ 
 init/version.c            |   68 ++++++++++++++++++++++++++++++++++++++++----- 
 kernel/exit.c             |    2 + 
 kernel/fork.c             |    9 +++++- 
 7 files changed, 120 insertions(+), 14 deletions(-) 
 
1546b386a091cfd18a5f42f61bcba60e2763d3a2 
diff --git a/include/linux/init_task.h b/include/linux/init_task.h 
index 41ecbb8..21b1751 100644 
--- a/include/linux/init_task.h 
+++ b/include/linux/init_task.h 
@@ -3,6 +3,7 @@ 
  
 #include <linux/file.h> 
 #include <linux/rcupdate.h> 
+#include <linux/utsname.h> 
  
 #define INIT_FDTABLE \ 
 {							\ 
@@ -123,6 +124,7 @@ extern struct group_info init_groups; 
 	.journal_info	= NULL,						\ 
 	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\ 
 	.fs_excl	= ATOMIC_INIT(0),				\ 
+	.uts_ns		= &init_uts_ns,					\ 
 } 
  
  
diff --git a/include/linux/sched.h b/include/linux/sched.h 
index 541f482..97c7990 100644 
--- a/include/linux/sched.h 
+++ b/include/linux/sched.h 
@@ -684,6 +684,7 @@ static inline void prefetch_stack(struct 
  
 struct audit_context;		/* See audit.c */ 
 struct mempolicy; 
+struct uts_namespace; 
  
 enum sleep_type { 
 	SLEEP_NORMAL, 
@@ -807,6 +808,7 @@ struct task_struct { 
 	struct files_struct *files; 
 /* namespace */ 
 	struct namespace *namespace; 
+	struct uts_namespace *uts_ns; 
 /* signal handlers */ 
 	struct signal_struct *signal; 
 	struct sighand_struct *sighand; 
diff --git a/include/linux/utsname.h b/include/linux/utsname.h 
index 8f0decf..e6ce607 100644 
--- a/include/linux/utsname.h 
+++ b/include/linux/utsname.h 
@@ -1,5 +1,8 @@ 
 #ifndef _LINUX_UTSNAME_H 
 #define _LINUX_UTSNAME_H 
+#include <linux/sched.h> 
+#include <linux/kref.h> 
+#include <asm/atomic.h> 
  
 #define __OLD_UTS_LEN 8 
  
@@ -30,15 +33,47 @@ struct new_utsname { 
 	char domainname[65]; 
 }; 
  
-extern struct new_utsname system_utsname; 
+struct uts_namespace { 
+	struct kref kref; 
+	struct new_utsname name; 
+}; 
+extern struct uts_namespace init_uts_ns; 
+ 
+#ifdef CONFIG_UTS_NS 
+ 
+extern struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns); 
+extern struct uts_namespace *unshare_uts_ns(void); 
+extern void free_uts_ns(struct kref *kref); 
+ 
+static inline void get_uts_ns(struct uts_namespace *ns) 
+{ 
+	kref_get(&ns->kref); 
+} 
+ 
+static inline void put_uts_ns(struct uts_namespace *ns) 
+{ 
+	kref_put(&ns->kref, free_uts_ns); 
+} 
+ 
+#else 
+static inline void get_uts_ns(struct uts_namespace *ns) 
+{ 
+} 
+static inline void put_uts_ns(struct uts_namespace *ns) 
+{ 
+} 
+#endif 
  
-static inline struct new_utsname *utsname(void) { 
-	return &system_utsname; 
+static inline struct new_utsname *utsname(void) 
+{ 
+	return ¤t->uts_ns->name; 
 } 
  
 static inline struct new_utsname *init_utsname(void) { 
-	return &system_utsname; 
+	return &init_uts_ns.name; 
 } 
  
+#define system_utsname init_uts_ns.name 
+ 
 extern struct rw_semaphore uts_sem; 
 #endif 
diff --git a/init/Kconfig b/init/Kconfig 
index 3b36a1d..8460e5a 100644 
--- a/init/Kconfig 
+++ b/init/Kconfig 
@@ -166,6 +166,14 @@ config SYSCTL 
 	  building a kernel for install/rescue disks or your system is very 
 	  limited in memory. 
  
+config UTS_NS 
+	bool "UTS Namespaces" 
+	default n 
+	help 
+	  Support uts namespaces.  This allows containers, i.e. 
+	  vservers, to use uts namespaces to provide different 
+	  uts info for different servers.  If unsure, say N. 
+ 
 config AUDIT 
 	bool "Auditing support" 
 	depends on NET 
diff --git a/init/version.c b/init/version.c 
index 3ddc3ce..c05d8f8 100644 
--- a/init/version.c 
+++ b/init/version.c 
@@ -11,22 +11,74 @@ 
 #include <linux/uts.h> 
 #include <linux/utsname.h> 
 #include <linux/version.h> 
+#include <linux/sched.h> 
  
 #define version(a) Version_ ## a 
 #define version_string(a) version(a) 
  
 int version_string(LINUX_VERSION_CODE); 
  
-struct new_utsname system_utsname = { 
-	.sysname	= UTS_SYSNAME, 
-	.nodename	= UTS_NODENAME, 
-	.release	= UTS_RELEASE, 
-	.version	= UTS_VERSION, 
-	.machine	= UTS_MACHINE, 
-	.domainname	= UTS_DOMAINNAME, 
+struct uts_namespace init_uts_ns = { 
+	.kref = { 
+		.refcount	= ATOMIC_INIT(2), 
+	}, 
+	.name = { 
+		.sysname	= UTS_SYSNAME, 
+		.nodename	= UTS_NODENAME, 
+		.release	= UTS_RELEASE, 
+		.version	= UTS_VERSION, 
+		.machine	= UTS_MACHINE, 
+		.domainname	= UTS_DOMAINNAME, 
+	}, 
 }; 
  
-EXPORT_SYMBOL(system_utsname); 
+#ifdef CONFIG_UTS_NS 
+/* 
+ * Clone a new ns copying an original utsname, setting refcount to 1 
+ * @old_ns: namespace to clone 
+ * Return NULL on error (failure to kmalloc), new ns otherwise 
+ */ 
+struct uts_namespace *clone_uts_ns(struct uts_namespace *old_ns) 
+{ 
+	struct uts_namespace *ns; 
+ 
+	ns = kmalloc(sizeof(struct uts_namespace), GFP_KERNEL); 
+	if (ns) { 
+		memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 
+		kref_init(&ns->kref); 
+	} 
+	return ns; 
+} 
+ 
+/* 
+ * unshare the current process' utsname namespace.  Changes 
+ * to the utsname of this process won't be seen by parent, and 
+ * vice versa 
+ * 
+ * Return NULL on error (failure to kmalloc), new ns otherwise 
+ * 
+ * TODO: decide where this should be locked  (depends on how/where 
+ * we decide to use this) 
+ */ 
+struct uts_namespace *unshare_uts_ns(void) 
+{ 
+	struct uts_namespace *old_ns = current->uts_ns; 
+	struct uts_namespace *new_ns = clone_uts_ns(old_ns); 
+	if (new_ns) { 
+		current->uts_ns = new_ns; 
+		put_uts_ns(old_ns); 
+	} 
+	return new_ns; 
+} 
+ 
+void free_uts_ns(struct kref *kref) 
+{ 
+	struct uts_namespace *ns; 
+ 
+	ns = container_of(kref, struct uts_namespace, kref); 
+	kfree(ns); 
+} 
+#endif 
  
 const char linux_banner[] = 
 	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" 
diff --git a/kernel/exit.c b/kernel/exit.c 
index 6c2eeb8..97c5405 100644 
--- a/kernel/exit.c 
+++ b/kernel/exit.c 
@@ -34,6 +34,7 @@ 
 #include <linux/mutex.h> 
 #include <linux/futex.h> 
 #include <linux/compat.h> 
+#include <linux/utsname.h> 
  
 #include <asm/uaccess.h> 
 #include <asm/unistd.h> 
@@ -173,6 +174,7 @@ repeat: 
 	spin_unlock(&p->proc_lock); 
 	proc_pid_flush(proc_dentry); 
 	release_thread(p); 
+	put_uts_ns(p->uts_ns); 
 	call_rcu(&p->rcu, delayed_put_task_struct); 
  
 	p = leader; 
diff --git a/kernel/fork.c b/kernel/fork.c 
index 3384eb8..62e4479 100644 
--- a/kernel/fork.c 
+++ b/kernel/fork.c 
@@ -44,6 +44,7 @@ 
 #include <linux/rmap.h> 
 #include <linux/acct.h> 
 #include <linux/cn_proc.h> 
+#include <linux/utsname.h> 
  
 #include <asm/pgtable.h> 
 #include <asm/pgalloc.h> 
@@ -1119,6 +1120,8 @@ static task_t *copy_process(unsigned lon 
 	/* Perform scheduler related setup. Assign this task to a CPU. */ 
 	sched_fork(p, clone_flags); 
  
+	get_uts_ns(p->uts_ns); 
+ 
 	/* Need tasklist lock for parent etc handling! */ 
 	write_lock_irq(&tasklist_lock); 
  
@@ -1158,7 +1161,7 @@ static task_t *copy_process(unsigned lon 
 		spin_unlock(¤t->sighand->siglock); 
 		write_unlock_irq(&tasklist_lock); 
 		retval = -ERESTARTNOINTR; 
-		goto bad_fork_cleanup_namespace; 
+		goto bad_fork_cleanup_utsns; 
 	} 
  
 	if (clone_flags & CLONE_THREAD) { 
@@ -1171,7 +1174,7 @@ static task_t *copy_process(unsigned lon 
 			spin_unlock(¤t->sighand->siglock); 
 			write_unlock_irq(&tasklist_lock); 
 			retval = -EAGAIN; 
-			goto bad_fork_cleanup_namespace; 
+			goto bad_fork_cleanup_utsns; 
 		} 
  
 		p->group_leader = current->group_leader; 
@@ -1223,6 +1226,8 @@ static task_t *copy_process(unsigned lon 
 	proc_fork_connector(p); 
 	return p; 
  
+bad_fork_cleanup_utsns: 
+	put_uts_ns(p->uts_ns); 
 bad_fork_cleanup_namespace: 
 	exit_namespace(p); 
 bad_fork_cleanup_keys: 
--  
1.2.4
...
  
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
  
 
Goto Forum:
 
 Current Time: Tue Nov 04 10:06:23 GMT 2025 
 Total time taken to generate the page: 0.12261 seconds 
 |