sys_restore prototype
Subsystems (4)
cover sys_restore prototype
We were talking this morning about what trivial patchset to begin with to get a start on checkpoint and restart. We thought that rather than start with checkpoint, maybe we should start with something that reads a "checkpoint file" and "restarts" a single task. In this case, restart means it sets the process id and executes the file which are found in the checkpoint file.
So here's what we whipped up for a half hour this morning, and during some of Mark's talk this afternoon.
It refuses to run if it isn't the container init, so you must unshare your pidns before calling sys_restore().
To test, I did:
[root@kvm-f9 ~]# cat mycheckpoint
99 /root/whoami
[root@kvm-f9 ~]# cat restore.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int ret;
char *argv[3];
char *envp[1];
//argv[0] = argv[1] = "/bin/bash";
//argv[2] = envp[0] = NULL;
argv[0] = "/root/whoami";
argv[1] = envp[0] = NULL;
int fd = open("/root/mycheckpoint", O_RDONLY);
if (fd < 0)
perror("open checkpoint file");
ret = syscall(327, fd, argv, envp);
printf("syscall returned %d\n", ret);
perror("syscall for checkpoint");
close(fd);
return ret;
}[root@kvm-f9 ~]# cat whoami.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
printf("I am %d\n", getpid());
return 0;
}Next, I create a new pid namespace, remount /proc, and
execute 'restore' using 'exec' so that pid 1 is doing it:
[root@kvm-f9 ~]# /home/hallyn/cryo/utils/ns_exec -cp /bin/bash about to clone with 20020000
[root@kvm-f9 ~]# mount -t proc none /proc [root@kvm-f9 ~]# ps -ef
UID PID PPID C STIME TTY TIME CMD root 1 0 1 18:46 pts/0 00:00:00 /bin/bash root 26 1 0 18:46 pts/0 00:00:00 ps -ef
[root@kvm-f9 ~]# exec ./restore
I am 99
Seems to work.
-serge
A message that is not in the archive (sent off-list or not yet received): 20080725225655.GA28276-r/[email protected]
PATCH 1/2 introduce sys_restore
Create a useless (?) sys_restore system call. All it does is read a "checkpoint file" :) for a pid number and a file to execute.
Since we don't take things like argv and envp and registers from the checkpoint file, in order to make this easily testable, we take those things as arguments.
--- arch/x86/kernel/process_32.c | 10 ++++++++ arch/x86/kernel/syscall_table_32.S | 2 + kernel/fork.c | 43 ++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 0 deletions(-)
arch/x86/kernel/process_32.c +10 -0
@@ -688,6 +688,16 @@ out:return error; } +long do_restore (unsigned int fd, +char __user *__user *argv, +char __user *__user *envp, +struct pt_regs *regs); + +asmlinkage long sys_restore (struct pt_regs regs) +{ +return do_restore (regs.bx, regs.cx, regs.dx, ®s); +} +#define top_esp (THREAD_SIZE - sizeof(unsigned long))#define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long))
arch/x86/kernel/syscall_table_32.S +2 -0
@@ -326,3 +326,5 @@ ENTRY(sys_call_table) .long sys_fallocate .long sys_timerfd_settime /* 325 */ .long sys_timerfd_gettime + .long sys_restore +
kernel/fork.c +43 -0
46 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 2/2 sys_restore: set the pid number
In reply to a message not in the archiveSet the pid number for a restored task. This is purely a toy, as it only sets the pidnr in the lowest level pid namespace.
--- kernel/fork.c | 5 +++++ kernel/pid.c | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 0 deletions(-)
kernel/fork.c +5 -0
@@ -1685,6 +1685,8 @@ int unshare_files(struct files_struct **displaced)char buf[CKPT_SIZE ];char exe_filename[PAGE_SIZE ]; +extern int choose_pidmap (struct pid *pid,int new); +/* * userspace will already have made us a new pidns */
@@ -1717,6 +1719,9 @@ long do_restore(unsigned int fd,if (nr_scanned !=2 )return -EINVAL ; + ret =choose_pidmap (task_pid (current), pid); +if (!ret) +return -EAGAIN ; ret =do_execve (exe_filename, argv, envp, regs); out:
kernel/pid.c +19 -0
@@ -122,6 +122,25 @@ static void free_pidmap(struct upid *upid)atomic_inc (&map->nr_free); } +int choose_pidmap (struct pid *pid,int new) +{ +struct pidmap *map; +int level = pid->level; +struct upid *upid = &pid->numbers[level]; +struct pid_namespace *pid_ns = upid->ns; +int old = upid->nr; + + map = &pid_ns->pidmap[new/BITS_PER_PAGE ]; +if (!test_and_set_bit (new, map->page)) { + map = &pid_ns->pidmap[old/BITS_PER_PAGE ]; +clear_bit (old, map->page); + upid->nr = new; +return 1 ; + } + +return 0 ; +} +static int alloc_pidmap (struct pid_namespace *pid_ns) {int i, offset, max_scan, pid, last = pid_ns->last_pid;
Signature · 1 line
1.5.4.3
A message that is not in the archive (sent off-list or not yet received): 20080725225935.GB28764-r/[email protected]
Re: [Devel] [PATCH 2/2] sys_restore: set the pid number
Quoted 40 lines · Serge E. Hallyn
Set the pid number for a restored task. This is purely a toy, as it only sets the pidnr in the lowest level pid namespace.
Signed-off-by Serge Hallyn <serue-r/[email protected]>--- kernel/fork.c | 5 +++++ kernel/pid.c | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 0 deletions(-)kernel/fork.c +5
-0@@ -1685,6 +1685,8 @@ int unshare_files(struct files_struct **displaced)char buf[CKPT_SIZE ];char exe_filename[PAGE_SIZE ]; +extern int choose_pidmap (struct pid *pid,int new); +/* * userspace will already have made us a new pidns */ @@ -1717,6 +1719,9 @@ long do_restore(unsigned int fd,if (nr_scanned !=2 )return -EINVAL ; + ret =choose_pidmap (task_pid (current), pid); +if (!ret) +return -EAGAIN ; ret =do_execve (exe_filename, argv, envp, regs); out:kernel/pid.c +0
-0@@ -122,6 +122,25 @@ static void free_pidmap(struct upid *upid)atomic_inc (&map->nr_free); }
kernel/pid.c static void free_pidmap(struct upid *upid) · line 134
Quoted 10 lines
kernel/pid.c +10
-0+int choose_pidmap (struct pid *pid,int new) +{ +struct pidmap *map; +int level = pid->level; +struct upid *upid = &pid->numbers[level]; +struct pid_namespace *pid_ns = upid->ns; +int old = upid->nr; + + map = &pid_ns->pidmap[new/BITS_PER_PAGE ]; +if (!test_and_set_bit (new, map->page)) {
This and...
kernel/pid.c static void free_pidmap(struct upid *upid) · line 136
Quoted 2 lines
kernel/pid.c +2
-0+ map = &pid_ns->pidmap[old/BITS_PER_PAGE ]; +clear_bit (old, map->page);
this are both a bit buggy, since the bit number on the page is not the same as the pid id itself ;)
Quoted 10 lines
kernel/pid.c +7
-0+ upid->nr = new; +return 1 ; + } + +return 0 ; +} +static int alloc_pidmap (struct pid_namespace *pid_ns) {int i, offset, max_scan, pid, last = pid_ns->last_pid;
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [Devel] [PATCH 2/2] sys_restore: set the pid number
Quoted 54 lines · Pavel Emelyanov
Quoted 40 lines · Serge E. Hallyn
Set the pid number for a restored task. This is purely a toy, as it only sets the pidnr in the lowest level pid namespace.
Signed-off-by Serge Hallyn <serue-r/[email protected]>--- kernel/fork.c | 5 +++++ kernel/pid.c | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 0 deletions(-)kernel/fork.c +5
-0@@ -1685,6 +1685,8 @@ int unshare_files(struct files_struct **displaced)char buf[CKPT_SIZE ];char exe_filename[PAGE_SIZE ]; +extern int choose_pidmap (struct pid *pid,int new); +/* * userspace will already have made us a new pidns */ @@ -1717,6 +1719,9 @@ long do_restore(unsigned int fd,if (nr_scanned !=2 )return -EINVAL ; + ret =choose_pidmap (task_pid (current), pid); +if (!ret) +return -EAGAIN ; ret =do_execve (exe_filename, argv, envp, regs); out:kernel/pid.c +0
-0@@ -122,6 +122,25 @@ static void free_pidmap(struct upid *upid)atomic_inc (&map->nr_free); }kernel/pid.c static void free_pidmap(struct upid *upid) · line 134
Quoted 10 lines
kernel/pid.c +10
-0+int choose_pidmap (struct pid *pid,int new) +{ +struct pidmap *map; +int level = pid->level; +struct upid *upid = &pid->numbers[level]; +struct pid_namespace *pid_ns = upid->ns; +int old = upid->nr; + + map = &pid_ns->pidmap[new/BITS_PER_PAGE ]; +if (!test_and_set_bit (new, map->page)) {This and...
Quoted 5 lines
kernel/pid.c static void free_pidmap(struct upid *upid) · line 136
Quoted 2 lines
kernel/pid.c +2
-0+ map = &pid_ns->pidmap[old/BITS_PER_PAGE ]; +clear_bit (old, map->page);this are both a bit buggy, since the bit number on the page is not the same as the pid id itself ;)
Oops. Yes, I see.
thanks,
-serge
Quoted 10 lines
Quoted 10 lines
kernel/pid.c +7
-0+ upid->nr = new; +return 1 ; + } + +return 0 ; +} +static int alloc_pidmap (struct pid_namespace *pid_ns) {int i, offset, max_scan, pid, last = pid_ns->last_pid;
Quoted 7 lines · Serge E. Hallyn
We were talking this morning about what trivial patchset to begin with to get a start on checkpoint and restart. We thought that rather than start with checkpoint, maybe we should start with something that reads a "checkpoint file" and "restarts" a single task. In this case, restart means it sets the process id and executes the file which are found in the checkpoint file.
Quoted 5 lines
So here's what we whipped up for a half hour this morning, and during some of Mark's talk this afternoon.
It refuses to run if it isn't the container init, so you must unshare your pidns before calling
sys_restore().
A reasonable approximation.
Dave Hansen made a good point when he asked how do we graft a restored checkpoint into the rest of the system. Requiring us to unshare everything we intend to unshare before restore achieves this easily, and you are following in that model.
That leads to an interesting implication. We don't need to set the pid of the first process. At most we can verify that the pid is the same. If we have unshared the pid namespace the pid will be 1 and the needed pid of the first process will be 1.
More later.
Eric
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 22 lines · Eric W. Biederman
Quoted 7 lines · Serge E. Hallyn
We were talking this morning about what trivial patchset to begin with to get a start on checkpoint and restart. We thought that rather than start with checkpoint, maybe we should start with something that reads a "checkpoint file" and "restarts" a single task. In this case, restart means it sets the process id and executes the file which are found in the checkpoint file.
Quoted 5 lines
So here's what we whipped up for a half hour this morning, and during some of Mark's talk this afternoon.
It refuses to run if it isn't the container init, so you must unshare your pidns before calling
sys_restore().A reasonable approximation.
Dave Hansen made a good point when he asked how do we graft a restored checkpoint into the rest of the system. Requiring us to unshare everything we intend to unshare before restore achieves this easily, and you are following in that model.
Quoted 6 lines
That leads to an interesting implication. We don't need to set the pid of the first process. At most we can verify that the pid is the same. If we have unshared the pid namespace the pid will be 1 and the needed pid of the first process will be 1.
More later.
Good point. Sounds like our trivial prototype was still way over-featureful :)
-serge