Difference between revisions of "Plugins"
m (nit) |
m (→Examples: update links) |
||
(3 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | + | Linux processes are not things-in-themselves. They tend to cooperate with other parts of the system very actively. When CRIU tries to dump a process having such an external connection, it refuses to make the dump. The reason is simple: without knowing the details of such connections it is impossible to correctly detach the process from its peer on dump and attach back on restore. | |
− | Linux processes are not things-in-themselves. They tend to cooperate with other parts of the system very actively. When CRIU tries to dump a process | ||
− | Though sometimes we can handle this (this is what --shell-job, --ext-unix-sk and --tcp-established options are about), in many cases we cannot provide generic solution. | + | Though sometimes we can handle this (this is what <code>--shell-job</code>, <code>--ext-unix-sk</code> and <code>--tcp-established</code> options are about), in many cases we cannot provide a generic solution. |
− | So, in order to address this problem we | + | So, in order to address this problem we made CRIU pluggable. |
− | =Libraries= | + | == Libraries == |
− | |||
− | Each library can have cr_plugin_init() and cr_plugin_fini() functions for initializing and finalizing. cr_plugin_init() can return a negative value in an error | + | A CRIU plugin is a shared library, loaded before dumping or restoring. |
+ | |||
+ | Each library can have <code>cr_plugin_init()</code> and <code>cr_plugin_fini()</code> functions for initializing and finalizing. <code>cr_plugin_init()</code> can return a negative value in case of an error. | ||
+ | |||
+ | == Headers == | ||
+ | |||
+ | The public headers have <code>criu-</code> prefix. The backward compatibility of all functions declared there will be retained. | ||
− | |||
− | |||
# ls include/criu-* | # ls include/criu-* | ||
include/criu-log.h include/criu-plugin.h | include/criu-log.h include/criu-plugin.h | ||
− | ==Images== | + | == Images == |
− | |||
− | All images are saved in a specified directory and plugins can call | + | CRIU saves [[images]] in google protocol buffer (PB) format. We recommend using this format for plugin images as well. |
+ | |||
+ | All images are saved in a specified directory and plugins can call <code>criu_get_image_dir()</code> to get the file descriptor on this directory. The file descriptor is used as the directory can be unreachable by path (for example, if processes are restored in a new mount namespace). | ||
== Callbacks == | == Callbacks == | ||
− | When CRIU receives an unsupported object, it enumerates callbacks until one of them doesn't return something other than -ENOSUPP. Usually callbacks | + | When CRIU receives an unsupported object, it enumerates callbacks until one of them doesn't return something other than <code>-ENOSUPP</code>. Usually callbacks return negative code in an error case. The <code>-ENOSUPP</code> code is special — it is returned if the callback is not suitable for the object. |
− | A callback gets an unique | + | A callback gets an unique identifier for a serialized object. On restore, this identifier is used to request a specific object. |
− | The CRIU tool looks up | + | The CRIU tool looks up callbacks by their names. A library may provide any set of callbacks. All callback prototypes are defined in <code>criu-plugins.h</code>. |
=== External unix sockets === | === External unix sockets === | ||
− | |||
− | The most popular example of this type of sockets is a D-Bus socket. Only D-Bus daemon knows | + | A socket is external, if it is dumped without a peer. In this case some state can be present on the other side. |
+ | |||
+ | The most popular example of this type of sockets is a D-Bus socket. Only D-Bus daemon knows which events a socket is subscribed to. | ||
− | + | <source lang="c"> | |
+ | int cr_plugin_dump_unix_sk(int sk, int id); | ||
− | + | int cr_plugin_restore_unix_sk(int id); | |
+ | </source> | ||
− | The dump callback gets a socket | + | The dump callback gets a socket to be dumped. |
The restore callback returns a restored socket. | The restore callback returns a restored socket. | ||
=== External files === | === External files === | ||
+ | |||
External files are files, which are dumped and restored with help plugins. | External files are files, which are dumped and restored with help plugins. | ||
− | |||
− | int | + | <source lang="c"> |
+ | int cr_plugin_dump_file(int fd, int id); | ||
− | The dump callback gets a file descriptor | + | int cr_plugin_restore_file(int id); |
+ | </source> | ||
+ | |||
+ | The dump callback gets a file descriptor to be dumped. | ||
The restore callback returns a restored file. | The restore callback returns a restored file. | ||
=== External bind mounts === | === External bind mounts === | ||
− | These are mount points with target sitting out of the namespace's visible FS tree. | + | These are mount points with target sitting out of the namespace's visible FS tree. For example, this is how LXC people configure the console and ttys for a container. In order to dump and restore those plugin can define calls: |
− | int cr_plugin_dump_ext_mount(char *mountpoint, int id) | + | <source lang="c"> |
+ | int cr_plugin_dump_ext_mount(char *mountpoint, int id); | ||
+ | </source> | ||
The <code>mountpoint</code> is the path where the mount is. | The <code>mountpoint</code> is the path where the mount is. | ||
− | The <code>id</code> is an identifier of a mountpoint as seen in <code>/proc/self/mountinfo</code> and that will at restore time be passed to identify the mount to restore (at that time it will no longer match the proc info!). | + | The <code>id</code> is an identifier of a mountpoint as seen in <code>/proc/self/mountinfo</code> and that will at restore time be passed to identify the mount to restore (note at that time it will no longer match the proc info!). |
+ | <source lang="c"> | ||
int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *is_file) | int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *is_file) | ||
+ | </source> | ||
The <code>id</code> is the mountpoint id. | The <code>id</code> is the mountpoint id. | ||
Line 68: | Line 82: | ||
The <code>old_root</code> argument is the path to a tree where files visible from the original namespace are. Plugins should get files they want to bind-mount inside the new namespace starting from that path. | The <code>old_root</code> argument is the path to a tree where files visible from the original namespace are. Plugins should get files they want to bind-mount inside the new namespace starting from that path. | ||
− | The <code>is_file</code> if not NULL points to the boolean variable saying whether the mountpoint is file or directory. Since in Linux one can bind mount files or directories, CRIU need to know whether the new mount point | + | The <code>is_file</code>, if not NULL, points to the boolean variable saying whether the mountpoint is a file or a directory. Since in Linux one can bind mount files or directories, CRIU need to know whether the new mount point created by plugin is one of those. |
=== External net devices (links) === | === External net devices (links) === | ||
− | When trying to C/R a net namespace with links put outside of it (physical devices assigned or macvlans/vlans) CRIU will call | + | When trying to C/R a net namespace with links put outside of it (physical devices assigned or macvlans/vlans), CRIU will call |
+ | <source lang="c"> | ||
int cr_plugin_dump_ext_link(int index, int type, char *kind); | int cr_plugin_dump_ext_link(int index, int type, char *kind); | ||
+ | </source> | ||
− | + | The <code>index</code> is the link index, <code>type</code> is one of the <code>ARPHRD_*</code> values, and <code>kind</code> is the link driver name. | |
− | Restoring external links should happen in | + | Restoring external links should happen in <code>setup-namespaces</code> [[action scripts]]. |
=== Examples === | === Examples === | ||
− | |||
− | |||
− | Here is a plugin | + | Here is a small test program that opens <code>/dev/rtc</code> and sets up a timer. |
− | [ | + | [https://github.com/checkpoint-restore/criu/blob/master/test/zdtm/static/rtc.c RTC test] |
+ | |||
+ | Here is a plugin used for dumping and restoring the previous test. | ||
+ | [https://github.com/checkpoint-restore/criu/blob/master/test/zdtm/static/criu-rtc.c criu-rtc.so] | ||
+ | |||
+ | [https://github.com/checkpoint-restore/criu/tree/master/test/others/ext-links External links test] | ||
+ | |||
+ | [https://github.com/checkpoint-restore/criu/tree/master/test/others/mounts/ext External mountpoints test] | ||
− | + | == External links == | |
+ | * https://plus.google.com/103175467322423551911/posts/Fu3pNm82zS8 | ||
− | [ | + | [[Category:Development]] |
+ | [[Category:API]] |
Latest revision as of 19:39, 6 January 2019
Linux processes are not things-in-themselves. They tend to cooperate with other parts of the system very actively. When CRIU tries to dump a process having such an external connection, it refuses to make the dump. The reason is simple: without knowing the details of such connections it is impossible to correctly detach the process from its peer on dump and attach back on restore.
Though sometimes we can handle this (this is what --shell-job
, --ext-unix-sk
and --tcp-established
options are about), in many cases we cannot provide a generic solution.
So, in order to address this problem we made CRIU pluggable.
Libraries[edit]
A CRIU plugin is a shared library, loaded before dumping or restoring.
Each library can have cr_plugin_init()
and cr_plugin_fini()
functions for initializing and finalizing. cr_plugin_init()
can return a negative value in case of an error.
Headers[edit]
The public headers have criu-
prefix. The backward compatibility of all functions declared there will be retained.
# ls include/criu-* include/criu-log.h include/criu-plugin.h
Images[edit]
CRIU saves images in google protocol buffer (PB) format. We recommend using this format for plugin images as well.
All images are saved in a specified directory and plugins can call criu_get_image_dir()
to get the file descriptor on this directory. The file descriptor is used as the directory can be unreachable by path (for example, if processes are restored in a new mount namespace).
Callbacks[edit]
When CRIU receives an unsupported object, it enumerates callbacks until one of them doesn't return something other than -ENOSUPP
. Usually callbacks return negative code in an error case. The -ENOSUPP
code is special — it is returned if the callback is not suitable for the object.
A callback gets an unique identifier for a serialized object. On restore, this identifier is used to request a specific object.
The CRIU tool looks up callbacks by their names. A library may provide any set of callbacks. All callback prototypes are defined in criu-plugins.h
.
External unix sockets[edit]
A socket is external, if it is dumped without a peer. In this case some state can be present on the other side.
The most popular example of this type of sockets is a D-Bus socket. Only D-Bus daemon knows which events a socket is subscribed to.
int cr_plugin_dump_unix_sk(int sk, int id);
int cr_plugin_restore_unix_sk(int id);
The dump callback gets a socket to be dumped. The restore callback returns a restored socket.
External files[edit]
External files are files, which are dumped and restored with help plugins.
int cr_plugin_dump_file(int fd, int id);
int cr_plugin_restore_file(int id);
The dump callback gets a file descriptor to be dumped. The restore callback returns a restored file.
External bind mounts[edit]
These are mount points with target sitting out of the namespace's visible FS tree. For example, this is how LXC people configure the console and ttys for a container. In order to dump and restore those plugin can define calls:
int cr_plugin_dump_ext_mount(char *mountpoint, int id);
The mountpoint
is the path where the mount is.
The id
is an identifier of a mountpoint as seen in /proc/self/mountinfo
and that will at restore time be passed to identify the mount to restore (note at that time it will no longer match the proc info!).
int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *is_file)
The id
is the mountpoint id.
The mountpoint
is where the mount should be attached to. Note, that this path may not coincide with the one at dump stage! CRIU may ask to mount it as some different location and will move it to proper place eventually.
The old_root
argument is the path to a tree where files visible from the original namespace are. Plugins should get files they want to bind-mount inside the new namespace starting from that path.
The is_file
, if not NULL, points to the boolean variable saying whether the mountpoint is a file or a directory. Since in Linux one can bind mount files or directories, CRIU need to know whether the new mount point created by plugin is one of those.
External net devices (links)[edit]
When trying to C/R a net namespace with links put outside of it (physical devices assigned or macvlans/vlans), CRIU will call
int cr_plugin_dump_ext_link(int index, int type, char *kind);
The index
is the link index, type
is one of the ARPHRD_*
values, and kind
is the link driver name.
Restoring external links should happen in setup-namespaces
action scripts.
Examples[edit]
Here is a small test program that opens /dev/rtc
and sets up a timer.
RTC test
Here is a plugin used for dumping and restoring the previous test. criu-rtc.so