Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
59f1c5ca
Commit
59f1c5ca
authored
Nov 02, 2016
by
Christian Brauner
Committed by
GitHub
Nov 02, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1270 from tych0/save-dump-state-too
c/r: save dump stdout too
parents
52e12945
2735dfae
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
77 additions
and
31 deletions
+77
-31
criu.c
src/lxc/criu.c
+77
-31
No files found.
src/lxc/criu.c
View file @
59f1c5ca
...
@@ -62,6 +62,9 @@
...
@@ -62,6 +62,9 @@
lxc_log_define
(
lxc_criu
,
lxc
);
lxc_log_define
(
lxc_criu
,
lxc
);
struct
criu_opts
{
struct
criu_opts
{
/* the thing to hook to stdout and stderr for logging */
int
pipefd
;
/* The type of criu invocation, one of "dump" or "restore" */
/* The type of criu invocation, one of "dump" or "restore" */
char
*
action
;
char
*
action
;
...
@@ -134,6 +137,7 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -134,6 +137,7 @@ static void exec_criu(struct criu_opts *opts)
char
buf
[
4096
],
tty_info
[
32
];
char
buf
[
4096
],
tty_info
[
32
];
size_t
pos
;
size_t
pos
;
/* If we are currently in a cgroup /foo/bar, and the container is in a
/* If we are currently in a cgroup /foo/bar, and the container is in a
* cgroup /lxc/foo, lxcfs will give us an ENOENT if some task in the
* cgroup /lxc/foo, lxcfs will give us an ENOENT if some task in the
* container has an open fd that points to one of the cgroup files
* container has an open fd that points to one of the cgroup files
...
@@ -212,7 +216,7 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -212,7 +216,7 @@ static void exec_criu(struct criu_opts *opts)
ret
=
snprintf
(
log
,
PATH_MAX
,
"%s/%s.log"
,
opts
->
user
->
directory
,
opts
->
action
);
ret
=
snprintf
(
log
,
PATH_MAX
,
"%s/%s.log"
,
opts
->
user
->
directory
,
opts
->
action
);
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
{
if
(
ret
<
0
||
ret
>=
PATH_MAX
)
{
ERROR
(
"logfile name too long
\n
"
);
ERROR
(
"logfile name too long"
);
return
;
return
;
}
}
...
@@ -235,7 +239,7 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -235,7 +239,7 @@ static void exec_criu(struct criu_opts *opts)
argv
[
argc
++
]
=
on_path
(
"criu"
,
NULL
);
argv
[
argc
++
]
=
on_path
(
"criu"
,
NULL
);
if
(
!
argv
[
argc
-
1
])
{
if
(
!
argv
[
argc
-
1
])
{
ERROR
(
"Couldn't find criu binary
\n
"
);
ERROR
(
"Couldn't find criu binary"
);
goto
err
;
goto
err
;
}
}
...
@@ -502,7 +506,7 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -502,7 +506,7 @@ static void exec_criu(struct criu_opts *opts)
break
;
break
;
case
LXC_NET_MACVLAN
:
case
LXC_NET_MACVLAN
:
if
(
!
n
->
link
)
{
if
(
!
n
->
link
)
{
ERROR
(
"no host interface for macvlan %s
\n
"
,
n
->
name
);
ERROR
(
"no host interface for macvlan %s"
,
n
->
name
);
goto
err
;
goto
err
;
}
}
...
@@ -515,7 +519,7 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -515,7 +519,7 @@ static void exec_criu(struct criu_opts *opts)
break
;
break
;
default:
default:
/* we have screened for this earlier... */
/* we have screened for this earlier... */
ERROR
(
"unexpected network type %d
\n
"
,
n
->
type
);
ERROR
(
"unexpected network type %d"
,
n
->
type
);
goto
err
;
goto
err
;
}
}
...
@@ -541,6 +545,21 @@ static void exec_criu(struct criu_opts *opts)
...
@@ -541,6 +545,21 @@ static void exec_criu(struct criu_opts *opts)
INFO
(
"execing: %s"
,
buf
);
INFO
(
"execing: %s"
,
buf
);
/* before criu inits its log, it sometimes prints things to stdout/err;
* let's be sure we capture that.
*/
if
(
dup2
(
opts
->
pipefd
,
STDOUT_FILENO
)
<
0
)
{
SYSERROR
(
"dup2 stdout failed"
);
goto
err
;
}
if
(
dup2
(
opts
->
pipefd
,
STDERR_FILENO
)
<
0
)
{
SYSERROR
(
"dup2 stderr failed"
);
goto
err
;
}
close
(
opts
->
pipefd
);
#undef DECLARE_ARG
#undef DECLARE_ARG
execv
(
argv
[
0
],
argv
);
execv
(
argv
[
0
],
argv
);
err:
err:
...
@@ -651,7 +670,7 @@ version_match:
...
@@ -651,7 +670,7 @@ version_match:
version_error:
version_error:
fclose
(
f
);
fclose
(
f
);
free
(
tmp
);
free
(
tmp
);
ERROR
(
"must have criu "
CRIU_VERSION
" or greater to checkpoint/restore
\n
"
);
ERROR
(
"must have criu "
CRIU_VERSION
" or greater to checkpoint/restore"
);
return
false
;
return
false
;
}
}
}
}
...
@@ -666,7 +685,7 @@ static bool criu_ok(struct lxc_container *c, char **criu_version)
...
@@ -666,7 +685,7 @@ static bool criu_ok(struct lxc_container *c, char **criu_version)
return
false
;
return
false
;
if
(
geteuid
())
{
if
(
geteuid
())
{
ERROR
(
"Must be root to checkpoint
\n
"
);
ERROR
(
"Must be root to checkpoint"
);
return
false
;
return
false
;
}
}
...
@@ -680,7 +699,7 @@ static bool criu_ok(struct lxc_container *c, char **criu_version)
...
@@ -680,7 +699,7 @@ static bool criu_ok(struct lxc_container *c, char **criu_version)
case
LXC_NET_MACVLAN
:
case
LXC_NET_MACVLAN
:
break
;
break
;
default:
default:
ERROR
(
"Found un-dumpable network: %s (%s)
\n
"
,
lxc_net_type_to_str
(
n
->
type
),
n
->
name
);
ERROR
(
"Found un-dumpable network: %s (%s)"
,
lxc_net_type_to_str
(
n
->
type
),
n
->
name
);
return
false
;
return
false
;
}
}
}
}
...
@@ -781,15 +800,6 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
...
@@ -781,15 +800,6 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
close
(
pipes
[
0
]);
close
(
pipes
[
0
]);
pipes
[
0
]
=
-
1
;
pipes
[
0
]
=
-
1
;
if
(
dup2
(
pipes
[
1
],
STDERR_FILENO
)
<
0
)
{
SYSERROR
(
"dup2 failed"
);
goto
out_fini_handler
;
}
if
(
dup2
(
pipes
[
1
],
STDOUT_FILENO
)
<
0
)
{
SYSERROR
(
"dup2 failed"
);
goto
out_fini_handler
;
}
if
(
unshare
(
CLONE_NEWNS
))
if
(
unshare
(
CLONE_NEWNS
))
goto
out_fini_handler
;
goto
out_fini_handler
;
...
@@ -816,6 +826,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
...
@@ -816,6 +826,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
}
}
}
}
os
.
pipefd
=
pipes
[
1
];
os
.
action
=
"restore"
;
os
.
action
=
"restore"
;
os
.
user
=
opts
;
os
.
user
=
opts
;
os
.
c
=
c
;
os
.
c
=
c
;
...
@@ -872,9 +883,11 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
...
@@ -872,9 +883,11 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
goto
out_fini_handler
;
goto
out_fini_handler
;
}
}
if
(
n
==
sizeof
(
buf
))
n
--
;
buf
[
n
]
=
0
;
buf
[
n
]
=
0
;
ERROR
(
"criu process exited %d, output:
\n
%s
\n
"
,
WEXITSTATUS
(
status
),
buf
);
ERROR
(
"criu process exited %d, output:
\n
%s"
,
WEXITSTATUS
(
status
),
buf
);
goto
out_fini_handler
;
goto
out_fini_handler
;
}
else
{
}
else
{
ret
=
snprintf
(
buf
,
sizeof
(
buf
),
"/proc/self/task/%lu/children"
,
(
unsigned
long
)
syscall
(
__NR_gettid
));
ret
=
snprintf
(
buf
,
sizeof
(
buf
),
"/proc/self/task/%lu/children"
,
(
unsigned
long
)
syscall
(
__NR_gettid
));
...
@@ -885,7 +898,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
...
@@ -885,7 +898,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
FILE
*
f
=
fopen
(
buf
,
"r"
);
FILE
*
f
=
fopen
(
buf
,
"r"
);
if
(
!
f
)
{
if
(
!
f
)
{
SYSERROR
(
"couldn't read restore's children file %s
\n
"
,
buf
);
SYSERROR
(
"couldn't read restore's children file %s"
,
buf
);
goto
out_fini_handler
;
goto
out_fini_handler
;
}
}
...
@@ -902,7 +915,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
...
@@ -902,7 +915,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
}
}
}
}
}
else
{
}
else
{
ERROR
(
"CRIU was killed with signal %d
\n
"
,
WTERMSIG
(
status
));
ERROR
(
"CRIU was killed with signal %d"
,
WTERMSIG
(
status
));
goto
out_fini_handler
;
goto
out_fini_handler
;
}
}
...
@@ -1013,29 +1026,38 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
...
@@ -1013,29 +1026,38 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
{
{
pid_t
pid
;
pid_t
pid
;
char
*
criu_version
=
NULL
;
char
*
criu_version
=
NULL
;
int
criuout
[
2
];
if
(
!
criu_ok
(
c
,
&
criu_version
))
if
(
!
criu_ok
(
c
,
&
criu_version
))
return
false
;
return
false
;
if
(
mkdir_p
(
opts
->
directory
,
0700
)
<
0
)
if
(
pipe
(
criuout
)
<
0
)
{
SYSERROR
(
"pipe() failed"
);
return
false
;
return
false
;
}
if
(
mkdir_p
(
opts
->
directory
,
0700
)
<
0
)
goto
fail
;
pid
=
fork
();
pid
=
fork
();
if
(
pid
<
0
)
{
if
(
pid
<
0
)
{
SYSERROR
(
"fork failed"
);
SYSERROR
(
"fork failed"
);
return
false
;
goto
fail
;
}
}
if
(
pid
==
0
)
{
if
(
pid
==
0
)
{
struct
criu_opts
os
;
struct
criu_opts
os
;
struct
lxc_handler
h
;
struct
lxc_handler
h
;
close
(
criuout
[
0
]);
h
.
name
=
c
->
name
;
h
.
name
=
c
->
name
;
if
(
!
cgroup_init
(
&
h
))
{
if
(
!
cgroup_init
(
&
h
))
{
ERROR
(
"failed to cgroup_init()"
);
ERROR
(
"failed to cgroup_init()"
);
exit
(
1
);
exit
(
1
);
}
}
os
.
pipefd
=
criuout
[
1
];
os
.
action
=
mode
;
os
.
action
=
mode
;
os
.
user
=
opts
;
os
.
user
=
opts
;
os
.
c
=
c
;
os
.
c
=
c
;
...
@@ -1050,27 +1072,51 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
...
@@ -1050,27 +1072,51 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
exit
(
1
);
exit
(
1
);
}
else
{
}
else
{
int
status
;
int
status
;
ssize_t
n
;
char
buf
[
4096
];
bool
ret
;
close
(
criuout
[
1
]);
pid_t
w
=
waitpid
(
pid
,
&
status
,
0
);
pid_t
w
=
waitpid
(
pid
,
&
status
,
0
);
if
(
w
==
-
1
)
{
if
(
w
==
-
1
)
{
SYSERROR
(
"waitpid"
);
SYSERROR
(
"waitpid"
);
close
(
criuout
[
0
]);
return
false
;
return
false
;
}
}
n
=
read
(
criuout
[
0
],
buf
,
sizeof
(
buf
));
close
(
criuout
[
0
]);
if
(
n
<
0
)
{
SYSERROR
(
"read"
);
n
=
0
;
}
buf
[
n
]
=
0
;
if
(
WIFEXITED
(
status
))
{
if
(
WIFEXITED
(
status
))
{
if
(
WEXITSTATUS
(
status
))
{
if
(
WEXITSTATUS
(
status
))
{
ERROR
(
"dump failed with %d
\n
"
,
WEXITSTATUS
(
status
));
ERROR
(
"dump failed with %d"
,
WEXITSTATUS
(
status
));
return
false
;
ret
=
false
;
}
else
{
ret
=
true
;
}
}
return
true
;
}
else
if
(
WIFSIGNALED
(
status
))
{
}
else
if
(
WIFSIGNALED
(
status
))
{
ERROR
(
"dump signaled with %d
\n
"
,
WTERMSIG
(
status
));
ERROR
(
"dump signaled with %d"
,
WTERMSIG
(
status
));
ret
urn
false
;
ret
=
false
;
}
else
{
}
else
{
ERROR
(
"unknown dump exit %d
\n
"
,
status
);
ERROR
(
"unknown dump exit %d"
,
status
);
ret
urn
false
;
ret
=
false
;
}
}
if
(
!
ret
)
ERROR
(
"criu output: %s"
,
buf
);
return
ret
;
}
}
fail:
close
(
criuout
[
0
]);
close
(
criuout
[
1
]);
rmdir
(
opts
->
directory
);
return
false
;
}
}
bool
__criu_pre_dump
(
struct
lxc_container
*
c
,
struct
migrate_opts
*
opts
)
bool
__criu_pre_dump
(
struct
lxc_container
*
c
,
struct
migrate_opts
*
opts
)
...
@@ -1088,7 +1134,7 @@ bool __criu_dump(struct lxc_container *c, struct migrate_opts *opts)
...
@@ -1088,7 +1134,7 @@ bool __criu_dump(struct lxc_container *c, struct migrate_opts *opts)
return
false
;
return
false
;
if
(
access
(
path
,
F_OK
)
==
0
)
{
if
(
access
(
path
,
F_OK
)
==
0
)
{
ERROR
(
"please use a fresh directory for the dump directory
\n
"
);
ERROR
(
"please use a fresh directory for the dump directory"
);
return
false
;
return
false
;
}
}
...
@@ -1106,7 +1152,7 @@ bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts)
...
@@ -1106,7 +1152,7 @@ bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts)
return
false
;
return
false
;
if
(
geteuid
())
{
if
(
geteuid
())
{
ERROR
(
"Must be root to restore
\n
"
);
ERROR
(
"Must be root to restore"
);
return
false
;
return
false
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment