From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758150AbZEVFCz (ORCPT ); Fri, 22 May 2009 01:02:55 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756182AbZEVE42 (ORCPT ); Fri, 22 May 2009 00:56:28 -0400 Received: from fg-out-1718.google.com ([72.14.220.157]:33823 "EHLO fg-out-1718.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755095AbZEVE4U (ORCPT ); Fri, 22 May 2009 00:56:20 -0400 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=LWenVbl5Ez+K7afhhN2UuNCZbxE7SDSI8PqB3ZvMlnE5c/3ySZUtI5/phrlRijL4Xl Hr8x1MCBZpg8dMKp1Dd8dSGIjNl6WBiB8I8Gct9HyGn7SFeRD5suhkzqGRXcqfucUp7S SnAI/sYTAkmMNHsNAWGbCoprZDpnxzYle9jNY= From: Alexey Dobriyan 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 Subject: [PATCH 29/38] C/R: formally checkpoint/restore struct mnt_namespace Date: Fri, 22 May 2009 08:55:23 +0400 Message-Id: <1242968132-1044-29-git-send-email-adobriyan@gmail.com> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: <1242968132-1044-1-git-send-email-adobriyan@gmail.com> References: <1242968132-1044-1-git-send-email-adobriyan@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Signed-off-by: Alexey Dobriyan --- fs/namespace.c | 70 ++++++++++++++++++++++++++++++++++++++++ include/linux/kstate-image.h | 6 +++ include/linux/kstate.h | 4 ++ kernel/kstate/cpt-sys.c | 6 +++ kernel/kstate/kstate-context.c | 6 +++ kernel/kstate/kstate-object.c | 4 ++ kernel/nsproxy.c | 24 +++++++++++--- 7 files changed, 115 insertions(+), 5 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index be33bfc..ccd7b54 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3,6 +3,7 @@ * * (C) Copyright Al Viro 2000, 2001 * Released under GPL v2. + * Copyright (C) 2000-2009 Parallels Holdings, Ltd. * * Based on code from fs/super.c, copyright Linus Torvalds and others. * Heavily rewritten. @@ -2309,3 +2310,72 @@ void __put_mnt_ns(struct mnt_namespace *ns) release_mounts(&umount_list); kfree(ns); } + +#ifdef CONFIG_CHECKPOINT +#include +#include + +static int collect_mnt_ns(struct kstate_context *ctx, struct mnt_namespace *mnt_ns) +{ + int rv; + + rv = kstate_collect_object(ctx, mnt_ns, KSTATE_CTX_MNT_NS); + pr_debug("collect mnt_ns %p: rv %d\n", mnt_ns, rv); + return rv; +} + +int kstate_collect_all_mnt_ns(struct kstate_context *ctx) +{ + struct kstate_object *obj; + int rv; + + for_each_kstate_object(ctx, obj, KSTATE_CTX_NSPROXY) { + struct nsproxy *nsproxy = obj->o_obj; + + rv = collect_mnt_ns(ctx, nsproxy->mnt_ns); + if (rv < 0) + return rv; + } + for_each_kstate_object(ctx, obj, KSTATE_CTX_MNT_NS) { + struct mnt_namespace *mnt_ns = obj->o_obj; + unsigned int cnt = atomic_read(&mnt_ns->count); + + if (obj->o_count + 1 != cnt) { + pr_err("mnt_ns %p has external references %lu:%u\n", mnt_ns, obj->o_count, cnt); + return -EINVAL; + } + } + return 0; +} + +static int dump_mnt_ns(struct kstate_context *ctx, struct kstate_object *obj) +{ + struct mnt_namespace *mnt_ns = obj->o_obj; + struct kstate_image_mnt_ns *i; + int rv; + + i = kstate_prepare_image(KSTATE_OBJ_MNT_NS, sizeof(*i)); + if (!i) + return -ENOMEM; + + rv = kstate_write_image(ctx, i, sizeof(*i), obj); + kfree(i); + pr_debug("dump mnt_ns %p: ref {%llu, %u}, rv %d\n", mnt_ns, (unsigned long long)obj->o_ref.pos, obj->o_ref.id, rv); + return rv; +} + +int kstate_dump_all_mnt_ns(struct kstate_context *ctx) +{ + struct kstate_object *obj; + int rv; + + for_each_kstate_object(ctx, obj, KSTATE_CTX_MNT_NS) { + rv = dump_mnt_ns(ctx, obj); + if (rv < 0) + return rv; + } + return 0; +} + +/* FIXME kstate_restore_mnt_ns() */ +#endif diff --git a/include/linux/kstate-image.h b/include/linux/kstate-image.h index 43a1458..fa4921b 100644 --- a/include/linux/kstate-image.h +++ b/include/linux/kstate-image.h @@ -46,6 +46,7 @@ struct kstate_image_header { #define KSTATE_OBJ_NSPROXY 6 #define KSTATE_OBJ_UTS_NS 7 #define KSTATE_OBJ_IPC_NS 8 +#define KSTATE_OBJ_MNT_NS 9 struct kstate_object_header { __u32 obj_type; @@ -213,6 +214,7 @@ struct kstate_image_nsproxy { kstate_ref_t ref_uts_ns; kstate_ref_t ref_ipc_ns; /* KSTATE_REF_UNDEF if IPC_NS=n */ + kstate_ref_t ref_mnt_ns; } __packed; struct kstate_image_uts_ns { @@ -229,4 +231,8 @@ struct kstate_image_uts_ns { struct kstate_image_ipc_ns { struct kstate_object_header hdr; } __packed; + +struct kstate_image_mnt_ns { + struct kstate_object_header hdr; +} __packed; #endif diff --git a/include/linux/kstate.h b/include/linux/kstate.h index 61bed98..43e2556 100644 --- a/include/linux/kstate.h +++ b/include/linux/kstate.h @@ -26,6 +26,7 @@ enum kstate_context_obj_type { KSTATE_CTX_IPC_NS, #endif KSTATE_CTX_MM_STRUCT, + KSTATE_CTX_MNT_NS, KSTATE_CTX_NSPROXY, KSTATE_CTX_TASK_STRUCT, KSTATE_CTX_UTS_NS, @@ -96,6 +97,9 @@ static inline int kstate_dump_all_ipc_ns(struct kstate_context *ctx) } #endif +int kstate_collect_all_mnt_ns(struct kstate_context *ctx); +int kstate_dump_all_mnt_ns(struct kstate_context *ctx); + #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 1b03de5..0e3c74c 100644 --- a/kernel/kstate/cpt-sys.c +++ b/kernel/kstate/cpt-sys.c @@ -74,6 +74,9 @@ static int kstate_collect(struct kstate_context *ctx) rv = kstate_collect_all_ipc_ns(ctx); if (rv < 0) return rv; + rv = kstate_collect_all_mnt_ns(ctx); + if (rv < 0) + return rv; rv = kstate_collect_all_mm_struct(ctx); if (rv < 0) return rv; @@ -136,6 +139,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_mnt_ns(ctx); + if (rv < 0) + return rv; rv = kstate_dump_all_ipc_ns(ctx); if (rv < 0) return rv; diff --git a/kernel/kstate/kstate-context.c b/kernel/kstate/kstate-context.c index c2449d5..700c0f4 100644 --- a/kernel/kstate/kstate-context.c +++ b/kernel/kstate/kstate-context.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,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_MNT_NS) { + put_mnt_ns((struct mnt_namespace *)obj->o_obj); + 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); diff --git a/kernel/kstate/kstate-object.c b/kernel/kstate/kstate-object.c index 0056572..6b1ab4a 100644 --- a/kernel/kstate/kstate-object.c +++ b/kernel/kstate/kstate-object.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,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_MNT_NS: + get_mnt_ns((struct mnt_namespace *)obj->o_obj); + break; case KSTATE_CTX_NSPROXY: get_nsproxy((struct nsproxy *)obj->o_obj); break; diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 7cb82e3..4e22ec4 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -286,6 +286,8 @@ static int dump_nsproxy(struct kstate_context *ctx, struct kstate_object *obj) #else i->ref_ipc_ns = KSTATE_REF_UNDEF; #endif + tmp = find_kstate_obj_by_ptr(ctx, nsproxy->mnt_ns, KSTATE_CTX_MNT_NS); + i->ref_mnt_ns = tmp->o_ref; rv = kstate_write_image(ctx, i, sizeof(*i), obj); kfree(i); @@ -373,11 +375,22 @@ static int restore_ipc_ns(struct kstate_context *ctx, kstate_ref_t *ref, struct } #endif +static int restore_mnt_ns(struct kstate_context *ctx, kstate_ref_t *ref, struct nsproxy *nsproxy) +{ + struct mnt_namespace *mnt_ns; + + /* FIXME */ + mnt_ns = ctx->init_tsk->nsproxy->mnt_ns; + + get_mnt_ns(mnt_ns); + nsproxy->mnt_ns = mnt_ns; + return 0; +} + int kstate_restore_nsproxy(struct kstate_context *ctx, kstate_ref_t *ref) { struct kstate_image_nsproxy *i; struct nsproxy *nsproxy; - struct mnt_namespace *mnt_ns; struct pid_namespace *pid_ns; #ifdef CONFIG_NET_NS struct net *net_ns; @@ -400,10 +413,9 @@ int kstate_restore_nsproxy(struct kstate_context *ctx, kstate_ref_t *ref) rv = restore_ipc_ns(ctx, &i->ref_ipc_ns, nsproxy); if (rv < 0) goto out_ipc_ns; - - mnt_ns = ctx->init_tsk->nsproxy->mnt_ns; - get_mnt_ns(mnt_ns); - nsproxy->mnt_ns = mnt_ns; + rv = restore_mnt_ns(ctx, &i->ref_mnt_ns, nsproxy); + if (rv < 0) + goto out_mnt_ns; pid_ns = ctx->init_tsk->nsproxy->pid_ns; nsproxy->pid_ns = get_pid_ns(pid_ns); @@ -420,6 +432,8 @@ int kstate_restore_nsproxy(struct kstate_context *ctx, kstate_ref_t *ref) pr_debug("restore nsproxy %p, ref {%llu, %u}, rv %d\n", nsproxy, (unsigned long long)ref->pos, ref->id, rv); return rv; +out_mnt_ns: + put_ipc_ns(nsproxy->ipc_ns); out_ipc_ns: put_uts_ns(nsproxy->uts_ns); out_uts_ns: -- 1.5.6.5