linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alexey Dobriyan <adobriyan@gmail.com>
To: akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org,
	containers@lists.linux-foundation.org,
	torvalds@linux-foundation.org, xemul@parallels.com,
	orenl@cs.columbia.edu, serue@us.ibm.com, dave@linux.vnet.ibm.com,
	mingo@elte.hu, Alexey Dobriyan <adobriyan@gmail.com>
Subject: [PATCH 26/38] C/R: nsproxy
Date: Fri, 22 May 2009 08:55:20 +0400	[thread overview]
Message-ID: <1242968132-1044-26-git-send-email-adobriyan@gmail.com> (raw)
In-Reply-To: <1242968132-1044-1-git-send-email-adobriyan@gmail.com>

It can't be argued, that nsproxy shouldn't even be dumped,
because pointers inside nsproxy are interesting. This is correct,
however this creates addtitional code on restart and frankly
more that several nsproxies are rare, so nobody cares.

Current algorithm is simplest:
- dump all namespaces
- dump nsproxy as KSTATE_OBJ_NSPROXY type filled with references
- on restore, read reference, read and restore namespace if needed,
  bump refcount, glue namespace to nsproxy.

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
 include/linux/kstate-image.h   |    6 ++
 include/linux/kstate.h         |    5 ++
 kernel/kstate/cpt-sys.c        |    6 ++
 kernel/kstate/kstate-context.c |    6 ++
 kernel/kstate/kstate-object.c  |    4 +
 kernel/kstate/kstate-task.c    |   26 ++++++++
 kernel/nsproxy.c               |  129 +++++++++++++++++++++++++++++++++++++++-
 7 files changed, 181 insertions(+), 1 deletions(-)
 create mode 100644 kernel/kstate/kstate-nsproxy.c

diff --git a/include/linux/kstate-image.h b/include/linux/kstate-image.h
index d956d05..b8263c8 100644
--- a/include/linux/kstate-image.h
+++ b/include/linux/kstate-image.h
@@ -43,6 +43,7 @@ struct kstate_image_header {
 #define KSTATE_OBJ_FILE		3
 #define KSTATE_OBJ_VMA		4
 #define KSTATE_OBJ_PAGE		5
+#define KSTATE_OBJ_NSPROXY	6
 
 struct kstate_object_header {
 	__u32		obj_type;
@@ -65,6 +66,7 @@ struct kstate_image_task_struct {
 	kstate_ref_t	ref_real_parent;
 
 	kstate_ref_t	ref_mm;
+	kstate_ref_t	ref_nsproxy;
 
 	__u8		comm[16];
 
@@ -203,4 +205,8 @@ struct kstate_image_file {
 	__u32		name_len;	/* including NUL */
 	/* __u8	name[name_len] */
 } __packed;
+
+struct kstate_image_nsproxy {
+	struct kstate_object_header hdr;
+} __packed;
 #endif
diff --git a/include/linux/kstate.h b/include/linux/kstate.h
index 95898ec..bd5c9f1 100644
--- a/include/linux/kstate.h
+++ b/include/linux/kstate.h
@@ -23,6 +23,7 @@ struct kstate_object {
 enum kstate_context_obj_type {
 	KSTATE_CTX_FILE,
 	KSTATE_CTX_MM_STRUCT,
+	KSTATE_CTX_NSPROXY,
 	KSTATE_CTX_TASK_STRUCT,
 	NR_KSTATE_CTX_TYPES
 };
@@ -67,6 +68,10 @@ int kstate_collect_all_file(struct kstate_context *ctx);
 int kstate_dump_all_file(struct kstate_context *ctx);
 int kstate_restore_file(struct kstate_context *ctx, kstate_ref_t *ref);
 
+int kstate_collect_all_nsproxy(struct kstate_context *ctx);
+int kstate_dump_all_nsproxy(struct kstate_context *ctx);
+int kstate_restore_nsproxy(struct kstate_context *ctx, kstate_ref_t *ref);
+
 #if defined(CONFIG_X86_32) || defined(CONFIG_X86_64)
 extern const __u32 kstate_kernel_arch;
 int kstate_arch_check_image_header(struct kstate_image_header *i);
diff --git a/kernel/kstate/cpt-sys.c b/kernel/kstate/cpt-sys.c
index 6bc1d0a..1d5e79d 100644
--- a/kernel/kstate/cpt-sys.c
+++ b/kernel/kstate/cpt-sys.c
@@ -65,6 +65,9 @@ static int kstate_collect(struct kstate_context *ctx)
 	rv = kstate_collect_all_task_struct(ctx);
 	if (rv < 0)
 		return rv;
+	rv = kstate_collect_all_nsproxy(ctx);
+	if (rv < 0)
+		return rv;
 	rv = kstate_collect_all_mm_struct(ctx);
 	if (rv < 0)
 		return rv;
@@ -127,6 +130,9 @@ static int kstate_dump(struct kstate_context *ctx)
 	rv = kstate_dump_all_mm_struct(ctx);
 	if (rv < 0)
 		return rv;
+	rv = kstate_dump_all_nsproxy(ctx);
+	if (rv < 0)
+		return rv;
 	rv = kstate_dump_all_task_struct(ctx);
 	if (rv < 0)
 		return rv;
diff --git a/kernel/kstate/kstate-context.c b/kernel/kstate/kstate-context.c
index 85d1514..8c728f5 100644
--- a/kernel/kstate/kstate-context.c
+++ b/kernel/kstate/kstate-context.c
@@ -1,6 +1,7 @@
 /* Copyright (C) 2000-2009 Parallels Holdings, Ltd. */
 #include <linux/file.h>
 #include <linux/list.h>
+#include <linux/nsproxy.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 
@@ -40,6 +41,11 @@ void kstate_context_destroy(struct kstate_context *ctx)
 		list_del(&obj->o_list);
 		kfree(obj);
 	}
+	for_each_kstate_object_safe(ctx, obj, tmp, KSTATE_CTX_NSPROXY) {
+		put_nsproxy((struct nsproxy *)obj->o_obj);
+		list_del(&obj->o_list);
+		kfree(obj);
+	}
 	for_each_kstate_object_safe(ctx, obj, tmp, KSTATE_CTX_TASK_STRUCT) {
 		put_task_struct((struct task_struct *)obj->o_obj);
 		list_del(&obj->o_list);
diff --git a/kernel/kstate/kstate-nsproxy.c b/kernel/kstate/kstate-nsproxy.c
new file mode 100644
index 0000000..e69de29
diff --git a/kernel/kstate/kstate-object.c b/kernel/kstate/kstate-object.c
index 60ba70d..078bd36 100644
--- a/kernel/kstate/kstate-object.c
+++ b/kernel/kstate/kstate-object.c
@@ -1,6 +1,7 @@
 /* Copyright (C) 2000-2009 Parallels Holdings, Ltd. */
 #include <linux/fs.h>
 #include <linux/mm_types.h>
+#include <linux/nsproxy.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 
@@ -35,6 +36,9 @@ int kstate_collect_object(struct kstate_context *ctx, void *p, enum kstate_conte
 	case KSTATE_CTX_MM_STRUCT:
 		atomic_inc(&((struct mm_struct *)obj->o_obj)->mm_users);
 		break;
+	case KSTATE_CTX_NSPROXY:
+		get_nsproxy((struct nsproxy *)obj->o_obj);
+		break;
 	case KSTATE_CTX_TASK_STRUCT:
 		get_task_struct((struct task_struct *)obj->o_obj);
 		break;
diff --git a/kernel/kstate/kstate-task.c b/kernel/kstate/kstate-task.c
index 4f48c32..de876fe 100644
--- a/kernel/kstate/kstate-task.c
+++ b/kernel/kstate/kstate-task.c
@@ -120,6 +120,9 @@ static int dump_task_struct(struct kstate_context *ctx, struct kstate_object *ob
 	tmp = find_kstate_obj_by_ptr(ctx, tsk->mm, KSTATE_CTX_MM_STRUCT);
 	i->ref_mm = tmp->o_ref;
 
+	tmp = find_kstate_obj_by_ptr(ctx, tsk->nsproxy, KSTATE_CTX_NSPROXY);
+	i->ref_nsproxy = tmp->o_ref;
+
 	BUILD_BUG_ON(sizeof(i->comm) != sizeof(tsk->comm));
 	strlcpy((char *)i->comm, (const char *)tsk->comm, sizeof(i->comm));
 
@@ -208,6 +211,26 @@ static int restore_mm(struct kstate_context *ctx, kstate_ref_t *ref)
 	return 0;
 }
 
+static int restore_nsproxy(struct kstate_context *ctx, kstate_ref_t *ref)
+{
+	struct nsproxy *nsproxy;
+	struct kstate_object *tmp;
+	int rv;
+
+	tmp = find_kstate_obj_by_ref(ctx, ref, KSTATE_CTX_NSPROXY);
+	if (!tmp) {
+		rv = kstate_restore_nsproxy(ctx, ref);
+		if (rv < 0)
+			return rv;
+		tmp = find_kstate_obj_by_ref(ctx, ref, KSTATE_CTX_NSPROXY);
+	}
+	nsproxy = tmp->o_obj;
+
+	get_nsproxy(nsproxy);
+	switch_task_namespaces(current, nsproxy);
+	return 0;
+}
+
 struct task_struct_restore_context {
 	struct kstate_context *ctx;
 	struct kstate_image_task_struct *i;
@@ -253,6 +276,9 @@ static int task_struct_restorer(void *_tsk_ctx)
 	rv = restore_mm(ctx, &i->ref_mm);
 	if (rv < 0)
 		goto out;
+	rv = restore_nsproxy(ctx, &i->ref_nsproxy);
+	if (rv < 0)
+		goto out;
 
 out:
 	tsk_ctx->rv = rv;
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 09b4ff9..b7ccd68 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -1,5 +1,6 @@
 /*
  *  Copyright (C) 2006 IBM Corporation
+ *  Copyright (C) 2009 Parallels Holdings, Ltd.
  *
  *  Author: Serge Hallyn <serue@us.ibm.com>
  *
@@ -26,7 +27,7 @@ static struct kmem_cache *nsproxy_cachep;
 
 struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
 
-static inline struct nsproxy *create_nsproxy(void)
+static struct nsproxy *create_nsproxy(void)
 {
 	struct nsproxy *nsproxy;
 
@@ -228,3 +229,129 @@ static int __init nsproxy_cache_init(void)
 }
 
 module_init(nsproxy_cache_init);
+
+#ifdef CONFIG_CHECKPOINT
+#include <linux/kstate.h>
+#include <linux/kstate-image.h>
+
+static int collect_nsproxy(struct kstate_context *ctx, struct nsproxy *nsproxy)
+{
+	int rv;
+
+	rv = kstate_collect_object(ctx, nsproxy, KSTATE_CTX_NSPROXY);
+	pr_debug("collect nsproxy %p: rv %d\n", nsproxy, rv);
+	return rv;
+}
+
+int kstate_collect_all_nsproxy(struct kstate_context *ctx)
+{
+	struct kstate_object *obj;
+	int rv;
+
+	for_each_kstate_object(ctx, obj, KSTATE_CTX_TASK_STRUCT) {
+		struct task_struct *tsk = obj->o_obj;
+
+		rv = collect_nsproxy(ctx, tsk->nsproxy);
+		if (rv < 0)
+			return rv;
+	}
+	for_each_kstate_object(ctx, obj, KSTATE_CTX_NSPROXY) {
+		struct nsproxy *nsproxy = obj->o_obj;
+		unsigned int cnt = atomic_read(&nsproxy->count);
+
+		if (obj->o_count + 1 != cnt) {
+			pr_err("nsproxy %p has external references %lu:%u\n", nsproxy, obj->o_count, cnt);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int dump_nsproxy(struct kstate_context *ctx, struct kstate_object *obj)
+{
+	struct nsproxy *nsproxy = obj->o_obj;
+	struct kstate_image_nsproxy *i;
+	int rv;
+
+	i = kstate_prepare_image(KSTATE_OBJ_NSPROXY, sizeof(*i));
+	if (!i)
+		return -ENOMEM;
+
+	rv = kstate_write_image(ctx, i, sizeof(*i), obj);
+	kfree(i);
+	pr_debug("dump nsproxy %p: ref {%llu, %u}, rv %d\n", nsproxy, (unsigned long long)obj->o_ref.pos, obj->o_ref.id, rv);
+	return rv;
+}
+
+int kstate_dump_all_nsproxy(struct kstate_context *ctx)
+{
+	struct kstate_object *obj;
+	int rv;
+
+	for_each_kstate_object(ctx, obj, KSTATE_CTX_NSPROXY) {
+		rv = dump_nsproxy(ctx, obj);
+		if (rv < 0)
+			return rv;
+	}
+	return 0;
+}
+
+int kstate_restore_nsproxy(struct kstate_context *ctx, kstate_ref_t *ref)
+{
+	struct kstate_image_nsproxy *i;
+	struct nsproxy *nsproxy;
+	struct uts_namespace *uts_ns;
+#ifdef CONFIG_IPC_NS
+	struct ipc_namespace *ipc_ns;
+#endif
+	struct mnt_namespace *mnt_ns;
+	struct pid_namespace *pid_ns;
+#ifdef CONFIG_NET_NS
+	struct net *net_ns;
+#endif
+	int rv;
+
+	i = kstate_read_image(ctx, ref,  KSTATE_OBJ_NSPROXY, sizeof(*i));
+	if (IS_ERR(i))
+		return PTR_ERR(i);
+
+	nsproxy = create_nsproxy();
+	if (!nsproxy) {
+		rv = -ENOMEM;
+		goto out_free_image;
+	}
+
+	uts_ns = ctx->init_tsk->nsproxy->uts_ns;
+	get_uts_ns(uts_ns);
+	nsproxy->uts_ns = uts_ns;
+
+#ifdef CONFIG_IPC_NS
+	ipc_ns = ctx->init_tsk->nsproxy->ipc_ns;
+	nsproxy->ipc_ns = get_ipc_ns(ipc_ns);
+#endif
+
+	mnt_ns = ctx->init_tsk->nsproxy->mnt_ns;
+	get_mnt_ns(mnt_ns);
+	nsproxy->mnt_ns = mnt_ns;
+
+	pid_ns = ctx->init_tsk->nsproxy->pid_ns;
+	nsproxy->pid_ns = get_pid_ns(pid_ns);
+
+#ifdef CONFIG_NET_NS
+	net_ns = ctx->init_tsk->nsproxy->net_ns;
+	nsproxy->net_ns = get_net(net_ns);
+#endif
+	kfree(i);
+
+	rv = kstate_restore_object(ctx, nsproxy, KSTATE_CTX_NSPROXY, ref);
+	if (rv < 0)
+		put_nsproxy(nsproxy);
+	pr_debug("restore nsproxy %p, ref {%llu, %u}, rv %d\n", nsproxy, (unsigned long long)ref->pos, ref->id, rv);
+	return rv;
+
+out_free_image:
+	kfree(i);
+	pr_debug("%s: return %d, ref {%llu, %u}\n", __func__, rv, (unsigned long long)ref->pos, ref->id);
+	return rv;
+}
+#endif
-- 
1.5.6.5


  parent reply	other threads:[~2009-05-22  5:02 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-22  4:54 [PATCH 01/38] cred: #include init.h in cred.h Alexey Dobriyan
2009-05-22  4:54 ` [PATCH 02/38] utsns: extract create_uts_ns() Alexey Dobriyan
2009-05-24 22:37   ` Serge E. Hallyn
2009-05-22  4:54 ` [PATCH 03/38] ipcns 1/4: remove useless get/put while CLONE_NEWIPC Alexey Dobriyan
2009-05-22  9:00   ` Amerigo Wang
2009-05-22  4:54 ` [PATCH 04/38] ipcns 2/4: extract create_ipc_ns() Alexey Dobriyan
2009-05-22  8:59   ` Amerigo Wang
2009-05-22  4:54 ` [PATCH 05/38] ipcns 3/4: make free_ipc_ns() static Alexey Dobriyan
2009-05-24 22:40   ` Serge E. Hallyn
2009-05-22  4:55 ` [PATCH 06/38] ipcns 4/2: move free_ipcs() proto Alexey Dobriyan
2009-05-24 22:49   ` Serge E. Hallyn
2009-05-22  4:55 ` [PATCH 07/38] pidns 1/2: make create_pid_namespace() accept parent pidns Alexey Dobriyan
2009-05-22  9:20   ` Amerigo Wang
2009-05-24 22:44   ` Serge E. Hallyn
2009-06-04  0:20   ` Sukadev Bhattiprolu
2009-05-22  4:55 ` [PATCH 08/38] pidns 2/2: rewrite copy_pid_ns() Alexey Dobriyan
2009-05-22  9:14   ` Amerigo Wang
2009-05-24 22:45   ` Serge E. Hallyn
2009-06-04  0:17   ` Sukadev Bhattiprolu
2009-05-22  4:55 ` [PATCH 09/38] netns 1/2: don't get/put old netns on CLONE_NEWNET Alexey Dobriyan
2009-05-22  6:30   ` David Miller
2009-05-22  4:55 ` [PATCH 10/38] netns 2/2: extract net_create() Alexey Dobriyan
2009-05-22  6:30   ` David Miller
2009-05-22  4:55 ` [PATCH 11/38] nsproxy: extract create_nsproxy() Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 12/38] i386: ifdef out struct thread_struct::fs Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 13/38] x86_64: ifdef out struct thread_struct::ip Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 14/38] Remove struct mm_struct::exe_file et al Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 15/38] dcache: extract and use d_unlinked() Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 16/38] x86: ptrace debugreg checks rewrite Alexey Dobriyan
2009-05-26 23:25   ` Andrew Morton
2009-05-22  4:55 ` [PATCH 17/38] groups: move code to kernel/groups.c Alexey Dobriyan
2009-05-25  0:53   ` Serge E. Hallyn
2009-05-26 14:48   ` Serge E. Hallyn
2009-05-26 18:34     ` Alexey Dobriyan
2009-05-26 23:25       ` Serge E. Hallyn
2009-05-22  4:55 ` [PATCH 18/38] C/R: core stuff Alexey Dobriyan
2009-05-26 13:16   ` Serge E. Hallyn
2009-05-26 19:35     ` Alexey Dobriyan
2009-05-26 23:14       ` Serge E. Hallyn
2009-05-26 23:44       ` Serge E. Hallyn
2009-05-28 15:38         ` Alexey Dobriyan
2009-05-28 18:17           ` Serge E. Hallyn
2009-05-28 22:42           ` Oren Laadan
2009-05-27 18:52       ` Dave Hansen
2009-05-27 20:56       ` Oren Laadan
2009-05-27 22:17         ` Alexey Dobriyan
2009-05-27 22:40           ` Andrew Morton
2009-05-27 22:45           ` Oren Laadan
2009-05-28 15:33             ` Alexey Dobriyan
2009-05-28 22:20               ` Oren Laadan
2009-05-28 22:33                 ` Matt Helsley
2009-05-29  6:01                 ` Alexey Dobriyan
2009-05-29 17:26                   ` Dave Hansen
2009-05-27 22:25         ` Alexey Dobriyan
2009-05-27 16:28   ` Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 19/38] C/R: multiple tasks Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 20/38] C/R: i386 support Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 21/38] C/R: i386 debug registers Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 22/38] C/R: i386 xstate Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 23/38] C/R: x86_64 support Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 24/38] C/R: x86_64 debug registers Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 25/38] C/R: x86_64 xstate Alexey Dobriyan
2009-05-22  4:55 ` Alexey Dobriyan [this message]
2009-05-22  4:55 ` [PATCH 27/38] C/R: checkpoint/restore struct uts_namespace Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 28/38] C/R: formally checkpoint/restore struct ipc_namespace Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 29/38] C/R: formally checkpoint/restore struct mnt_namespace Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 30/38] C/R: checkpoint/restore struct pid_namespace Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 31/38] C/R: formally checkpoint/restore struct net_namespace Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 32/38] C/R: checkpoint/restore struct cred Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 33/38] C/R: checkpoint/restore aux groups (structy group_info) Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 34/38] C/R: checkpoint/restore struct user Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 35/38] C/R: checkpoint/restore struct user_namespace Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 36/38] C/R: checkpoint/restore struct pid Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 37/38] C/R: checkpoint/restore opened files Alexey Dobriyan
2009-05-22  4:55 ` [PATCH 38/38] C/R: checkpoint/restart struct sighand_struct Alexey Dobriyan
2009-05-22  5:02 ` [PATCH 01/38] cred: #include init.h in cred.h Alexey Dobriyan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1242968132-1044-26-git-send-email-adobriyan@gmail.com \
    --to=adobriyan@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=containers@lists.linux-foundation.org \
    --cc=dave@linux.vnet.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=orenl@cs.columbia.edu \
    --cc=serue@us.ibm.com \
    --cc=torvalds@linux-foundation.org \
    --cc=xemul@parallels.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).