[Devel] [RFC] [PATCH 1/3] container: implement 'containers' as a namespace naming device
Serge E. Hallyn
serue at us.ibm.com
Tue Dec 19 22:02:02 PST 2006
From: Serge E. Hallyn <serue at us.ibm.com>
Subject: [RFC] [PATCH 1/3] container: implement 'containers' as a namespace naming device
Implement containers and their reference counting, as the device
for providing simple, hierarchical naming of namespaces.
Signed-off-by: Serge E. Hallyn <serue at us.ibm.com>
---
include/linux/container.h | 24 ++++++++++
include/linux/init_task.h | 13 +++++
include/linux/nsproxy.h | 2 +
kernel/Makefile | 2 -
kernel/container.c | 108 +++++++++++++++++++++++++++++++++++++++++++++
kernel/nsproxy.c | 11 ++++-
6 files changed, 158 insertions(+), 2 deletions(-)
diff --git a/include/linux/container.h b/include/linux/container.h
new file mode 100644
index 0000000..fcd85f3
--- /dev/null
+++ b/include/linux/container.h
@@ -0,0 +1,24 @@
+#ifndef _LINUX_CONTAINER_H
+#define _LINUX_CONTAINER_H
+
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+
+struct nsproxy;
+
+struct container {
+ struct container *parent;
+ char *name;
+ struct nsproxy *nsproxy;
+ struct list_head children;
+ struct list_head peers;
+ struct kref ref;
+};
+extern struct container init_container;
+
+void put_container(struct container *c);
+struct container *new_container(struct container *parent,
+ struct nsproxy *nsproxy);
+
+#endif
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index a2d95ff..445a556 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -70,6 +70,18 @@ #define INIT_SIGNALS(sig) { \
{ .__session = 1}, \
}
+/* presumably the init container name will come from .config */
+#define INIT_CONTAINER_NAME "init_container"
+extern struct container init_container;
+#define INIT_CONTAINER(container) { \
+ .parent = &init_container, \
+ .name = INIT_CONTAINER_NAME, \
+ .nsproxy = &init_nsproxy, \
+ .children = LIST_HEAD_INIT(container.children), \
+ .peers = LIST_HEAD_INIT(container.peers), \
+ .ref = {.refcount = ATOMIC_INIT(1)}, \
+}
+
extern struct nsproxy init_nsproxy;
#define INIT_NSPROXY(nsproxy) { \
.pid_ns = &init_pid_ns, \
@@ -77,6 +89,7 @@ #define INIT_NSPROXY(nsproxy) { \
.nslock = __SPIN_LOCK_UNLOCKED(nsproxy.nslock), \
.uts_ns = &init_uts_ns, \
.mnt_ns = NULL, \
+ .container = &init_container, \
INIT_IPC_NS(ipc_ns) \
}
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 0b9f0dc..30c9876 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -8,6 +8,7 @@ struct mnt_namespace;
struct uts_namespace;
struct ipc_namespace;
struct pid_namespace;
+struct container;
/*
* A structure to contain pointers to all per-process
@@ -28,6 +29,7 @@ struct nsproxy {
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
struct pid_namespace *pid_ns;
+ struct container *container;
};
extern struct nsproxy init_nsproxy;
diff --git a/kernel/Makefile b/kernel/Makefile
index 839a58b..e5d82c1 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -8,7 +8,7 @@ obj-y = sched.o fork.o exec_domain.o
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o extable.o params.o posix-timers.o \
kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
- hrtimer.o rwsem.o latency.o nsproxy.o srcu.o
+ hrtimer.o rwsem.o latency.o nsproxy.o srcu.o container.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += time/
diff --git a/kernel/container.c b/kernel/container.c
new file mode 100644
index 0000000..ed3269f
--- /dev/null
+++ b/kernel/container.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2006 IBM Corporation
+ *
+ * Author: Serge Hallyn <serue at us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ * Jun 2006 - namespaces support
+ * OpenVZ, SWsoft Inc.
+ * Pavel Emelianov <xemul at openvz.org>
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/container.h>
+#include <linux/init_task.h>
+
+struct nsproxy;
+
+struct container init_container = INIT_CONTAINER(init_container);
+
+/*
+ * free_container: called from rcu_call when all references
+ * are gone
+ * all references won't be gone until all children are already
+ * freed.
+ */
+static void free_container(struct kref *ref)
+{
+ struct container *c = container_of(ref, struct container, ref);
+
+ if (c->parent != c)
+ kfree(c->name);
+ if (!list_empty(&c->peers))
+ list_del(&c->peers);
+ kfree(c);
+}
+
+
+/*
+ * get a container reference
+ * we also grab a reference to all it's parents
+ */
+struct container *get_container(struct container *c)
+{
+ struct container *c2 = c;
+
+ if (c) {
+ kref_get(&c2->ref);
+ while (c2->parent != c2) {
+ c2 = c2->parent;
+ kref_get(&c2->ref);
+ }
+ }
+ return c;
+}
+
+/*
+ * put a container
+ * when we put a container, we also put all it's parents.
+ */
+void put_container(struct container *c)
+{
+ struct container *parent;
+ if (!c)
+ return;
+ parent = c->parent;
+ while (parent != c) {
+ kref_put(&c->ref, free_container);
+ c = parent;
+ parent = parent->parent;
+ }
+ kref_put(&c->ref, free_container);
+}
+
+/* i expect this lock to be moved into the containers... */
+static DEFINE_SPINLOCK(container_lock);
+static int last_unnamed_container = 1;
+
+struct container *new_container(struct container *parent,
+ struct nsproxy *nsproxy)
+{
+ struct container *c;
+
+ c = kmalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return NULL;
+ c->name = kzalloc(20, GFP_KERNEL);
+ if (!c->name) {
+ kfree(c);
+ return NULL;
+ }
+ spin_lock(&container_lock);
+ sprintf(c->name, "container_%d", last_unnamed_container++);
+ spin_unlock(&container_lock);
+ INIT_LIST_HEAD(&c->peers);
+ c->parent = parent;
+ get_container(parent);
+ list_add_tail(&c->peers, &parent->children);
+ INIT_LIST_HEAD(&c->children);
+ c->nsproxy = nsproxy;
+ kref_init(&c->ref);
+
+ return c;
+}
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index f5b9ee6..0cfa4c4 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -20,6 +20,7 @@ #include <linux/init_task.h>
#include <linux/mnt_namespace.h>
#include <linux/utsname.h>
#include <linux/pid_namespace.h>
+#include <linux/container.h>
struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
@@ -46,8 +47,14 @@ static inline struct nsproxy *clone_name
struct nsproxy *ns;
ns = kmemdup(orig, sizeof(struct nsproxy), GFP_KERNEL);
- if (ns)
+ if (ns) {
atomic_set(&ns->count, 1);
+ ns->container = new_container(orig->container, ns);
+ if (!ns->container) {
+ kfree(ns);
+ ns = NULL;
+ }
+ }
return ns;
}
@@ -145,5 +152,7 @@ void free_nsproxy(struct nsproxy *ns)
put_ipc_ns(ns->ipc_ns);
if (ns->pid_ns)
put_pid_ns(ns->pid_ns);
+ put_container(ns->container);
+ ns->container->nsproxy = NULL;
kfree(ns);
}
--
1.4.1
_______________________________________________
Containers mailing list
Containers at lists.osdl.org
https://lists.osdl.org/mailman/listinfo/containers
More information about the Devel
mailing list