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
12401528
Unverified
Commit
12401528
authored
Dec 14, 2017
by
Christian Brauner
Committed by
GitHub
Dec 14, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2035 from adrianreber/master
criu: add feature check capability
parents
81b10e37
739ef90c
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
217 additions
and
1 deletion
+217
-1
criu.c
src/lxc/criu.c
+98
-0
criu.h
src/lxc/criu.h
+1
-0
lxccontainer.c
src/lxc/lxccontainer.c
+10
-0
lxccontainer.h
src/lxc/lxccontainer.h
+14
-0
Makefile.am
src/tests/Makefile.am
+4
-1
criu_check_feature.c
src/tests/criu_check_feature.c
+90
-0
No files found.
src/lxc/criu.c
View file @
12401528
...
@@ -653,6 +653,104 @@ err:
...
@@ -653,6 +653,104 @@ err:
}
}
/*
/*
* Function to check if the checks activated in 'features_to_check' are
* available with the current architecture/kernel/criu combination.
*
* Parameter features_to_check is a bit mask of all features that should be
* checked (see feature check defines in lxc/lxccontainer.h).
*
* If the return value is true, all requested features are supported. If
* the return value is false the features_to_check parameter is updated
* to reflect which features are available. '0' means no feature but
* also that something went totally wrong.
*
* Some of the code flow of criu_version_ok() is duplicated and maybe it
* is a good candidate for refactoring.
*/
bool
__criu_check_feature
(
uint64_t
*
features_to_check
)
{
pid_t
pid
;
uint64_t
current_bit
=
0
;
int
ret
;
int
features
=
*
features_to_check
;
/* Feature checking is currently always like
* criu check --feature <feature-name>
*/
char
*
args
[]
=
{
"criu"
,
"check"
,
"--feature"
,
NULL
,
NULL
};
if
((
features
&
~
FEATURE_MEM_TRACK
&
~
FEATURE_LAZY_PAGES
)
!=
0
)
{
/* There are feature bits activated we do not understand.
* Refusing to answer at all */
*
features_to_check
=
0
;
return
false
;
}
while
(
current_bit
<
sizeof
(
uint64_t
)
*
8
)
{
/* only test requested features */
if
(
!
(
features
&
(
1ULL
<<
current_bit
)))
{
/* skip this */
current_bit
++
;
continue
;
}
pid
=
fork
();
if
(
pid
<
0
)
{
SYSERROR
(
"fork() failed"
);
*
features_to_check
=
0
;
return
false
;
}
if
(
pid
==
0
)
{
if
((
1ULL
<<
current_bit
)
==
FEATURE_MEM_TRACK
)
/* This is needed for pre-dump support, which
* enables pre-copy migration. */
args
[
3
]
=
"mem_dirty_track"
;
else
if
((
1ULL
<<
current_bit
)
==
FEATURE_LAZY_PAGES
)
/* CRIU has two checks for userfaultfd support.
*
* The simpler check is only for 'uffd'. If the
* kernel supports userfaultfd without noncoop
* then only process can be lazily restored
* which do not fork. With 'uffd-noncoop'
* it is also possible to lazily restore processes
* which do fork. For a container runtime like
* LXC checking only for 'uffd' makes not much sense. */
args
[
3
]
=
"uffd-noncoop"
;
else
exit
(
1
);
null_stdfds
();
execvp
(
"criu"
,
args
);
SYSERROR
(
"Failed to exec
\"
criu
\"
"
);
exit
(
1
);
}
ret
=
wait_for_pid
(
pid
);
if
(
ret
==
-
1
)
{
/* It is not known why CRIU failed. Either
* CRIU is not available, the feature check
* does not exist or the feature is not
* supported. */
INFO
(
"feature not supported"
);
/* Clear not supported feature bit */
features
&=
~
(
1ULL
<<
current_bit
);
}
current_bit
++
;
/* no more checks requested; exit check loop */
if
(
!
(
features
&
~
((
1ULL
<<
current_bit
)
-
1
)))
break
;
}
if
(
features
!=
*
features_to_check
)
{
*
features_to_check
=
features
;
return
false
;
}
return
true
;
}
/*
* Check to see if the criu version is recent enough for all the features we
* Check to see if the criu version is recent enough for all the features we
* use. This version allows either CRIU_VERSION or (CRIU_GITID_VERSION and
* use. This version allows either CRIU_VERSION or (CRIU_GITID_VERSION and
* CRIU_GITID_PATCHLEVEL) to work, enabling users building from git to c/r
* CRIU_GITID_PATCHLEVEL) to work, enabling users building from git to c/r
...
...
src/lxc/criu.h
View file @
12401528
...
@@ -30,5 +30,6 @@
...
@@ -30,5 +30,6 @@
bool
__criu_pre_dump
(
struct
lxc_container
*
c
,
struct
migrate_opts
*
opts
);
bool
__criu_pre_dump
(
struct
lxc_container
*
c
,
struct
migrate_opts
*
opts
);
bool
__criu_dump
(
struct
lxc_container
*
c
,
struct
migrate_opts
*
opts
);
bool
__criu_dump
(
struct
lxc_container
*
c
,
struct
migrate_opts
*
opts
);
bool
__criu_restore
(
struct
lxc_container
*
c
,
struct
migrate_opts
*
opts
);
bool
__criu_restore
(
struct
lxc_container
*
c
,
struct
migrate_opts
*
opts
);
bool
__criu_check_feature
(
uint64_t
*
features_to_check
);
#endif
#endif
src/lxc/lxccontainer.c
View file @
12401528
...
@@ -4510,6 +4510,7 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
...
@@ -4510,6 +4510,7 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
{
{
int
ret
=
-
1
;
int
ret
=
-
1
;
struct
migrate_opts
*
valid_opts
=
opts
;
struct
migrate_opts
*
valid_opts
=
opts
;
uint64_t
features_to_check
=
0
;
/* If the caller has a bigger (newer) struct migrate_opts, let's make
/* If the caller has a bigger (newer) struct migrate_opts, let's make
* sure that the stuff on the end is zero, i.e. that they didn't ask us
* sure that the stuff on the end is zero, i.e. that they didn't ask us
...
@@ -4563,6 +4564,15 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
...
@@ -4563,6 +4564,15 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
}
}
ret
=
!
__criu_restore
(
c
,
valid_opts
);
ret
=
!
__criu_restore
(
c
,
valid_opts
);
break
;
break
;
case
MIGRATE_FEATURE_CHECK
:
features_to_check
=
valid_opts
->
features_to_check
;
ret
=
!
__criu_check_feature
(
&
features_to_check
);
if
(
ret
)
{
/* Something went wrong. Let's let the caller
* know which feature checks failed. */
valid_opts
->
features_to_check
=
features_to_check
;
}
break
;
default
:
default
:
ERROR
(
"invalid migrate command %u"
,
cmd
);
ERROR
(
"invalid migrate command %u"
,
cmd
);
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
...
...
src/lxc/lxccontainer.h
View file @
12401528
...
@@ -904,9 +904,16 @@ enum {
...
@@ -904,9 +904,16 @@ enum {
MIGRATE_PRE_DUMP
,
MIGRATE_PRE_DUMP
,
MIGRATE_DUMP
,
MIGRATE_DUMP
,
MIGRATE_RESTORE
,
MIGRATE_RESTORE
,
MIGRATE_FEATURE_CHECK
,
};
};
/*!
/*!
* \brief Available feature checks.
*/
#define FEATURE_MEM_TRACK (1ULL << 0)
#define FEATURE_LAZY_PAGES (1ULL << 1)
/*!
* \brief Options for the migrate API call.
* \brief Options for the migrate API call.
*/
*/
struct
migrate_opts
{
struct
migrate_opts
{
...
@@ -942,6 +949,13 @@ struct migrate_opts {
...
@@ -942,6 +949,13 @@ struct migrate_opts {
* which at this time is 1MB.
* which at this time is 1MB.
*/
*/
uint64_t
ghost_limit
;
uint64_t
ghost_limit
;
/* Some features cannot be checked by comparing the CRIU version.
* Features like dirty page tracking or userfaultfd depend on
* the architecture/kernel/criu combination. This is a bitmask
* in which the desired feature checks can be encoded.
*/
uint64_t
features_to_check
;
};
};
struct
lxc_console_log
{
struct
lxc_console_log
{
...
...
src/tests/Makefile.am
View file @
12401528
...
@@ -32,6 +32,7 @@ lxc_test_shortlived_SOURCES = shortlived.c
...
@@ -32,6 +32,7 @@ lxc_test_shortlived_SOURCES = shortlived.c
lxc_test_livepatch_SOURCES
=
livepatch.c lxctest.h
lxc_test_livepatch_SOURCES
=
livepatch.c lxctest.h
lxc_test_state_server_SOURCES
=
state_server.c lxctest.h
lxc_test_state_server_SOURCES
=
state_server.c lxctest.h
lxc_test_share_ns_SOURCES
=
share_ns.c lxctest.h
lxc_test_share_ns_SOURCES
=
share_ns.c lxctest.h
lxc_test_criu_check_feature_SOURCES
=
criu_check_feature.c lxctest.h
AM_CFLAGS
=
-DLXCROOTFSMOUNT
=
\"
$(LXCROOTFSMOUNT)
\"
\
AM_CFLAGS
=
-DLXCROOTFSMOUNT
=
\"
$(LXCROOTFSMOUNT)
\"
\
-DLXCPATH
=
\"
$(LXCPATH)
\"
\
-DLXCPATH
=
\"
$(LXCPATH)
\"
\
...
@@ -61,7 +62,8 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
...
@@ -61,7 +62,8 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
lxc-test-reboot lxc-test-list lxc-test-attach lxc-test-device-add-remove
\
lxc-test-reboot lxc-test-list lxc-test-attach lxc-test-device-add-remove
\
lxc-test-apparmor lxc-test-utils lxc-test-parse-config-file
\
lxc-test-apparmor lxc-test-utils lxc-test-parse-config-file
\
lxc-test-config-jump-table lxc-test-shortlived lxc-test-livepatch
\
lxc-test-config-jump-table lxc-test-shortlived lxc-test-livepatch
\
lxc-test-api-reboot lxc-test-state-server lxc-test-share-ns
lxc-test-api-reboot lxc-test-state-server lxc-test-share-ns
\
lxc-test-criu-check-feature
bin_SCRIPTS
=
lxc-test-automount
\
bin_SCRIPTS
=
lxc-test-automount
\
lxc-test-autostart
\
lxc-test-autostart
\
...
@@ -93,6 +95,7 @@ EXTRA_DIST = \
...
@@ -93,6 +95,7 @@ EXTRA_DIST = \
console_log.c
\
console_log.c
\
containertests.c
\
containertests.c
\
createtest.c
\
createtest.c
\
criu_check_feature.c
\
destroytest.c
\
destroytest.c
\
device_add_remove.c
\
device_add_remove.c
\
get_item.c
\
get_item.c
\
...
...
src/tests/criu_check_feature.c
0 → 100644
View file @
12401528
/* liblxcapi
*
* Copyright © 2017 Adrian Reber <areber@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <limits.h>
#include "lxc/lxccontainer.h"
#include "lxctest.h"
int
main
(
int
argc
,
char
*
argv
[])
{
struct
lxc_container
*
c
;
struct
migrate_opts
m_opts
;
int
ret
=
EXIT_FAILURE
;
/* Test the feature check interface,
* we actually do not need a container. */
c
=
lxc_container_new
(
"check_feature"
,
NULL
);
if
(
!
c
)
{
lxc_error
(
"%s"
,
"Failed to create container
\"
check_feature
\"
"
);
exit
(
ret
);
}
if
(
c
->
is_defined
(
c
))
{
lxc_error
(
"%s
\n
"
,
"Container
\"
check_feature
\"
is defined"
);
goto
on_error_put
;
}
/* check the migrate API call with wrong 'cmd' */
if
(
!
c
->
migrate
(
c
,
UINT_MAX
,
&
m_opts
,
sizeof
(
struct
migrate_opts
)))
{
/* This should failed */
lxc_error
(
"%s
\n
"
,
"Migrate API calls with command UINT_MAX did not fail"
);
goto
on_error_put
;
}
/* do the actual fature check for memory tracking */
m_opts
.
features_to_check
=
FEATURE_MEM_TRACK
;
if
(
c
->
migrate
(
c
,
MIGRATE_FEATURE_CHECK
,
&
m_opts
,
sizeof
(
struct
migrate_opts
)))
{
lxc_debug
(
"%s
\n
"
,
"System does not support
\"
FEATURE_MEM_TRACK
\"
."
);
}
/* check for lazy pages */
m_opts
.
features_to_check
=
FEATURE_LAZY_PAGES
;
if
(
c
->
migrate
(
c
,
MIGRATE_FEATURE_CHECK
,
&
m_opts
,
sizeof
(
struct
migrate_opts
)))
{
lxc_debug
(
"%s
\n
"
,
"System does not support
\"
FEATURE_LAZY_PAGES
\"
."
);
}
/* check for lazy pages and memory tracking */
m_opts
.
features_to_check
=
FEATURE_LAZY_PAGES
|
FEATURE_MEM_TRACK
;
if
(
c
->
migrate
(
c
,
MIGRATE_FEATURE_CHECK
,
&
m_opts
,
sizeof
(
struct
migrate_opts
)))
{
if
(
m_opts
.
features_to_check
==
FEATURE_LAZY_PAGES
)
lxc_debug
(
"%s
\n
"
,
"System does not support
\"
FEATURE_MEM_TRACK
\"
"
);
else
if
(
m_opts
.
features_to_check
==
FEATURE_MEM_TRACK
)
lxc_debug
(
"%s
\n
"
,
"System does not support
\"
FEATURE_LAZY_PAGES
\"
"
);
else
lxc_debug
(
"%s
\n
"
,
"System does not support
\"
FEATURE_MEM_TRACK
\"
"
"and
\"
FEATURE_LAZY_PAGES
\"
"
);
}
/* test for unknown feature; once there are 64 features to test
* this will be valid... */
m_opts
.
features_to_check
=
-
1ULL
;
if
(
!
c
->
migrate
(
c
,
MIGRATE_FEATURE_CHECK
,
&
m_opts
,
sizeof
(
struct
migrate_opts
)))
{
lxc_error
(
"%s
\n
"
,
"Unsupported feature supported, which is strange."
);
goto
on_error_put
;
}
ret
=
EXIT_SUCCESS
;
on_error_put:
lxc_container_put
(
c
);
if
(
ret
==
EXIT_SUCCESS
)
lxc_debug
(
"%s
\n
"
,
"All criu feature check tests passed"
);
exit
(
ret
);
}
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