From mboxrd@z Thu Jan 1 00:00:00 1970 From: Oren Laadan Subject: [RFC v13][PATCH 11/14] External checkpoint of a task other than ourself Date: Tue, 27 Jan 2009 12:08:09 -0500 Message-ID: <1233076092-8660-12-git-send-email-orenl__41530.1327746876$1233077899$gmane$org@cs.columbia.edu> References: <1233076092-8660-1-git-send-email-orenl@cs.columbia.edu> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1233076092-8660-1-git-send-email-orenl-eQaUEPhvms7ENvBUuze7eA@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org Errors-To: containers-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org To: Andrew Morton Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Dave Hansen , linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org, Linus Torvalds , Alexander Viro , "H. Peter Anvin" , Thomas Gleixner , Ingo Molnar List-Id: containers.vger.kernel.org Now we can do "external" checkpoint, i.e. act on another task. sys_checkpoint() now looks up the target pid (in our namespace) and checkpoints that corresponding task. That task should be the root of a container. sys_restart() remains the same, as the restart is always done in the context of the restarting task. Changelog[v12]: - Replace obsolete cr_debug() with pr_debug() Changelog[v11]: - Copy contents of 'init->fs->root' instead of pointing to them Changelog[v10]: - Grab vfs root of container init, rather than current process Signed-off-by: Oren Laadan Acked-by: Serge Hallyn --- checkpoint/checkpoint.c | 72 ++++++++++++++++++++++++++++++++++++++++++- checkpoint/restart.c | 4 +- checkpoint/sys.c | 6 ++++ include/linux/checkpoint.h | 2 + 4 files changed, 80 insertions(+), 4 deletions(-) diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c index dd0f527..e0af8a2 100644 --- a/checkpoint/checkpoint.c +++ b/checkpoint/checkpoint.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -225,6 +226,13 @@ static int cr_write_task(struct cr_ctx *ctx, struct task_struct *t) { int ret; + /* TODO: verity that the task is frozen (unless self) */ + + if (t->state == TASK_DEAD) { + pr_warning("c/r: task may not be in state TASK_DEAD\n"); + return -EAGAIN; + } + ret = cr_write_task_struct(ctx, t); pr_debug("task_struct: ret %d\n", ret); if (ret < 0) @@ -247,22 +255,82 @@ static int cr_write_task(struct cr_ctx *ctx, struct task_struct *t) return ret; } +static int cr_get_container(struct cr_ctx *ctx, pid_t pid) +{ + struct task_struct *task = NULL; + struct nsproxy *nsproxy = NULL; + int err = -ESRCH; + + ctx->root_pid = pid; + + read_lock(&tasklist_lock); + task = find_task_by_vpid(pid); + if (task) + get_task_struct(task); + read_unlock(&tasklist_lock); + + if (!task) + goto out; + +#if 0 /* enable to use containers */ + if (!is_container_init(task)) { + err = -EINVAL; + goto out; + } +#endif + + if (!ptrace_may_access(task, PTRACE_MODE_READ)) { + err = -EPERM; + goto out; + } + + rcu_read_lock(); + if (task_nsproxy(task)) { + nsproxy = task_nsproxy(task); + get_nsproxy(nsproxy); + } + rcu_read_unlock(); + + if (!nsproxy) + goto out; + + /* TODO: verify that the container is frozen */ + + ctx->root_task = task; + ctx->root_nsproxy = nsproxy; + + return 0; + + out: + if (task) + put_task_struct(task); + return err; +} + +/* setup checkpoint-specific parts of ctx */ static int cr_ctx_checkpoint(struct cr_ctx *ctx, pid_t pid) { struct fs_struct *fs; + int ret; ctx->root_pid = pid; + ret = cr_get_container(ctx, pid); + if (ret < 0) + return ret; + /* * assume checkpointer is in container's root vfs * FIXME: this works for now, but will change with real containers */ - fs = current->fs; + task_lock(ctx->root_task); + fs = ctx->root_task->fs; read_lock(&fs->lock); ctx->fs_mnt = fs->root; path_get(&ctx->fs_mnt); read_unlock(&fs->lock); + task_unlock(ctx->root_task); return 0; } @@ -277,7 +345,7 @@ int do_checkpoint(struct cr_ctx *ctx, pid_t pid) ret = cr_write_head(ctx); if (ret < 0) goto out; - ret = cr_write_task(ctx, current); + ret = cr_write_task(ctx, ctx->root_task); if (ret < 0) goto out; ret = cr_write_tail(ctx); diff --git a/checkpoint/restart.c b/checkpoint/restart.c index ece05b7..0c46abf 100644 --- a/checkpoint/restart.c +++ b/checkpoint/restart.c @@ -277,7 +277,7 @@ static int cr_read_task(struct cr_ctx *ctx) } /* setup restart-specific parts of ctx */ -static int cr_ctx_restart(struct cr_ctx *ctx) +static int cr_ctx_restart(struct cr_ctx *ctx, pid_t pid) { return 0; } @@ -286,7 +286,7 @@ int do_restart(struct cr_ctx *ctx, pid_t pid) { int ret; - ret = cr_ctx_restart(ctx); + ret = cr_ctx_restart(ctx, pid); if (ret < 0) goto out; ret = cr_read_head(ctx); diff --git a/checkpoint/sys.c b/checkpoint/sys.c index a506b3a..4a51ed3 100644 --- a/checkpoint/sys.c +++ b/checkpoint/sys.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -163,6 +164,11 @@ static void cr_ctx_free(struct cr_ctx *ctx) cr_pgarr_free(ctx); cr_objhash_free(ctx); + if (ctx->root_nsproxy) + put_nsproxy(ctx->root_nsproxy); + if (ctx->root_task) + put_task_struct(ctx->root_task); + kfree(ctx); } diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h index ea9ab4c..cf54f47 100644 --- a/include/linux/checkpoint.h +++ b/include/linux/checkpoint.h @@ -19,6 +19,8 @@ struct cr_ctx { int crid; /* unique checkpoint id */ pid_t root_pid; /* container identifier */ + struct task_struct *root_task; /* container root task */ + struct nsproxy *root_nsproxy; /* container root nsproxy */ unsigned long flags; unsigned long oflags; /* restart: old flags */ -- 1.5.4.3