mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-19 01:26:22 +00:00
Compare commits
No commits in common. "criu-dev" and "v2.12" have entirely different histories.
2048 changed files with 33668 additions and 158341 deletions
|
|
@ -1,44 +0,0 @@
|
|||
version: 2.1
|
||||
jobs:
|
||||
test-local:
|
||||
machine:
|
||||
image: default
|
||||
working_directory: ~/criu
|
||||
parameters:
|
||||
compiler:
|
||||
type: string
|
||||
shard_index:
|
||||
type: integer
|
||||
shard_count:
|
||||
type: integer
|
||||
default: 4
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Test local << parameters.compiler >> shard << parameters.shard_index >>"
|
||||
command: >
|
||||
sudo -E make -C scripts/ci local << parameters.compiler >>=1
|
||||
ZDTM_SHARD_INDEX=<< parameters.shard_index >>
|
||||
ZDTM_SHARD_COUNT=<< parameters.shard_count >>
|
||||
- run:
|
||||
name: Print dmesg
|
||||
when: always
|
||||
command: sudo dmesg
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
builds:
|
||||
jobs:
|
||||
- test-local:
|
||||
matrix:
|
||||
parameters:
|
||||
compiler: ["GCC", "CLANG"]
|
||||
shard_index: [0, 1, 2, 3]
|
||||
- test-local:
|
||||
name: "GCC non-zdtm"
|
||||
compiler: "GCC"
|
||||
shard_index: 4
|
||||
- test-local:
|
||||
name: "CLANG non-zdtm"
|
||||
compiler: "CLANG"
|
||||
shard_index: 4
|
||||
565
.clang-format
565
.clang-format
|
|
@ -1,565 +0,0 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# clang-format configuration file. Intended for clang-format >= 11.
|
||||
#
|
||||
# For more information, see:
|
||||
#
|
||||
# Documentation/process/clang-format.rst
|
||||
# https://clang.llvm.org/docs/ClangFormat.html
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
#
|
||||
---
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left # Unknown to clang-format-4.0
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AlignConsecutiveMacros: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false # Unknown to clang-format-5.0
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true # Unknown to clang-format-4.0
|
||||
SplitEmptyRecord: true # Unknown to clang-format-4.0
|
||||
SplitEmptyNamespace: true # Unknown to clang-format-4.0
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 0
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false # Unknown to clang-format-4.0
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false # Unknown to clang-format-4.0
|
||||
|
||||
# Taken from:
|
||||
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
|
||||
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
||||
# | sort | uniq
|
||||
ForEachMacros:
|
||||
- 'for_each_pstree_item'
|
||||
- 'for_each_bit'
|
||||
- 'apei_estatus_for_each_section'
|
||||
- 'ata_for_each_dev'
|
||||
- 'ata_for_each_link'
|
||||
- '__ata_qc_for_each'
|
||||
- 'ata_qc_for_each'
|
||||
- 'ata_qc_for_each_raw'
|
||||
- 'ata_qc_for_each_with_internal'
|
||||
- 'ax25_for_each'
|
||||
- 'ax25_uid_for_each'
|
||||
- '__bio_for_each_bvec'
|
||||
- 'bio_for_each_bvec'
|
||||
- 'bio_for_each_bvec_all'
|
||||
- 'bio_for_each_integrity_vec'
|
||||
- '__bio_for_each_segment'
|
||||
- 'bio_for_each_segment'
|
||||
- 'bio_for_each_segment_all'
|
||||
- 'bio_list_for_each'
|
||||
- 'bip_for_each_vec'
|
||||
- 'bitmap_for_each_clear_region'
|
||||
- 'bitmap_for_each_set_region'
|
||||
- 'blkg_for_each_descendant_post'
|
||||
- 'blkg_for_each_descendant_pre'
|
||||
- 'blk_queue_for_each_rl'
|
||||
- 'bond_for_each_slave'
|
||||
- 'bond_for_each_slave_rcu'
|
||||
- 'bpf_for_each_spilled_reg'
|
||||
- 'btree_for_each_safe128'
|
||||
- 'btree_for_each_safe32'
|
||||
- 'btree_for_each_safe64'
|
||||
- 'btree_for_each_safel'
|
||||
- 'card_for_each_dev'
|
||||
- 'cgroup_taskset_for_each'
|
||||
- 'cgroup_taskset_for_each_leader'
|
||||
- 'cpufreq_for_each_entry'
|
||||
- 'cpufreq_for_each_entry_idx'
|
||||
- 'cpufreq_for_each_valid_entry'
|
||||
- 'cpufreq_for_each_valid_entry_idx'
|
||||
- 'css_for_each_child'
|
||||
- 'css_for_each_descendant_post'
|
||||
- 'css_for_each_descendant_pre'
|
||||
- 'device_for_each_child_node'
|
||||
- 'displayid_iter_for_each'
|
||||
- 'dma_fence_chain_for_each'
|
||||
- 'do_for_each_ftrace_op'
|
||||
- 'drm_atomic_crtc_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane'
|
||||
- 'drm_atomic_crtc_state_for_each_plane_state'
|
||||
- 'drm_atomic_for_each_plane_damage'
|
||||
- 'drm_client_for_each_connector_iter'
|
||||
- 'drm_client_for_each_modeset'
|
||||
- 'drm_connector_for_each_possible_encoder'
|
||||
- 'drm_for_each_bridge_in_chain'
|
||||
- 'drm_for_each_connector_iter'
|
||||
- 'drm_for_each_crtc'
|
||||
- 'drm_for_each_crtc_reverse'
|
||||
- 'drm_for_each_encoder'
|
||||
- 'drm_for_each_encoder_mask'
|
||||
- 'drm_for_each_fb'
|
||||
- 'drm_for_each_legacy_plane'
|
||||
- 'drm_for_each_plane'
|
||||
- 'drm_for_each_plane_mask'
|
||||
- 'drm_for_each_privobj'
|
||||
- 'drm_mm_for_each_hole'
|
||||
- 'drm_mm_for_each_node'
|
||||
- 'drm_mm_for_each_node_in_range'
|
||||
- 'drm_mm_for_each_node_safe'
|
||||
- 'flow_action_for_each'
|
||||
- 'for_each_acpi_dev_match'
|
||||
- 'for_each_active_dev_scope'
|
||||
- 'for_each_active_drhd_unit'
|
||||
- 'for_each_active_iommu'
|
||||
- 'for_each_aggr_pgid'
|
||||
- 'for_each_available_child_of_node'
|
||||
- 'for_each_bio'
|
||||
- 'for_each_board_func_rsrc'
|
||||
- 'for_each_bvec'
|
||||
- 'for_each_card_auxs'
|
||||
- 'for_each_card_auxs_safe'
|
||||
- 'for_each_card_components'
|
||||
- 'for_each_card_dapms'
|
||||
- 'for_each_card_pre_auxs'
|
||||
- 'for_each_card_prelinks'
|
||||
- 'for_each_card_rtds'
|
||||
- 'for_each_card_rtds_safe'
|
||||
- 'for_each_card_widgets'
|
||||
- 'for_each_card_widgets_safe'
|
||||
- 'for_each_cgroup_storage_type'
|
||||
- 'for_each_child_of_node'
|
||||
- 'for_each_clear_bit'
|
||||
- 'for_each_clear_bit_from'
|
||||
- 'for_each_cmsghdr'
|
||||
- 'for_each_compatible_node'
|
||||
- 'for_each_component_dais'
|
||||
- 'for_each_component_dais_safe'
|
||||
- 'for_each_comp_order'
|
||||
- 'for_each_console'
|
||||
- 'for_each_cpu'
|
||||
- 'for_each_cpu_and'
|
||||
- 'for_each_cpu_not'
|
||||
- 'for_each_cpu_wrap'
|
||||
- 'for_each_dapm_widgets'
|
||||
- 'for_each_dev_addr'
|
||||
- 'for_each_dev_scope'
|
||||
- 'for_each_dma_cap_mask'
|
||||
- 'for_each_dpcm_be'
|
||||
- 'for_each_dpcm_be_rollback'
|
||||
- 'for_each_dpcm_be_safe'
|
||||
- 'for_each_dpcm_fe'
|
||||
- 'for_each_drhd_unit'
|
||||
- 'for_each_dss_dev'
|
||||
- 'for_each_dtpm_table'
|
||||
- 'for_each_efi_memory_desc'
|
||||
- 'for_each_efi_memory_desc_in_map'
|
||||
- 'for_each_element'
|
||||
- 'for_each_element_extid'
|
||||
- 'for_each_element_id'
|
||||
- 'for_each_endpoint_of_node'
|
||||
- 'for_each_evictable_lru'
|
||||
- 'for_each_fib6_node_rt_rcu'
|
||||
- 'for_each_fib6_walker_rt'
|
||||
- 'for_each_free_mem_pfn_range_in_zone'
|
||||
- 'for_each_free_mem_pfn_range_in_zone_from'
|
||||
- 'for_each_free_mem_range'
|
||||
- 'for_each_free_mem_range_reverse'
|
||||
- 'for_each_func_rsrc'
|
||||
- 'for_each_hstate'
|
||||
- 'for_each_if'
|
||||
- 'for_each_iommu'
|
||||
- 'for_each_ip_tunnel_rcu'
|
||||
- 'for_each_irq_nr'
|
||||
- 'for_each_link_codecs'
|
||||
- 'for_each_link_cpus'
|
||||
- 'for_each_link_platforms'
|
||||
- 'for_each_lru'
|
||||
- 'for_each_matching_node'
|
||||
- 'for_each_matching_node_and_match'
|
||||
- 'for_each_member'
|
||||
- 'for_each_memcg_cache_index'
|
||||
- 'for_each_mem_pfn_range'
|
||||
- '__for_each_mem_range'
|
||||
- 'for_each_mem_range'
|
||||
- '__for_each_mem_range_rev'
|
||||
- 'for_each_mem_range_rev'
|
||||
- 'for_each_mem_region'
|
||||
- 'for_each_migratetype_order'
|
||||
- 'for_each_msi_entry'
|
||||
- 'for_each_msi_entry_safe'
|
||||
- 'for_each_msi_vector'
|
||||
- 'for_each_net'
|
||||
- 'for_each_net_continue_reverse'
|
||||
- 'for_each_netdev'
|
||||
- 'for_each_netdev_continue'
|
||||
- 'for_each_netdev_continue_rcu'
|
||||
- 'for_each_netdev_continue_reverse'
|
||||
- 'for_each_netdev_feature'
|
||||
- 'for_each_netdev_in_bond_rcu'
|
||||
- 'for_each_netdev_rcu'
|
||||
- 'for_each_netdev_reverse'
|
||||
- 'for_each_netdev_safe'
|
||||
- 'for_each_net_rcu'
|
||||
- 'for_each_new_connector_in_state'
|
||||
- 'for_each_new_crtc_in_state'
|
||||
- 'for_each_new_mst_mgr_in_state'
|
||||
- 'for_each_new_plane_in_state'
|
||||
- 'for_each_new_private_obj_in_state'
|
||||
- 'for_each_node'
|
||||
- 'for_each_node_by_name'
|
||||
- 'for_each_node_by_type'
|
||||
- 'for_each_node_mask'
|
||||
- 'for_each_node_state'
|
||||
- 'for_each_node_with_cpus'
|
||||
- 'for_each_node_with_property'
|
||||
- 'for_each_nonreserved_multicast_dest_pgid'
|
||||
- 'for_each_of_allnodes'
|
||||
- 'for_each_of_allnodes_from'
|
||||
- 'for_each_of_cpu_node'
|
||||
- 'for_each_of_pci_range'
|
||||
- 'for_each_old_connector_in_state'
|
||||
- 'for_each_old_crtc_in_state'
|
||||
- 'for_each_old_mst_mgr_in_state'
|
||||
- 'for_each_oldnew_connector_in_state'
|
||||
- 'for_each_oldnew_crtc_in_state'
|
||||
- 'for_each_oldnew_mst_mgr_in_state'
|
||||
- 'for_each_oldnew_plane_in_state'
|
||||
- 'for_each_oldnew_plane_in_state_reverse'
|
||||
- 'for_each_oldnew_private_obj_in_state'
|
||||
- 'for_each_old_plane_in_state'
|
||||
- 'for_each_old_private_obj_in_state'
|
||||
- 'for_each_online_cpu'
|
||||
- 'for_each_online_node'
|
||||
- 'for_each_online_pgdat'
|
||||
- 'for_each_pci_bridge'
|
||||
- 'for_each_pci_dev'
|
||||
- 'for_each_pci_msi_entry'
|
||||
- 'for_each_pcm_streams'
|
||||
- 'for_each_physmem_range'
|
||||
- 'for_each_populated_zone'
|
||||
- 'for_each_possible_cpu'
|
||||
- 'for_each_present_cpu'
|
||||
- 'for_each_prime_number'
|
||||
- 'for_each_prime_number_from'
|
||||
- 'for_each_process'
|
||||
- 'for_each_process_thread'
|
||||
- 'for_each_prop_codec_conf'
|
||||
- 'for_each_prop_dai_codec'
|
||||
- 'for_each_prop_dai_cpu'
|
||||
- 'for_each_prop_dlc_codecs'
|
||||
- 'for_each_prop_dlc_cpus'
|
||||
- 'for_each_prop_dlc_platforms'
|
||||
- 'for_each_property_of_node'
|
||||
- 'for_each_registered_fb'
|
||||
- 'for_each_requested_gpio'
|
||||
- 'for_each_requested_gpio_in_range'
|
||||
- 'for_each_reserved_mem_range'
|
||||
- 'for_each_reserved_mem_region'
|
||||
- 'for_each_rtd_codec_dais'
|
||||
- 'for_each_rtd_components'
|
||||
- 'for_each_rtd_cpu_dais'
|
||||
- 'for_each_rtd_dais'
|
||||
- 'for_each_set_bit'
|
||||
- 'for_each_set_bit_from'
|
||||
- 'for_each_set_clump8'
|
||||
- 'for_each_sg'
|
||||
- 'for_each_sg_dma_page'
|
||||
- 'for_each_sg_page'
|
||||
- 'for_each_sgtable_dma_page'
|
||||
- 'for_each_sgtable_dma_sg'
|
||||
- 'for_each_sgtable_page'
|
||||
- 'for_each_sgtable_sg'
|
||||
- 'for_each_sibling_event'
|
||||
- 'for_each_subelement'
|
||||
- 'for_each_subelement_extid'
|
||||
- 'for_each_subelement_id'
|
||||
- '__for_each_thread'
|
||||
- 'for_each_thread'
|
||||
- 'for_each_unicast_dest_pgid'
|
||||
- 'for_each_vsi'
|
||||
- 'for_each_wakeup_source'
|
||||
- 'for_each_zone'
|
||||
- 'for_each_zone_zonelist'
|
||||
- 'for_each_zone_zonelist_nodemask'
|
||||
- 'fwnode_for_each_available_child_node'
|
||||
- 'fwnode_for_each_child_node'
|
||||
- 'fwnode_graph_for_each_endpoint'
|
||||
- 'gadget_for_each_ep'
|
||||
- 'genradix_for_each'
|
||||
- 'genradix_for_each_from'
|
||||
- 'hash_for_each'
|
||||
- 'hash_for_each_possible'
|
||||
- 'hash_for_each_possible_rcu'
|
||||
- 'hash_for_each_possible_rcu_notrace'
|
||||
- 'hash_for_each_possible_safe'
|
||||
- 'hash_for_each_rcu'
|
||||
- 'hash_for_each_safe'
|
||||
- 'hctx_for_each_ctx'
|
||||
- 'hlist_bl_for_each_entry'
|
||||
- 'hlist_bl_for_each_entry_rcu'
|
||||
- 'hlist_bl_for_each_entry_safe'
|
||||
- 'hlist_for_each'
|
||||
- 'hlist_for_each_entry'
|
||||
- 'hlist_for_each_entry_continue'
|
||||
- 'hlist_for_each_entry_continue_rcu'
|
||||
- 'hlist_for_each_entry_continue_rcu_bh'
|
||||
- 'hlist_for_each_entry_from'
|
||||
- 'hlist_for_each_entry_from_rcu'
|
||||
- 'hlist_for_each_entry_rcu'
|
||||
- 'hlist_for_each_entry_rcu_bh'
|
||||
- 'hlist_for_each_entry_rcu_notrace'
|
||||
- 'hlist_for_each_entry_safe'
|
||||
- 'hlist_for_each_entry_srcu'
|
||||
- '__hlist_for_each_rcu'
|
||||
- 'hlist_for_each_safe'
|
||||
- 'hlist_nulls_for_each_entry'
|
||||
- 'hlist_nulls_for_each_entry_from'
|
||||
- 'hlist_nulls_for_each_entry_rcu'
|
||||
- 'hlist_nulls_for_each_entry_safe'
|
||||
- 'i3c_bus_for_each_i2cdev'
|
||||
- 'i3c_bus_for_each_i3cdev'
|
||||
- 'ide_host_for_each_port'
|
||||
- 'ide_port_for_each_dev'
|
||||
- 'ide_port_for_each_present_dev'
|
||||
- 'idr_for_each_entry'
|
||||
- 'idr_for_each_entry_continue'
|
||||
- 'idr_for_each_entry_continue_ul'
|
||||
- 'idr_for_each_entry_ul'
|
||||
- 'in_dev_for_each_ifa_rcu'
|
||||
- 'in_dev_for_each_ifa_rtnl'
|
||||
- 'inet_bind_bucket_for_each'
|
||||
- 'inet_lhash2_for_each_icsk_rcu'
|
||||
- 'key_for_each'
|
||||
- 'key_for_each_safe'
|
||||
- 'klp_for_each_func'
|
||||
- 'klp_for_each_func_safe'
|
||||
- 'klp_for_each_func_static'
|
||||
- 'klp_for_each_object'
|
||||
- 'klp_for_each_object_safe'
|
||||
- 'klp_for_each_object_static'
|
||||
- 'kunit_suite_for_each_test_case'
|
||||
- 'kvm_for_each_memslot'
|
||||
- 'kvm_for_each_vcpu'
|
||||
- 'list_for_each'
|
||||
- 'list_for_each_codec'
|
||||
- 'list_for_each_codec_safe'
|
||||
- 'list_for_each_continue'
|
||||
- 'list_for_each_entry'
|
||||
- 'list_for_each_entry_continue'
|
||||
- 'list_for_each_entry_continue_rcu'
|
||||
- 'list_for_each_entry_continue_reverse'
|
||||
- 'list_for_each_entry_from'
|
||||
- 'list_for_each_entry_from_rcu'
|
||||
- 'list_for_each_entry_from_reverse'
|
||||
- 'list_for_each_entry_lockless'
|
||||
- 'list_for_each_entry_rcu'
|
||||
- 'list_for_each_entry_reverse'
|
||||
- 'list_for_each_entry_safe'
|
||||
- 'list_for_each_entry_safe_continue'
|
||||
- 'list_for_each_entry_safe_from'
|
||||
- 'list_for_each_entry_safe_reverse'
|
||||
- 'list_for_each_entry_srcu'
|
||||
- 'list_for_each_prev'
|
||||
- 'list_for_each_prev_safe'
|
||||
- 'list_for_each_safe'
|
||||
- 'llist_for_each'
|
||||
- 'llist_for_each_entry'
|
||||
- 'llist_for_each_entry_safe'
|
||||
- 'llist_for_each_safe'
|
||||
- 'mci_for_each_dimm'
|
||||
- 'media_device_for_each_entity'
|
||||
- 'media_device_for_each_intf'
|
||||
- 'media_device_for_each_link'
|
||||
- 'media_device_for_each_pad'
|
||||
- 'nanddev_io_for_each_page'
|
||||
- 'netdev_for_each_lower_dev'
|
||||
- 'netdev_for_each_lower_private'
|
||||
- 'netdev_for_each_lower_private_rcu'
|
||||
- 'netdev_for_each_mc_addr'
|
||||
- 'netdev_for_each_uc_addr'
|
||||
- 'netdev_for_each_upper_dev_rcu'
|
||||
- 'netdev_hw_addr_list_for_each'
|
||||
- 'nft_rule_for_each_expr'
|
||||
- 'nla_for_each_attr'
|
||||
- 'nla_for_each_nested'
|
||||
- 'nlmsg_for_each_attr'
|
||||
- 'nlmsg_for_each_msg'
|
||||
- 'nr_neigh_for_each'
|
||||
- 'nr_neigh_for_each_safe'
|
||||
- 'nr_node_for_each'
|
||||
- 'nr_node_for_each_safe'
|
||||
- 'of_for_each_phandle'
|
||||
- 'of_property_for_each_string'
|
||||
- 'of_property_for_each_u32'
|
||||
- 'pci_bus_for_each_resource'
|
||||
- 'pcl_for_each_chunk'
|
||||
- 'pcl_for_each_segment'
|
||||
- 'pcm_for_each_format'
|
||||
- 'ping_portaddr_for_each_entry'
|
||||
- 'plist_for_each'
|
||||
- 'plist_for_each_continue'
|
||||
- 'plist_for_each_entry'
|
||||
- 'plist_for_each_entry_continue'
|
||||
- 'plist_for_each_entry_safe'
|
||||
- 'plist_for_each_safe'
|
||||
- 'pnp_for_each_card'
|
||||
- 'pnp_for_each_dev'
|
||||
- 'protocol_for_each_card'
|
||||
- 'protocol_for_each_dev'
|
||||
- 'queue_for_each_hw_ctx'
|
||||
- 'radix_tree_for_each_slot'
|
||||
- 'radix_tree_for_each_tagged'
|
||||
- 'rb_for_each'
|
||||
- 'rbtree_postorder_for_each_entry_safe'
|
||||
- 'rdma_for_each_block'
|
||||
- 'rdma_for_each_port'
|
||||
- 'rdma_umem_for_each_dma_block'
|
||||
- 'resource_list_for_each_entry'
|
||||
- 'resource_list_for_each_entry_safe'
|
||||
- 'rhl_for_each_entry_rcu'
|
||||
- 'rhl_for_each_rcu'
|
||||
- 'rht_for_each'
|
||||
- 'rht_for_each_entry'
|
||||
- 'rht_for_each_entry_from'
|
||||
- 'rht_for_each_entry_rcu'
|
||||
- 'rht_for_each_entry_rcu_from'
|
||||
- 'rht_for_each_entry_safe'
|
||||
- 'rht_for_each_from'
|
||||
- 'rht_for_each_rcu'
|
||||
- 'rht_for_each_rcu_from'
|
||||
- '__rq_for_each_bio'
|
||||
- 'rq_for_each_bvec'
|
||||
- 'rq_for_each_segment'
|
||||
- 'scsi_for_each_prot_sg'
|
||||
- 'scsi_for_each_sg'
|
||||
- 'sctp_for_each_hentry'
|
||||
- 'sctp_skb_for_each'
|
||||
- 'shdma_for_each_chan'
|
||||
- '__shost_for_each_device'
|
||||
- 'shost_for_each_device'
|
||||
- 'sk_for_each'
|
||||
- 'sk_for_each_bound'
|
||||
- 'sk_for_each_entry_offset_rcu'
|
||||
- 'sk_for_each_from'
|
||||
- 'sk_for_each_rcu'
|
||||
- 'sk_for_each_safe'
|
||||
- 'sk_nulls_for_each'
|
||||
- 'sk_nulls_for_each_from'
|
||||
- 'sk_nulls_for_each_rcu'
|
||||
- 'snd_array_for_each'
|
||||
- 'snd_pcm_group_for_each_entry'
|
||||
- 'snd_soc_dapm_widget_for_each_path'
|
||||
- 'snd_soc_dapm_widget_for_each_path_safe'
|
||||
- 'snd_soc_dapm_widget_for_each_sink_path'
|
||||
- 'snd_soc_dapm_widget_for_each_source_path'
|
||||
- 'tb_property_for_each'
|
||||
- 'tcf_exts_for_each_action'
|
||||
- 'udp_portaddr_for_each_entry'
|
||||
- 'udp_portaddr_for_each_entry_rcu'
|
||||
- 'usb_hub_for_each_child'
|
||||
- 'v4l2_device_for_each_subdev'
|
||||
- 'v4l2_m2m_for_each_dst_buf'
|
||||
- 'v4l2_m2m_for_each_dst_buf_safe'
|
||||
- 'v4l2_m2m_for_each_src_buf'
|
||||
- 'v4l2_m2m_for_each_src_buf_safe'
|
||||
- 'virtio_device_for_each_vq'
|
||||
- 'while_for_each_ftrace_op'
|
||||
- 'xa_for_each'
|
||||
- 'xa_for_each_marked'
|
||||
- 'xa_for_each_range'
|
||||
- 'xa_for_each_start'
|
||||
- 'xas_for_each'
|
||||
- 'xas_for_each_conflict'
|
||||
- 'xas_for_each_marked'
|
||||
- 'xbc_array_for_each_value'
|
||||
- 'xbc_for_each_key_value'
|
||||
- 'xbc_node_for_each_array_value'
|
||||
- 'xbc_node_for_each_child'
|
||||
- 'xbc_node_for_each_key_value'
|
||||
- 'zorro_for_each_dev'
|
||||
|
||||
IncludeBlocks: Preserve # Unknown to clang-format-5.0
|
||||
IncludeCategories:
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: None # Unknown to clang-format-5.0
|
||||
IndentWidth: 8
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
|
||||
ObjCBlockIndentWidth: 8
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
|
||||
# Taken from git's rules
|
||||
PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakString: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false # Unknown to clang-format-4.0
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
|
||||
SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
|
||||
SpaceBeforeParens: ControlStatementsExceptForEachMacros
|
||||
SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp03
|
||||
TabWidth: 8
|
||||
UseTab: Always
|
||||
...
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
[codespell]
|
||||
skip = ./.git,./test/pki,./tags,./plugins/amdgpu/amdgpu_drm.h,./plugins/amdgpu/drm.h,./plugins/amdgpu/drm_mode.h
|
||||
ignore-words-list = creat,fpr,fle,ue,bord,parms,nd,te,testng,inh,wronly,renderd,bui,clen,sems
|
||||
63
.github/ISSUE_TEMPLATE.md
vendored
63
.github/ISSUE_TEMPLATE.md
vendored
|
|
@ -1,63 +0,0 @@
|
|||
<!--
|
||||
Before reporting a new issue, please make sure that it's not a duplicate.
|
||||
|
||||
If you suspect your issue is a bug, please provide information as shown below. If your issue is a feature request, this information is not always necessary.
|
||||
-->
|
||||
|
||||
**Description**
|
||||
|
||||
<!--
|
||||
Briefly describe the problem you are having in a few paragraphs.
|
||||
-->
|
||||
|
||||
**Steps to reproduce the issue:**
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
**Describe the results you received:**
|
||||
|
||||
|
||||
**Describe the results you expected:**
|
||||
|
||||
|
||||
**Additional information you deem important (e.g. issue happens only occasionally):**
|
||||
|
||||
|
||||
**CRIU logs and information:**
|
||||
|
||||
<!--
|
||||
You can either attach logs as files to the issue or put them under details
|
||||
-->
|
||||
|
||||
<details><summary>CRIU full dump/restore logs:</summary>
|
||||
<p>
|
||||
|
||||
```
|
||||
(paste your output here)
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details><summary>Output of `criu --version`:</summary>
|
||||
<p>
|
||||
|
||||
```
|
||||
(paste your output here)
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details><summary>Output of `criu check --all`:</summary>
|
||||
<p>
|
||||
|
||||
```
|
||||
(paste your output here)
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
**Additional environment details:**
|
||||
18
.github/PULL_REQUEST_TEMPLATE.md
vendored
18
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -1,18 +0,0 @@
|
|||
<!--
|
||||
Please make sure you've read and understood our contributing guidelines:
|
||||
https://github.com/checkpoint-restore/criu/blob/criu-dev/CONTRIBUTING.md
|
||||
|
||||
In short you need to:
|
||||
|
||||
- Describe What you do and How you do it;
|
||||
- Separate each logical change into a separate commit;
|
||||
- Add a "Signed-off-by:" line identifying that you certify your work with DCO;
|
||||
- If you fix some specific bug or commit, please add "Fixes: ..." line;
|
||||
- Review fixes should be made by amending the original commits. For example:
|
||||
a) fix the code (e.g. this fixes commit with hash aaa1111)
|
||||
b) git commit -a --fixup aaa1111
|
||||
c) git rebase --interactive --autosquash aaa1111^
|
||||
- Pull request integration tests should generally be passing;
|
||||
- If you change something non-obvious, please consider adding a ZDTM test for it;
|
||||
|
||||
-->
|
||||
35
.github/actions/lima-vm-setup/action.yml
vendored
35
.github/actions/lima-vm-setup/action.yml
vendored
|
|
@ -1,35 +0,0 @@
|
|||
name: 'Lima VM Setup'
|
||||
description: 'Install Lima, enable KVM, start a VM and copy the CRIU source into it'
|
||||
|
||||
inputs:
|
||||
template:
|
||||
description: 'Lima VM template name (e.g. fedora, centos-stream-9)'
|
||||
required: true
|
||||
cache-key-prefix:
|
||||
description: 'Prefix for the Lima image cache key'
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install Lima
|
||||
uses: lima-vm/lima-actions/setup@55627e31b78637bf254a8b2a14da8ea7d12564e5 # v1
|
||||
- name: Cache Lima images
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: ~/.cache/lima
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ github.sha }}
|
||||
restore-keys: ${{ inputs.cache-key-prefix }}-
|
||||
- name: Start VM
|
||||
shell: bash
|
||||
# Enable VNC display so QEMU attaches a VGA device instead of
|
||||
# passing -vga none. Without it the kernel only registers a CGA
|
||||
# text console and VT ioctls (TIOCSLCKTRMIOS, TIOCSWINSZ) fail,
|
||||
# which breaks the zdtm/static/vt test on restore.
|
||||
run: limactl start --plain --name=default --cpus=4 --memory=12 --set '.video.display = "vnc"' template://${{ inputs.template }}
|
||||
- name: Copy source into VM
|
||||
shell: bash
|
||||
run: |
|
||||
lima sudo mkdir -p /home/criu
|
||||
lima sudo chown "$(lima whoami)" /home/criu
|
||||
limactl copy -r . default:/home/criu
|
||||
95
.github/copilot-instructions.md
vendored
95
.github/copilot-instructions.md
vendored
|
|
@ -1,95 +0,0 @@
|
|||
# GitHub Copilot Instructions for CRIU
|
||||
|
||||
CRIU (Checkpoint/Restore In User-space) is a specialized tool for checkpointing
|
||||
and restoring running processes on Linux.
|
||||
|
||||
## Coding Style & Conventions
|
||||
All C code MUST follow the [Linux Kernel Coding Style](https://www.kernel.org/doc/html/latest/process/coding-style.html).
|
||||
|
||||
- **Indentation**: Use hard tabs. Set tab width to 8 characters.
|
||||
- **Line Length**: Preferred limit is 80 characters. Max 120 if it
|
||||
significantly improves readability.
|
||||
- **Braces**:
|
||||
- Functions: Opening brace on a new line.
|
||||
- Blocks (`if`, `for`, `while`, `switch`): Opening brace on the same line as
|
||||
the statement.
|
||||
- **Spaces**: Use spaces around operators (`+`, `-`, `*`, `/`, `%`, `<`, `>`,
|
||||
`=`, etc.).
|
||||
- **Naming**: Use descriptive, snake_case names for functions and variables.
|
||||
- **Comments**: Use C-style comments (`/* ... */`).
|
||||
- Multi-line format:
|
||||
```c
|
||||
/*
|
||||
* This is a multi-line
|
||||
* comment.
|
||||
*/
|
||||
```
|
||||
|
||||
## Architecture Overview
|
||||
- **criu/**: Contains the main logic for checkpoint and restore.
|
||||
- **compel/**: Sub-project for "parasite" code injection and PIE blob
|
||||
generation.
|
||||
- **images/**: Protobuf descriptions for image files. Use these to understand
|
||||
the state being saved.
|
||||
- **restorer**: PIE code that handles the final stages of process restoration.
|
||||
See `criu/include/restorer.h` for `CR_STATE_*` definitions.
|
||||
- **crit**: Tooling for inspecting CRIU image files.
|
||||
- **soccr**: Library for TCP socket checkpoint/restore.
|
||||
- **pie/ directories**: Code in these directories (e.g., `criu/pie/`) should be
|
||||
self-contained Position-Independent Executable (PIE) code. It MUST NOT
|
||||
depend on any external libraries and can only depend on things implemented by
|
||||
Compel.
|
||||
|
||||
### CRIU Commands
|
||||
- **dump**: Saves a process tree and all its related resources into a
|
||||
collection of image files.
|
||||
- **restore**: Restores processes from image files to the same state they were
|
||||
in before the dump.
|
||||
- **check**: Checks whether the kernel supports the features needed by CRIU to
|
||||
dump and restore a process tree.
|
||||
- **pre-dump**: Performs the pre-dump procedure, creating a snapshot of memory
|
||||
changes since the previous dump/pre-dump (incremental checkpointing).
|
||||
- **service**: Launches CRIU in RPC daemon mode, listening for commands over a
|
||||
socket.
|
||||
- **dedup**: Starts pagemap data deduplication, minimizing image size by
|
||||
obtaining references from parent images.
|
||||
- **page-server**: Launches CRIU in page server mode to send memory pages over
|
||||
the network during migration.
|
||||
|
||||
## Development & Testing
|
||||
- **ZDTM (Zero-Downtime Migration)**: The primary test suite located in
|
||||
`test/zdtm`.
|
||||
- **Test Scope**: Each test case targets a specific kernel primitive type
|
||||
(e.g., file descriptors, sockets, timers).
|
||||
- **Test Purpose**: Verifies that the targeted kernel primitive is
|
||||
Checkpointed/Restored (C/R-ed) correctly.
|
||||
- **Test Executor**: `test/zdtm.py`.
|
||||
- **Running a test**: `sudo ./test/zdtm.py run -t zdtm/static/env00`.
|
||||
- **Test Structure**: Tests typically use `test_daemon()` to signal readiness
|
||||
and `test_waitsig()` to wait for the C/R cycle to complete. After being
|
||||
restored, the test checks that all its resources are still in a valid state.
|
||||
|
||||
## Commit Message Guidelines
|
||||
Follow these principles when forming commits:
|
||||
|
||||
- **Separate each logical change into a separate patch**: Each commit must
|
||||
represent a single logical change. Separate bug fixes from performance
|
||||
improvements or API updates.
|
||||
- **The commit subject has to start with the sub-system prefix**: Prefix the
|
||||
subject with the affected component (e.g., `criu:`, `compel:`, `images:`,
|
||||
`test:`, or specific file names like `criu-ns:`).
|
||||
- **Imperative Mood**: Use the imperative mood in the subject (e.g., "make
|
||||
xyzzy do frotz" instead of "changed xyzzy").
|
||||
- **Detailed Body**: Explain the problem being solved (the "why") and the
|
||||
technical details of the implementation (the "how").
|
||||
- **Hard Wrap**: The commit message has to be hard wrapped at 72 characters.
|
||||
- **Signed-off-by**: Every commit MUST be signed off (`git commit -s`). This
|
||||
certifies the Developer's Certificate of Origin (DCO).
|
||||
- **Fixes Tag**:
|
||||
- For bugs: `Fixes: <12-char-commit-id> ("summary")`. The `<commit-id>` has
|
||||
to be the first 12 characters of the commit SHA-1 ID.
|
||||
- For GitHub issues: `Fixes: #<issue-number>`
|
||||
- **Atomicity**: Ensure CRIU builds and tests pass after *every* commit in a
|
||||
series to maintain bisectability.
|
||||
- **No Fixups**: Squash "fixup!" or "work in progress" commits before final
|
||||
submission.
|
||||
35
.github/workflows/check-commits.yml
vendored
35
.github/workflows/check-commits.yml
vendored
|
|
@ -1,35 +0,0 @@
|
|||
name: Verify self-contained commits
|
||||
|
||||
on: pull_request
|
||||
|
||||
# Cancel any preceding run on the pull request
|
||||
concurrency:
|
||||
group: commit-test-${{ github.event.pull_request.number }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
# Check if pull request does not have label "not-selfcontained-ok"
|
||||
if: "!contains(github.event.pull_request.labels.*.name, 'not-selfcontained-ok')"
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
# Needed to rebase against the base branch
|
||||
fetch-depth: 0
|
||||
# Checkout pull request HEAD commit instead of merge commit
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install dependencies
|
||||
run: sudo contrib/apt-install libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler protobuf-compiler python3-protobuf libnl-3-dev libnet-dev libcap-dev uuid-dev liblz4-dev
|
||||
- name: Configure git user details
|
||||
run: |
|
||||
git config --global user.email "checkpoint-restore@users.noreply.github.com"
|
||||
git config --global user.name "checkpoint-restore"
|
||||
- name: Configure base branch without switching current branch
|
||||
run: git fetch origin ${{ github.base_ref }}:${{ github.base_ref }}
|
||||
- name: Build each commit
|
||||
run: git rebase ${{ github.base_ref }} -x "make -C scripts/ci check-commit"
|
||||
- name: Build without LZ4
|
||||
run: |
|
||||
make mrproper
|
||||
make -j "$(nproc)" NO_LZ4=1
|
||||
make unittest NO_LZ4=1
|
||||
367
.github/workflows/ci.yml
vendored
367
.github/workflows/ci.yml
vendored
|
|
@ -1,367 +0,0 @@
|
|||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
# Cancel any preceding run on the pull request.
|
||||
concurrency:
|
||||
group: ci-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/criu-dev' }}
|
||||
|
||||
jobs:
|
||||
alpine-test:
|
||||
name: Alpine Test (${{ matrix.target }}, ${{ matrix.shard_name }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04]
|
||||
target: [GCC=1, CLANG=1]
|
||||
shard: [0, 1, 2, 3, 4]
|
||||
include:
|
||||
- shard: 0
|
||||
shard_name: zdtm 1/4
|
||||
- shard: 1
|
||||
shard_name: zdtm 2/4
|
||||
- shard: 2
|
||||
shard_name: zdtm 3/4
|
||||
- shard: 3
|
||||
shard_name: zdtm 4/4
|
||||
- shard: 4
|
||||
shard_name: non-zdtm
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Alpine ${{ matrix.target }} ${{ matrix.shard_name }} Test
|
||||
run: >
|
||||
sudo -E make -C scripts/ci alpine ${{ matrix.target }}
|
||||
ZDTM_SHARD_INDEX=${{ matrix.shard }}
|
||||
ZDTM_SHARD_COUNT=4
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
alpine-test-arm64:
|
||||
name: Alpine Test ARM64
|
||||
needs: [alpine-test]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04-arm]
|
||||
target: [GCC=1, CLANG=1]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Alpine ${{ matrix.target }} Test
|
||||
run: sudo -E make -C scripts/ci alpine ${{ matrix.target }}
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
aarch64-test:
|
||||
needs: [alpine-test]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-26.04-arm, ubuntu-22.04-arm]
|
||||
target: [GCC=1, CLANG=1]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Tests ${{ matrix.target }} on ${{ matrix.os }}
|
||||
run: |
|
||||
# The 'sched_policy00' needs the following:
|
||||
sudo sysctl -w kernel.sched_rt_runtime_us=-1
|
||||
# etc/hosts entry is needed for netns_lock_iptables
|
||||
echo "127.0.0.1 localhost" | sudo tee -a /etc/hosts
|
||||
sudo -E make -C scripts/ci local ${{ matrix.target }} RUN_TESTS=1 \
|
||||
ZDTM_OPTS="-x zdtm/static/change_mnt_context -x zdtm/static/maps05"
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
archlinux-test:
|
||||
name: Arch Linux Test (${{ matrix.shard_name }})
|
||||
needs: [alpine-test]
|
||||
# archlinux:latest + pacman -Syu is a rolling-release build; failures
|
||||
# caused by upstream package churn are outside CRIU's control.
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shard: [0, 1, 2, 3, 4]
|
||||
include:
|
||||
- shard: 0
|
||||
shard_name: zdtm 1/4
|
||||
- shard: 1
|
||||
shard_name: zdtm 2/4
|
||||
- shard: 2
|
||||
shard_name: zdtm 3/4
|
||||
- shard: 3
|
||||
shard_name: zdtm 4/4
|
||||
- shard: 4
|
||||
shard_name: non-zdtm
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Arch Linux ${{ matrix.shard_name }} Test
|
||||
run: >
|
||||
sudo -E make -C scripts/ci archlinux
|
||||
ZDTM_SHARD_INDEX=${{ matrix.shard }}
|
||||
ZDTM_SHARD_COUNT=4
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
centos-stream-test:
|
||||
name: CentOS Stream ${{ matrix.version }}
|
||||
# aarch64 is not supported by lima-vm/lima-actions
|
||||
# https://github.com/lima-vm/lima-actions/pull/1
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: [9, 10]
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: ./.github/actions/lima-vm-setup
|
||||
with:
|
||||
template: centos-stream-${{ matrix.version }}
|
||||
cache-key-prefix: lima-centos-stream-${{ matrix.version }}
|
||||
- name: Setup VM
|
||||
run: lima sudo /home/criu/scripts/ci/lima.sh centos-stream-setup
|
||||
- name: Show VM info
|
||||
run: |
|
||||
lima uname -a
|
||||
lima cat /proc/cmdline
|
||||
- name: Run tests
|
||||
run: ssh -tt lima-default sudo -i /home/criu/scripts/ci/lima.sh centos-stream-test
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: lima sudo dmesg
|
||||
|
||||
compat-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: [GCC, CLANG]
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Compat Tests (${{ matrix.target }})
|
||||
run: sudo -E make -C scripts/ci local COMPAT_TEST=y ${{ matrix.target }}=1
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
cross-compile:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
experimental: [false]
|
||||
target: [
|
||||
armv7-stable-cross,
|
||||
aarch64-stable-cross,
|
||||
ppc64-stable-cross,
|
||||
riscv64-stable-cross,
|
||||
]
|
||||
include:
|
||||
- experimental: true
|
||||
target: armv7-unstable-cross
|
||||
- experimental: true
|
||||
target: aarch64-unstable-cross
|
||||
- experimental: true
|
||||
target: ppc64-unstable-cross
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Cross Compilation Targets
|
||||
run: >
|
||||
sudo make -C scripts/ci ${{ matrix.target }}
|
||||
BUILD_OPTIONS="--build-arg CI_CROSS_COMPILE=1"
|
||||
|
||||
docker-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04]
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Docker Test (${{ matrix.os }})
|
||||
run: sudo make -C scripts/ci docker-test
|
||||
|
||||
fedora-asan-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Fedora ASAN Test
|
||||
run: sudo -E make -C scripts/ci fedora-asan
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
fedora-rawhide-test:
|
||||
name: ${{ matrix.name }}
|
||||
needs: [alpine-test]
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
name: x86_64 Fedora Rawhide
|
||||
- os: ubuntu-24.04-arm
|
||||
name: aarch64 Fedora Rawhide
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Fedora Rawhide Test
|
||||
# We need to pass environment variables from the CI environment to
|
||||
# distinguish between CI environments. However, we need to make sure that
|
||||
# XDG_RUNTIME_DIR environment variable is not set due to a bug in Podman.
|
||||
# FIXME: https://github.com/containers/podman/issues/14920
|
||||
run: sudo -E XDG_RUNTIME_DIR= make -C scripts/ci fedora-rawhide CONTAINER_RUNTIME=podman BUILD_OPTIONS="--security-opt seccomp=unconfined"
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
vm-fedora-rawhide-test:
|
||||
name: VM Fedora ${{ matrix.name }} based test
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- variant: fedora-stable
|
||||
name: Stable
|
||||
reboot: true
|
||||
- variant: fedora-next
|
||||
name: Next
|
||||
reboot: true
|
||||
- variant: fedora-no-vdso
|
||||
name: No VDSO
|
||||
reboot: true
|
||||
- variant: fedora-non-root
|
||||
name: Non-Root
|
||||
reboot: false
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: ./.github/actions/lima-vm-setup
|
||||
with:
|
||||
template: fedora
|
||||
cache-key-prefix: lima-fedora
|
||||
- name: Setup VM
|
||||
run: lima sudo /home/criu/scripts/ci/lima.sh ${{ matrix.variant }}-setup
|
||||
- name: Reboot VM to activate new kernel
|
||||
if: matrix.reboot
|
||||
run: |
|
||||
limactl stop default
|
||||
limactl start default
|
||||
- name: Show VM info
|
||||
run: |
|
||||
lima uname -a
|
||||
lima cat /proc/cmdline
|
||||
- name: Run tests
|
||||
run: ssh -tt lima-default sudo -i /home/criu/scripts/ci/lima.sh ${{ matrix.variant }}-test
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: lima sudo dmesg
|
||||
|
||||
gcov-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Coverage Tests
|
||||
run: sudo -E make -C scripts/ci local GCOV=1
|
||||
- name: Run gcov
|
||||
run: sudo -E find . -name '*gcda' -type f -print0 | sudo -E xargs --null --max-args 128 gcov
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
java-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Java Test
|
||||
run: sudo make -C scripts/ci java-test
|
||||
|
||||
loongarch64-qemu-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- run: sudo make -C scripts/ci loongarch64-qemu-test
|
||||
|
||||
nftables-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-26.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Remove iptables
|
||||
run: sudo apt remove -y iptables
|
||||
- name: Install libnftables-dev
|
||||
run: sudo contrib/apt-install libnftables-dev
|
||||
- name: chmod 755 /home/runner
|
||||
# CRIU's tests are sometimes running as some random user and need
|
||||
# to be able to access the test files.
|
||||
run: sudo chmod 755 /home/runner
|
||||
- name: Build with nftables network locking backend
|
||||
run: sudo make -C scripts/ci local COMPILE_FLAGS="NETWORK_LOCK_DEFAULT=NETWORK_LOCK_NFTABLES"
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
podman-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run Podman Test
|
||||
run: sudo make -C scripts/ci podman-test
|
||||
|
||||
stream-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run CRIU Image Streamer Test
|
||||
run: sudo -E make -C scripts/ci local STREAM_TEST=1
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
x86-64-clang-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run X86_64 CLANG Test
|
||||
run: sudo make -C scripts/ci x86_64 CLANG=1
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
|
||||
x86-64-gcc-test:
|
||||
needs: [alpine-test]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Run X86_64 GCC Test
|
||||
run: sudo make -C scripts/ci x86_64
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: sudo dmesg
|
||||
50
.github/workflows/codeql.yml
vendored
50
.github/workflows/codeql.yml
vendored
|
|
@ -1,50 +0,0 @@
|
|||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "criu-dev", "master" ]
|
||||
pull_request:
|
||||
branches: [ "criu-dev" ]
|
||||
schedule:
|
||||
- cron: "11 6 * * 3"
|
||||
|
||||
# Cancel any preceding run on the pull request.
|
||||
concurrency:
|
||||
group: codeql-test-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/criu-dev' }}
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ python, cpp ]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Install Packages (cpp)
|
||||
if: ${{ matrix.language == 'cpp' }}
|
||||
run: |
|
||||
sudo contrib/apt-install protobuf-c-compiler libprotobuf-c-dev libprotobuf-dev build-essential libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler protobuf-compiler python3-protobuf libnet-dev pkg-config libnl-3-dev libbsd0 libbsd-dev iproute2 libcap-dev libaio-dev libbsd-dev python3-yaml libnl-route-3-dev gnutls-dev
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v4
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
22
.github/workflows/cross-compile-daily.yml
vendored
22
.github/workflows/cross-compile-daily.yml
vendored
|
|
@ -1,22 +0,0 @@
|
|||
name: Daily Cross Compile Tests
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 12 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
target: [armv7-stable-cross, aarch64-stable-cross, ppc64-stable-cross, mips64el-stable-cross, riscv64-stable-cross]
|
||||
branches: [criu-dev, master]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ matrix.branches }}
|
||||
- name: Run Cross Compilation Targets
|
||||
run: >
|
||||
sudo make -C scripts/ci ${{ matrix.target }}
|
||||
40
.github/workflows/lint.yml
vendored
40
.github/workflows/lint.yml
vendored
|
|
@ -1,40 +0,0 @@
|
|||
name: Run code linter
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
# Cancel any preceding run on the pull request.
|
||||
concurrency:
|
||||
group: lint-test-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/criu-dev' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: registry.fedoraproject.org/fedora:latest
|
||||
steps:
|
||||
- name: Install tools
|
||||
run: sudo dnf -y install git make ruff xz clang-tools-extra codespell git-clang-format ShellCheck
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Set git safe directory
|
||||
# https://github.com/actions/checkout/issues/760
|
||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
|
||||
- name: Run make lint
|
||||
run: make lint
|
||||
|
||||
- name: Run make indent
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if [ -z "${{github.base_ref}}" ]; then
|
||||
git fetch --deepen=1
|
||||
make indent
|
||||
else
|
||||
git fetch origin ${{github.base_ref}}
|
||||
make indent BASE=origin/${{github.base_ref}}
|
||||
fi
|
||||
- name: Raise in-line make indent warnings
|
||||
run: |
|
||||
git diff | ./scripts/github-indent-warnings.py
|
||||
402
.github/workflows/linux-next.yml
vendored
402
.github/workflows/linux-next.yml
vendored
|
|
@ -1,402 +0,0 @@
|
|||
name: linux-next-tests
|
||||
on:
|
||||
schedule:
|
||||
- cron: "20 8 * * 0"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
#
|
||||
# This workflow is to test CRIU on linux-next tree.
|
||||
# It involves external GitHub Actions runners (EC2 instances on AWS).
|
||||
# To run it requires necessary setup on AWS side (auth via GitHub OIDC to
|
||||
# manage EC2 instances and S3 bucket), and GH_RUNNERS_PAT_TOKEN
|
||||
# (GitHub Personal Access Token to manage GitHub Actions Runners for a repo).
|
||||
#
|
||||
# Logic is simple:
|
||||
# 1. Build linux kernel on GitHub-hosted runner and upload .deb-packages
|
||||
# to S3 bucket
|
||||
# 2. Create EC2 instance and register it as GH self-hosted runner
|
||||
# (we use machulav/ec2-github-runner for this)
|
||||
# 3. Schedule a job on newly created runner, install a new kernel
|
||||
# 4. Reboot EC2 instance
|
||||
# 5. Schedule CRIU test job on EC2 runner
|
||||
# 6. Destroy EC2 instance and unregister it from GitHub.
|
||||
#
|
||||
# I use explicit commit hashes for actions steps which are not GitHub-provided
|
||||
# (for example machulav/ec2-github-runner@343a1b2ae682e681c3cec9a235d882da17ff04ef).
|
||||
# This is to be on a safe side and ensure that any update is done manually.
|
||||
#
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
kernel-build:
|
||||
env:
|
||||
BUILDDIR: "/home/runner/kernel-build/tmp"
|
||||
name: Kernel build
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
date: ${{ steps.get-date.outputs.date }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Prepare directory for build
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
echo $BUILDDIR
|
||||
mkdir -p $BUILDDIR
|
||||
# Not enough RAM for kernel builds anymore
|
||||
# sudo mount -t tmpfs tmpfs $BUILDDIR
|
||||
|
||||
- name: Get Date
|
||||
id: get-date
|
||||
run: |
|
||||
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore linux-next build artifacts from cache
|
||||
id: build-artifacts-restore
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ env.BUILDDIR }}/artifacts
|
||||
key: linux-next-build-${{ steps.get-date.outputs.date }}
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.build-artifacts-restore.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
sudo apt-get update
|
||||
|
||||
sudo apt-get install --no-install-recommends -y \
|
||||
curl \
|
||||
git \
|
||||
build-essential \
|
||||
libssl-dev \
|
||||
libelf-dev \
|
||||
libdw-dev \
|
||||
bc \
|
||||
bison \
|
||||
cpio \
|
||||
flex \
|
||||
debhelper-compat
|
||||
|
||||
# We don't want to put too much stress to git.kernel.org so we
|
||||
# use a cache (valid for 1 day) for git clone copy of the repo.
|
||||
- name: Restore linux-next git cache
|
||||
if: steps.build-artifacts-restore.outputs.cache-hit != 'true'
|
||||
id: linux-next-git-restore
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ env.BUILDDIR }}/linux
|
||||
key: linux-next-git-cache-${{ steps.get-date.outputs.date }}
|
||||
|
||||
- name: Checkout Linux kernel
|
||||
if: ${{ steps.build-artifacts-restore.outputs.cache-hit != 'true' &&
|
||||
steps.linux-next-git-restore.outputs.cache-hit != 'true' }}
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
cd "$BUILDDIR"
|
||||
|
||||
git clone --depth=1 --branch master --single-branch \
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git linux
|
||||
|
||||
# Record exactly which linux-next state we built, so a CI failure
|
||||
# can be correlated with a specific tree (and its daily next-* tag).
|
||||
git -C linux --no-pager log -1 --format='linux-next HEAD: %H %cs %s'
|
||||
|
||||
- name: Save linux-next git cache
|
||||
if: ${{ steps.build-artifacts-restore.outputs.cache-hit != 'true' &&
|
||||
steps.linux-next-git-restore.outputs.cache-hit != 'true' }}
|
||||
uses: actions/cache/save@v5
|
||||
with:
|
||||
path: |
|
||||
${{ env.BUILDDIR }}/linux
|
||||
key: linux-next-git-cache-${{ steps.get-date.outputs.date }}
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # 6.2.1
|
||||
with:
|
||||
role-to-assume: ${{ vars.AWS_IAM_ROLE }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
|
||||
- name: Build Linux kernel
|
||||
if: steps.build-artifacts-restore.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
cd "$BUILDDIR/linux"
|
||||
|
||||
# kernel config was generated with make localmodconfig on EC2 instance
|
||||
# after full CRIU tests run (to trigger all modules load)
|
||||
aws s3 cp \
|
||||
s3://criu-linux-next-ci-634567146514-eu-central-1-an/t3.xlarge-kernel-config \
|
||||
.config
|
||||
|
||||
scripts/config --disable SYSTEM_TRUSTED_KEYS
|
||||
scripts/config --disable SYSTEM_REVOCATION_KEYS
|
||||
|
||||
make olddefconfig
|
||||
|
||||
time make -j$(nproc) bindeb-pkg LOCALVERSION="-criu-ci"
|
||||
|
||||
ls -la .
|
||||
ls -la ..
|
||||
|
||||
cd "$BUILDDIR"
|
||||
mkdir artifacts/
|
||||
mv linux-*.deb artifacts/
|
||||
|
||||
echo "artifactPath=${BUILDDIR}/artifacts" >> $GITHUB_ENV
|
||||
|
||||
- name: Save linux-next build results cache
|
||||
if: steps.build-artifacts-restore.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v5
|
||||
with:
|
||||
path: ${{ env.artifactPath }}
|
||||
key: linux-next-build-${{ steps.get-date.outputs.date }}
|
||||
|
||||
- name: Upload kernel packages to S3
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
cd "$BUILDDIR"
|
||||
|
||||
BUILD_DATE="${{ steps.get-date.outputs.date }}"
|
||||
|
||||
aws s3 cp \
|
||||
artifacts \
|
||||
s3://criu-linux-next-ci-634567146514-eu-central-1-an/artifacts/$BUILD_DATE/ \
|
||||
--recursive
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: linux-kernel-build
|
||||
path: ${{ env.BUILDDIR }}/artifacts/linux-*.deb
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
|
||||
start-runner:
|
||||
name: Start self-hosted EC2 runner
|
||||
needs:
|
||||
- kernel-build
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
label: ${{ steps.start-ec2-runner.outputs.label }}
|
||||
ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }}
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # 6.2.1
|
||||
with:
|
||||
role-to-assume: ${{ vars.AWS_IAM_ROLE }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
|
||||
- name: Start EC2 runner
|
||||
id: start-ec2-runner
|
||||
uses: machulav/ec2-github-runner@343a1b2ae682e681c3cec9a235d882da17ff04ef # 2.6.1
|
||||
with:
|
||||
mode: start
|
||||
startup-timeout-minutes: 10
|
||||
github-token: ${{ secrets.GH_RUNNERS_PAT_TOKEN }}
|
||||
ec2-image-id: ami-0596cf3199908321b # Ubuntu 24.04 LTS image id on AWS
|
||||
ec2-instance-type: t3.xlarge
|
||||
subnet-id: subnet-0ddb356c3fc41e51a
|
||||
security-group-id: sg-054aa948984162822
|
||||
packages: '["git", "docker.io"]'
|
||||
runner-debug: true
|
||||
|
||||
# we need this so GitHub runner software survives EC2 reboot
|
||||
run-runner-as-service: true
|
||||
|
||||
# we need this to make EC2 runner capable of accessing S3 bucket with kernel builds
|
||||
iam-role-name: ec2-linux-next-vm
|
||||
|
||||
aws-resource-tags: > # attach tags to distinguish GH Actions instances on AWS
|
||||
[
|
||||
{"Key": "Name", "Value": "ec2-github-runner"},
|
||||
{"Key": "GitHubRepository", "Value": "${{ github.repository }}"},
|
||||
{"Key": "GitHubRunId", "Value": "${{ github.run_id }}"}
|
||||
]
|
||||
|
||||
install-kernel:
|
||||
name: Install kernel on the EC2 runner
|
||||
needs:
|
||||
- kernel-build
|
||||
- start-runner # required to start the main job when the runner is ready
|
||||
runs-on: ${{ needs.start-runner.outputs.label }} # run the job on the newly created runner
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Install unzip
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
sudo apt-get update
|
||||
|
||||
sudo apt-get install --no-install-recommends -y \
|
||||
unzip
|
||||
|
||||
- name: Install AWS CLI
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
|
||||
unzip awscliv2.zip
|
||||
sudo ./aws/install --update
|
||||
|
||||
- name: Install linux-next kernel
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
BUILD_DATE="${{ needs.kernel-build.outputs.date }}"
|
||||
|
||||
aws s3 cp \
|
||||
s3://criu-linux-next-ci-634567146514-eu-central-1-an/artifacts/$BUILD_DATE/ \
|
||||
artifacts \
|
||||
--recursive
|
||||
|
||||
ls -la artifacts
|
||||
|
||||
sudo dpkg -i artifacts/linux-image-*-criu-ci_*_amd64.deb
|
||||
|
||||
reboot-runner:
|
||||
name: Reboot EC2 runner instance
|
||||
needs:
|
||||
- start-runner
|
||||
- install-kernel # required to start the main job when the runner is ready
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # 6.2.1
|
||||
with:
|
||||
role-to-assume: ${{ vars.AWS_IAM_ROLE }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
|
||||
- name: Reboot runner
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
INSTANCE_ID="${{ needs.start-runner.outputs.ec2-instance-id }}"
|
||||
aws ec2 reboot-instances --instance-ids "$INSTANCE_ID"
|
||||
aws ec2 wait instance-status-ok --instance-ids "$INSTANCE_ID"
|
||||
|
||||
do-the-job:
|
||||
name: Do the job on the runner
|
||||
needs:
|
||||
- start-runner
|
||||
- reboot-runner # required to start the main job when the runner is ready
|
||||
runs-on: ${{ needs.start-runner.outputs.label }} # run the job on the newly created runner
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Validate kernel
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
# ensure that we are running linux-next kernel
|
||||
uname -a | grep next | grep "criu-ci"
|
||||
|
||||
- name: Install make
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
sudo apt-get install --no-install-recommends -y \
|
||||
make
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Run CRIU tests
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
#
|
||||
# We have to set oom_score_adj to the minimal possible value,
|
||||
# otherwise zdtm/static/oom_score_adj test will fail with EACCES
|
||||
# check (see __set_oom_adj() [1] in the kernel).
|
||||
#
|
||||
# This is not a problem on a normal GitHub runners, but is a problem
|
||||
# on a self-hosted ones cause we run GitHub stuff via systemd service
|
||||
# and systemd sets oom_score_adj on a parent process to 500, while
|
||||
# in the test we want to set 400.
|
||||
#
|
||||
# [1] https://github.com/torvalds/linux/blob/27fa82620cbaa89a7fc11ac3057701d598813e87/fs/proc/base.c#L1151
|
||||
echo "-1000" > /proc/self/oom_score_adj
|
||||
|
||||
echo 131072 > /sys/kernel/debug/tracing/buffer_size_kb
|
||||
echo 1 > /sys/kernel/tracing/events/x86_fpu/x86_fpu_xstate_check_failed/enable
|
||||
echo 1 > /sys/kernel/tracing/tracing_on
|
||||
|
||||
sudo make -C scripts/ci local
|
||||
|
||||
- name: Print trace buffer
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
cat /sys/kernel/tracing/trace
|
||||
|
||||
! grep x86_fpu_xstate_check_failed /sys/kernel/tracing/trace
|
||||
|
||||
- name: Get tainted state
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
cat /proc/sys/kernel/tainted
|
||||
|
||||
- name: Print dmesg
|
||||
if: always()
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
dmesg
|
||||
|
||||
get-serial-console:
|
||||
name: Get EC2 serial console output
|
||||
needs:
|
||||
- start-runner
|
||||
- do-the-job # required to wait when the main job is done
|
||||
if: ${{ always() }} # required to get logs even if the error happened in the previous jobs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # 6.2.1
|
||||
with:
|
||||
role-to-assume: ${{ vars.AWS_IAM_ROLE }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
|
||||
- name: Get serial console output
|
||||
run: |
|
||||
set -eux
|
||||
|
||||
INSTANCE_ID="${{ needs.start-runner.outputs.ec2-instance-id }}"
|
||||
aws ec2 get-console-output \
|
||||
--instance-id "$INSTANCE_ID" \
|
||||
--latest \
|
||||
--output text
|
||||
|
||||
stop-runner:
|
||||
name: Stop self-hosted EC2 runner
|
||||
needs:
|
||||
- start-runner # required to get output from the start-runner job
|
||||
- get-serial-console
|
||||
if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # 6.2.1
|
||||
with:
|
||||
role-to-assume: ${{ vars.AWS_IAM_ROLE }}
|
||||
aws-region: ${{ vars.AWS_REGION }}
|
||||
- name: Stop EC2 runner
|
||||
uses: machulav/ec2-github-runner@343a1b2ae682e681c3cec9a235d882da17ff04ef # 2.6.1
|
||||
with:
|
||||
mode: stop
|
||||
github-token: ${{ secrets.GH_RUNNERS_PAT_TOKEN }}
|
||||
label: ${{ needs.start-runner.outputs.label }}
|
||||
ec2-instance-id: ${{ needs.start-runner.outputs.ec2-instance-id }}
|
||||
14
.github/workflows/manage-labels.yml
vendored
14
.github/workflows/manage-labels.yml
vendored
|
|
@ -1,14 +0,0 @@
|
|||
name: Remove labels
|
||||
on: [issue_comment, pull_request_review_comment]
|
||||
jobs:
|
||||
remove-labels-on-comments:
|
||||
name: Remove labels on comments
|
||||
if: github.event_name == 'issue_comment'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: mondeja/remove-labels-gh-action@b7118e4ba5dca74acf1059b3cb7660378ff9ab1a # v2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: |
|
||||
changes requested
|
||||
awaiting reply
|
||||
27
.github/workflows/stale.yml
vendored
27
.github/workflows/stale.yml
vendored
|
|
@ -1,27 +0,0 @@
|
|||
name: Mark stale issues and pull requests
|
||||
|
||||
# Please refer to https://github.com/actions/stale/blob/master/action.yml
|
||||
# to see all config knobs of the stale action.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v10
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'A friendly reminder that this issue had no activity for 30 days.'
|
||||
stale-pr-message: 'A friendly reminder that this PR had no activity for 30 days.'
|
||||
stale-issue-label: 'stale-issue'
|
||||
stale-pr-label: 'stale-pr'
|
||||
days-before-stale: 30
|
||||
days-before-close: 365
|
||||
remove-stale-when-updated: true
|
||||
exempt-pr-labels: 'no-auto-close'
|
||||
exempt-issue-labels: 'no-auto-close,new feature,enhancement'
|
||||
21
.gitignore
vendored
21
.gitignore
vendored
|
|
@ -16,20 +16,23 @@ cscope*
|
|||
tags
|
||||
TAGS
|
||||
Makefile.local
|
||||
compel/compel
|
||||
compel/compel-host-bin
|
||||
images/*.c
|
||||
images/*.h
|
||||
images/google/protobuf/*.c
|
||||
images/google/protobuf/*.h
|
||||
.gitid
|
||||
criu/criu
|
||||
criu/unittest/unittest
|
||||
criu/arch/*/sys-exec-tbl.c
|
||||
criu/arch/*/syscalls.S
|
||||
criu/include/config.h
|
||||
criu/include/syscall-codes.h
|
||||
criu/include/syscall.h
|
||||
soccr/config.h
|
||||
criu/include/version.h
|
||||
criu/pie/restorer-blob.h
|
||||
criu/pie/parasite-blob.h
|
||||
criu/pie/piegen/piegen
|
||||
criu/pie/pie.lds.S
|
||||
criu/protobuf-desc-gen.h
|
||||
lib/build/
|
||||
lib/c/criu.pc
|
||||
compel/include/asm
|
||||
include/common/asm
|
||||
include/common/config.h
|
||||
build/**
|
||||
scripts/build/qemu-user-static/*
|
||||
lib/.crit-setup.files
|
||||
|
|
|
|||
25
.lgtm.yml
25
.lgtm.yml
|
|
@ -1,25 +0,0 @@
|
|||
extraction:
|
||||
cpp:
|
||||
prepare:
|
||||
packages:
|
||||
- "protobuf-c-compiler"
|
||||
- "libprotobuf-c-dev"
|
||||
- "libprotobuf-dev"
|
||||
- "build-essential"
|
||||
- "libprotobuf-dev"
|
||||
- "libprotobuf-c-dev"
|
||||
- "protobuf-c-compiler"
|
||||
- "protobuf-compiler"
|
||||
- "python3-protobuf"
|
||||
- "libnet-dev"
|
||||
- "pkg-config"
|
||||
- "libnl-3-dev"
|
||||
- "libbsd0"
|
||||
- "libbsd-dev"
|
||||
- "iproute2"
|
||||
- "libcap-dev"
|
||||
- "libaio-dev"
|
||||
- "libbsd-dev"
|
||||
- "python3-yaml"
|
||||
- "libnl-route-3-dev"
|
||||
- "gnutls-dev"
|
||||
10
.mailmap
10
.mailmap
|
|
@ -1,10 +1,6 @@
|
|||
Stanislav Kinsbursky <skinsbursky@parallels.com> <skinsbursky@openvz.org>
|
||||
Pavel Emelyanov <xemul@parallels.com> <xemul@openvz.org>
|
||||
Andrei Vagin <avagin@gmail.com> <avagin@openvz.org>
|
||||
Andrei Vagin <avagin@gmail.com> <avagin@parallels.com>
|
||||
Andrei Vagin <avagin@gmail.com> <avagin@virtuozzo.com>
|
||||
Andrei Vagin <avagin@gmail.com> <avagin@odin.com>
|
||||
Andrei Vagin <avagin@gmail.com> <avagin@google.com>
|
||||
Andrey Vagin <avagin@parallels.com> <avagin@openvz.org>
|
||||
Andrey Vagin <avagin@parallels.com> <avagin@gmail.com>
|
||||
Andrey Vagin <avagin@parallels.com> Andrew Vagin <avagin@parallels.com>
|
||||
Cyrill Gorcunov <gorcunov@openvz.org> <gorcunov@gmail.com>
|
||||
Alexander Mikhalitsyn <alexander@mihalicyn.com> <alexander.mikhalitsyn@virtuozzo.com>
|
||||
Alexander Mikhalitsyn <alexander@mihalicyn.com> <aleksandr.mikhalitsyn@canonical.com>
|
||||
|
|
|
|||
21
.travis.yml
Normal file
21
.travis.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
language: c
|
||||
sudo: required
|
||||
dist: trusty
|
||||
services:
|
||||
- docker
|
||||
env:
|
||||
- TR_ARCH=local GCOV=1
|
||||
- TR_ARCH=local CLANG=1
|
||||
- TR_ARCH=alpine
|
||||
- TR_ARCH=x86_64
|
||||
- TR_ARCH=armv7hf
|
||||
- TR_ARCH=aarch64
|
||||
- TR_ARCH=ppc64le
|
||||
- TR_ARCH=armv7hf CLANG=1
|
||||
- TR_ARCH=aarch64 CLANG=1
|
||||
- TR_ARCH=ppc64le CLANG=1
|
||||
- TR_ARCH=alpine CLANG=1
|
||||
script:
|
||||
- sudo make -C scripts/travis $TR_ARCH
|
||||
after_success:
|
||||
- make -C scripts/travis after_success
|
||||
|
|
@ -1 +0,0 @@
|
|||
GEMINI.md
|
||||
449
CONTRIBUTING.md
449
CONTRIBUTING.md
|
|
@ -1,449 +0,0 @@
|
|||
## How to contribute to CRIU
|
||||
|
||||
CRIU project is (almost) the never-ending story, because we have to always keep up with the
|
||||
Linux kernel supporting checkpoint and restore for all the features it provides. Thus we're
|
||||
looking for contributors of all kinds -- feedback, bug reports, testing, coding, writing, etc.
|
||||
Here are some useful hints to get involved.
|
||||
|
||||
* We have both -- [very simple](https://github.com/checkpoint-restore/criu/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) and [more sophisticated](https://github.com/checkpoint-restore/criu/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+feature%22) coding tasks;
|
||||
* CRIU does need [extensive testing](https://github.com/checkpoint-restore/criu/issues?q=is%3Aissue+is%3Aopen+label%3Atesting);
|
||||
* Documentation is always hard, we have [some information](https://criu.org/Category:Empty_articles) that is to be extracted from people's heads into wiki pages as well as [some texts](https://criu.org/Category:Editor_help_needed) that all need to be converted into useful articles;
|
||||
* Feedback is expected on the GitHub issues page and on the [mailing list](https://lore.kernel.org/criu);
|
||||
* We accept GitHub pull requests and this is the preferred way to contribute to CRIU. If you prefer to send patches by email, you are welcome to send them to [CRIU development mailing list](https://lore.kernel.org/criu).
|
||||
Below we describe in more detail recommend practices for CRIU development.
|
||||
* Spread the word about CRIU in [social networks](http://criu.org/Contacts);
|
||||
* If you're giving a talk about CRIU -- let us know, we'll mention it on the [wiki main page](https://criu.org/News/events);
|
||||
|
||||
### Setting up the development environment
|
||||
|
||||
Although `criu` could be run as non-root (see [Security](https://criu.org/Security)), development is better to be done as root. For example, some tests require root. So, it would be a good idea to set up some recent Linux distro on a virtual machine.
|
||||
|
||||
### Get the source code
|
||||
|
||||
The CRIU sources are tracked by Git. Official CRIU repo is at https://github.com/checkpoint-restore/criu.
|
||||
|
||||
The repository may contain multiple branches. Development happens in the **criu-dev** branch.
|
||||
|
||||
To clone CRIU repo and switch to the proper branch, run:
|
||||
|
||||
```
|
||||
git clone https://github.com/checkpoint-restore/criu criu
|
||||
cd criu
|
||||
git checkout criu-dev
|
||||
```
|
||||
|
||||
### Building from source
|
||||
|
||||
Follow these steps to compile CRIU from source code.
|
||||
|
||||
#### Installing build dependencies
|
||||
|
||||
First, you need to install the required build dependencies. We provide scripts to simplify this process for several Linux distributions in [contrib/dependencies](contrib/dependencies). For a complete list of dependencies, please refer to the [installation guide](https://criu.org/Installation).
|
||||
|
||||
##### On Ubuntu/Debian-based systems:
|
||||
|
||||
```
|
||||
./contrib/dependencies/apt-packages.sh
|
||||
```
|
||||
|
||||
##### On Fedora/CentOS-based systems:
|
||||
|
||||
```
|
||||
./contrib/dependencies/dnf-packages.sh
|
||||
```
|
||||
|
||||
##### Using Nix:
|
||||
|
||||
```
|
||||
nix develop
|
||||
```
|
||||
|
||||
#### Compiling CRIU
|
||||
|
||||
Once the dependencies are installed, you can compile CRIU by running the `make` command from the root of the source directory:
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
This should create the `./criu/criu` executable.
|
||||
|
||||
## Edit the source code
|
||||
|
||||
When you change the source code, please keep in mind the following code conventions:
|
||||
|
||||
* code is written to be read, so the code readability is the most important thing you need to have in mind when preparing patches
|
||||
* we prefer tabs and indentations to be 8 characters width
|
||||
* we prefer line length of 80 characters or less, more is allowed if it helps with code readability
|
||||
* CRIU mostly follows [Linux kernel coding style](https://www.kernel.org/doc/Documentation/process/coding-style.rst), but we are less strict than the kernel community
|
||||
|
||||
Other conventions can be learned from the source code itself. In short, make sure your new code looks similar to what is already there.
|
||||
|
||||
## Automatic tools to fix coding-style
|
||||
|
||||
Important: These tools are there to advise you, but should not be considered as a "source of truth", as tools also make nasty mistakes from time to time which can completely break code readability.
|
||||
|
||||
The following command can be used to automatically run a code linter for Python files (ruff), Shell scripts (shellcheck),
|
||||
text spelling (codespell), and a number of CRIU-specific checks (usage of print macros and EOL whitespace for C files).
|
||||
|
||||
```
|
||||
make lint
|
||||
```
|
||||
|
||||
In addition, we have adopted a [clang-format configuration file](https://www.kernel.org/doc/Documentation/process/clang-format.rst)
|
||||
based on the kernel source tree. However, compliance with the clang-format autoformat rules is optional. If the automatic code formatting
|
||||
results in decreased readability, we may choose to ignore these errors.
|
||||
|
||||
Run the following command to check if your changes are compliant with the clang-format rules:
|
||||
|
||||
```
|
||||
make indent
|
||||
```
|
||||
|
||||
This command is built upon the `git-clang-format` tool and supports two options `BASE` and `OPTS`. The `BASE` option allows you to
|
||||
specify a range of commits to check for coding style issues. By default, it is set to `HEAD~1`, so that only the last commit is checked.
|
||||
If you are developing on top of the criu-dev branch and want to check all your commits for compliance with the clang-format rules, you
|
||||
can use `BASE=origin/criu-dev`. The `OPTS` option can be used to pass additional options to `git-clang-format`. For example, if you want
|
||||
to check the last *N* commits for formatting errors, without applying the changes to the codebase you can use the following command.
|
||||
|
||||
```
|
||||
make indent OPTS=--diff BASE=HEAD~N
|
||||
```
|
||||
|
||||
Note that for pull requests, the "Run code linter" workflow runs these checks for all commits. If a clang-format error is detected
|
||||
we need to review the suggested changes and decide if they should be fixed before merging.
|
||||
|
||||
Here are some bad examples of clang-format-ing:
|
||||
|
||||
* if clang-format tries to force 120 characters and breaks readability - it is wrong:
|
||||
|
||||
```
|
||||
@@ -58,8 +59,7 @@ static int register_membarriers(void)
|
||||
}
|
||||
|
||||
if (!all_ok) {
|
||||
- fail("can't register membarrier()s - tried %#x, kernel %#x",
|
||||
- barriers_registered, barriers_supported);
|
||||
+ fail("can't register membarrier()s - tried %#x, kernel %#x", barriers_registered, barriers_supported);
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
* if clang-format breaks your beautiful readability friendly alignment in structures, comments or defines - it is wrong:
|
||||
|
||||
```
|
||||
--- a/test/zdtm/static/membarrier.c
|
||||
+++ b/test/zdtm/static/membarrier.c
|
||||
@@ -27,9 +27,10 @@ static const struct {
|
||||
int register_cmd;
|
||||
int execute_cmd;
|
||||
} membarrier_cmds[] = {
|
||||
- { "", MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, MEMBARRIER_CMD_PRIVATE_EXPEDITED },
|
||||
- { "_SYNC_CORE", MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE, MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE },
|
||||
- { "_RSEQ", MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ, MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ },
|
||||
+ { "", MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, MEMBARRIER_CMD_PRIVATE_EXPEDITED },
|
||||
+ { "_SYNC_CORE", MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE,
|
||||
+ MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE },
|
||||
+ { "_RSEQ", MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ, MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ },
|
||||
};
|
||||
```
|
||||
|
||||
## Test your changes
|
||||
|
||||
CRIU comes with an extensive test suite. To check whether your changes introduce any regressions, run
|
||||
|
||||
```
|
||||
make test
|
||||
```
|
||||
|
||||
The command runs [ZDTM Test Suite](https://criu.org/ZDTM_Test_Suite). Check for any error messages produced by it.
|
||||
|
||||
## Describe your changes
|
||||
|
||||
Describe your problem. Whether your change is a one-line bug fix or
|
||||
5000 lines of a new feature, there must be an underlying problem that
|
||||
motivated you to do this work. Convince the reviewer that there is a
|
||||
problem worth fixing and that it makes sense for them to read past the
|
||||
first paragraph.
|
||||
|
||||
Once the problem is established, describe what you are actually doing
|
||||
about it in technical detail. It's important to describe the change
|
||||
in plain English for the reviewer to verify that the code is behaving
|
||||
as you intend it to.
|
||||
|
||||
Solve only one problem per commit. If your description starts to get
|
||||
long, that's a sign that you probably need to split up your commit.
|
||||
See [Separate your changes](#separate-your-changes).
|
||||
|
||||
Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
|
||||
instead of "[This commit] makes xyzzy do frotz" or "[I] changed xyzzy
|
||||
to do frotz", as if you are giving orders to the codebase to change
|
||||
its behaviour.
|
||||
|
||||
If your change fixes a bug in a specific commit, e.g. you found an issue using
|
||||
`git bisect`, please use the `Fixes:` tag with the abbreviation of
|
||||
the SHA-1 ID, and the one line summary. For example:
|
||||
|
||||
```
|
||||
Fixes: 9433b7b9db3e ("make: use cflags/ldflags for config.h detection mechanism")
|
||||
```
|
||||
|
||||
The following `git config` settings can be used to add a pretty format for
|
||||
outputting the above style in the `git log` or `git show` commands:
|
||||
|
||||
```
|
||||
[pretty]
|
||||
fixes = Fixes: %h (\"%s\")
|
||||
```
|
||||
|
||||
If your change address an issue listed in GitHub, please use `Fixes:` tag with the number of the issue. For instance:
|
||||
|
||||
```
|
||||
Fixes: #339
|
||||
```
|
||||
|
||||
The `Fixes:` tags should be put at the end of the detailed description.
|
||||
|
||||
Please add a prefix to your commit subject line describing the part of the
|
||||
project your change is related to. This can be either the name of the file or
|
||||
directory you changed, or just a general word. If your patch is touching
|
||||
multiple components you may separate prefixes with "/"-es. Here are some good
|
||||
examples of subject lines from git log:
|
||||
|
||||
```
|
||||
criu-ns: Convert to python3 style print() syntax
|
||||
compel: Calculate sh_addr if not provided by linker
|
||||
style: Enforce kernel style -Wstrict-prototypes
|
||||
rpc/libcriu: Add lsm-profile option
|
||||
```
|
||||
|
||||
You may refer to [How to Write a Git Commit
|
||||
Message](https://chris.beams.io/posts/git-commit/) article for
|
||||
recommendations for good commit message.
|
||||
|
||||
## Separate your changes
|
||||
|
||||
Separate each **logical change** into a separate commit.
|
||||
|
||||
For example, if your changes include both bug fixes and performance
|
||||
enhancements for a single driver, separate those changes into two
|
||||
or more commits. If your changes include an API update, and a new
|
||||
driver which uses that new API, separate those into two commits.
|
||||
|
||||
On the other hand, if you make a single change to numerous files,
|
||||
group those changes into a single commit. Thus a single logical change
|
||||
is contained within a single commit.
|
||||
|
||||
The point to remember is that each commit should make an easily understood
|
||||
change that can be verified by reviewers. Each commit should be justifiable
|
||||
on its own merits.
|
||||
|
||||
When dividing your change into a series of commits, take special care to
|
||||
ensure that CRIU builds and runs properly after each commit in the
|
||||
series. Developers using `git bisect` to track down a problem can end up
|
||||
splitting your patch series at any point; they will not thank you if you
|
||||
introduce bugs in the middle.
|
||||
|
||||
## Sign your work
|
||||
|
||||
To improve tracking of who did what, we ask you to sign off the commits in
|
||||
your fork of CRIU or the patches that are to be emailed.
|
||||
|
||||
The sign-off is a simple line at the end of the explanation for the
|
||||
patch, which certifies that you wrote it or otherwise have the right to
|
||||
pass it on as an open-source patch. The rules are pretty simple: if you
|
||||
can certify the below:
|
||||
|
||||
### Developer's Certificate of Origin 1.1
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
|
||||
then you just add a line saying
|
||||
|
||||
```
|
||||
Signed-off-by: Random J Developer <random at developer.example.org>
|
||||
```
|
||||
|
||||
using your real name (please, no pseudonyms or anonymous contributions if
|
||||
it possible).
|
||||
|
||||
Hint: you can use `git commit -s` to add Signed-off-by line to your
|
||||
commit message. To append such line to a commit you already made, use
|
||||
`git commit --amend -s`.
|
||||
|
||||
```
|
||||
From: Random J Developer <random at developer.example.org>
|
||||
Subject: [PATCH] component: Short patch description
|
||||
|
||||
Long patch description (could be skipped if patch
|
||||
is trivial enough)
|
||||
|
||||
Signed-off-by: Random J Developer <random at developer.example.org>
|
||||
---
|
||||
Patch body here
|
||||
```
|
||||
|
||||
## AI-assisted contributions
|
||||
|
||||
Use this tag when AI tools meaningfully contribute to the code,
|
||||
design, or commit message. Trivial use (e.g. basic autocomplete)
|
||||
does not require attribution. Following the
|
||||
[Linux kernel guidance on coding assistants](https://docs.kernel.org/process/coding-assistants.html),
|
||||
the tag format is:
|
||||
|
||||
```
|
||||
Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]
|
||||
```
|
||||
|
||||
Where `AGENT_NAME` identifies the AI tool or framework, `MODEL_VERSION`
|
||||
specifies which model was used, and the optional `[TOOL1] [TOOL2]`
|
||||
fields list any specialized analysis tools (e.g. coccinelle, sparse,
|
||||
smatch, clang-tidy) that were used alongside the AI assistant. Basic
|
||||
development tools (git, gcc, make, editors) should not be listed.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
Assisted-by: Claude:claude-3-opus coccinelle sparse
|
||||
```
|
||||
|
||||
The `Assisted-by` tag should be placed after the commit message body
|
||||
and before the `Signed-off-by` line.
|
||||
|
||||
Note that AI agents should not add `Signed-off-by` tags. Only human
|
||||
developers can certify the Developer's Certificate of Origin. The
|
||||
submitter is responsible for reviewing all AI-generated code and
|
||||
ensuring its correctness and license compliance.
|
||||
|
||||
## Submit your work upstream
|
||||
|
||||
We accept GitHub pull requests and this is the preferred way to contribute to CRIU.
|
||||
For that you should push your work to your fork of CRIU at [GitHub](https://github.com) and create a [pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)
|
||||
|
||||
### Pull request guidelines
|
||||
|
||||
Pull request comment should contain description of the problem your changes
|
||||
solve and a brief outline of the changes included in the pull request.
|
||||
|
||||
Please avoid pushing fixup commits to an existent pull request. Each commit
|
||||
should be self contained and there should not be fixup commits in a patch
|
||||
series. Pull requests that contain one commit which breaks something
|
||||
and another commit which fixes it, will be rejected.
|
||||
|
||||
Please merge the fixup commits into the commits that has introduced the
|
||||
problem before creating a pull request.
|
||||
|
||||
It may happen that the reviewers were not completely happy with your
|
||||
changes and requested changes to your patches. After you updated your
|
||||
changes please close the old pull request and create a new one that
|
||||
contains the following:
|
||||
|
||||
* Description of the problem your changes solve and a brief outline of the
|
||||
changes
|
||||
* Link to the previous version of the pull request
|
||||
* Brief description of the changes between old and new versions of the pull
|
||||
request. If there were more than one previous pull request, all the
|
||||
revisions should be listed. For example:
|
||||
|
||||
```
|
||||
v3: rebase on the current criu-dev
|
||||
v2: add commit to foo() and update bar() coding style
|
||||
```
|
||||
|
||||
If there are only minor updates to the commits in a pull request, it is
|
||||
possible to force-push them into an existing pull request. This only applies
|
||||
to small changes and should be used with care. If you update an existing
|
||||
pull request, remember to add the description of the changes from the
|
||||
previous version.
|
||||
|
||||
### Mailing list submission
|
||||
|
||||
Historically, CRIU worked with mailing lists and patches so if you still prefer this way continue reading till the end of this section.
|
||||
|
||||
### Make a patch
|
||||
|
||||
To create a patch, run
|
||||
|
||||
```
|
||||
git format-patch --signoff origin/criu-dev
|
||||
```
|
||||
|
||||
You might need to read GIT documentation on how to prepare patches
|
||||
for mail submission. Take a look at http://book.git-scm.com/ and/or
|
||||
http://git-scm.com/documentation for details. It should not be hard
|
||||
at all.
|
||||
|
||||
We recommend to post patches using `git send-email`
|
||||
|
||||
```
|
||||
git send-email --cover-letter --no-chain-reply-to --annotate \
|
||||
--confirm=always --to=criu@lists.linux.dev criu-dev
|
||||
```
|
||||
|
||||
Note that the `git send-email` subcommand may not be in
|
||||
the main git package and using it may require installation of a
|
||||
separate package, for example the "git-email" package in Fedora and
|
||||
Debian.
|
||||
|
||||
If this is your first time using git send-email, you might need to
|
||||
configure it to point it to your SMTP server with something like:
|
||||
|
||||
```
|
||||
git config --global sendemail.smtpServer stmp.example.net
|
||||
```
|
||||
|
||||
If you get tired of typing `--to=criu@lists.linux.dev` all the time,
|
||||
you can configure that to be automatically handled as well:
|
||||
|
||||
```
|
||||
git config sendemail.to criu@lists.linux.dev
|
||||
```
|
||||
|
||||
If a developer is sending another version of the patch (e.g. to address
|
||||
review comments), they are advised to note differences to previous versions
|
||||
after the `---` line in the patch so that it helps reviewers but
|
||||
doesn't become part of git history. Moreover, such patch needs to be prefixed
|
||||
correctly with `--subject-prefix=PATCHv2` appended to
|
||||
`git send-email` (substitute `v2` with the correct
|
||||
version if needed though).
|
||||
|
||||
### Mail patches
|
||||
|
||||
The patches should be sent to CRIU development mailing list, `criu AT lists.linux.dev`. Note that you need to be subscribed first in order to post. The list web interface is available at https://lore.kernel.org/criu; you can also use standard mailman aliases to work with it.
|
||||
|
||||
Please make sure the email client you're using doesn't screw your patch (line wrapping and so on).
|
||||
|
||||
> **Note:** When sending a patch set that consists of more than one patch, please, push your changes in your local repo and provide the URL of the branch in the cover-letter
|
||||
|
||||
### Wait for response
|
||||
|
||||
Be patient. Most CRIU developers are pretty busy people so if
|
||||
there is no immediate response on your patch — don't be surprised,
|
||||
sometimes a patch may fly around a week before it gets reviewed.
|
||||
|
||||
## Continuous integration
|
||||
|
||||
Wiki article: [Continuous integration](https://criu.org/Continuous_integration)
|
||||
|
||||
CRIU tests are run for each series sent to the mailing list. If you get a message from our patchwork that patches failed to pass the tests, you have to investigate what is wrong.
|
||||
1
Documentation/.gitignore
vendored
1
Documentation/.gitignore
vendored
|
|
@ -3,4 +3,3 @@
|
|||
*.[1-8]
|
||||
*.pdf
|
||||
*.ps
|
||||
footer.txt
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
How to cross-compile CRIU on x86:
|
||||
|
||||
Use the Dockerfile provided:
|
||||
scripts/build/Dockerfile.armv7-cross
|
||||
|
||||
Historical guide how-to do it without docker container:
|
||||
[Unsupported, may not work anymore!]
|
||||
This HOWTO explains how to cross-compile CRIU on x86
|
||||
|
||||
1. Download the protobuf sources.
|
||||
2. Apply the patch http://16918.selcdn.ru/crtools/aarch64/0001-protobuf-added-the-support-for-the-acrchitecture-AAr.patch
|
||||
|
|
@ -35,11 +29,3 @@ Historical guide how-to do it without docker container:
|
|||
13. Compile CRIU:
|
||||
|
||||
ARCH=<target arch> CROSS_COMPILE=$TARGET- CFLAGS=`pkg-config --cflags libprotobuf-c` LDFLAGS="`pkg-config --libs libprotobuf-c`" make
|
||||
|
||||
Special notes for Android NDK cross compile:
|
||||
|
||||
1, Android NDK doesn't have some headers required by CRIU build, they are <aio.h>, <sys/fanotify.h>
|
||||
|
||||
2, Android NDK doesn't have some function required by CRIU build, they are aio*, fanotify_init, fanotify_mark, povit_root, index.
|
||||
|
||||
3, in order to pass build with Android NDK, you implement them yourself, and link them to CRIU.
|
||||
|
|
|
|||
|
|
@ -2,19 +2,12 @@ __nmk_dir ?= ../scripts/nmk/scripts/
|
|||
include $(__nmk_dir)include.mk
|
||||
include $(__nmk_dir)macro.mk
|
||||
|
||||
ifneq ($(USE_ASCIIDOCTOR),)
|
||||
ASCIIDOC := asciidoctor
|
||||
XMLTO :=
|
||||
else
|
||||
ASCIIDOC := asciidoc
|
||||
A2X := a2x
|
||||
XMLTO := xmlto
|
||||
endif
|
||||
|
||||
FOOTER := footer.txt
|
||||
SRC1 += crit.txt
|
||||
SRC1 += criu-ns.txt
|
||||
SRC1 += compel.txt
|
||||
SRC1 += criu-amdgpu-plugin.txt
|
||||
SRC8 += criu.txt
|
||||
SRC := $(SRC1) $(SRC8)
|
||||
XMLS := $(patsubst %.txt,%.xml,$(SRC))
|
||||
|
|
@ -36,7 +29,7 @@ pdf: $(PDFS)
|
|||
.PHONY: all ps pdf check
|
||||
|
||||
check:
|
||||
$(Q) for B in $(ASCIIDOC) $(XMLTO); do \
|
||||
$(Q) for B in $(ASCIIDOC) $(A2X) $(XMLTO); do \
|
||||
$$B --version > /dev/null || exit 1; \
|
||||
done
|
||||
|
||||
|
|
@ -52,21 +45,13 @@ $(FOOTER): ../Makefile.versions
|
|||
|
||||
%.1: %.txt $(FOOTER) custom.xsl
|
||||
$(call msg-gen, $@)
|
||||
ifneq ($(USE_ASCIIDOCTOR),)
|
||||
$(Q) $(ASCIIDOC) -b manpage -d manpage -o $@ $<
|
||||
else
|
||||
$(Q) $(ASCIIDOC) -b docbook -d manpage -o $(patsubst %.1,%.xml,$@) $<
|
||||
$(Q) $(XMLTO) man -m custom.xsl $(patsubst %.1,%.xml,$@)
|
||||
endif
|
||||
$(Q) $(XMLTO) man -m custom.xsl $(patsubst %.1,%.xml,$@) 2>/dev/null
|
||||
|
||||
%.8: %.txt $(FOOTER) custom.xsl
|
||||
$(call msg-gen, $@)
|
||||
ifneq ($(USE_ASCIIDOCTOR),)
|
||||
$(Q) $(ASCIIDOC) -b manpage -d manpage -o $@ $<
|
||||
else
|
||||
$(Q) $(ASCIIDOC) -b docbook -d manpage -o $(patsubst %.8,%.xml,$@) $<
|
||||
$(Q) $(XMLTO) man -m custom.xsl $(patsubst %.8,%.xml,$@)
|
||||
endif
|
||||
$(Q) $(XMLTO) man -m custom.xsl $(patsubst %.8,%.xml,$@) 2>/dev/null
|
||||
|
||||
%.ps: %.1
|
||||
$(call msg-gen, $@)
|
||||
|
|
@ -84,7 +69,7 @@ clean:
|
|||
$(call msg-clean, "Documentation")
|
||||
$(Q) rm -f $(XMLS) $(MANS) $(PSS) $(PDFS) $(FOOTER)
|
||||
|
||||
install: check $(MANS)
|
||||
install: $(MANS)
|
||||
$(E) " INSTALL " $(MAN8S)
|
||||
$(Q) mkdir -p $(DESTDIR)$(MAN8DIR)
|
||||
$(Q) install -m 644 $(MAN8S) $(DESTDIR)$(MAN8DIR)
|
||||
|
|
|
|||
|
|
@ -1,122 +0,0 @@
|
|||
COMPEL(1)
|
||||
==========
|
||||
include::footer.txt[]
|
||||
|
||||
NAME
|
||||
----
|
||||
compel - Execute parasitic code within another process.
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
*compel* 'hgen' ['option' ...]
|
||||
|
||||
*compel* 'plugins' ['PLUGIN_NAME' ...]
|
||||
|
||||
*compel* ['--compat'] 'includes' | 'cflags' | 'ldflags'
|
||||
|
||||
*compel* ['--compat'] ['--static'] 'libs'
|
||||
|
||||
DESCRIPTION
|
||||
------------
|
||||
*compel* is a utility to execute arbitrary code, also called parasite code,
|
||||
in the context of a foreign process. The parasitic code, once compiled with
|
||||
compel flags and packed, can be executed in the context of other tasks. Currently
|
||||
there is only one way to load the parasitic blob into victim task using libcompel.a,
|
||||
called c-header.
|
||||
|
||||
ARGUMENTS
|
||||
----------
|
||||
|
||||
Positional Arguments
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
*hgen*::
|
||||
create a header from the .po file, which is the parasite binary.
|
||||
|
||||
*plugins*::
|
||||
prints the plugins available.
|
||||
|
||||
*ldflags*::
|
||||
prints the ldflags available to compel during linking of parasite code.
|
||||
|
||||
*cflags*::
|
||||
prints the compel cflags to be used during compilation of parasitic code.
|
||||
|
||||
*includes*::
|
||||
prints list of standard include directories.
|
||||
|
||||
*libs*::
|
||||
prints list of static or dynamic libraries that compel can link with.
|
||||
|
||||
OPTIONS
|
||||
--------
|
||||
*-f*, *--file* 'FILE'::
|
||||
Path to the binary file, 'FILE', which *compel* must turn into a header
|
||||
|
||||
*-o*, *--output* 'FILE'::
|
||||
Path to the header file, 'FILE', where compel must write the resulting header.
|
||||
|
||||
*-p*, *--prefix* 'NAME'::
|
||||
Specify prefix for var names
|
||||
|
||||
*-l*, *--log-level* 'NUM'::
|
||||
Default log level of compel.
|
||||
|
||||
*-h*, *--help*::
|
||||
Prints usage and exits.
|
||||
|
||||
*-V*, *--version*::
|
||||
Prints version number of compel.
|
||||
|
||||
SOURCE EXAMPLES
|
||||
----------------
|
||||
|
||||
Parasitic Code
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
*#include <compel/plugins/std.h>*
|
||||
|
||||
*int parasite_trap_cmd(int cmd, void *args);* //gets called by compel_run_in_thread()
|
||||
|
||||
*int parasite_daemon_cmd(int cmd, void *arg);* // gets called by compel_rpc_call() and compel_rpc_call_sync()
|
||||
|
||||
*void parasite_cleanup(void);* //gets called on parasite unload by compel_cure()
|
||||
|
||||
Infecting code
|
||||
~~~~~~~~~~~~~~
|
||||
The parasitic code is compiled and converted to a header using *compel*, and included here.
|
||||
|
||||
*#include <compel/infect.h>*
|
||||
|
||||
*#include "parasite.h"*
|
||||
|
||||
Following steps are performed to infect the victim process:
|
||||
|
||||
- stop the task: *int compel_stop_task(int pid);*
|
||||
- prepare infection handler: *struct parasite_ctl *compel_prepare(int pid);*
|
||||
- execute system call: *int compel_syscall(ctl, int syscall_nr, long *ret, int arg ...);*
|
||||
- infect victim: *int compel_infect(ctl, nr_thread, size_of_args_area);*
|
||||
- cure the victim: *int compel_cure(ctl);* //ctl pointer is freed by this call
|
||||
- Resume victim: *int compel_resume_task(pid, orig_state, state)* or
|
||||
*int compel_resume_task_sig(pid, orig_state, state, stop_signo).*
|
||||
//compel_resume_task_sig() could be used in case when victim is in stopped state.
|
||||
stop_signo could be read by calling compel_parse_stop_signo().
|
||||
|
||||
*ctl* must be configured with blob information by calling *PREFIX_setup_c_header()*, with ctl as its argument.
|
||||
*PREFIX* is the argument given to *-p* when calling hgen, else it is deduced from file name.
|
||||
|
||||
|
||||
EXAMPLES
|
||||
---------
|
||||
To generate a header file(.h) from a parasite binary file(.po) use:
|
||||
|
||||
----------
|
||||
compel hgen -f parasite.po -o parasite.h
|
||||
----------
|
||||
|
||||
'parasite.po' file is obtained by compiling the parasite source with compel flags and
|
||||
linking it with the compel plugins.
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
The CRIU team.
|
||||
|
|
@ -18,10 +18,6 @@ SYNOPSIS
|
|||
|
||||
*crit* 'show' [-h] in
|
||||
|
||||
*crit* 'compress' [-h] [--in-place] [--acceleration N] dir
|
||||
|
||||
*crit* 'decompress' [-h] [--in-place] dir
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
*crit* is a feature-rich replacement for existing *criu* show.
|
||||
|
|
@ -47,46 +43,12 @@ Positional Arguments
|
|||
*show*::
|
||||
convert *criu* image from binary to human-readable JSON
|
||||
|
||||
*compress*::
|
||||
compress memory page images in a checkpoint directory using CRIU's
|
||||
per-page LZ4 format. The command rewrites *pages-*.img*,
|
||||
*pagemap-*.img*, and *inventory.img*. Pages that are zero-filled or
|
||||
do not meet CRIU's compression threshold are stored without an LZ4
|
||||
payload. By default, the original files are preserved with a *.bak*
|
||||
suffix; use *--in-place* to skip these backup files. The inventory
|
||||
is updated to record compression metadata and the compressed-image
|
||||
version. Existing *.bak* files are never overwritten.
|
||||
|
||||
*decompress*::
|
||||
decompress memory page images in a checkpoint directory back to
|
||||
uncompressed page payloads. The command removes compression metadata
|
||||
from the pagemap and inventory images. When the directory has no parent
|
||||
reference, the command also restores the normal image version. It retains
|
||||
the compressed-image version for incremental checkpoints because a parent
|
||||
may still contain compressed payloads. By default, rewritten files are
|
||||
preserved with a *.bak* suffix; use *--in-place* to skip these backup
|
||||
files. Existing *.bak* files are never overwritten.
|
||||
|
||||
Both transformations preserve the ownership, permissions, ACLs, security
|
||||
labels, and other extended attributes of rewritten images. All output is
|
||||
staged and synchronized before it is installed. If a write, rename, *SIGHUP*,
|
||||
*SIGINT*, or *SIGTERM* interrupts the commit, CRIT restores the complete
|
||||
original image set instead of leaving a partially transformed set.
|
||||
|
||||
Optional Arguments
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
*-h*, *--help*::
|
||||
Print some help and exit
|
||||
|
||||
*--in-place*::
|
||||
Rewrite files without creating *.bak* backup files. This option is
|
||||
accepted by *compress* and *decompress*.
|
||||
|
||||
*--acceleration* 'N'::
|
||||
Set the LZ4 acceleration level used by *compress*. Higher values
|
||||
trade compression ratio for speed.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
criu(8)
|
||||
|
|
|
|||
|
|
@ -1,114 +0,0 @@
|
|||
ROCM Support(1)
|
||||
===============
|
||||
|
||||
NAME
|
||||
----
|
||||
criu-amdgpu-plugin - A plugin extension to CRIU to support checkpoint/restore in
|
||||
userspace for AMD GPUs.
|
||||
|
||||
|
||||
CURRENT SUPPORT
|
||||
---------------
|
||||
Single and Multi GPU systems (Gfx9)
|
||||
Checkpoint / Restore on different system
|
||||
Checkpoint / Restore inside a docker container
|
||||
Pytorch
|
||||
Tensorflow
|
||||
Using CRIU Image Streamer
|
||||
Parallel Restore
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Though *criu* is a great tool for checkpointing and restoring running
|
||||
applications, it has certain limitations such as it cannot handle
|
||||
applications that have device files open. In order to support *ROCm* based
|
||||
workloads with *criu* we need to augment criu's core functionality with a
|
||||
plugin based extension mechanism. *criu-amdgpu-plugin* provides the necessary support
|
||||
to criu to allow Checkpoint / Restore with ROCm.
|
||||
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
*amdkfd support*::
|
||||
In order to snapshot the *VRAM* and other *GPU* device states, we require
|
||||
an updated version of amdkfd(amdgpu) driver.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
Optional parameters can be passed in as environment variables before
|
||||
executing criu command.
|
||||
|
||||
*KFD_FW_VER_CHECK*::
|
||||
Enable or disable firmware version check.
|
||||
If enabled, firmware version on restored gpu needs to be greater than or
|
||||
equal firmware version on checkpointed GPU. Default:Enabled
|
||||
|
||||
E.g:
|
||||
KFD_FW_VER_CHECK=0
|
||||
|
||||
*KFD_SDMA_FW_VER_CHECK*::
|
||||
Enable or disable SDMA firmware version check.
|
||||
If enabled, SDMA firmware version on restored gpu needs to be greater than or
|
||||
equal firmware version on checkpointed GPU. Default:Enabled
|
||||
|
||||
E.g:
|
||||
KFD_SDMA_FW_VER_CHECK=0
|
||||
|
||||
*KFD_CACHES_COUNT_CHECK*::
|
||||
Enable or disable caches count check. If enabled, the caches count on
|
||||
restored GPU needs to be greater than or equal caches count on checkpointed
|
||||
GPU. Default:Enabled
|
||||
|
||||
E.g:
|
||||
KFD_CACHES_COUNT_CHECK=0
|
||||
|
||||
*KFD_NUM_GWS_CHECK*::
|
||||
Enable or disable num_gws check. If enabled, the num_gws on
|
||||
restored GPU needs to be greater than or equal num_gws on checkpointed
|
||||
GPU. Default:Enabled
|
||||
|
||||
E.g:
|
||||
KFD_NUM_GWS_CHECK=0
|
||||
|
||||
*KFD_VRAM_SIZE_CHECK*::
|
||||
Enable or disable VRAM size check. If enabled, the VRAM size on
|
||||
restored GPU needs to be greater than or equal VRAM size on checkpointed
|
||||
GPU. Default:Enabled
|
||||
|
||||
E.g:
|
||||
KFD_VRAM_SIZE_CHECK=0
|
||||
|
||||
*KFD_NUMA_CHECK*::
|
||||
Enable or disable NUMA CPU region check. If enabled, the plugin will restore
|
||||
GPUs that belong to one CPU NUMA region to the same CPU NUMA region.
|
||||
Default:Enabled
|
||||
|
||||
E.g:
|
||||
KFD_NUMA_CHECK=1
|
||||
|
||||
*KFD_CAPABILITY_CHECK*::
|
||||
Enable or disable capability check. If enabled, the capability on
|
||||
restored GPU needs to be equal to the capability on the checkpointed GPU.
|
||||
Default:Enabled
|
||||
|
||||
E.g:
|
||||
KFD_CAPABILITY_CHECK=1
|
||||
|
||||
*KFD_MAX_BUFFER_SIZE*::
|
||||
On some systems, VRAM sizes may exceed RAM sizes, and so buffers for dumping
|
||||
and restoring VRAM may be unable to fit. Set to a nonzero value (in bytes)
|
||||
to set a limit on the plugin's memory usage.
|
||||
Default:0 (Disabled)
|
||||
|
||||
E.g:
|
||||
KFD_MAX_BUFFER_SIZE="2G"
|
||||
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
The AMDKFD team.
|
||||
|
||||
|
||||
COPYRIGHT
|
||||
---------
|
||||
Copyright \(C) 2020-2021, Advanced Micro Devices, Inc. (AMD)
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
CRIU-NS(1)
|
||||
==========
|
||||
include::footer.txt[]
|
||||
|
||||
NAME
|
||||
----
|
||||
criu-ns - run criu in different namespaces
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
*criu-ns* 'dump' -t PID [<options>]
|
||||
|
||||
*criu-ns* 'pre-dump' -t PID [<options>]
|
||||
|
||||
*criu-ns* 'restore' [<options>]
|
||||
|
||||
*criu-ns* 'check' [<options>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
The *criu-ns* command executes 'criu' in a new PID and mount namespace.
|
||||
The purpose of this wrapper script is to enable restoring a process tree
|
||||
that might require a specific PID that is already used on the system;
|
||||
so called "PID mismatch" problem.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
nsenter(1) namespaces(7) criu(8)
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
The CRIU team
|
||||
|
|
@ -24,20 +24,16 @@ on a different system, or both.
|
|||
OPTIONS
|
||||
-------
|
||||
|
||||
Most of the long flags can be
|
||||
prefixed with *no-* to negate the option (example: *--display-stats*
|
||||
and *--no-display-stats*).
|
||||
|
||||
Common options
|
||||
~~~~~~~~~~~~~~
|
||||
Common options are applicable to any 'command'.
|
||||
|
||||
*-v*[*v*...], *--verbosity*::
|
||||
Increase verbosity up from the default level. In case of short option,
|
||||
multiple *v* can be used, each increasing verbosity by one.
|
||||
*-v*[*v*...]::
|
||||
Increase verbosity up from the default level. Multiple *v* can be used,
|
||||
each increasing verbosity by one level.
|
||||
|
||||
**-v**__num__, **--verbosity=**__num__::
|
||||
Set verbosity level to _num_. The higher the level, the more output
|
||||
*-v*'num'::
|
||||
Set verbosity level to 'num'. The higher the level, the more output
|
||||
is produced.
|
||||
+
|
||||
The following levels are available:
|
||||
|
|
@ -52,35 +48,27 @@ The following levels are available:
|
|||
* *-v4*
|
||||
above plus lots of debug.
|
||||
|
||||
*--config* 'file'::
|
||||
Pass a specific configuration file to criu.
|
||||
|
||||
*--no-default-config*::
|
||||
Disable parsing of default configuration files.
|
||||
|
||||
*--pidfile* 'file'::
|
||||
Write root task, service or page-server pid into a 'file'.
|
||||
|
||||
*-o*, *--log-file* 'file'::
|
||||
Write logging messages to a 'file'.
|
||||
Write logging messages to 'file'.
|
||||
|
||||
*--log-pid*::
|
||||
Write separate logging files per each pid.
|
||||
|
||||
*--display-stats*::
|
||||
During dump, as well as during restore, *criu* collects some statistics,
|
||||
like the time required to dump or restore the process, or the
|
||||
During dump as well as during restore *criu* collects information
|
||||
like the time required to dump or restore the process or the
|
||||
number of pages dumped or restored. This information is always
|
||||
saved to the *stats-dump* and *stats-restore* files, and can
|
||||
be shown using *crit*(1). The option *--display-stats*
|
||||
prints out this information on the console at the end
|
||||
of a dump or restore operation.
|
||||
written to the files 'stats-dump' and 'stats-restore' and can
|
||||
be easily displayed using *crit*. The option *--display-stats*
|
||||
additionally prints out this information on the console at the end
|
||||
of a dump or a restore.
|
||||
|
||||
*-D*, *--images-dir* 'path'::
|
||||
Use 'path' as a base directory where to look for sets of image files.
|
||||
|
||||
*--stream*::
|
||||
dump/restore images using criu-image-streamer.
|
||||
See https://github.com/checkpoint-restore/criu-image-streamer for detailed
|
||||
usage.
|
||||
|
||||
*--prev-images-dir* 'path'::
|
||||
Use 'path' as a parent directory where to look for sets of image files.
|
||||
This option makes sense in case of incremental dumps.
|
||||
|
|
@ -95,19 +83,6 @@ The following levels are available:
|
|||
*-L*, *--libdir* 'path'::
|
||||
Path to plugins directory.
|
||||
|
||||
*--enable-fs* ['fs'[,'fs'...]]::
|
||||
Specify a comma-separated list of filesystem names that should
|
||||
be auto-detected. The value 'all' enables auto-detection for
|
||||
all filesystems.
|
||||
+
|
||||
Note: This option is not safe, use at your own risk.
|
||||
Auto-detecting a filesystem mount assumes that the mountpoint can
|
||||
be restored with *mount(src, mountpoint, flags, options)*. When used,
|
||||
*dump* is expected to always succeed if a mountpoint is to be
|
||||
auto-detected, however *restore* may fail (or do something wrong)
|
||||
if the assumption for restore logic is incorrect. This option is
|
||||
not compatible with *--external* *dev*.
|
||||
|
||||
*--action-script* 'script'::
|
||||
Add an external action script to be executed at certain stages.
|
||||
The environment variable *CRTOOLS_SCRIPT_ACTION* is available
|
||||
|
|
@ -122,17 +97,13 @@ not compatible with *--external* *dev*.
|
|||
*pre-restore*:::
|
||||
run prior to beginning a *restore*
|
||||
|
||||
*post-restore*:::
|
||||
run upon *restore* completion
|
||||
|
||||
*pre-resume*:::
|
||||
run when all processes and resources are
|
||||
restored but tasks are stopped waiting for
|
||||
final kick to run. Must not fail.
|
||||
|
||||
*post-resume*:::
|
||||
called at the very end, when everything is
|
||||
restored and processes were resumed
|
||||
*post-restore*:::
|
||||
run upon *restore* completion
|
||||
|
||||
*network-lock*:::
|
||||
run to lock network in a target network namespace
|
||||
|
|
@ -141,30 +112,10 @@ not compatible with *--external* *dev*.
|
|||
run to unlock network in a target network namespace
|
||||
|
||||
*setup-namespaces*:::
|
||||
run once root task has just been created
|
||||
run once root task just been created
|
||||
with required namespaces. Note it is an early stage
|
||||
of restore, when nothing is restored yet, except for
|
||||
namespaces themselves
|
||||
|
||||
*post-setup-namespaces*:::
|
||||
called after the namespaces are configured
|
||||
|
||||
*orphan-pts-master*:::
|
||||
called after master pty is opened and unlocked. This
|
||||
hook can be used only in the RPC mode, and the
|
||||
notification message contains a file descriptor for
|
||||
the master pty
|
||||
|
||||
*query-ext-files*:::
|
||||
called after the process tree is stopped and network is locked.
|
||||
This hook is used only in the RPC mode. The notification reply
|
||||
contains file ids to be added to external file list (may be empty).
|
||||
|
||||
*--unprivileged*::
|
||||
This option tells *criu* to accept the limitations when running
|
||||
as non-root. Running as non-root requires *criu* at least to have
|
||||
*CAP_SYS_ADMIN* or *CAP_CHECKPOINT_RESTORE*. For details about running
|
||||
*criu* as non-root please consult the *NON-ROOT* section.
|
||||
of restore, when nothing is restored yet except for namespaces
|
||||
themselves
|
||||
|
||||
*-V*, *--version*::
|
||||
Print program version and exit.
|
||||
|
|
@ -184,12 +135,6 @@ In addition, *page-server* options may be specified.
|
|||
Turn on memory changes tracker in the kernel. If the option is
|
||||
not passed the memory tracker get turned on implicitly.
|
||||
|
||||
*--pre-dump-mode*='mode'::
|
||||
There are two 'mode' to operate pre-dump algorithm. The 'splice' mode
|
||||
is parasite based, whereas 'read' mode is based on process_vm_readv
|
||||
syscall. The 'read' mode incurs reduced frozen time and reduced
|
||||
memory pressure as compared to 'splice' mode. Default is 'splice' mode.
|
||||
|
||||
*dump*
|
||||
~~~~~~
|
||||
Performs a checkpoint procedure.
|
||||
|
|
@ -213,57 +158,44 @@ In other words, do not use it unless really needed.
|
|||
*-s*, *--leave-stopped*::
|
||||
Leave tasks in stopped state after checkpoint, instead of killing.
|
||||
|
||||
*--external* __type__**[**__id__**]:**__value__::
|
||||
*--external* 'type'*[*'id'*]:*'value'::
|
||||
Dump an instance of an external resource. The generic syntax is
|
||||
'type' of resource, followed by resource 'id' (enclosed in literal
|
||||
square brackets), and optional 'value' (prepended by a literal colon).
|
||||
square brackets), and optional 'value' (prepended by a literal semicolon).
|
||||
The following resource types are currently supported: *mnt*, *dev*,
|
||||
*file*, *tty*, *unix*. Syntax depends on type.
|
||||
Note to restore external resources, either *--external* or *--inherit-fd*
|
||||
is used, depending on resource type.
|
||||
|
||||
*--external* **mnt[**__mountpoint__**]:**__name__::
|
||||
*--external mnt[*'mountpoint'*]:*'name'::
|
||||
Dump an external bind mount referenced by 'mountpoint', saving it
|
||||
to image under the identifier 'name'.
|
||||
|
||||
*--external* **mnt[]:**__flags__::
|
||||
*--external mnt[]:*'flags'::
|
||||
Dump all external bind mounts, autodetecting those. Optional 'flags'
|
||||
can contain *m* to also dump external master mounts, *s* to also
|
||||
dump external shared mounts (default behavior is to abort dumping
|
||||
if such mounts are found). If 'flags' are not provided, colon
|
||||
if such mounts are found). If 'flags' are not provided, semicolon
|
||||
is optional.
|
||||
|
||||
*--external* **dev[**__major__**/**__minor__**]:**__name__::
|
||||
*--external dev[*'major'*/*'minor'*]:*'name'::
|
||||
Allow to dump a mount namespace having a real block device mounted.
|
||||
A block device is identified by its 'major' and 'minor' numbers,
|
||||
and *criu* saves its information to image under the identifier 'name'.
|
||||
|
||||
*--external* **file[**__mnt_id__**:**__inode__**]**::
|
||||
*--external file[*'mnt_id'*:*'inode'*]*::
|
||||
Dump an external file, i.e. an opened file that is can not be resolved
|
||||
from the current mount namespace, which can not be dumped without using
|
||||
this option. The file is identified by 'mnt_id' (a field obtained from
|
||||
**/proc/**__pid__**/fdinfo/**__N__) and 'inode' (as returned by
|
||||
*stat*(2)).
|
||||
*/proc/*'pid'*/fdinfo/*'N') and 'inode' (as returned by *stat*(2)).
|
||||
|
||||
*--external* **tty[**__rdev__**:**__dev__**]**::
|
||||
*--external tty[*'rdev'*:*'dev'*]*::
|
||||
Dump an external TTY, identified by *st_rdev* and *st_dev* fields
|
||||
returned by *stat*(2).
|
||||
|
||||
*--external* **unix[**__id__**]**::
|
||||
*--external unix[*'id'*]*::
|
||||
Tell *criu* that one end of a pair of UNIX sockets (created by
|
||||
*socketpair*(2)) with the given _id_ is OK to be disconnected.
|
||||
|
||||
*--external* **net[**__inode__**]:**__name__::
|
||||
Mark a network namespace as external and do not include it in the
|
||||
checkpoint. The label 'name' can be used with *--inherit-fd* during
|
||||
restore to specify a file descriptor to a preconfigured network
|
||||
namespace.
|
||||
|
||||
*--external* **pid[**__inode__**]:**__name__::
|
||||
Mark a PID namespace as external. This can be later used to restore
|
||||
a process into an existing PID namespace. The label 'name' can be
|
||||
used to assign another PID namespace during restore with the help
|
||||
of *--inherit-fd*.
|
||||
*socketpair*(2)) with 'id' is OK to be disconnected.
|
||||
|
||||
*--freeze-cgroup*::
|
||||
Use cgroup freezer to collect processes.
|
||||
|
|
@ -313,42 +245,14 @@ For example, the command line for the above example should look like this:
|
|||
discovered automatically (usually via */proc*). This option is
|
||||
useful when one needs *criu* to skip some controllers.
|
||||
|
||||
*--cgroup-yard* 'path'::
|
||||
Instead of trying to mount cgroups in CRIU, provide a path to a directory
|
||||
with already created cgroup yard. Useful if you don't want to grant
|
||||
CAP_SYS_ADMIN to CRIU. For every cgroup mount there should be exactly one
|
||||
directory. If there is only one controller in this mount, the dir's name
|
||||
should be just the name of the controller. If there are multiple controllers
|
||||
comounted, the directory name should have them be separated by a comma.
|
||||
+
|
||||
For example, if */proc/cgroups* looks like this:
|
||||
+
|
||||
----------
|
||||
#subsys_name hierarchy num_cgroups enabled
|
||||
cpu 1 1 1
|
||||
devices 2 2 1
|
||||
freezer 2 2 1
|
||||
----------
|
||||
+
|
||||
then you can create the cgroup yard by the following commands:
|
||||
+
|
||||
----------
|
||||
mkdir private_yard
|
||||
cd private_yard
|
||||
mkdir cpu
|
||||
mount -t cgroup -o cpu none cpu
|
||||
mkdir devices,freezer
|
||||
mount -t cgroup -o devices,freezer none devices,freezer
|
||||
----------
|
||||
*--cgroup-props-ignore-default*::
|
||||
When combined with *--cgroup-props*, makes *criu* substitute
|
||||
a predefined controller property with the new one shipped. If the option
|
||||
is not used, the predefined properties are merged with the provided ones.
|
||||
|
||||
*--tcp-established*::
|
||||
Checkpoint established TCP connections.
|
||||
|
||||
*--tcp-close*::
|
||||
Don't dump the state of, or block, established tcp connections
|
||||
(including the connection is once established but now closed).
|
||||
This is useful when tcp connections are not going to be restored.
|
||||
|
||||
*--skip-in-flight*::
|
||||
This option skips in-flight TCP connections. If any TCP connections
|
||||
that are not yet completely established are found, *criu* ignores
|
||||
|
|
@ -378,64 +282,6 @@ mount -t cgroup -o devices,freezer none devices,freezer
|
|||
Allows to link unlinked files back, if possible (modifies filesystem
|
||||
during *restore*).
|
||||
|
||||
*-c, --compress*::
|
||||
Enable LZ4 per-page compression of memory pages during *dump*.
|
||||
Each system page is compressed as an independent LZ4 block.
|
||||
Zero-filled pages are detected and stored with no data; pages that
|
||||
do not compress well are stored raw to avoid decompression overhead
|
||||
on *restore*. The compression choice made at *dump* time is recorded
|
||||
in the inventory image and applied automatically on *restore*.
|
||||
Compatible with *--page-server* when *--tls* is not used, *--stream*,
|
||||
*--lazy-pages*, iterative checkpointing, *--auto-dedup*, and the *dedup*
|
||||
command.
|
||||
|
||||
*--compress-region* 'size'::
|
||||
Enable LZ4 region compression of memory pages during *dump*.
|
||||
A run of consecutive pages totalling 'size' bytes is compressed as
|
||||
a single LZ4 block, which yields a better ratio and faster dump
|
||||
on heap-shaped data than per-page compression at the cost of
|
||||
slightly slower restore on partial reads. 'size' accepts K/M/G
|
||||
suffixes (e.g. *256K*, *1M*); it must be a multiple of the system
|
||||
page size and at most 4M. Mutually exclusive with *--compress*.
|
||||
Currently supports only the local image path (no
|
||||
*--page-server* / *--stream*). Hole-punching deduplication is
|
||||
skipped for compressed images since compressed pages are
|
||||
variably-sized.
|
||||
|
||||
*--compress-acceleration* 'N'::
|
||||
Set the LZ4 acceleration level for page compression (1 to 65537).
|
||||
Controls how thoroughly the compressor searches for matching byte
|
||||
sequences. The default value of 1 gives the best compression
|
||||
ratio. Higher values skip more match candidates, resulting in
|
||||
faster compression but larger output. Decompression speed is not
|
||||
affected. Implies *--compress* unless *--compress-region* is set.
|
||||
|
||||
*--decompress-threads* 'N'::
|
||||
Set worker concurrency for LZ4 decoding and eligible large zero fills,
|
||||
including the calling restore thread. The default value of 1 keeps each
|
||||
LZ4 decode serial and handles zero blocks without a worker pool;
|
||||
independent private, shmem, and memfd requests can still run concurrently.
|
||||
A value of 0 lets CRIU choose the concurrency for each batch. CRIU starts
|
||||
with the CPUs allowed by its affinity mask, then limits the width by the
|
||||
number and decoded size of the blocks in that batch and by the restore-wide
|
||||
CPU budget. Small batches and zero runs with fewer than two blocks remain
|
||||
serial. Values above 1 set an upper bound on aggregate worker concurrency
|
||||
instead of using the automatic CPU count. Explicit requests above the
|
||||
available CPU count are reduced with a warning. The accepted range is 0
|
||||
through 1024; this validation ceiling does not determine the automatic
|
||||
concurrency.
|
||||
Encoded staging memory is bounded independently of the thread count.
|
||||
Restore keeps at most two active 32 MiB encoded input buffers. When a
|
||||
local reader can reserve a second buffer without waiting, its calling thread
|
||||
reads the next payload while pool workers decode the current one. If
|
||||
another restore request already owns the second buffer, reading remains
|
||||
synchronous. The option can also be set through a configuration file
|
||||
(*decompress-threads 0*).
|
||||
|
||||
*--timeout* 'number'::
|
||||
Set a time limit in seconds for collecting tasks during the
|
||||
dump operation. The timeout is 10 seconds by default.
|
||||
|
||||
*--ghost-limit* 'size'::
|
||||
Set the maximum size of deleted file to be carried inside image.
|
||||
By default, up to 1M file is allowed. Using this
|
||||
|
|
@ -443,13 +289,6 @@ mount -t cgroup -o devices,freezer none devices,freezer
|
|||
'size' may be postfixed with a *K*, *M* or *G*, which stands for kilo-,
|
||||
mega, and gigabytes, accordingly.
|
||||
|
||||
*--ghost-fiemap*::
|
||||
Enable an optimization based on fiemap ioctl that can reduce the
|
||||
number of system calls used when checkpointing highly sparse ghost
|
||||
files. This option is enabled by default, and it can be disabled
|
||||
with *--no-ghost-fiemap*. An automatic fallback to SEEK_HOLE/SEEK_DATA
|
||||
is used when fiemap is not supported.
|
||||
|
||||
*-j*, *--shell-job*::
|
||||
Allow one to dump shell jobs. This implies the restored task will
|
||||
inherit session and process group ID from the *criu* itself.
|
||||
|
|
@ -459,17 +298,9 @@ mount -t cgroup -o devices,freezer none devices,freezer
|
|||
|
||||
*--cpu-cap* ['cap'[,'cap'...]]::
|
||||
Specify CPU capabilities to write to an image file. The argument is a
|
||||
comma-separated list of:
|
||||
+
|
||||
- *none* to ignore capabilities at all; the image will not be produced
|
||||
on dump, neither any check performed on restore;
|
||||
- *fpu* to check if FPU module is compatible;
|
||||
- *ins* to check if CPU supports all instructions required;
|
||||
- *cpu* to check if CPU capabilities are exactly matching;
|
||||
- *all* for all above set.
|
||||
|
||||
+
|
||||
By default the option is set to *fpu* and *ins*.
|
||||
comma-separated list of *none*, *fpu*, *cpu*, *ins*, *all*. If the
|
||||
argument is omitted or set to *none*, capabilities will not be written,
|
||||
which is the default behavior.
|
||||
|
||||
*--cgroup-root* ['controller':]/'newroot'::
|
||||
Change the root for the controller that will be dumped. By default, *criu*
|
||||
|
|
@ -478,103 +309,22 @@ By default the option is set to *fpu* and *ins*.
|
|||
engine's default directory for tasks, permissions will not be preserved on
|
||||
the upper directories with no tasks in them, which may cause problems.
|
||||
|
||||
*--lazy-pages*::
|
||||
Perform the dump procedure without writing memory pages into the
|
||||
image files and prepare to service page requests over the
|
||||
network. When *dump* runs in this mode it presumes that
|
||||
*lazy-pages* daemon will connect to it and fetch memory pages to
|
||||
lazily inject them into the restored process address space. This
|
||||
option is intended for post-copy (lazy) migration and should be
|
||||
used in conjunction with *restore* with appropriate options.
|
||||
|
||||
*--file-validation* ['mode']::
|
||||
Set the method to be used to validate open files. Validation is done
|
||||
to ensure that the version of the file being restored is the same
|
||||
version when it was dumped.
|
||||
+
|
||||
The 'mode' may be one of the following:
|
||||
|
||||
*filesize*:::
|
||||
To explicitly use only the file size check all the time.
|
||||
This is the fastest and least intensive check.
|
||||
|
||||
*buildid*:::
|
||||
To validate ELF files with their build-ID. If the
|
||||
build-ID cannot be obtained, 'chksm-first' method will be
|
||||
used. This is the default if mode is unspecified.
|
||||
|
||||
*--image-io-mode* ['mode']::
|
||||
Set the I/O mode used when writing and reading the memory pages
|
||||
image. It controls whether the host page cache is used. The mode is
|
||||
selected independently for *dump* and *restore*; the image bytes are
|
||||
identical either way.
|
||||
+
|
||||
The 'mode' may be one of the following:
|
||||
|
||||
*writeback*:::
|
||||
Buffered I/O via the host page cache. This is the default.
|
||||
|
||||
*direct*:::
|
||||
Use O_DIRECT to bypass the host page cache. If the
|
||||
filesystem does not support O_DIRECT, *criu* falls back to
|
||||
buffered I/O.
|
||||
|
||||
*--network-lock* ['mode']::
|
||||
Set the method to be used for network locking/unlocking. Locking is done
|
||||
to ensure that tcp packets are dropped between dump and restore. This is
|
||||
done to avoid the kernel sending RST when a packet arrives destined for
|
||||
the dumped process.
|
||||
+
|
||||
The 'mode' may be one of the following:
|
||||
|
||||
*iptables*::: Use iptables rules to drop the packets.
|
||||
This is the default if 'mode' is not specified.
|
||||
|
||||
*nftables*::: Use nftables rules to drop the packets.
|
||||
|
||||
*skip*::: Don't lock the network. If *--tcp-close* is not used, the network
|
||||
must be locked externally to allow CRIU to dump TCP connections.
|
||||
|
||||
*--allow-uprobes*::
|
||||
Allow dumping when uprobes vma is present. When used on dump, this option is
|
||||
required on restore as well.
|
||||
|
||||
A uprobes vma is automatically created by the kernel once a uprobe is
|
||||
triggered. This mapping is not removed even once the uprobe is deleted. So,
|
||||
even if a process once had uprobes attached to it, and they're removed by
|
||||
the time the process is dumped, this option is still required because criu
|
||||
has no way of knowing whether there are active uprobes or not.
|
||||
|
||||
When using this option on restore, make sure the uprobes (if any) active on
|
||||
the dumped processes are still active. Otherwise, when execution reaches
|
||||
a uprobe'd location in any of the restored processes, that process will be
|
||||
sent a SIGTRAP.
|
||||
|
||||
As an example, say a uprobe is set at function foo in the executable of the
|
||||
process p_bar. Whenever execution in p_bar reaches function foo, the uprobe
|
||||
is triggered. If the uprobe has been triggered at least once, then the kernel
|
||||
will have created the uprobes vma. To dump p_bar, this option is
|
||||
necessary. After dumping, say the uprobe is deleted. Now, on restoring with
|
||||
this option, once execution reaches function foo, SIGTRAP will be sent to
|
||||
the restored p_bar. Unless it has a signal handler installed for SIGTRAP,
|
||||
it will be terminated and core dumped.
|
||||
|
||||
*restore*
|
||||
~~~~~~~~~
|
||||
Restores previously checkpointed processes.
|
||||
|
||||
*--inherit-fd* **fd[**__N__**]:**__resource__::
|
||||
*--inherit-fd* *fd[*'N'*]:*'resource'::
|
||||
Inherit a file descriptor. This option lets *criu* use an already opened
|
||||
file descriptor 'N' for restoring a file identified by 'resource'.
|
||||
This option can be used to restore an external resource dumped
|
||||
with the help of *--external* *file*, *tty*, *pid* and *unix* options.
|
||||
with the help of *--external* *file*, *tty*, and *unix* options.
|
||||
+
|
||||
The 'resource' argument can be one of the following:
|
||||
+
|
||||
- **tty[**__rdev__**:**__dev__**]**
|
||||
- **pipe:[**__inode__**]**
|
||||
- **socket:[**__inode__*]*
|
||||
- **file[**__mnt_id__**:**__inode__**]**
|
||||
- *tty[*'rdev'*:*'dev'*]*
|
||||
- *pipe[*'inode'*]*
|
||||
- *socket[*'inode'*]*
|
||||
- *file[*'mnt_id'*:*'inode'*]*
|
||||
- 'path/to/file'
|
||||
|
||||
+
|
||||
|
|
@ -592,25 +342,20 @@ usually need to be escaped from shell.
|
|||
Restore root task as a sibling (makes sense only with
|
||||
*--restore-detached*).
|
||||
|
||||
*--log-pid*::
|
||||
Write separate logging files per each pid.
|
||||
|
||||
*-r*, *--root* 'path'::
|
||||
Change the root filesystem to 'path' (when run in a mount namespace).
|
||||
This option is required to restore a mount namespace. The directory
|
||||
'path' must be a mount point and its parent must not be overmounted.
|
||||
|
||||
*--external* __type__**[**__id__**]:**__value__::
|
||||
*--external* 'type'*[*'id'*]:*'value'::
|
||||
Restore an instance of an external resource. The generic syntax is
|
||||
'type' of resource, followed by resource 'id' (enclosed in literal
|
||||
square brackets), and optional 'value' (prepended by a literal colon).
|
||||
square brackets), and optional 'value' (prepended by a literal semicolon).
|
||||
The following resource types are currently supported: *mnt*, *dev*,
|
||||
*veth*, *macvlan*. Syntax depends on type. Note to restore external
|
||||
resources dealing with opened file descriptors (such as dumped with
|
||||
the help of *--external* *file*, *tty*, and *unix* options), option
|
||||
*--inherit-fd* should be used.
|
||||
|
||||
*--external* **mnt[**__name__**]:**__mountpoint__::
|
||||
*--external mnt[*'name'*]:*'mountpoint'::
|
||||
Restore an external bind mount referenced in the image by 'name',
|
||||
bind-mounting it from the host 'mountpoint' to a proper mount point.
|
||||
|
||||
|
|
@ -618,36 +363,26 @@ usually need to be escaped from shell.
|
|||
Restore all external bind mounts (dumped with the help of
|
||||
*--external mnt[]* auto-detection).
|
||||
|
||||
*--external* **dev[**__name__**]:**__/dev/path__::
|
||||
*--external dev[*'name'*]:*'/dev/path'::
|
||||
Restore an external mount device, identified in the image by 'name',
|
||||
using the existing block device '/dev/path'.
|
||||
|
||||
*--external* **veth[**__inner_dev__**]:**__outer_dev__**@**__bridge__::
|
||||
*--external veth[*'inner_dev'*]:*'outer_dev'*@*'bridge'::
|
||||
Set the outer VETH device name (corresponding to 'inner_dev' being
|
||||
restored) to 'outer_dev'. If optional **@**_bridge_ is specified,
|
||||
restored) to 'outer_dev'. If optional *@*'bridge' is specified,
|
||||
'outer_dev' is added to that bridge. If the option is not used,
|
||||
'outer_dev' will be autogenerated by the kernel.
|
||||
|
||||
*--external* **macvlan[**__inner_dev__**]:**__outer_dev__::
|
||||
*--external macvlan[*'inner_dev'*]:*'outer_dev'::
|
||||
When restoring an image that have a MacVLAN device in it, this option
|
||||
must be used to specify to which 'outer_dev' (an existing network device
|
||||
in CRIU namespace) the restored 'inner_dev' should be bound to.
|
||||
|
||||
*-J*, *--join-ns* **NS**:{**PID**|**NS_FILE**}[,**EXTRA_OPTS**]::
|
||||
Restore process tree inside an existing namespace. The namespace can
|
||||
be specified in 'PID' or 'NS_FILE' path format (example:
|
||||
*--join-ns net:12345* or *--join-ns net:/foo/bar*). Currently supported
|
||||
values for **NS** are: *ipc*, *net*, *time*, *user*, and *uts*.
|
||||
This option doesn't support joining a PID namespace, however, this is
|
||||
possible using *--external* and *--inheritfd*. 'EXTRA_OPTS' is optional
|
||||
and can be used to specify UID and GID for user namespace (e.g.,
|
||||
*--join-ns user:PID,UID,GID*).
|
||||
|
||||
*--manage-cgroups* ['mode']::
|
||||
Restore cgroups configuration associated with a task from the image.
|
||||
Controllers are always restored in an optimistic way -- if already present
|
||||
in system, *criu* reuses it, otherwise it will be created.
|
||||
+
|
||||
|
||||
The 'mode' may be one of the following:
|
||||
|
||||
*none*::: Do not restore cgroup properties but require cgroup to
|
||||
|
|
@ -657,20 +392,13 @@ The 'mode' may be one of the following:
|
|||
|
||||
*soft*::: Restore cgroup properties if only cgroup has been created
|
||||
by *criu*, otherwise do not restore properties. This is the
|
||||
default if mode is unspecified.
|
||||
default if mode is unspecified.
|
||||
|
||||
*full*::: Always restore all cgroups and their properties.
|
||||
|
||||
*strict*::: Restore all cgroups and their properties from the scratch,
|
||||
requiring them to not present in the system.
|
||||
|
||||
*ignore*::: Don't deal with cgroups and pretend that they don't exist.
|
||||
|
||||
*--cgroup-yard* 'path'::
|
||||
Instead of trying to mount cgroups in CRIU, provide a path to a directory
|
||||
with already created cgroup yard. For more information look in the *dump*
|
||||
section.
|
||||
|
||||
*--cgroup-root* ['controller'*:*]/'newroot'::
|
||||
Change the root cgroup the controller will be installed into. No controller
|
||||
means that root is the default for all controllers not specified.
|
||||
|
|
@ -680,41 +408,12 @@ The 'mode' may be one of the following:
|
|||
the network has been locked between *dump* and *restore* phases so other
|
||||
side of a connection simply notice a kind of lag.
|
||||
|
||||
*--tcp-close*::
|
||||
Restore connected TCP sockets in closed state.
|
||||
|
||||
*--veth-pair* __IN__**=**__OUT__::
|
||||
*--veth-pair* 'IN'*=*'OUT'::
|
||||
Correspondence between outside and inside names of veth devices.
|
||||
|
||||
*-l*, *--file-locks*::
|
||||
Restore file locks from the image.
|
||||
|
||||
*--lsm-profile* __type__**:**__name__::
|
||||
Specify an LSM profile to be used during restore. The _type_ can be
|
||||
either *apparmor* or *selinux*.
|
||||
|
||||
*--lsm-mount-context* 'context'::
|
||||
Specify a new mount context to be used during restore.
|
||||
+
|
||||
This option will only replace existing mount context information
|
||||
with the one specified with this option. Mounts without the
|
||||
'context=' option will not be changed.
|
||||
+
|
||||
If a mountpoint has been checkpointed with an option like
|
||||
|
||||
context="system_u:object_r:container_file_t:s0:c82,c137"
|
||||
+
|
||||
it is possible to change this option using
|
||||
|
||||
--lsm-mount-context "system_u:object_r:container_file_t:s0:c204,c495"
|
||||
+
|
||||
which will result that the mountpoint will be restored
|
||||
with the new 'context='.
|
||||
+
|
||||
This option is useful if using *selinux* and if the *selinux*
|
||||
labels need to be changed on restore like if a container is
|
||||
restored into an existing Pod.
|
||||
|
||||
*--auto-dedup*::
|
||||
As soon as a page is restored it get punched out from image.
|
||||
|
||||
|
|
@ -759,53 +458,6 @@ are not adequate, but this can be suppressed by using *--cpu-cap=none*.
|
|||
to restore on an older kernel, or a kernel configured without some
|
||||
options.
|
||||
|
||||
*--lazy-pages*::
|
||||
Restore the processes without filling out the entire memory
|
||||
contents. When this option is used, *restore* sets up the
|
||||
infrastructure required to fill memory pages either on demand when
|
||||
the process accesses them or in the background without stopping the
|
||||
restored process.
|
||||
This option requires running *lazy-pages* daemon.
|
||||
|
||||
*--file-validation* ['mode']::
|
||||
Set the method to be used to validate open files. Validation is done
|
||||
to ensure that the version of the file being restored is the same
|
||||
version when it was dumped.
|
||||
+
|
||||
The 'mode' may be one of the following:
|
||||
|
||||
*filesize*:::
|
||||
To explicitly use only the file size check all the time.
|
||||
This is the fastest and least intensive check.
|
||||
|
||||
*buildid*:::
|
||||
To validate ELF files with their build-ID. If the
|
||||
build-ID cannot be obtained, 'chksm-first' method will be
|
||||
used. This is the default if mode is unspecified.
|
||||
|
||||
*--image-io-mode* ['mode']::
|
||||
Set the I/O mode used when writing and reading the memory pages
|
||||
image. It controls whether the host page cache is used. The mode is
|
||||
selected independently for *dump* and *restore*; the image bytes are
|
||||
identical either way.
|
||||
+
|
||||
The 'mode' may be one of the following:
|
||||
|
||||
*writeback*:::
|
||||
Buffered I/O via the host page cache. This is the default.
|
||||
|
||||
*direct*:::
|
||||
Use O_DIRECT to bypass the host page cache. If the
|
||||
filesystem does not support O_DIRECT, *criu* falls back to
|
||||
buffered I/O.
|
||||
|
||||
*--skip-file-rwx-check*::
|
||||
Skip checking file permissions (r/w/x for u/g/o) on restore.
|
||||
|
||||
*--allow-uprobes*::
|
||||
Required when dumped with this option. Refer to this option in the section
|
||||
on dumping for more details.
|
||||
|
||||
*check*
|
||||
~~~~~~~
|
||||
Checks whether the kernel supports the features needed by *criu* to
|
||||
|
|
@ -816,17 +468,17 @@ check* always checks Category 1 features unless *--feature* is specified
|
|||
which only checks a specified feature.
|
||||
|
||||
*Category 1*::: Absolutely required. These are features like support for
|
||||
*/proc/PID/map_files*, *NETLINK_SOCK_DIAG* socket
|
||||
monitoring, */proc/sys/kernel/ns_last_pid* etc.
|
||||
*/proc/PID/map_files*, *NETLINK_SOCK_DIAG* socket
|
||||
monitoring, */proc/sys/kernel/ns_last_pid* etc.
|
||||
|
||||
*Category 2*::: Required only for specific cases. These are features
|
||||
like AIO remap, */dev/net/tun* and others that are only
|
||||
required if a process being dumped or restored
|
||||
is using those.
|
||||
like AIO remap, */dev/net/tun* and others that are only
|
||||
required if a process being dumped or restored
|
||||
is using those.
|
||||
|
||||
*Category 3*::: Experimental. These are features like *task-diag* that
|
||||
are used for experimental purposes (mostly
|
||||
during development).
|
||||
are used for experimental purposes (mostly
|
||||
during development).
|
||||
|
||||
If there are no errors or warnings, *criu* prints "Looks good." and its
|
||||
exit code is 0.
|
||||
|
|
@ -860,69 +512,18 @@ Launches *criu* in page server mode.
|
|||
*--daemon*::
|
||||
Runs page server as a daemon (background process).
|
||||
|
||||
*--status-fd*::
|
||||
Write \0 to the FD and close it once page-server is ready to handle
|
||||
*--status_fd*::
|
||||
Write \\0 to the FD and close it once page-server is ready to handle
|
||||
requests. The status-fd allows to not daemonize a process and get its
|
||||
exit code at the end.
|
||||
It isn't supposed to use --daemon and --status-fd together.
|
||||
|
||||
*--address* 'address'::
|
||||
Page server IP address or hostname.
|
||||
Page server IP address.
|
||||
|
||||
*--port* 'number'::
|
||||
Page server port number.
|
||||
|
||||
*--ps-socket* 'fd'::
|
||||
Use provided file descriptor as socket for incoming connection.
|
||||
In this case --address and --port are ignored.
|
||||
Useful for intercepting page-server traffic e.g. to add encryption
|
||||
or authentication.
|
||||
|
||||
*--lazy-pages*::
|
||||
Serve local memory dump to a remote *lazy-pages* daemon. In this
|
||||
mode the *page-server* reads local memory dump and allows the
|
||||
remote *lazy-pages* daemon to request memory pages in random
|
||||
order.
|
||||
|
||||
*--tls-cacert* 'file'::
|
||||
Specifies the path to a trusted Certificate Authority (CA) certificate
|
||||
file to be used for verification of a client or server certificate.
|
||||
The 'file' must be in PEM format. When this option is used only the
|
||||
specified CA is used for verification. Otherwise, the system's trusted CAs
|
||||
and, if present, '/etc/pki/CA/cacert.pem' will be used.
|
||||
|
||||
*--tls-cacrl* 'file'::
|
||||
Specifies a path to a Certificate Revocation List (CRL) 'file' which
|
||||
contains a list of revoked certificates that should no longer be trusted.
|
||||
The 'file' must be in PEM format. When this option is not specified, the
|
||||
file, if present, '/etc/pki/CA/cacrl.pem' will be used.
|
||||
|
||||
*--tls-cert* 'file'::
|
||||
Specifies a path to a file that contains a X.509 certificate to present
|
||||
to the remote entity. The 'file' must be in PEM format. When this option
|
||||
is not specified, the default location ('/etc/pki/criu/cert.pem') will be
|
||||
used.
|
||||
|
||||
*--tls-key* 'file'::
|
||||
Specifies a path to a file that contains TLS private key. The 'file' must
|
||||
be in PEM format. When this option is not the default location
|
||||
('/etc/pki/criu/private/key.pem') will be used.
|
||||
|
||||
*--tls*::
|
||||
Use TLS to secure remote connections.
|
||||
|
||||
*lazy-pages*
|
||||
~~~~~~~~~~~~
|
||||
Launches *criu* in lazy-pages daemon mode.
|
||||
|
||||
The *lazy-pages* daemon is responsible for managing user-level demand
|
||||
paging for the restored processes. It gets information required to
|
||||
fill the process memory pages from the *restore* and from the
|
||||
checkpoint directory. When a restored process access certain memory
|
||||
page for the first time, the *lazy-pages* daemon injects its contents
|
||||
into the process address space. The memory pages that are not yet
|
||||
requested by the restored processes are injected in the background.
|
||||
|
||||
*exec*
|
||||
~~~~~~
|
||||
Executes a system call inside a destination task\'s context. This functionality
|
||||
|
|
@ -951,103 +552,6 @@ Fetches current CPU features (i.e. CPU the *criu* is running on) and test if
|
|||
they are compatible with the ones present in an image file.
|
||||
|
||||
|
||||
CONFIGURATION FILES
|
||||
-------------------
|
||||
*Criu* supports usage of configuration files to avoid the need of writing every
|
||||
option on command line, which is useful especially with repeated usage of
|
||||
same options. A specific configuration file can be passed with
|
||||
the "*--config* 'file'" option. If no file is passed, the default configuration
|
||||
files '/etc/criu/default.conf' and '$HOME/.criu/default.conf' are parsed (if
|
||||
present on the system). If the environment variable CRIU_CONFIG_FILE is set,
|
||||
it will also be parsed.
|
||||
|
||||
The options passed to CRIU via CLI, RPC or configuration file are evaluated
|
||||
in the following order:
|
||||
|
||||
- apply_config(/etc/criu/default.conf)
|
||||
- apply_config($HOME/.criu/default.conf)
|
||||
- apply_config(CRIU_CONFIG_FILE)
|
||||
- apply_config(*--config* 'file')
|
||||
- apply_config(CLI) or apply_config(RPC)
|
||||
- apply_config(RPC configuration file) (only for RPC mode)
|
||||
|
||||
Default configuration file parsing can be deactivated
|
||||
with "*--no-default-config*" if needed. Parsed configuration files are merged
|
||||
with command line options, which allows overriding boolean options.
|
||||
|
||||
Configuration file syntax
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Comments are supported using \'#' sign. The rest of the line is ignored.
|
||||
Options are the same as command line options without the \'--' prefix, use
|
||||
one option per line (with corresponding argument if applicable, divided by
|
||||
whitespaces). If needed, the argument can be provided in double quotes (this
|
||||
should be needed only if the argument contains whitespaces). In case this type
|
||||
of argument contains a literal double quote as well, it can be escaped using
|
||||
the \'\' sign. Usage of commands is disallowed and all other escape sequences
|
||||
are interpreted literally.
|
||||
|
||||
Example of configuration file to illustrate syntax:
|
||||
---------------
|
||||
$ cat ~/.criu/default.conf
|
||||
tcp-established
|
||||
work-dir "/home/USERNAME/criu/my \"work\" directory"
|
||||
#this is a comment
|
||||
no-restore-sibling # this is another comment
|
||||
---------------
|
||||
|
||||
Configuration files in RPC mode
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Not only does *criu* evaluate configuration files in CLI mode, it also
|
||||
evaluates configuration files in RPC mode. Just as in CLI mode the
|
||||
configuration file values are evaluated first. This means that any option
|
||||
set via RPC will overwrite the configuration file setting. The user can
|
||||
thus change *criu*'s default behavior but it is not possible to change
|
||||
settings which are explicitly set by the RPC client.
|
||||
|
||||
The RPC client can, however, specify an additional configuration file
|
||||
which will be evaluated after the RPC options (see above for option evaluation
|
||||
order). The RPC client can specify this additional configuration file
|
||||
via "req.opts.config_file = '/path/to/file'". The values from this
|
||||
configuration file will overwrite all other configuration file settings
|
||||
or RPC options. *This can lead to undesired behavior of criu and
|
||||
should only be used carefully.*
|
||||
|
||||
NON-ROOT
|
||||
--------
|
||||
*criu* can be used as non-root with either the *CAP_SYS_ADMIN* capability
|
||||
or with the *CAP_CHECKPOINT_RESTORE* capability introduces in Linux kernel 5.9.
|
||||
*CAP_CHECKPOINT_RESTORE* is the minimum that is required.
|
||||
|
||||
*criu* also needs either *CAP_SYS_PTRACE* or a value of 0 in
|
||||
*/proc/sys/kernel/yama/ptrace_scope* (see *ptrace*(2)) to be able to interrupt
|
||||
the process for dumping.
|
||||
|
||||
Running *criu* as non-root has many limitations and depending on the process
|
||||
to checkpoint and restore it may not be possible.
|
||||
|
||||
In addition to *CAP_CHECKPOINT_RESTORE* it is possible to give *criu* additional
|
||||
capabilities to enable additional features in non-root mode.
|
||||
|
||||
Currently *criu* can benefit from the following additional capabilities:
|
||||
|
||||
- *CAP_NET_ADMIN*
|
||||
- *CAP_SYS_CHROOT*
|
||||
- *CAP_SETUID*
|
||||
- *CAP_SYS_RESOURCE*
|
||||
|
||||
Note that for some operations, having a capability in a namespace other than
|
||||
the init namespace (i.e. the default/root namespace) is not sufficient. For
|
||||
example, in order to read symlinks in proc/[pid]/map_files CRIU requires
|
||||
CAP_CHECKPOINT_RESTORE in the init namespace; having CAP_CHECKPOINT_RESTORE
|
||||
while running in another user namespace (e.g. in a container) does not allow
|
||||
CRIU to read symlinks in /proc/[pid]/map_files.
|
||||
|
||||
Without access to /proc/[pid]/map_files checkpointing/restoring processes
|
||||
that have mapped deleted files may not be possible.
|
||||
|
||||
Independent of the capabilities it is always necessary to use "*--unprivileged*" to
|
||||
accept *criu*'s limitation in non-root mode.
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
To checkpoint a program with pid of *1234* and write all image files into
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="560px" height="560px" viewBox="0 0 560 560" enable-background="new 0 0 560 560" xml:space="preserve">
|
||||
<path opacity="0.3" fill="#990000" d="M315.137,360.271c-18.771-7.159-41.548-8.85-68.479-8.85c-16.661,0-46.255,2.939-74.654,3.38
|
||||
c11.209-4.884,20.734-10.265,24.842-16.87c14.531-23.346,17.645-65.893,17.645-65.893l-20.758,3.114c0,0-2.591,35.8-16.085,47.733
|
||||
c-5.35,4.736-15.96,7.834-27.916,10.856c2.447-26.071,29.477-57.552,29.477-57.552l-14.874-3.966l-5.88-7.448
|
||||
c0,0-3.011,1.761-7.588,5.315c-18.298,4.208-75.946,20.443-75.946,57.983c0,15.292,5.77,26.308,14.768,34.244
|
||||
c-22.858,26.966-20.755,61.618-20.755,61.618s-8.945,16.61-8.021,31.254c2.083,32.973,34.931,25.097,44.313,26.374
|
||||
c9.644,1.313,34.313-4.18,34.313-4.18s-16.276-2.639-15.329-18.562c0.5-8.369-0.947-27.628-21.404-37.307
|
||||
c-1.13-10.066,2.111-18.309,6.379-28.015c18.452,45.263,92.601,53.97,92.601,53.97c0.393-0.097-10.269,20.047,0.221,35.632
|
||||
c4.652,6.915,18.284,10.019,22.436,19.356c4.151,9.341,2.199,30.354,2.199,30.354s21.267-16.864,27.239-30.18
|
||||
c3.334-7.432,25.989,0.926,25.989-34.047c0-14.077-12.26-26.841-13.675-29.815c-20.858-20.334-5.427-4.743,2.677-8.236
|
||||
c12.758-5.499,35.412,11.657,35.412,11.657s-10.402-20.119-11.437-31.013c-0.795-8.335-4.537-16.816-16.624-30.042
|
||||
c7.166-0.752,20.362,2.327,20.362,2.327s-5.202,11.251-0.879,25.515c3.588,11.84,7.193,7.193,14.736,14.737
|
||||
c6.599,6.598,3.146,26.284,3.146,26.284s4.674-4.513,18.081-18.235c9.072-9.29,23.645-16.717,23.645-47.86
|
||||
C355.312,365.969,334.97,360.979,315.137,360.271z M134.108,285.901c-11.5,13.048-23.667,32.329-28.23,58.293
|
||||
c-4.821-3.519-7.613-8.1-7.613-14.043C98.265,309.699,117.078,295.016,134.108,285.901z"/>
|
||||
<path fill="#990000" d="M382.184,115.435c3.654,1.208,7.327,2.37,10.968,3.444c14.16,4.183,26.745-9.798,26.745-9.798
|
||||
s-8.785-2.243-17.857-3.497c12.173-2.653,21.085-18.66,21.085-18.66s-17.366,4.819-27.224,5.087
|
||||
c-2.042,0.057-4.107,0.118-6.189,0.186c2.464-0.37,4.925-0.847,7.361-1.485c14.201-3.714,21.505-23.382,21.505-23.382
|
||||
s-15.411,6.743-24.951,9.239c-2.694,0.703-5.438,1.437-8.197,2.185c3.038-1.071,6.008-2.306,8.815-3.82
|
||||
c12.922-6.965,12.241-29.347,12.241-29.347s-10.162,11.926-18.844,16.605c-3.557,1.916-7.199,3.904-10.846,5.911
|
||||
c3.798-2.277,7.45-4.743,10.596-7.569c10.918-9.814,7.722-29.605,7.722-29.605s-9.801,12.54-17.135,19.131
|
||||
c-8.939,8.037-18.775,14.104-27.014,21.81c-6.427,6.011-25.14,35.236-36.812,46.283c-11.671,11.047-18.301,12.476-19.159,14.388
|
||||
c-0.863,1.913,1.006,30.46-14.078,39.145c-16.476-21.583-50.565-44.007-53.101-72.033c-2.079-22.959,5.209-34.055,19.149-35.316
|
||||
c14.994-1.359,15.998,24.507,15.998,24.507s-1.379,1.064-1.708,6.391c-0.097,0.629-0.145,1.272-0.083,1.934
|
||||
c0.004,0.031,0.008,0.06,0.011,0.091c-0.014,1.674,0.065,3.664,0.278,6.039c1.131,12.474,4.53,14.574,4.53,14.574l2.075-0.722
|
||||
c0,0-2.24-4.079-2.554-7.529c-0.172-1.917-0.187-3.556-0.079-4.977c0.45,0.067,0.949,0.081,1.506,0.031
|
||||
c4.398-0.399,6.049-4.141,5.65-8.539c-0.042-0.45-0.069-0.885-0.094-1.316c2.485-26.032-1.756-29.637,4.788-41.391
|
||||
c9.032-16.218,17.279-16.015,17.279-16.015l1.402-8.155c0,0-6.817,2.462-14.819,13.652c-8.833,12.354-8.983,26.229-9.066,47.958
|
||||
c-0.188-0.761-0.502-1.37-1.017-1.784c-2.457-11.192-9.087-32.13-24.112-30.77c-16.72,1.514-29.419,14.974-26.773,44.171
|
||||
c3.609,39.832,26.186,52.701,29.829,80.84c-13.47-2.349-23.883-10.656-30.866-20.282c-7.803-10.749-7.297-22.949-8.324-24.779
|
||||
c-1.027-1.829-7.761-2.662-20.367-12.627c-12.605-9.965-33.845-37.41-40.78-42.824c-8.895-6.942-19.229-12.111-28.848-19.32
|
||||
c-7.892-5.915-18.769-17.531-18.769-17.531s-1.419,19.995,10.323,28.8c3.386,2.536,7.246,4.665,11.229,6.597
|
||||
c-3.808-1.674-7.616-3.33-11.327-4.925c-9.062-3.887-20.246-14.861-20.246-14.861s1.31,22.353,14.803,28.143
|
||||
c2.931,1.257,6,2.223,9.12,3.019c-2.818-0.5-5.615-0.985-8.357-1.447c-9.728-1.636-25.677-6.981-25.677-6.981
|
||||
s9.025,18.94,23.5,21.376c2.485,0.417,4.975,0.674,7.466,0.822c-2.08,0.118-4.148,0.242-6.183,0.368
|
||||
c-9.843,0.61-27.566-2.645-27.566-2.645S85.667,120.333,110,120c-8.922,2.057-25.678,6.008-25.678,6.008s13.778,12.806,27.508,7.38
|
||||
c3.533-1.394,7.087-2.876,10.62-4.404c-3.726,1.804-7.424,3.581-11.005,5.273c-8.963,4.243-19.428,10.176-19.428,10.176
|
||||
s15.069,9.759,27.305,1.497c0.558-0.378,3.121-1.76,3.678-2.143c-7.904,5.808-19.754,14.937-19.754,14.937
|
||||
s15.802,6.027,27.092-3.354c4.663-3.875,8.104-7.185,12.238-11.618c-3.773,4.55-6.699,8.018-10.634,12.106
|
||||
c-6.839,7.104-13.06,19.791-13.06,19.791s15.597,0.39,24.359-11.388c4.488-6.035,7.482-11.633,10.974-18.191
|
||||
c-3.113,6.479-5.468,11.95-8.911,17.788c-5.018,8.49-7.574,22.624-7.574,22.624s15.342-3.655,21.07-17.17
|
||||
c2.231-5.266,2.107-9.783,3.694-15.291c-1.257,5.272-0.666,9.475-2.24,14.319c-3.045,9.379,0.011,25.554,0.011,25.554
|
||||
s9.713-5.855,10.359-20.52c0.006-0.153,0.5-8.47,0.5-8.625L171,171.496c0,9.917,6.295,23.276,6.295,23.276
|
||||
s11.459-10.649,9.369-25.266c-0.188-1.31-0.1-2.627-0.305-3.947c0.408,1.507,0.998,3.016,1.493,4.524
|
||||
c3.075,9.429,3.5,15.957,3.5,15.957s6.483,1.251,8.73-1.594c0.764,5.625-0.843,10.2-0.843,10.2s5.471-1.1,8.893-3.756
|
||||
c0.705,5.331,0.155,8.789,0.155,8.789s5.106-1.603,8.419-4.323c0.611,4.642,1.764,7.542,1.764,7.542s6.398-0.88,9.021-5.393
|
||||
c0.199,0.038,0.395,0.079,0.59,0.117c2.269,4.875,1.438,8.517,1.438,8.517s7.492-2.14,9.492-6.14c0.003,0,0.007,0,0.01,0
|
||||
c1.798,4,2.727,6.102,2.727,6.102s4.853-2.349,7.093-6.064c0.189,0.009,0.364-0.093,0.547-0.086
|
||||
c-4.702,19.629-23.62,29.658-42.207,42.764c-1.392,0.981-2.712,1.925-3.97,2.884c-2.891,1.512-6.788,3.495-11.311,5.724
|
||||
c-9.829,3.363-23.7,6.057-41.038,4.084c-9.798-1.115-21.037,10.02-21.037,10.02s6.87,4.843,16.565,5.028
|
||||
c-8.819,3.621-17.438,12.632-17.438,12.632s0.045,0.019,0.069,0.029c-27.096,11.688-51.621,29.917-47.651,57.105
|
||||
c2.375,16.27,14.692,25.475,31.704,30.254c-17.81,14.742-32.921,36.129-30.707,60.59c0.134,1.487,0.309,2.916,0.508,4.311
|
||||
c-2.209,5.6-3.288,17.842-2.674,24.886c0.949,10.838,13.686,8.662,18.219,6.729c14.139,12.202,32.258,10.252,32.258,10.252
|
||||
s-17.301,1.211-30.306-11.156c5.551-2.659,6.424-3.925,6.788-11.579c0.36-7.61-9.104-20.759-20.57-21.966
|
||||
c-1.25-20.07,9.861-43.32,30.603-60.203c0.02,0.249,0.023,0.491,0.048,0.742c4.248,46.957,30.584,54.634,81.148,63.26
|
||||
c12.603,2.15,22.04,5.821,29.042,10.457c-3.844,5.388-5.706,21.559-2.895,32.325c3.045,11.655,12.647,14.53,19.429,14.955
|
||||
c-3.304,16.035-11.235,29.024-11.235,29.024s10.015-11.628,15.04-29.016c0.48-0.031,0.928-0.069,1.319-0.114
|
||||
c10.922-1.262,16.17-11.338,14.743-23.071c-1.195-9.826-13.974-24.54-28.598-25.992c-33.117-21.52-109.104-9.05-113.877-61.769
|
||||
c-0.341-3.746-0.517-7.367-0.571-10.888c5.709,1.111,11.782,1.844,18.104,2.244c14.111,28.517,62.158,22.269,95.818,20.694
|
||||
c1.764,3.09,7.043,7.064,13.929,9.779c11.751,4.633,14.889,3.742,18.869,1.502c1.484-0.835,2.828-1.92,3.979-3.155
|
||||
c10.822,10.456,25.37,30.251,25.37,30.251s-12.29-22.284-22.733-33.97c2.601-4.923,2.433-10.619-2.559-13.297
|
||||
c-6.956-3.732-31.321,1.581-36.316,4.981c-30.811,1.668-71.853,6.551-89.576-16.474c41.005,1.192,88.786-9.133,102.385-10.365
|
||||
c21.726-1.966,47.319,1.367,64.887,8.228c-0.783,5.681,1.867,18.47,4.641,25.318c3.316,8.197,11.561,5.887,16.562,3.028
|
||||
c-0.588,13.3-4.495,22.638-4.495,22.638s7.86-14.125,9.117-26.183c4.354-4.041,4.774-5.562,2.904-12.887
|
||||
c-1.849-7.24-14.317-16.821-25.47-15.096c-21.855-8.906-54.594-11.087-75.74-9.175c-18.253,1.653-61.404,10.802-97.611,10.237
|
||||
c-1.895-3.338-3.402-7.122-4.412-11.479c5.113-2.364,10.551-4.388,16.307-5.975c30.999-8.551,40.97-29.258,42.943-48.579
|
||||
c1.127,1.303,1.938,2.069,1.938,2.069s7.087-12.679,5.522-27.275c-0.264-2.469-0.429-4.737-0.553-6.911
|
||||
c2.499,6.741,7.778,13.001,7.778,13.001s16.438-20.208,5.846-27.268c-11.583-7.714-6.836-13.283-4.31-15.299
|
||||
c3.354-1.984,6.973-3.94,10.859-5.817c26.561-12.817,59.903-20.002,64.443-40.039c0.265-1.172,0.388-2.34,0.443-3.507
|
||||
c3.701,2.396,9.165,2.053,9.165,2.053s-0.367-2.88-0.601-7.556c3.747,2.081,8.874,1.758,8.874,1.758s-0.986-2.319-1.255-7.689
|
||||
c3.846,1.998,8.434,2.278,8.434,2.278s-0.725-2.246-1.24-5.573c3.788,0.719,8.84,0.419,8.84,0.419s-3.543-7.302-1.316-16.965
|
||||
c0.357-1.547,0.666-3.09,0.938-4.626c-0.087,1.332-0.169,2.662-0.238,3.985c-0.783,14.742,10.85,24.47,10.85,24.47
|
||||
S337,172.178,337,162.303c0-0.021,0-0.042,0-0.061c0,0.153-0.804,0.309-0.782,0.46c1.951,14.548,13.499,20.839,13.499,20.839
|
||||
s2.388-16.471-1.478-25.542c-1.998-4.686-3.966-9.742-5.688-14.881c2.068,5.344,4.374,10.673,7.067,15.72
|
||||
c6.909,12.952,20.498,15.406,20.498,15.406s-1.832-14.029-7.581-22.041c-3.952-5.505-7.874-11.654-11.551-17.83
|
||||
c4.059,6.22,8.622,12.438,13.631,18.048c9.774,10.953,25.27,9.178,25.27,9.178s-7.323-12.085-14.767-18.552
|
||||
c-4.283-3.722-8.589-7.824-12.754-12.019c4.513,4.047,9.319,7.944,14.31,11.39c12.077,8.341,27.281,0.931,27.281,0.931
|
||||
s-10.533-7.219-18.926-12.302c0.595,0.332,1.186,0.662,1.777,0.988c12.922,7.14,28.146-3.013,28.146-3.013
|
||||
s-12.036-5.887-21.343-9.313C389.896,118.341,386.055,116.903,382.184,115.435z M116.917,367.418
|
||||
c-0.172,0.131-0.344,0.268-0.516,0.398c-17.301-3.899-29.646-12.415-31.124-28.752c-2.244-24.777,21.669-42.631,47.562-54.59
|
||||
c3.553,1,9.203,1.919,15.541,0.503c-4.694,4.817-7.998,9.859-7.998,9.859s2.076,0.564,5.3,0.733
|
||||
C133.582,308.673,115.917,333.715,116.917,367.418z M146.295,295.598c1.834,0.062,3.979-0.014,6.326-0.386
|
||||
c-0.141,0.365-0.274,0.72-0.401,1.069c-10.511,14.57-18.745,34.363-17.404,59.912c-4.522,2.267-9.248,5.074-13.939,8.343
|
||||
C122.237,330.3,136.218,307.613,146.295,295.598z M121.776,368.86c4.131-2.979,8.589-5.697,13.361-8.115
|
||||
c0.358,3.527,1.032,6.741,2.025,9.634C131.805,370.131,126.629,369.657,121.776,368.86z M150.478,350.278
|
||||
c-3.791,0.864-8.16,2.403-12.812,4.546c-0.062-0.425-0.168-0.803-0.224-1.236c-2.557-19.875,3.873-37.276,13.005-51.347
|
||||
c0,0.005-0.007,0.032-0.007,0.032s13.533-3.395,23.088-14.017c-1.715,7.205,0.158,14.79,0.158,14.79s9.774-5.185,16.654-15.216
|
||||
c-0.131,5.548,2.84,10.803,5.451,14.331C193.303,321.731,182.711,342.934,150.478,350.278z M259.516,275.357
|
||||
c0.846-4.127,1.649-8.135,2.42-12.012c2.199-4.002,5.203-6.524,9.011-7.55c3.808-1.04,7.78-1.559,11.919-1.559l1.739-17.042
|
||||
c-5.942,0.378-11.657,1.419-17.144,3.105c-5.492,1.672-10.946,3.611-16.369,5.8c-4.526,4.131-7.915,8.875-10.169,14.237
|
||||
c-2.262,5.359-3.755,11.051-4.655,17.055c-0.906,6.007-1.268,12.17-1.268,18.489v18.209c0,3.23,0.201,6.368,0.779,9.393
|
||||
c0.584,3.045,1.728,5.66,3.543,7.85c3.614,2.588,7.203,3.85,10.822,3.771c3.619-0.066,7.224-0.712,10.842-1.925
|
||||
c3.611-1.23,7.162-2.757,10.647-4.558c3.484-1.811,6.904-3.293,10.266-4.457l7.159-14.521c-2.066,0.505-4.2,1.23-6.394,2.127
|
||||
c-2.199,0.9-4.453,1.643-6.777,2.224c-2.322,0.585-4.649,0.773-6.977,0.585c-2.322-0.189-4.649-1.2-6.976-2.994
|
||||
c-2.063-3.626-3.355-7.475-3.87-11.541c-0.519-4.065-0.612-8.165-0.289-12.296C258.1,283.619,258.674,279.488,259.516,275.357z
|
||||
M367.6,320.582c-0.196-3.025-1.001-5.908-2.42-8.623c-1.031-3.608-2.649-6.588-4.846-8.905c-2.193-2.333-4.682-4.162-7.458-5.516
|
||||
c-2.773-1.358-5.712-2.364-8.812-3.014c-3.098-0.643-6.004-1.056-8.717-1.259c-2.711-0.188-5.101-0.285-7.166-0.285
|
||||
s-3.419-0.062-4.064-0.189c0.25-1.037,0.449-2.302,0.574-3.783c0.133-1.481,0.322-2.866,0.584-4.162
|
||||
c0.258-1.419,0.512-2.977,0.773-4.65c6.326,0,12.073-0.581,17.242-1.749c5.165-1.148,9.688-3.059,13.558-5.705
|
||||
c3.876-2.646,7.135-6.131,9.781-10.469c2.649-4.318,4.558-9.583,5.715-15.776c-5.684,0-11.596,0.029-17.727,0.093
|
||||
s-12.328,0.158-18.593,0.284c-6.266,0.143-12.431,0.332-18.5,0.583c-6.066,0.27-11.812,0.584-17.236,0.979
|
||||
c0.128,0,0.221,1.387,0.293,4.161c0.062,2.775,0.062,6.465,0,11.035c-0.072,4.588-0.2,9.788-0.386,15.589
|
||||
c-0.199,5.819-0.49,11.73-0.875,17.734c-0.386,6.007-0.878,11.901-1.451,17.72c-0.584,5.815-1.262,10.908-2.035,15.304
|
||||
c5.552-0.268,11.432-0.488,17.624-0.677c2.162-0.065,4.33-0.127,6.503-0.176l1.247-5.547c0.385-2.192,0.708-4.776,0.969-7.739
|
||||
c0.259-2.979,0.513-5.754,0.773-8.338c0.259-3.093,0.386-6.196,0.386-9.286c0.646-0.127,1.677-0.206,3.103-0.206
|
||||
c1.547,0,3.225,0.269,5.039,0.773c1.804,0.519,3.68,1.292,5.612,2.334c1.938,1.041,3.615,2.522,5.034,4.46
|
||||
c1.42,1.925,2.45,4.352,3.104,7.252c0.638,2.914,0.638,6.495,0,10.75l0.631,5.39c1.609,0.033,3.207,0.079,4.796,0.144
|
||||
c6.068,0.189,11.812,0.471,17.234,0.866C367.891,326.747,367.795,323.609,367.6,320.582z M327.506,263.345
|
||||
c0.707-4.397,1.323-8.133,1.835-11.238c1.168-0.521,2.522-0.835,4.069-0.962c1.549-0.125,3.103-0.205,4.65-0.205
|
||||
c1.677,0,3.291,0.031,4.845,0.112c1.547,0.062,2.901,0.093,4.069,0.093c0,1.151-0.041,2.586-0.103,4.256
|
||||
c-0.066,1.688-0.189,3.42-0.389,5.232c-0.189,1.815-0.512,3.578-0.97,5.331c-0.446,1.732-1.127,3.182-2.034,4.347
|
||||
c-0.896,0.918-2.128,1.657-3.681,2.224c-1.543,0.584-3.159,1.042-4.84,1.357c-1.677,0.33-3.291,0.55-4.838,0.677
|
||||
c-1.555,0.141-2.78,0.207-3.682,0.207C326.439,271.542,326.798,267.727,327.506,263.345z M393.035,246.385
|
||||
c-2.517,0.33-4.84,0.584-6.97,0.773c-2.135,0.205-3.781,0.172-4.939-0.096l3.678,2.711c0.899,5.423,1.356,11.051,1.356,16.851
|
||||
c0,5.818-0.195,11.695-0.584,17.642c-0.385,5.941-0.872,11.805-1.45,17.624c-0.581,5.801-1,11.427-1.261,16.85
|
||||
c-0.907,4.522-1.519,9.238-1.835,14.139c-0.331,4.901-0.843,9.713-1.554,14.425c-0.708,4.712-1.812,9.3-3.297,13.761
|
||||
c-1.48,4.443-3.773,8.481-6.869,12.107l-2.908,1.543c0.513,0.52,1.323,0.993,2.42,1.45c1.093,0.457,1.842,0.678,2.23,0.678
|
||||
c2.708-3.23,4.712-6.558,6.004-9.978c1.286-3.419,2.64-6.746,4.069-9.963c1.544-2.711,2.969-5.626,4.261-8.716
|
||||
c1.286-3.107,2.774-6.008,4.455-8.719c1.671-2.708,3.681-5.045,6.008-6.984c2.322-1.938,5.285-3.15,8.903-3.67
|
||||
c0.386-6.319,0.836-13.114,1.354-20.335c0.517-7.235,1.001-14.534,1.451-21.896c0.457-7.361,0.846-14.596,1.168-21.689
|
||||
c0.323-7.111,0.482-13.684,0.482-19.769c-2.713,0-5.458,0.143-8.229,0.394C398.196,245.785,395.553,246.07,393.035,246.385z
|
||||
M483.002,245c0,4-0.061,5.618-0.188,7.038c-0.135,1.419-0.323,3.525-0.581,5.259c-0.261,1.751-0.584,4.166-0.972,6.752
|
||||
c-0.386,2.584-0.843,6.388-1.354,11.165c-0.519,4.791-1.135,11.551-1.839,19.167c-0.715,7.612-1.519,18.619-2.427,29.619h-32.15
|
||||
c0-15,1.065-26.686,3.192-39.535c2.138-12.847,4.101-25.911,5.911-38.695c-5.034,0.52-9.85,1.042-14.427,1.812
|
||||
c-4.589,0.773-9.136,0.898-13.662,0.52c-0.513,13.682-1.543,27.507-3.097,41.521c-1.553,13.998-3.23,27.586-5.038,40.749
|
||||
c4.52,0,9.396-0.166,14.631-0.496c5.224-0.316,10.292-0.479,15.2-0.479c0.649,1.152,1.285,2.776,1.942,4.838
|
||||
c0.638,2.065,1.22,4.318,1.738,6.779c0.517,2.457,0.997,5.027,1.454,7.753c0.447,2.715,0.873,5.424,1.258,8.135
|
||||
c0.9,6.32,1.681,13.102,2.327,20.336c2.192-6.196,4.454-12.28,6.777-18.209c1.938-5.045,4.004-10.262,6.196-15.699
|
||||
c2.199-5.423,4.327-10.073,6.393-13.936c2.323,0.254,4.649,0.316,6.974,0.188c2.326-0.124,4.681-0.25,7.071-0.392
|
||||
c2.386-0.127,4.775-0.127,7.163,0c2.389,0.142,4.681,0.52,6.88,1.165c-0.257-6.716-0.164-13.619,0.293-20.728
|
||||
c0.449-7.093,1.096-14.204,1.932-21.297c0.841-7.111,1.707-15.14,2.615-22.062c0.907-6.901,1.742-13.27,2.522-21.27H483.002z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 15 KiB |
|
|
@ -1,105 +0,0 @@
|
|||
# 32-bit tasks C/R
|
||||
|
||||
## Compatible applications
|
||||
|
||||
On x86_64, there are two types of compatibility mode applications:
|
||||
- ia32: Compiled to run on an i686 target, these can be executed on x86_64 if the `IA32_EMULATION` configuration option is enabled.
|
||||
- x32: Specially compiled binaries designed to run on x86_64 with the `CONFIG_X86_X32` configuration option enabled.
|
||||
|
||||
Both use 4-byte pointers and thus can address no more than 4 GB of virtual memory.
|
||||
However, x32 uses the full 64-bit register set and therefore cannot be launched natively on an i686 host.
|
||||
Both require an additional environment on x86_64, such as Glibc, libraries, and compiler support.
|
||||
x32 is rarely distributed; currently, only the [Debian x32 port](https://wiki.debian.org/X32Port) is easily found.
|
||||
Currently, CRIU supports ia32 C/R. Support for x32 can be added relatively easily, as the necessary kernel patches for ia32 C/R are already in place.
|
||||
In this document, the terms *compatible* and *32-bit* refer to ia32 applications unless otherwise specified.
|
||||
|
||||
## Difference between native and compatibility mode applications
|
||||
|
||||
From the CPU's point of view, 32-bit compatibility mode applications differ from 64-bit applications by the current Code Segment (CS) selector. If the L-bit (Long mode) in the segment descriptor is set, the CPU operates in 64-bit mode when that descriptor is used. There are other differences between 32-bit and 64-bit selectors; for more details, see [the article "The 0x33 Segment Selector (Heavens Gate)"](https://www.malwaretech.com/2014/02/the-0x33-segment-selector-heavens-gate.html). Code selectors for both modes are defined in kernel headers as `__USER32_CS` and `__USER_CS`, corresponding to descriptors in the Global Descriptor Table (GDT). The mode can be switched from 64-bit to compatibility mode by changing the CS value (e.g., using a long jump).
|
||||
|
||||
From the Linux kernel's point of view, applications differ based on values set during `exec`, such as `mmap_base` or thread info flags like `TIF_ADDR32`, `TIF_IA32`, or `TIF_X32`.
|
||||
Both native and compatibility mode applications can perform either 32-bit or 64-bit syscalls.
|
||||
|
||||
## Mixed-bitness applications
|
||||
|
||||
The current kernel ABI allows for the creation of mixed-bitness applications, which can become quite complex.
|
||||
For instance, an application could set both 32-bit and 64-bit robust futex list pointers.
|
||||
Alternatively, a multi-threaded application could have some threads executing 32-bit code while others execute 64-bit code.
|
||||
|
||||
If support for such mixed-bitness applications is ever needed, it could be added to CRIU relatively easily. However, this should likely be a compile-time configuration option to avoid adding unnecessary syscalls to standard C/R operations.
|
||||
|
||||
Currently, there are no plans to add this support, as such applications are unlikely to be encountered outside of synthetic tests.
|
||||
|
||||
## Approaches to C/R for compatibility mode applications
|
||||
|
||||
32-bit C/R can be implemented in several ways. This section describes the pros and cons of various approaches and explains why the current implementation was chosen.
|
||||
|
||||
### Restore via exec() of a 32-bit dummy binary vs. from 64-bit CRIU
|
||||
|
||||
Restoring a 32-bit application could be done using a 32-bit daemon that communicates with the 64-bit CRIU binary or a 32-bit CRIU subprocess.
|
||||
|
||||
**Pros**:
|
||||
- No kernel patches expected (though `vDSO mremap()` would still require support).
|
||||
|
||||
**Cons**:
|
||||
- The CRIU codebase lacks a dedicated restore daemon, requiring significant rework.
|
||||
- A 64-bit application can have a 32-bit child, which in turn could parent a 64-bit process. This would require re-executing the native 64-bit CRIU from the 32-bit dummy or subprocess.
|
||||
- It would be necessary to send process properties, open image file descriptors, and shared memory containing the parsed `ps_tree` to the daemon. The volume of IPC calls would slow down the restoration process.
|
||||
- Restoration becomes more complex, especially when considering user and PID namespaces.
|
||||
- Task properties that are erased during `exec()` cannot benefit from optimized inheritance.
|
||||
- A separate daemon would also be needed for x32.
|
||||
|
||||
### Restore with a flag to sigreturn() or arch_prctl()
|
||||
|
||||
The initial attempt to implement 32-bit C/R was rejected by the LKML community for several reasons. It involved swapping thread info flags (e.g., `TIF_ADDR32`, `TIF_IA32`, `TIF_X32`), unmapping the native 64-bit vDSO, and mapping the 32-bit vDSO based on a bit in the `rt_sigreturn()` sigframe or a dedicated `arch_prctl()` call.
|
||||
|
||||
**Pros**:
|
||||
- Simple for CRIU: just perform a `sigreturn` with the new bit set or call `arch_prctl` before `sigreturn`.
|
||||
|
||||
**Cons**:
|
||||
- If the 32-bit vDSO on the restoration host differs from the dumped image, the task must be intercepted after `sigreturn` to create jump trampolines (this is simpler with `arch_prctl`).
|
||||
- Too many potential failure points for a single syscall; overly complex.
|
||||
- Allowing userspace to swap thread info flags could introduce new race conditions and bugs (e.g., since the `TASK_SIZE` macro depends on `TIF_ADDR32`, memory mapping behavior might become unpredictable).
|
||||
|
||||
Following LKML discussions, it was decided to separate personality changes from the vDSO mapping API, remove the `TIF_IA32` flag that distinguished 32-bit from 64-bit tasks, and instead rely on the nature of the syscall (compat, x32, or native).
|
||||
|
||||
### Seizing with separate 32-bit and 64-bit parasites
|
||||
|
||||
**Pros**:
|
||||
- No 32-bit calls in the 64-bit parasite and vice-versa.
|
||||
- Since `ptrace` does not allow setting a 32-bit register set on a 64-bit task (and vice versa), using a parasite of the same nature as the task avoids these limitations.
|
||||
|
||||
**Cons**:
|
||||
- Requires maintaining two or three (for x32) separate parasite blobs.
|
||||
- Requires complex Makefile macros to build multiple parasites.
|
||||
- Serializing parasite responses is difficult because argument sizes differ between modes, leading to complex and less readable C macros.
|
||||
|
||||
### Current approach
|
||||
|
||||
CRIU (a 64-bit process) handles 32-bit (ia32) tasks through a series of architecture-specific transitions:
|
||||
|
||||
1. **Architecture Detection**: CRIU uses `ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov)` to detect the task's architecture. The kernel returns different register set sizes depending on the mode: `sizeof(user_regs_struct64)` for native 64-bit tasks and `sizeof(user_regs_struct32)` for 32-bit compatibility mode tasks.
|
||||
2. **Dumping**: When dumping a 32-bit task, CRIU uses the 64-bit `ptrace` interface. The kernel handles the internal mapping of 32-bit registers into the structure expected by CRIU.
|
||||
3. **vDSO Handling**: To ensure the restored task uses a vDSO compatible with the current kernel, CRIU uses the `arch_prctl(ARCH_MAP_VDSO_32, addr)` system call (available since kernel v4.8) to map the 32-bit vDSO into the restored process's address space.
|
||||
4. **Restoration via Sigreturn**: The final restoration of 32-bit registers is performed using a 32-bit `rt_sigreturn` call:
|
||||
* CRIU prepares a 32-bit signal frame (`rt_sigframe_ia32`) on the target task's stack.
|
||||
* The CRIU restorer code, running in 64-bit mode, executes a far return (`lretq`) to switch the CPU to 32-bit mode with the `USER32_CS` (0x23) segment selector.
|
||||
* Once in 32-bit mode, it executes `int $0x80` with the `__NR32_rt_sigreturn` syscall number. The kernel then restores all registers from the 32-bit sigframe and resumes the task in 32-bit mode.
|
||||
|
||||
## To-Do
|
||||
|
||||
### vsyscall page handling
|
||||
|
||||
The `vsyscall` page is an emulated, fixed-address page (`0xffffffffff600000`) used for legacy support. It is not a standard VMA and is marked as `VMA_AREA_VSYSCALL` by CRIU, which avoids dumping or restoring its contents. Since its presence in `/proc/<pid>/maps` depends on kernel configuration (`vsyscall=emulate` or `vsyscall=xonly`), it can introduce noise during ZDTM tests that compare memory layouts. Consequently, tests are often run with `vsyscall=none`.
|
||||
|
||||
### Error reporting on x32 binary dumping
|
||||
|
||||
Currently, CRIU does not support x32 binaries (64-bit registers with 32-bit pointers). While the infrastructure for 32-bit pointers exists, the specific register handling and vDSO mapping for x32 are not implemented. Attempting to dump an x32 binary should result in an explicit error.
|
||||
|
||||
### Removal of TIF_IA32 from the kernel
|
||||
|
||||
The `TIF_IA32` thread info flag was historically used to distinguish 32-bit tasks. Kernel efforts (merged in v5.11) have moved towards relying on the nature of the syscall (compat vs. native) rather than a persistent thread flag. This unification simplifies how the kernel and CRIU interact, particularly for tracing tools like uprobes.
|
||||
|
||||
## External links
|
||||
- [GitHub issue](https://github.com/checkpoint-restore/criu/issues/43)
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
index.md
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# Asynchronous I/O (AIO)
|
||||
|
||||
CRIU supports checkpointing and restoring kernel-level Asynchronous I/O (AIO) contexts, which are managed via the `io_setup`, `io_submit`, `io_getevents`, and `io_destroy` system calls.
|
||||
|
||||
## How CRIU Handles AIO
|
||||
|
||||
To successfully checkpoint and restore an AIO context, CRIU manages three primary components:
|
||||
|
||||
1. **The AIO Ring Buffer**: This is a memory-mapped area where the kernel and userspace communicate. CRIU identifies these areas by their `[aio]` label in `/proc/pid/maps` or by detecting the specific VMA attributes.
|
||||
2. **Completed Events**: Events that have finished and are already residing in the ring buffer are dumped as part of the process's memory.
|
||||
3. **AIO Context State**: This includes the kernel's internal tracking of the ring's head and tail.
|
||||
|
||||
### The Restoration Process
|
||||
|
||||
The restoration of an AIO ring is complex because the kernel's AIO context ID (the `aio_context_t` value) is an internal pointer that cannot be arbitrarily assigned by userspace. CRIU uses the following strategy to restore it:
|
||||
|
||||
1. **New Ring Creation**: The restorer calls `io_setup` to create a fresh AIO ring with the original number of requested events.
|
||||
2. **Tail Synchronization**: To move the kernel's internal `tail` pointer to the original position, CRIU submits dummy I/O requests (typically writes to `/dev/null`). Since these operations are synchronous for the device, the kernel advances the tail as each request completes.
|
||||
3. **Head Synchronization**: CRIU manually adjusts the `head` pointer in the ring header to match the state at the time of the dump.
|
||||
4. **Event Data Restoration**: The original `io_events` data (the completed but unread events) is copied from the dump image into the new ring buffer.
|
||||
5. **Memory Remapping**: Finally, CRIU uses `mremap` to move the new ring buffer to its original virtual address, ensuring the application can continue using its existing AIO context ID.
|
||||
|
||||
## Limitations: In-Flight Events
|
||||
|
||||
Currently, **in-flight events** (I/O requests that have been submitted but not yet completed at the time of the dump) are **not supported**.
|
||||
|
||||
* **Dumping**: CRIU's parasite code checks for AIO rings but does not currently wait for pending requests to complete. If a request completes during or after the dump, it may lead to data inconsistency or a failed restore.
|
||||
* **Restoring**: There is no mechanism to re-submit pending I/O requests upon restoration. Applications using AIO should ideally be in a quiescent state (all submitted I/O completed) before being checkpointed.
|
||||
|
||||
## See also
|
||||
|
||||
* [Memory dumping and restoring](memory-dumping-and-restoring.md)
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# AppArmor Support
|
||||
|
||||
CRIU provides support for checkpointing and restoring **AppArmor** security profiles and namespaces. This is a critical feature for containerized environments (like Docker, LXC, or Podman) where each container frequently operates under its own set of specialized security policies.
|
||||
|
||||
## How CRIU Handles AppArmor
|
||||
|
||||
AppArmor integration in CRIU ensures that restored processes continue to operate under the same security constraints as the original processes, while also managing the temporary permissions needed for the checkpointing process itself.
|
||||
|
||||
### 1. Checkpointing (Dumping)
|
||||
During the dump phase, CRIU detects the AppArmor state of each task:
|
||||
* **Profile Identification**: CRIU captures the active profile name for every thread (e.g., `unconfined`, `docker-default`, or a custom user-defined profile).
|
||||
* **Namespace and Policy Dumping**: In modern containerized setups, containers often have their own AppArmor namespaces. CRIU walks the `/sys/kernel/security/apparmor/policy/` directory to capture the full hierarchy of namespaces and the raw binary blobs of all loaded policies.
|
||||
* **Parasite Profile**: To allow the [Parasite Code](parasite-code.md) to perform its necessary inspections (like opening network sockets or reading memory) without being blocked by the application's strict security policy, CRIU temporarily transitions the task into a special, permissive "parasite profile" while it is infected.
|
||||
|
||||
### 2. Restoration
|
||||
Restoring AppArmor state involves re-establishing the security context before the process resumes:
|
||||
* **Policy Loading**: CRIU uses the `apparmor_parser` utility on the destination host to re-load the policy blobs captured in the image files.
|
||||
* **Namespace Reconstruction**: It recreates any nested AppArmor namespaces to match the original environment.
|
||||
* **Profile Re-attachment**: As each process is restored, CRIU ensures it is transitioned back into its original profile (or stack of profiles) using the `aa_change_profile()` interface before the application code begins executing.
|
||||
|
||||
## Support for Stacking
|
||||
|
||||
Modern AppArmor implementations support **Profile Stacking**, where multiple security profiles are applied to a single process simultaneously (e.g., a container-wide profile plus a per-application profile). CRIU correctly identifies, dumps, and restores these complex stacked configurations.
|
||||
|
||||
## Kernel Requirements
|
||||
|
||||
Reliable AppArmor C/R requires:
|
||||
* A kernel with `CONFIG_SECURITY_APPARMOR` enabled and active.
|
||||
* The `securityfs` filesystem mounted (typically at `/sys/kernel/security`).
|
||||
* Support for AppArmor policy introspection and namespaces, which is standard in modern distributions like Ubuntu and Debian.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Parasite Code](parasite-code.md)
|
||||
* [Kerndat Feature Detection](kerndat.md)
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# ARM64 Guarded Control Stack (GCS)
|
||||
|
||||
CRIU supports checkpointing and restoring the **Guarded Control Stack (GCS)** feature on ARM64 (AArch64) architectures. GCS is a hardware-assisted shadow stack mechanism designed to prevent return-oriented programming (ROP) attacks by maintaining a protected stack of return addresses.
|
||||
|
||||
## How CRIU Handles GCS
|
||||
|
||||
GCS support is integrated into CRIU's architecture-specific code for AArch64 (`arch/aarch64/gcs.c`).
|
||||
|
||||
### 1. Checkpointing (Dumping)
|
||||
During the dump phase, CRIU detects if a task has GCS enabled by checking its CPU features and hardware capabilities (`HWCAP_GCS`).
|
||||
* **State Capture**: CRIU uses `ptrace(PTRACE_GETREGSET, ..., NT_ARM_GCS, ...)` to retrieve the current GCS state.
|
||||
* **Key Parameters**:
|
||||
* `gcspr_el0`: The current Guarded Control Stack Pointer.
|
||||
* `features_enabled`: The GCS configuration flags (e.g., `PR_SHADOW_STACK_ENABLE`).
|
||||
* **VMA Identification**: CRIU identifies the memory region (VMA) used for the shadow stack, which is marked with special kernel attributes.
|
||||
|
||||
### 2. Restoration
|
||||
Restoring GCS requires carefully re-establishing the shadow stack before the process resumes normal execution.
|
||||
* **Shadow Stack Mapping**: CRIU uses the `map_shadow_stack` system call to recreate the shadow stack at its original virtual address.
|
||||
* **Context Setup**: The captured GCS state (`gcspr_el0` and flags) is integrated into the task's **restorer context**.
|
||||
* **Sigframe Integration**: To ensure a seamless transition, CRIU places a `gcs_context` entry into the signal frame used for the final `sigreturn`. This informs the kernel to switch to the restored shadow stack as the process resumes.
|
||||
|
||||
## Kernel Requirements
|
||||
|
||||
GCS support in CRIU requires an ARM64 host and a kernel that supports the Guarded Control Stack ABI, typically including:
|
||||
* `PR_SHADOW_STACK_ENABLE` prctl support.
|
||||
* The `map_shadow_stack` system call.
|
||||
* `NT_ARM_GCS` ptrace regset.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Restorer Context](restorer-context.md)
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
# BPF Maps
|
||||
|
||||
BPF maps are kernel objects that store data used by BPF programs, typically in the form of key-value pairs. Applications access these maps via file descriptors. Checkpointing and restoring BPF maps involves serializing both their **metadata** and their **data contents**.
|
||||
|
||||
## How CRIU Handles BPF Maps
|
||||
|
||||
### Metadata Serialization
|
||||
CRIU collects essential map attributes from several sources:
|
||||
- **/proc filesystem**: Essential fields such as `map_type`, `key_size`, `value_size`, `max_entries`, and the `frozen` status are parsed from the task's `fdinfo`.
|
||||
- **BPF System Call**: CRIU uses the `bpf` system call with the `BPF_OBJ_GET_INFO_BY_FD` command to retrieve additional information, including the map name and interface index (`ifindex`).
|
||||
|
||||
### Data Serialization
|
||||
To preserve the map's contents, CRIU relies on batch operations:
|
||||
- **Dumping**: During the checkpoint stage, CRIU uses `BPF_MAP_LOOKUP_BATCH` to efficiently read all key-value pairs from the map.
|
||||
- **Restoring**: During the restore phase, CRIU recreates the map and uses `BPF_MAP_UPDATE_BATCH` to repopulate it with the saved key-value pairs.
|
||||
|
||||
### Supported Map Types
|
||||
CRIU currently supports data serialization for the following BPF map types:
|
||||
- `BPF_MAP_TYPE_HASH`
|
||||
- `BPF_MAP_TYPE_ARRAY`
|
||||
|
||||
For other map types, CRIU may be able to restore the map itself (metadata) but not its contents, depending on kernel support for batch operations on those types.
|
||||
|
||||
### Frozen Maps
|
||||
If a BPF map was marked as read-only (frozen) using `bpf_map_freeze()`, CRIU detects this state from `fdinfo` and reapplies the freeze during restoration after the data has been repopulated.
|
||||
|
||||
## To-Do
|
||||
|
||||
- **BTF Support**: Serialization and restoration of BPF Type Format (BTF) information associated with maps.
|
||||
- **Extended Map Types**: Implementation of data serialization for more BPF map types (e.g., `BPF_MAP_TYPE_PERF_EVENT_ARRAY`, `BPF_MAP_TYPE_LPM_TRIE`).
|
||||
- **Map Extra Data**: Full support for `map_extra` fields introduced in recent kernels (currently only partially parsed with limited restoration).
|
||||
|
||||
## External Links
|
||||
- [BPF Documentation](https://www.kernel.org/doc/html/latest/bpf/index.html)
|
||||
- [Notes on BPF](https://blogs.oracle.com/linux/notes-on-bpf-1)
|
||||
- [An eBPF Overview](https://www.collabora.com/news-and-blog/blog/2019/04/05/an-ebpf-overview-part-1-introduction/)
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
# CGroups
|
||||
|
||||
CRIU provides comprehensive support for checkpointing and restoring Control Groups (CGroups) for both cgroup v1 and cgroup v2.
|
||||
|
||||
## Overview
|
||||
|
||||
When managing CGroups, CRIU handles three main aspects:
|
||||
1. **Process Placement**: The specific cgroup sets (a list of controller/path pairs) that each task in the process tree belongs to.
|
||||
2. **Hierarchy and Properties**: The existing cgroup directory tree, its permissions, and various control properties (e.g., CPU shares, memory limits).
|
||||
3. **Namespace Boundaries**: Support for CGroup namespaces (`CLONE_NEWCGROUP`), ensuring that the restored tasks have the same view of the cgroup hierarchy.
|
||||
|
||||
## Default Behavior
|
||||
|
||||
By default, CRIU manages cgroups in **soft mode** (`--manage-cgroups=soft`). In this mode:
|
||||
* CRIU automatically dumps process cgroup memberships.
|
||||
* Upon restoration, it attempts to recreate the cgroup hierarchy and restore properties for cgroups that it created.
|
||||
* If a cgroup already exists, CRIU avoids overwriting its properties to prevent interference with other tasks on the system.
|
||||
|
||||
## CGroup V2 Support
|
||||
|
||||
CRIU fully supports the unified cgroup v2 hierarchy. Key features include:
|
||||
* **Global Properties**: Restoration of global v2 attributes such as `cgroup.subtree_control`, `cgroup.max.descendants`, and `cgroup.max.depth`.
|
||||
* **Process Migration**: Moving tasks between v2 cgroups using `cgroup.procs` (or `cgroup.threads` for threaded controllers).
|
||||
* **Freezer**: Integrated support for the cgroup v2 freezer mechanism (`cgroup.freeze`).
|
||||
|
||||
## CGroup Namespaces
|
||||
|
||||
CRIU leverages cgroup namespaces to accurately restore a container's view of the cgroup tree. During restoration:
|
||||
1. It identifies the cgroup namespace boundary (the path prefix) for each controller.
|
||||
2. It moves the root task into the appropriate cgroup relative to the host.
|
||||
3. It calls `unshare(CLONE_NEWCGROUP)` to pin the root of the cgroup namespace to that location, matching the original environment.
|
||||
|
||||
## Mountpoints of the "cgroup" Filesystem
|
||||
|
||||
CRIU supports dumping and restoring cgroup filesystem mountpoints. However, a significant limitation exists regarding bind-mounted subgroups:
|
||||
|
||||
**Root Mount Requirement**: By default, CRIU expects to find the "root" mount of a cgroup controller (where the mount root is `/`) within the dumped mount namespace.
|
||||
* If a container has only bind-mounted **subgroups** (e.g., `/sys/fs/cgroup/memory/my-container` is bind-mounted to `/sys/fs/cgroup/memory`) without a corresponding root mount of that controller being visible, CRIU may fail the dump.
|
||||
* This is because CRIU needs to identify the full path of the cgroup relative to the hierarchy root to accurately reconstruct it.
|
||||
|
||||
To overcome this, such mounts must often be treated as **external mounts** (`--external mnt[...]`) or the full hierarchy must be made visible to CRIU during the dump.
|
||||
|
||||
## CGroups Restoration Strategy
|
||||
|
||||
The `--manage-cgroups=MODE` option allows for fine-grained control:
|
||||
|
||||
* `none`: Requires cgroups to pre-exist; does not restore properties.
|
||||
* `props`: Requires cgroups to pre-exist; restores properties from the image.
|
||||
* `soft` (Default): Restores properties only for cgroups created by CRIU.
|
||||
* `full`: Always recreates all cgroups and restores all properties.
|
||||
* `strict`: Recreates all cgroups from scratch; fails if any already exist.
|
||||
* `ignore`: Completely ignores cgroup information.
|
||||
|
||||
## External CGroup Yard
|
||||
|
||||
The `--cgroup-yard PATH` option allows CRIU to use a pre-mounted cgroup hierarchy located at `PATH`. This is particularly useful in unprivileged environments where CRIU may not have the `CAP_SYS_ADMIN` capability required to mount cgroup filesystems itself. For every cgroup mount, there should be exactly one directory named after the controller(s) co-mounted there (or "unified" for cgroup v2).
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Changing IP Addresses During Migration
|
||||
|
||||
When performing a [live migration](live-migration.md) of a process between hosts, a common challenge is handling IP address changes. While the ideal solution often involves using containers with their own network namespaces and virtual IPs, migrating a service to a different physical IP address is sometimes necessary.
|
||||
|
||||
## The Core Problem
|
||||
|
||||
TCP connections are identified by a 4-tuple: (Source IP, Source Port, Destination IP, Destination Port). If either IP address changes during migration, the TCP stack on the peer will not recognize the migrated connection and will typically respond with a Reset (RST) or simply ignore the packets.
|
||||
|
||||
Consequently, there are three scenarios to consider when changing IPs:
|
||||
|
||||
### 1. Listening Sockets
|
||||
If a server is bound to `0.0.0.0` (INADDR_ANY), it will "just work" after migration, as it will listen on all available interfaces on the new host. However, if the server is bound to a specific IP address that does not exist on the destination host, restoration will fail unless the binding is updated.
|
||||
|
||||
**Solutions:**
|
||||
- **CRIT**: Use the [CRIT](../crit.md) tool to manually edit the `inetsk.img` or `files.img` images to update the binding address.
|
||||
- **Plugins**: Use the `UPDATE_INETSK` plugin hook (see below) to programmatically change the IP address during restoration.
|
||||
|
||||
### 2. In-Flight Connections
|
||||
These are connections that have been initiated but not yet accepted by the application. CRIU provides the `--skip-in-flight` option to ignore these connections during the dump.
|
||||
|
||||
### 3. Established Sockets
|
||||
These are active connections. Changing the IP address of an established socket is technically possible but will usually break the connection unless specialized network-level translation (like NAT) is used.
|
||||
|
||||
**CRIU Solutions:**
|
||||
- **--tcp-close**: This option tells CRIU to dump established connections but restore them in a closed state. This prevents application-level errors caused by "holes" in the file descriptor table while acknowledging that the specific network connection is terminated.
|
||||
- **--tcp-established**: Used in combination with IP translation mechanisms (like NAT or proxies), this allows the connection to be restored.
|
||||
|
||||
## Programmatic IP Remapping (Plugins)
|
||||
|
||||
CRIU provides a plugin hook, `UPDATE_INETSK`, specifically for modifying socket attributes during restoration. A plugin can implement this hook to intercept the restoration of an INET socket and change its source or destination IP addresses.
|
||||
|
||||
```c
|
||||
/* Plugin hook signature in criu-plugin.h */
|
||||
int cr_plugin_update_inetsk(uint32_t family, uint32_t state, uint32_t *src_ip, uint32_t *dst_ip);
|
||||
```
|
||||
|
||||
By modifying `src_ip` and `dst_ip` within the plugin, you can redirect sockets to new addresses as they are being recreated.
|
||||
|
||||
## Summary of Options
|
||||
|
||||
| Scenario | Recommendation | CRIU Flag / Tool |
|
||||
| :--- | :--- | :--- |
|
||||
| **Old IP not on new host** | Remap local binding | `CRIT` or `UPDATE_INETSK` plugin |
|
||||
| **In-Flight Connection** | Ignore | `--skip-in-flight` |
|
||||
| **Established Connection** | Terminate gracefully | `--tcp-close` |
|
||||
| **Established Connection** | Maintain (requires NAT) | `--tcp-established` + remapping |
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
# Checkpoint and Restore Architecture
|
||||
|
||||
This page describes the high-level design and internal mechanics of the Checkpoint and Restore processes in CRIU.
|
||||
|
||||
## Checkpoint
|
||||
|
||||
The checkpoint procedure captures the full state of a process tree. It combines information from the Linux kernel's `/proc` filesystem with data extracted directly from the processes' address space.
|
||||
|
||||
### 1. Freezing the Process Tree
|
||||
CRIU begins by identifying the process group leader (via the `--tree` option) and recursively collecting all threads and children. To ensure a consistent snapshot, the entire tree must be "frozen."
|
||||
|
||||
* **ptrace**: CRIU uses `PTRACE_SEIZE` followed by `PTRACE_INTERRUPT` to stop tasks without delivering signals that could be visible to the application.
|
||||
* **Freezer CGroup**: Alternatively, the [Freezer CGroup](freezing-the-tree.md) can be used to freeze all tasks in a single operation.
|
||||
|
||||
### 2. Resource Collection (External State)
|
||||
CRIU gathers state that the kernel exposes via `/proc`:
|
||||
* **File Descriptors**: Parsed from `/proc/$pid/fdinfo` (which includes positions and flags).
|
||||
* **Memory Maps**: Captured from `/proc/$pid/smaps` and `/proc/$pid/map_files`.
|
||||
* **Core State**: Task statistics and basic identifiers from `/proc/$pid/stat`.
|
||||
|
||||
### 3. Parasite Injection (Internal State)
|
||||
Some state (like memory contents and specific credentials) can only be captured from within the process. CRIU uses a technique called **parasite injection**:
|
||||
1. **Infection**: CRIU uses `ptrace` to inject a small bit of code into the task's instruction stream (at the current `CS:IP`).
|
||||
2. **Bootstrap**: This code executes an `mmap` syscall to allocate space for the full **parasite blob**.
|
||||
3. **Execution**: The parasite code runs as a daemon inside the task, communicating with the CRIU coordinator via a Unix socket to dump memory pages and other internal metadata.
|
||||
|
||||
### 4. Cleanup
|
||||
Once the state is captured, CRIU uses `ptrace` to remove the parasite code and restore the original instructions. The processes are then either resumed or killed, depending on the command-line options.
|
||||
|
||||
---
|
||||
|
||||
## Restore
|
||||
|
||||
The restore procedure is essentially the reverse of a checkpoint. CRIU "morphs" itself into the process tree it is restoring through a multi-stage process.
|
||||
|
||||
### 1. Resolve Shared Resources
|
||||
CRIU analyzes the image files to identify resources shared between processes (e.g., shared memory segments, pipes, or inherited file descriptors). It determines which process will "create" the resource and how others will "inherit" it.
|
||||
|
||||
### 2. Fork the Process Tree
|
||||
CRIU calls `fork()` repeatedly to recreate the original process hierarchy. To restore specific PIDs, it uses the `ns_last_pid` interface or the `clone3` system call. At this stage, only process leaders are created; threads are restored later.
|
||||
|
||||
### 3. Restore Basic Resources
|
||||
Each process in the new tree begins restoring its environment:
|
||||
* **Namespaces**: Joins or creates Network, Mount, UTS, and IPC namespaces.
|
||||
* **Files and Sockets**: Reopens file descriptors and recreates network sockets.
|
||||
* **Memory Prep**: Maps anonymous memory regions and fills them with data from the images.
|
||||
|
||||
### 4. The Restorer Context
|
||||
To restore the final memory layout, CRIU must unmap its own code and data. This requires a **restorer blob**:
|
||||
* **Self-Contained**: The blob is a Position-Independent Executable (PIE) that contains all necessary logic to perform the final `mmap` and `munmap` calls.
|
||||
* **Non-Conflicting**: It is mapped into a "hole" in the task's address space that does not conflict with either CRIU's current mappings or the task's original mappings.
|
||||
* **Final Transition**: The process jumps into the restorer blob, which unmaps CRIU, maps the final memory regions, restores timers and credentials, and recreates any additional threads.
|
||||
|
||||
### 5. Sigreturn
|
||||
The very last step of the restorer is to call `sigreturn`. CRIU prepares a special signal frame on the stack that contains the original register state (including the instruction pointer) of the process at the time of the checkpoint. The `sigreturn` syscall tells the kernel to load this state and resume execution of the application code.
|
||||
|
||||
*See also: [Restorer Context](restorer-context.md), [Tree After Restore](tree-after-restore.md)*
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
# Code Blobs and PIE Generation
|
||||
|
||||
CRIU and its sub-project **Compel** use specialized binary blobs to execute code in environments where standard libraries and runtime environments are unavailable. These blobs are Position-Independent Executables (PIE) that are converted into C headers for easy integration into the main CRIU binary.
|
||||
|
||||
## Why Code Blobs are Necessary
|
||||
|
||||
CRIU operates in two primary scenarios that require these specialized environments:
|
||||
|
||||
1. **Parasite Code Execution**: During a checkpoint, CRIU injects code into the target process's address space to extract internal state (like memory contents and credentials). This code must be self-contained and PIE-compiled to run at any address.
|
||||
2. **Restorer Context**: During restoration, the process must unmap its current memory (including CRIU's own code) and map the original memory of the checkpointed application. The code performing these operations must exist in a memory region that does not conflict with the target application's layout.
|
||||
|
||||
## Building PIE Code Blobs
|
||||
|
||||
The generation of these blobs is handled by the **Compel** utility. The process involves compiling C and assembly source files into a single ELF object and then using the `compel hgen` tool to transform that object into a C header.
|
||||
|
||||
### The `compel hgen` Tool
|
||||
|
||||
The `hgen` (header generator) tool performs the following tasks:
|
||||
1. **Relocation Extraction**: It identifies all symbols that require relocation and creates a structured `compel_reloc` array.
|
||||
2. **Binary Data Conversion**: It converts the allocated ELF sections (code and data) into a static C byte array.
|
||||
3. **Bootstrap Initialization**: It generates a setup function (e.g., `parasite_setup_c_header`) that populates a `parasite_blob_desc` structure, which CRIU uses to manage the blob's lifecycle.
|
||||
|
||||
### Example Header Format
|
||||
|
||||
The generated header file typically contains:
|
||||
|
||||
```c
|
||||
/* Relocation information */
|
||||
static const struct compel_reloc parasite_relocs[] = {
|
||||
{ .offset = 0x0000002c, .type = COMPEL_TYPE_INT, .addend = 0, .value = 0x12345678 },
|
||||
...
|
||||
};
|
||||
|
||||
/* The binary blob itself */
|
||||
static const char parasite_blob[] = {
|
||||
0x48, 0x8d, 0x25, 0x2d, 0x60, 0x00, 0x00, 0x48,
|
||||
...
|
||||
};
|
||||
|
||||
/* Setup function for CRIU integration */
|
||||
static void parasite_setup_c_header_desc(struct parasite_blob_desc *pbd, bool native)
|
||||
{
|
||||
pbd->parasite_type = COMPEL_BLOB_CHEADER;
|
||||
pbd->hdr.mem = parasite_blob;
|
||||
pbd->hdr.bsize = sizeof(parasite_blob);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Build Procedure
|
||||
|
||||
The build system follows these steps to generate the headers:
|
||||
|
||||
1. **Compilation**: Source files (like `parasite.c` or `restorer.c`) are compiled with PIE flags (`-fpie`, `-ffreestanding`, `-nostdlib`).
|
||||
2. **Linking**: Object files are linked into a single `.built-in.o` file using a specialized linker script (`compel-pack.lds.S`) that organizes sections into a layout suitable for a standalone blob.
|
||||
3. **Header Generation**: The `compel hgen` command is executed on the linked object to produce the final `-blob.h` header.
|
||||
|
||||
```bash
|
||||
# Example Makefile recipe
|
||||
$(obj)/parasite-blob.h: $(obj)/parasite.built-in.o
|
||||
compel hgen -f $< -o $@
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
* [Parasite Code](parasite-code.md)
|
||||
* [Restorer Context](restorer-context.md)
|
||||
* [Compel Sub-project](../compel.md)
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
# Comparison to Other Checkpoint/Restore Projects
|
||||
|
||||
This page explains the primary differences between CRIU and other checkpoint/restore (C/R) solutions available for Linux.
|
||||
|
||||
## DMTCP (Distributed MultiThreaded Checkpointing)
|
||||
|
||||
DMTCP implements checkpoint/restore at the library level. To use it, an application must be launched with the DMTCP library dynamically linked from the start. This library intercepts library calls, builds an internal shadow database of the process state, and forwards requests to `glibc` or the kernel.
|
||||
|
||||
**Key Characteristics of DMTCP:**
|
||||
* **No Kernel Patches**: Works on standard kernels without requiring specific features.
|
||||
* **Library Level**: Intercepts calls at the userspace level, which can introduce performance overhead.
|
||||
* **PID Virtualization**: Since the kernel does not traditionally allow setting a specific PID during fork, DMTCP "fools" the application by intercepting `getpid()` and returning a fake value. This can be problematic if the application accesses `/proc` using its real PID.
|
||||
* **Limited API Coverage**: May not support all kernel APIs (e.g., `inotify` support is limited).
|
||||
|
||||
In contrast, **CRIU** does not require pre-loading libraries. It uses standard kernel interfaces (extended where necessary for C/R) to transparently capture and restore arbitrary applications.
|
||||
|
||||
## BLCR (Berkeley Lab Checkpoint/Restart)
|
||||
|
||||
BLCR is a system-level checkpointer designed primarily for High Performance Computing (HPC) and MPI jobs. It is implemented as a loadable kernel module.
|
||||
|
||||
**Key Characteristics of BLCR:**
|
||||
* **Kernel Module**: Requires a specific GPL-licensed kernel module.
|
||||
* **HPC Focused**: Optimized for CPU and memory-intensive batch jobs.
|
||||
* **Limited Scope**: Traditionally lacks support for complex modern features like namespaces, containers, or diverse socket types.
|
||||
|
||||
## PinPlay
|
||||
|
||||
PinPlay is a checkpointing tool built on top of Intel's PIN binary instrumentation tool. It is primarily used for deterministic replay and architectural simulation. It records architectural register state and memory pages, often focusing on reducing runtime for simulators.
|
||||
|
||||
## OpenVZ (In-Kernel)
|
||||
|
||||
Legacy OpenVZ (RHEL6 and earlier) featured an in-kernel C/R implementation. While highly efficient and robust for its time, it required a heavily patched kernel. CRIU was developed as the "user-space" successor to this technology, moving the logic out of the kernel to improve maintainability and facilitate upstream adoption.
|
||||
|
||||
---
|
||||
|
||||
## Comparison Table
|
||||
|
||||
| Feature | CRIU | DMTCP | BLCR | OpenVZ (Legacy) |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| **Architectures** | x86_64, ARM, AArch64, PPC64, s390, MIPS, RISC-V, LoongArch | x86, x86_64, ARM | x86, x86_64, PPC, ARM | x86, x86_64 |
|
||||
| **OS** | Linux | Linux | Linux | Linux |
|
||||
| **Standard Kernel?** | Yes (v3.11+) | Yes | Yes (needs module) | No (Custom kernel) |
|
||||
| **No Preloading?** | Yes | No | No | Yes |
|
||||
| **Non-Root Support?** | Yes (limited) | Yes | Yes | No |
|
||||
| **Unmodified Apps?** | Yes | Yes | No (Static/Threaded issues) | Yes |
|
||||
| **Unprepared Tasks?** | Yes | No | No | Yes |
|
||||
| **Retains Behavior?** | Yes | No (Wrappers used) | No (Wrappers used) | Yes |
|
||||
| **Live Migration** | Yes (Optimized) | Yes | Yes (Identical env only) | Yes |
|
||||
| **Containers** | Yes (LXC, Docker, Podman) | No | No | Yes |
|
||||
| **GDB Support** | No (same interface) | Yes | No | Yes |
|
||||
| **Unix Sockets** | Yes | Yes | No | Yes |
|
||||
| **TCP Sockets** | Yes | Yes | No | Yes |
|
||||
| **Established TCP** | Yes | No (needs plugin) | No | Yes |
|
||||
| **Namespaces** | Yes | No | No | Yes |
|
||||
| **System V IPC** | Yes | Yes | No | Yes |
|
||||
| **Non-POSIX Files** | Yes (Inotify, Epoll) | Yes | No | Yes |
|
||||
| **Timers** | Yes | No | Yes | Yes |
|
||||
|
||||
## Sources and External Links
|
||||
|
||||
* **DMTCP**: [dmtcp.sourceforge.net](http://dmtcp.sourceforge.net/)
|
||||
* **BLCR**: [ftg.lbl.gov/projects/CheckpointRestart](https://ftg.lbl.gov/projects/CheckpointRestart/)
|
||||
* **CRIU FAQ**: [How does DMTCP differ?](http://dmtcp.sourceforge.net/FAQ.html#Internals)
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# Copy-on-Write (COW) Memory Restoration
|
||||
|
||||
CRIU employs a specialized multi-stage process to preserve Copy-on-Write (COW) sharing of private anonymous memory mappings during restoration. This prevents the memory duplication that would occur if each process's memory were restored independently, thereby significantly reducing the memory footprint of the restored process tree.
|
||||
|
||||
## The Problem
|
||||
|
||||
When a process calls `fork()`, the Linux kernel optimizes memory usage by sharing private anonymous mappings between the parent and child. Physical pages are only duplicated (COW) when one of the processes modifies them.
|
||||
|
||||
Traditional checkpointing captures each process's memory separately. If restored naively (by mapping and filling each VMA individually), the kernel would allocate separate physical pages for the parent and child, even for pages that were originally shared. This leads to a massive increase in physical memory usage upon restoration.
|
||||
|
||||
## CRIU's COW Restoration Strategy
|
||||
|
||||
To keep COW mappings intact, CRIU performs restoration in a way that mimics the original `fork()` behavior.
|
||||
|
||||
### 1. Identifying COW Candidates
|
||||
Before forking the process tree, CRIU analyzes the memory maps of all tasks:
|
||||
* It compares each task's VMAs with those of its parent.
|
||||
* Two VMAs are identified as COW candidates if they have identical start/end addresses, the same protection flags (e.g., `PROT_READ`, `PROT_WRITE`), and belong to the same executable.
|
||||
* This mapping is stored internally, marking which VMAs are "inherited" from a parent.
|
||||
|
||||
### 2. Pre-mapping and Filling
|
||||
During restoration, processes are created in a specific order:
|
||||
1. **Root VMA Population**: If a VMA is the "root" of a COW set (it is not inherited), the restoring task maps it and fills it with data from the image files.
|
||||
2. **Inheritance via Fork**: When a task forks a child, the child automatically inherits the parent's memory mappings via the standard kernel COW mechanism.
|
||||
3. **Content Verification**: The child then iterates through its own memory images:
|
||||
* It compares the page contents in the image with the data already present in its inherited memory (which it got from the parent).
|
||||
* If the contents match exactly, the physical page remains shared with the parent.
|
||||
* If they differ (meaning the page was modified in either process after the original fork), the child overwrites the page with the data from its image, triggering a kernel COW event for that specific page.
|
||||
|
||||
### 3. Cleaning Up (madvise)
|
||||
A parent may contain pages that were unmapped or modified in the child process. To ensure the child's memory layout is perfectly accurate:
|
||||
* CRIU maintains a bitmap of pages touched during the content verification stage.
|
||||
* After all pages are processed, CRIU uses `madvise(MADV_DONTNEED)` on any pages that exist in the inherited VMA but were not present in the child's dump images. This effectively "punches holes" in the child's VMA to match its original state while preserving the sharing of other pages.
|
||||
|
||||
## Current Limitations
|
||||
|
||||
* **Reparenting to Init**: If a process was reparented to the system `init` (PID 1) and that `init` process is not part of the checkpointed process tree, CRIU cannot identify the parent's VMAs, and COW sharing will not be restored for that process.
|
||||
* **VMA Movement**: If a VMA was moved (e.g., via `mremap`) after the original `fork()`, CRIU's current address-based matching algorithm will fail to identify it as a COW candidate.
|
||||
|
||||
## See Also
|
||||
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
|
||||
* [Restorer Context](restorer-context.md)
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# DMTCP vs. CRIU
|
||||
|
||||
This article explains the fundamental differences between CRIU and DMTCP (Distributed MultiThreaded Checkpointing), focusing on their architectural approaches to process capture and restoration.
|
||||
|
||||
## Architectural Approach
|
||||
|
||||
### DMTCP: Library-Level Interception
|
||||
DMTCP implements checkpoint/restore at the **userspace library level**. To use it, an application must be launched with the DMTCP library dynamically linked (`LD_PRELOAD`).
|
||||
* **Mechanism**: The library intercepts library calls (e.g., `glibc` wrappers for syscalls), builds an internal shadow database of the process state, and then forwards requests to the kernel.
|
||||
* **Implications**: This approach can introduce performance overhead due to proxying. Only applications compatible with the DMTCP library can be reliably dumped. Furthermore, DMTCP may not support all kernel APIs; for instance, complex features like `inotify` or specific socket types may lack sufficient proxies.
|
||||
|
||||
### CRIU: Kernel-Level Integration
|
||||
CRIU, by contrast, operates primarily from **outside the process** using standard kernel interfaces (extended where necessary for C/R).
|
||||
* **Mechanism**: CRIU uses tools like `ptrace`, `/proc`, and specialized system calls (e.g., `kcmp`, `map_files`) to transparently capture the process state without requiring pre-loaded libraries.
|
||||
* **Implications**: It can checkpoint and restore virtually any application, provided the kernel supports the required features. It requires a relatively modern kernel version but offers much deeper integration with system resources like namespaces and cgroups.
|
||||
|
||||
## PID Handling and Virtualization
|
||||
|
||||
Restoring a process tree often requires restoring specific Process IDs (PIDs).
|
||||
|
||||
* **DMTCP "Fake" PIDs**: Because the kernel does not traditionally allow userspace to request a specific PID during `fork()`, DMTCP "fools" the application. It intercepts the `getpid()` call and returns a fake value that matches the original PID. This is highly dangerous, as the application may see inconsistent information in the `/proc` filesystem (where directories are named by the *real* PID).
|
||||
* **CRIU Real PIDs**: CRIU restores the **actual PID** of the process. It achieves this by using the `ns_last_pid` interface or the modern `clone3` system call with a specified PID. This ensures that the restored process has the exact same identity as the original, with no inconsistencies in `/proc` or other kernel interfaces.
|
||||
|
||||
## Summary
|
||||
|
||||
DMTCP is often easier to deploy on older kernels since it doesn't require specific kernel support, but it suffers from the inherent limitations and risks of userspace interception. CRIU is the more robust and transparent solution for modern Linux systems, offering faithful restoration of the entire process environment.
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
# Dumping File Descriptors
|
||||
|
||||
This document explains the internal mechanisms CRIU uses to capture the state of opened file descriptors (FDs).
|
||||
|
||||
## Linux File Objects: Inodes, Dentries, and Files
|
||||
|
||||
In the Linux kernel, an opened file is represented by a chain of three distinct objects:
|
||||
|
||||
1. **Inode**: Contains metadata (owner, type, size) and pointers to the actual data on disk.
|
||||
2. **Dentry (Directory Entry)**: A helper object used to resolve file paths. An inode can have multiple dentries if hard links exist.
|
||||
3. **File (or "File Description")**: Represents an active handle to a dentry/inode pair. It maintains state such as the current file position (`pos`) and access flags.
|
||||
|
||||
Crucially, **file descriptors** are per-task integers that point to these shared "File" objects. When a task calls `fork()`, the child's FDs point to the same "File" objects as the parent's.
|
||||
|
||||
## How CRIU Collects FD Information
|
||||
|
||||
Dumping FDs requires CRIU to collect state from both the kernel's `/proc` filesystem and the file objects themselves.
|
||||
|
||||
### 1. Identifying Open FDs
|
||||
CRIU reads `/proc/$pid/fd/` and `/proc/$pid/fdinfo/` to determine which FD numbers are currently open and to retrieve their basic properties (position and flags).
|
||||
|
||||
### 2. Retrieving File Objects (SCM_RIGHTS)
|
||||
To perform deeper inspection (like `fstat` or `ioctl`), CRIU needs a local copy of the file descriptor. It achieves this by:
|
||||
* Injecting **parasite code** into the target task.
|
||||
* Commanding the parasite to send the FDs to the CRIU coordinator via a Unix domain socket using the `SCM_RIGHTS` mechanism.
|
||||
|
||||
### 3. Detecting Shared Files (gen_id and kcmp)
|
||||
To minimize image size and avoid redundant dumps, CRIU must identify if FDs in different tasks (or even the same task) point to the same underlying "File" object. It uses a two-stage optimization:
|
||||
1. **gen_id**: CRIU calculates a "generation ID" based on the file's device ID, inode number, and current position. If two FDs have different `gen_id`s, they are guaranteed to be different.
|
||||
2. **kcmp**: If `gen_id`s match, CRIU uses the `kcmp()` system call (with the `KCMP_FILE` flag) to definitively determine if the two descriptors refer to the same kernel "File" object.
|
||||
|
||||
## Image Storage
|
||||
|
||||
CRIU stores FD information in a two-tier structure:
|
||||
|
||||
### The `fdinfo-$id.img` Image
|
||||
This per-task image maps task-specific FD numbers to global **File IDs**. Each entry contains:
|
||||
* `fd`: The numeric descriptor in the task.
|
||||
* `id`: A unique identifier for the underlying file object.
|
||||
|
||||
### Specialized File Images
|
||||
The actual state of the file objects is stored in specialized images based on their type:
|
||||
* `reg-files.img`: Regular files (includes the path).
|
||||
* `pipes.img`: Pipes and FIFOs.
|
||||
* `unixsk.img` / `inetsk.img`: Sockets.
|
||||
* `signalfd.img`, `eventfd.img`, `epoll.img`, etc.
|
||||
|
||||
This separation allows CRIU to efficiently handle shared files: multiple `fdinfo` entries can point to a single entry in a specialized file image.
|
||||
|
||||
## See also
|
||||
|
||||
* [Kcmp Trees](kcmp-trees.md)
|
||||
* [Parasite Code](parasite-code.md)
|
||||
* [Invisible Files](invisible-files.md)
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
# Frequently Asked Questions (FAQ)
|
||||
|
||||
This page provides answers to common questions and technical insights into CRIU's behavior and limitations.
|
||||
|
||||
## General Questions
|
||||
|
||||
### Q: Why does CRIU dump parts of read-only code mappings?
|
||||
**A**: Even if a mapping (like the code section of `/usr/bin/something`) is marked as read-only, it may still contain "dirty" pages that CRIU must dump. This typically happens due to **Copy-on-Write (COW)** events during dynamic linking, relocation patching, or if the process modified its own code via `mprotect` and `ptrace`.
|
||||
|
||||
### Q: How can I verify that my system is ready for CRIU?
|
||||
**A**: Use the built-in check tool:
|
||||
```bash
|
||||
criu check --extra
|
||||
```
|
||||
This will verify that your kernel has all the necessary features (like `kcmp`, `ns_last_pid`, etc.) enabled. Additionally, running the [ZDTM Test Suite](zdtm-test-suite.md) is the best way to confirm functional correctness on your specific hardware and software stack.
|
||||
|
||||
### Q: Is it possible to change the IP address during live migration?
|
||||
**A**: Yes, but with caveats. Since TCP connections are identified by their IP/Port 4-tuple, changing the IP will normally break established connections.
|
||||
- If you can tolerate connection resets, use the `--tcp-close` flag.
|
||||
- For listening sockets, you can use the `UPDATE_INETSK` plugin hook or the `CRIT` tool to remap addresses.
|
||||
- For seamless migration, virtual IPs or network-level NAT are required. See [Changing IP Addresses](change-ip-address.md) for more details.
|
||||
|
||||
### Q: Why does restore fail with a "PID mismatch" error?
|
||||
**A**: This occurs because the PID CRIU is trying to restore is already in use by another process on the system.
|
||||
- **Solution**: The most common way to avoid this is to run the restored process inside a fresh **PID namespace**. This ensures that the PID range is entirely available to CRIU.
|
||||
- **Internal Note**: CRIU uses the `ns_last_pid` kernel interface or the modern `clone3` system call to request specific PIDs during restoration.
|
||||
|
||||
### Q: Why does dump fail with "Cannot dump half of a stream unix connection"?
|
||||
**A**: This usually happens when one end of a Unix domain socket is held by a process *outside* the process tree being checkpointed. CRIU cannot capture the state of the "external" peer, so it cannot safely restore the connection unless the socket is explicitly marked as external via the `--external unix[ino]` option.
|
||||
|
||||
---
|
||||
|
||||
## Testing (ZDTM)
|
||||
|
||||
### Q: Why do my ZDTM tests fail with "Permission Denied" even when run as root?
|
||||
**A**: The `zdtm.py` test runner executes many sub-tests as a non-privileged user to verify CRIU's behavior in unprivileged environments. If your specific test requires root privileges, you must add `'flags': 'suid'` to the test's `.desc` file.
|
||||
|
||||
---
|
||||
|
||||
## Containers and Docker
|
||||
|
||||
### Q: Why can't I restore a Docker container onto a different image?
|
||||
**A**: CRIU checkpoints the state of the processes, but it does **not** checkpoint the underlying filesystem. The process images contain paths to files that must exist exactly as they did during the dump.
|
||||
- **Solution**: To restore a container, you must ensure the filesystem state is identical. In Docker, this often involves using `docker commit` to create an image of the container's filesystem at the moment of the checkpoint.
|
||||
- **Modern Tools**: Container engines like Podman or newer versions of Docker/RunC handle this integration more seamlessly by managing the filesystem snapshots alongside the CRIU state.
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# File Restoration Engine (fdinfo)
|
||||
|
||||
CRIU uses a sophisticated state machine to restore file descriptors (FDs) across a process tree, handling shared files, complex dependencies, and inter-process synchronization.
|
||||
|
||||
## Master and Slave Descriptors
|
||||
|
||||
In the Linux kernel, multiple FDs can refer to the same underlying "File Description." CRIU mirrors this by categorizing FDs into **Masters** and **Slaves**:
|
||||
|
||||
1. **Master**: For each unique file object, one FD is designated as the master. This process is responsible for the actual `open()`, `socket()`, or `pipe()` system call that recreates the object.
|
||||
2. **Slaves**: All other FDs referring to the same object are slaves. They do not perform the creation call themselves; instead, they receive the file descriptor from the master.
|
||||
3. **Transport (SCM_RIGHTS)**: CRIU uses Unix domain sockets and the `SCM_RIGHTS` mechanism to "send" file descriptors from the master process to slave processes.
|
||||
|
||||
## Per-Process Restore Loop
|
||||
|
||||
Each task in the process tree executes a loop (`open_fdinfos`) to restore its descriptors. The core of this loop is the `file_desc_ops->open()` method.
|
||||
|
||||
### The `open()` State Machine
|
||||
The `open()` method for a master file can return one of three values:
|
||||
* **0 (Success)**: The file is fully restored.
|
||||
* **1 (In Progress)**: The file has been opened (or the process has started opening it), but it cannot be completed yet due to a dependency on another file. The loop will call this method again in the next iteration.
|
||||
* **-1 (Failure)**: An error occurred, and restoration must abort.
|
||||
|
||||
### Early FD Distribution
|
||||
To maximize parallelism, a master can return a valid FD in the `new_fd` argument even if it returns `1` (In Progress). This allows CRIU to immediately distribute the FD to all slave processes via `SCM_RIGHTS`, even before the master has finished its own restoration steps (e.g., a connected Unix socket waiting for its peer).
|
||||
|
||||
## Inter-Process Synchronization
|
||||
|
||||
CRIU uses **futexes** and a specialized event mechanism to coordinate between processes:
|
||||
* **set_fds_event(pid)**: Signals a task that a file it was waiting for (as a slave) is now available or that a dependency has changed.
|
||||
* **wait_fds_event()**: Causes a task to sleep until it receives a notification.
|
||||
* **FLE Stages**: Each descriptor entry (`struct fdinfo_list_entry` or `fle`) transitions through stages: `INITIALIZED` -> `OPEN` -> `RESTORED`.
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
The engine must resolve complex dependencies between different file types:
|
||||
1. **TTYs**: A slave TTY can only be fully restored after its master peer is active.
|
||||
2. **Unix Sockets**: A connected socket must wait for its peer to `bind()` to its address before it can `connect()`.
|
||||
3. **Epoll**: An epoll FD can be created immediately, but adding FDs to its interest list must wait until those FDs are themselves restored.
|
||||
4. **Pipes and Socketpairs**: These calls create two FDs at once. One is treated as the primary master, and the second is distributed to the appropriate task (which might be the same task or a different one).
|
||||
|
||||
## Technical Notes
|
||||
|
||||
* **Service FDs**: CRIU maintains its own internal FDs (for images, logs, etc.) in a "protected" range to avoid conflicts with the application's FDs during restoration.
|
||||
* **Ordering**: Descriptors are generally restored in ascending order of their FD number to improve efficiency, though dependencies can override this order.
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
# Filesystem Peculiarities in CRIU
|
||||
|
||||
While Linux aims for a uniform filesystem interface, several filesystems have unique behaviors ("peculiarities") that require specialized handling in CRIU to ensure accurate checkpointing and restoration.
|
||||
|
||||
## BTRFS: Virtual Device Numbers
|
||||
|
||||
When you `stat()` a file on BTRFS, the kernel often reports a **virtual device ID** (`st_dev`) that is unique to that specific subvolume or snapshot. However, other kernel interfaces, such as `/proc/$pid/mountinfo` or the `sock_diag` subsystem, may report the **physical device ID**.
|
||||
|
||||
**Problem**: CRIU cannot rely on simple `st_dev` comparisons to identify which mount a file belongs to, as the virtual and physical IDs will mismatch.
|
||||
|
||||
**Solution**: CRIU performs userspace path-to-device resolution. It analyzes `/proc/$pid/mountinfo` to build a mapping between virtual and physical IDs, allowing it to correctly resolve file locations. See `mount.c:phys_stat_resolve_dev()`.
|
||||
|
||||
**Workaround**: In some environments (like Podman), disabling Copy-on-Write for the container storage (`chattr +C`) can mitigate some BTRFS-related complexities.
|
||||
|
||||
## NFS: "Silly Rename" and Unlinked Files
|
||||
|
||||
NFS handles unlinked but open files differently than local filesystems. When a file is unlinked while still open, the NFS client performs a **"Silly Rename"**, renaming the file to something like `.nfsXXX` instead of truly removing it.
|
||||
|
||||
**Problem**: CRIU's standard logic for detecting unlinked files (checking if `st_nlink == 0`) fails on NFS because the "silly renamed" file still has a link count of 1.
|
||||
|
||||
**Solution**: CRIU explicitly checks if a file resides on an NFS mount. If it does, it examines the filename for the `.nfs` prefix. If both conditions match, CRIU treats the file as "opened and unlinked," capturing its contents into the image as a **ghost file**. See `files-reg.c:nfs_silly_rename()`.
|
||||
|
||||
## OverlayFS: Path Inconsistencies and Link-Remap
|
||||
|
||||
OverlayFS, the standard for modern container engines, has several known issues:
|
||||
|
||||
1. **Path Mismatches (Pre-v4.2)**: On older kernels, `/proc/$pid/fd/` and `/proc/$pid/fdinfo/` could report paths that did not include the OverlayFS mountpoint. CRIU detects OverlayFS mounts and manually corrects these paths using information from the mount table.
|
||||
2. **linkat() Failures**: In OverlayFS, the `linkat()` system call fails with `ENOENT` if the file being linked resides on a **lower layer** (read-only layer) and has been unlinked from the upper layer.
|
||||
* **CRIU Response**: When a "link-remap" (linking a deleted file back to the filesystem) fails on OverlayFS, CRIU automatically falls back to dumping the file as a **ghost file** (copying its contents into the image).
|
||||
|
||||
## AUFS: Branch Path Leakage (Legacy)
|
||||
|
||||
AUFS (mostly superseded by OverlayFS) has a bug where `/proc/$pid/maps` reveals the path of a file within its internal **branch** directory instead of its visible path within the AUFS mount.
|
||||
|
||||
**Solution**: CRIU identifies AUFS mounts, reads the branch configuration from `sysfs`, and "fixes" the paths in the memory map to ensure the file can be correctly located during restoration. See `sysfs_parse.c:fixup_aufs_vma_fd`.
|
||||
|
||||
## See also
|
||||
* [How Hard is it to Open a File?](how-hard-is-it-to-open-a-file.md)
|
||||
* [Invisible Files](invisible-files.md)
|
||||
* [Mount Points](mount-points.md)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# Process Tree Final States
|
||||
|
||||
This document describes the possible states a process tree can end up in after a successful CRIU **dump** or **restore** operation.
|
||||
|
||||
## Supported Final States
|
||||
|
||||
CRIU supports three primary final states for the process tree:
|
||||
|
||||
1. **Running (`TASK_ALIVE`)**: The processes continue execution as normal.
|
||||
2. **Stopped (`TASK_STOPPED`)**: The processes are left in a stopped state (equivalent to receiving `SIGSTOP`).
|
||||
3. **Dead (`TASK_DEAD`)**: The processes are terminated (equivalent to receiving `SIGKILL`).
|
||||
|
||||
## Controlling the Final State
|
||||
|
||||
You can specify the desired final state using the following command-line options:
|
||||
|
||||
* `--leave-running`: Forces the process tree to continue running after the operation.
|
||||
* `--leave-stopped`: Forces the process tree to remain stopped after the operation.
|
||||
|
||||
### Default Behavior for `criu dump`
|
||||
|
||||
By default, `criu dump` terminates the process tree (**Dead**).
|
||||
|
||||
**Rationale**: Leaving a process tree running after a full dump is risky. If the processes continue to run, they will likely modify the filesystem, network state, or shared memory. These changes can make the captured image inconsistent or impossible to restore later, as the system state will no longer match the process's internal state at the moment of the dump.
|
||||
|
||||
* **Exceptions**: The `pre-dump` command always enforces the **Running** state, as its purpose is to capture memory changes while the application continues to operate.
|
||||
|
||||
### Default Behavior for `criu restore`
|
||||
|
||||
By default, `criu restore` resumes the process tree (**Running**).
|
||||
|
||||
**Rationale**: The primary goal of restoration is typically to resume the application's work immediately.
|
||||
|
||||
* **Debugging**: Using `--leave-stopped` during restoration can be extremely useful for debugging. It allows you to inspect the restored process tree (e.g., via `/proc` or a debugger) before it begins executing any code.
|
||||
|
||||
## Resuming a Stopped Tree
|
||||
|
||||
If a process tree was left in the **Stopped** state (either by dump or restore), you can resume its execution by sending a `SIGCONT` signal to all processes in the tree.
|
||||
|
||||
For complex process trees, the [pstree_cont.py](https://github.com/checkpoint-restore/criu-scripts/blob/master/pstree_cont.py) script (available in the `criu-scripts` repository) can be used to safely resume the entire hierarchy by targeting the root PID.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Freezing the Tree](freezing-the-tree.md)
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
# Freezing the Process Tree
|
||||
|
||||
Before CRIU can begin checkpointing, it must ensure that the entire process tree is completely "immobilized." This prevents tasks from changing their state (e.g., opening files, creating children, or receiving network packets) while the snapshot is being taken. This freezing process must be transparent to the application, meaning it should not observe any disruption or unexpected signals.
|
||||
|
||||
CRIU employs two primary methods to achieve this:
|
||||
|
||||
## Capturing with ptrace
|
||||
|
||||
The most common method for freezing a tree is using the Linux `ptrace` interface. Unlike traditional debuggers that might send disruptive signals like `SIGSTOP`, CRIU uses a more modern, non-invasive approach:
|
||||
|
||||
1. **SEIZE**: CRIU calls `ptrace(PTRACE_SEIZE, pid, ...)` for every task in the tree. This "attaches" to the process without stopping it or delivering any signals.
|
||||
2. **INTERRUPT**: Once seized, CRIU sends a `ptrace(PTRACE_INTERRUPT, pid, ...)` command. This causes the kernel to stop the task at the next possible opportunity (typically upon entering or exiting a syscall or being preempted).
|
||||
3. **WAIT**: CRIU then waits for the task to enter the `TRAP_STOP` state. This state is invisible to the task's own signal handling logic, ensuring transparency.
|
||||
|
||||
By seizing every task in the tree, CRIU ensures that no task can resume execution or fork new children during the dump.
|
||||
|
||||
## Using Freezer CGroups
|
||||
|
||||
For large process trees or environments where `ptrace` might be restricted or inefficient, CRIU can use the Linux **Freezer CGroup**. This allows the kernel to freeze an entire group of processes in a single, atomic operation.
|
||||
|
||||
CRIU supports both versions of the freezer:
|
||||
|
||||
### CGroup v1 Freezer
|
||||
* **Mechanism**: CRIU identifies the freezer cgroup containing the process tree and writes `FROZEN` to the `freezer.state` file.
|
||||
* **Handling Inconsistency**: Historically, the v1 freezer could be unreliable, sometimes getting stuck in a `FREEZING` state. CRIU includes "kludges" to handle this, such as periodically retrying the freeze command or briefly thawing and re-freezing the group to kick the kernel's internal state machine.
|
||||
|
||||
### CGroup v2 Freezer
|
||||
* **Mechanism**: In the unified cgroup v2 hierarchy, CRIU writes `1` to the `cgroup.freeze` file.
|
||||
* **Verification**: It then monitors the `cgroup.events` file, waiting for the `frozen 1` event to signal that all processes in the sub-hierarchy have successfully stopped.
|
||||
|
||||
**Note**: Even when using a freezer cgroup, CRIU still attaches to the tasks via `ptrace` after they are frozen. This is necessary to perform internal inspections, such as extracting register states and injecting parasite code.
|
||||
|
||||
## See also
|
||||
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Process Tree Final States](final-states.md)
|
||||
* [Parasite Code](parasite-code.md)
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# FSNotify (Inotify and Fanotify)
|
||||
|
||||
CRIU supports checkpointing and restoring `inotify` and `fanotify` instances. These mechanisms allow applications to monitor filesystem events (like file creation, modification, or deletion).
|
||||
|
||||
## The Challenges of FSNotify C/R
|
||||
|
||||
Restoring an fsnotify instance is inherently difficult because the kernel does not provide a direct way to retrieve the original path of a watched object (the "watchee"). Furthermore, the event queues themselves pose consistency risks.
|
||||
|
||||
### 1. Identifying the Watchee
|
||||
When an application adds a watch (via `inotify_add_watch`), the kernel associates the watch with an **inode**, but it does not store the **path** used to create it. To restore the watch, CRIU must find a valid path to that specific inode.
|
||||
* **Open by Handle**: CRIU first attempts to use `open_by_handle_at()`. If the filesystem supports file handles, CRIU captures the handle during the dump and uses it to re-open the inode during restoration without needing the original path.
|
||||
* **Irmap (Inode Reverse Mapping)**: If file handles are unavailable, CRIU uses the [Irmap](irmap.md) engine to scan the filesystem and find a path that leads to the target inode.
|
||||
|
||||
### 2. Event Queue Consistency
|
||||
If there are pending events in the fsnotify queue at the time of the dump, CRIU cannot currently "peek" at them or safely migrate them.
|
||||
* **Dropped Events**: During a dump, CRIU checks if the fsnotify file descriptor has data. If it does, CRIU emits a warning: `The ... inotify events will be dropped`. These events are lost, and the application must be prepared to handle this gap in its event stream.
|
||||
* **Spurious Events**: The process of checkpointing and restoring itself can trigger new filesystem events. For example, creating or deleting **ghost files** (temporary files used to restore unlinked but open files) can generate `IN_CREATE` or `IN_DELETE` events that the application will see upon resumption.
|
||||
|
||||
### 3. Ghost Files and Circular Dependencies
|
||||
A "ghost file" is a file that was deleted by the application but is still held open. During restoration, CRIU must recreate these files. This action itself generates notify events, potentially confusing applications that monitor the directories where these ghost files are temporarily placed.
|
||||
|
||||
## Support for Fanotify
|
||||
|
||||
CRIU also supports `fanotify`, including:
|
||||
* **Inode Marks**: Similar to inotify, these target specific files or directories.
|
||||
* **Mount Marks**: Fanotify can monitor entire mount points. CRIU identifies the mount ID and restores the mark on the corresponding mount in the restored namespace.
|
||||
|
||||
## Current Strategy: "Chopping the Knot"
|
||||
|
||||
Due to the complexity of perfectly migrating event queues, CRIU's current strategy is:
|
||||
1. **Warn and Drop**: Acknowledge that pending events are lost.
|
||||
2. **Restore the Watches**: Ensure the application continues to receive *new* events after restoration.
|
||||
3. **Namespace Integration**: Correctly map mount-level fanotify marks within their respective mount namespaces.
|
||||
|
||||
## See also
|
||||
* [Irmap](irmap.md)
|
||||
* [Invisible Files](invisible-files.md)
|
||||
* [Mount Points](mount-points.md)
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# The Complexity of Re-opening Files during Restore
|
||||
|
||||
Re-creating an open file descriptor during restoration is far more complex than simply calling `open(path, flags)`. This article explores the numerous edge cases CRIU must handle to faithfully reconstruct the file state.
|
||||
|
||||
## 1. Basic Opening
|
||||
|
||||
At its simplest, a file is defined by its path and access mode:
|
||||
```c
|
||||
int fd = open(f->path, f->mode);
|
||||
```
|
||||
However, this is only the beginning of the process.
|
||||
|
||||
## 2. FIFOs and Blocking
|
||||
A standard `open()` call on a FIFO (named pipe) can hang indefinitely if there is no corresponding reader or writer on the other end. CRIU avoids this by first opening the FIFO with `O_RDWR` (to ensure at least one of each is present) and then using `dup2` to establish the final descriptor with the correct original flags.
|
||||
|
||||
## 3. Unlinked but Open Files (Ghost Files)
|
||||
Linux allows files to be deleted while they are still open. These "invisible" files no longer have a path in the filesystem.
|
||||
* **link-remap**: If the file still has other hard links elsewhere, CRIU may create a temporary link to it to allow it to be re-opened via a path.
|
||||
* **Ghost Files**: If the link count is zero, CRIU captures the entire content of the file during the dump. During restore, it recreates this file in a temporary location, opens it, and then unlinks it to match the original state.
|
||||
|
||||
## 4. Directories and Hard Links
|
||||
Directories cannot be hard-linked. If a directory was unlinked, CRIU must recreate it, open it, and then remove it. For files with multiple hard links that were all deleted, CRIU must ensure they all point back to the same physical inode upon restoration, requiring careful tracking of "temporary" paths and user-space reference counts.
|
||||
|
||||
## 5. Mount Namespaces and Chroot
|
||||
The same path (e.g., `/etc/passwd`) might refer to entirely different files depending on the mount namespace or `chroot` environment of the process.
|
||||
* **mnt_id**: CRIU records the mount ID for every file during the dump.
|
||||
* **open_ns_root**: During restoration, CRIU uses file descriptors referring to the root of the specific mount namespace to ensure that `openat()` targets the correct physical file, regardless of the restorer's current root.
|
||||
|
||||
## 6. File Ownership and Signals (fown)
|
||||
Files can have an associated "owner" (a PID or PGID) that receives signals (like `SIGIO` or `SIGPOLL`) when I/O events occur.
|
||||
* **F_SETOWN_EX**: CRIU restores this ownership using the extended owner structure.
|
||||
* **UID Switching**: Setting the owner of a file may require specific privileges. CRIU may temporarily switch its effective UIDs during the `fcntl` call to satisfy kernel permission checks if the file owner differs from the restorer.
|
||||
* **F_SETSIG**: The specific signal number to be delivered is also faithfully restored.
|
||||
|
||||
## 7. Position and Flags
|
||||
* **Lseek**: The current byte offset (`pos`) is restored using `lseek`.
|
||||
* **Flag Sanitization**: Certain flags (like `O_CREAT`, `O_EXCL`, `O_TRUNC`) only make sense during the initial creation of a file. CRIU strips these before the restore-time `open()` to avoid accidentally creating or truncating existing files.
|
||||
* **O_PATH**: Files opened with `O_PATH` are handled as pure path references; they do not have positions, ownership, or data access.
|
||||
|
||||
## 8. The Final Step: Descriptor Planting
|
||||
Once a file is successfully opened (at a temporary descriptor number assigned by the kernel), it must be moved to the exact numeric descriptor the application expects (e.g., FD 42). This is achieved via `dup2()`, but requires coordination when descriptors are shared across a process tree.
|
||||
|
||||
*See also: [How to assign needed file descriptor to a file](how-to-assign-needed-file-descriptor-to-a-file.md)*
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
# Assigning Descriptors and Sharing Files
|
||||
|
||||
Once a file is [opened during restoration](how-hard-is-it-to-open-a-file.md), it often needs to be moved to a specific numeric file descriptor (FD) and potentially shared with other tasks in the process tree. This document explains how CRIU coordinates this process.
|
||||
|
||||
## The Basic Mechanism: `dup2`
|
||||
|
||||
In Linux, the `dup2(oldfd, newfd)` system call is the standard way to assign a file to a specific descriptor number. CRIU uses this to move a newly opened file from its temporary descriptor (assigned by the kernel) to the target descriptor expected by the application.
|
||||
|
||||
```c
|
||||
int fd = open_a_file(f->file);
|
||||
dup2(fd, f->target_fd);
|
||||
close(fd);
|
||||
```
|
||||
|
||||
## Handling Multiple Descriptors for One File
|
||||
|
||||
A single task may have multiple FDs referring to the same kernel "File Description" (e.g., a shell where FD 0, 1, and 2 all point to the same TTY). CRIU handles this by identifying the unique file object, opening it once, and then calling `dup2()` for every target FD slot the application expects.
|
||||
|
||||
## Sharing Files Across the Process Tree
|
||||
|
||||
Files are frequently shared between processes. While these files were originally inherited via `fork()`, CRIU must often distribute them between processes that do not have a direct parent-child relationship during the restore phase.
|
||||
|
||||
### Master and Slave Descriptors
|
||||
For every unique file object in a checkpoint:
|
||||
1. **The Master**: One task is designated as the "master" for that file. It is responsible for the actual system call that recreates the object (e.g., `open()`, `socket()`, or `pipe()`).
|
||||
2. **The Slaves**: All other tasks that share the same file are "slaves." They do not create the file themselves.
|
||||
|
||||
### Transport via SCM_RIGHTS
|
||||
CRIU uses Unix domain sockets to "send" descriptors from the master process to slave processes using the `SCM_RIGHTS` mechanism.
|
||||
|
||||
**The Workflow:**
|
||||
1. **Master Opens**: The master task creates the file object.
|
||||
2. **Master Sends**: The master sends the resulting file descriptor to each slave task over a dedicated transport socket.
|
||||
3. **Slave Receives**: The slave task waits on its transport socket, receives the FD, and uses `dup2()` to plant it into the correct numeric slot.
|
||||
|
||||
## Solving the Coordination Problem
|
||||
|
||||
Distributing thousands of descriptors across a complex process tree requires careful management to avoid deadlocks and descriptor collisions.
|
||||
|
||||
### 1. Transport Sockets
|
||||
CRIU creates abstract Unix sockets for each process to receive descriptors. The names are uniquely generated using the PID and a `criu_run_id` (e.g., `\0x/crtools-fd-123-abcdef`) to ensure that multiple simultaneous CRIU runs on the same host do not interfere with each other.
|
||||
|
||||
### 2. Deterministic "Master" Selection
|
||||
To prevent circular dependencies (e.g., Task A waiting for Task B while B waits for A), CRIU uses a deterministic priority system to select the master. Typically, the task with the highest priority—usually the one closest to the root of the tree or with the lowest PID—is chosen to open and distribute the file.
|
||||
|
||||
### 3. Descriptor Collisions
|
||||
A task's target FDs may conflict with the internal "service" FDs CRIU uses for images, logs, or transport sockets. CRIU resolves this by:
|
||||
* **Service FD Range**: Restricting CRIU's own FDs to a specific range.
|
||||
* **Dynamic Relocation**: If a target FD slot is occupied by an active service FD, CRIU moves the service FD to a new, free slot using `dup()` before planting the application's FD.
|
||||
|
||||
## Complex Dependencies
|
||||
|
||||
Some file types have inherent dependencies. For instance, an `epoll` descriptor cannot be fully restored until the files it monitors are already opened and their numeric descriptors are known. CRIU's file restoration engine handles this via a multi-pass state machine, where some files are opened but their full restoration is deferred until their dependencies are satisfied.
|
||||
|
||||
*See also: [File Restoration Engine (fdinfo)](fdinfo-engine.md)*
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
# Re-opening Files without Paths (open_by_handle_at)
|
||||
|
||||
Occasionally, CRIU encounters an open file descriptor for which the kernel no longer maintains a path. This document explains how CRIU uses file handles and Inode Reverse Mapping (Irmap) to reconstruct these "nameless" files.
|
||||
|
||||
## When Paths Are Lost
|
||||
|
||||
The most common scenario for path loss occurs with **fsnotify** (inotify and fanotify) instances.
|
||||
When an application calls `inotify_add_watch(path)`, the kernel:
|
||||
1. Resolves the path to an **inode**.
|
||||
2. Attaches a watch generator to that inode.
|
||||
3. Immediately forgets the path used to create the watch.
|
||||
|
||||
The resulting file descriptor points to the fsnotify instance, which knows *which* inode it is watching but not *where* that inode lives in the filesystem hierarchy. Because the dentry (directory entry) cache can be shrunk by the kernel at any time, the path information is often permanently lost to userspace.
|
||||
|
||||
## Strategy 1: open_by_handle_at
|
||||
|
||||
Linux provides a specialized system call, `open_by_handle_at()`, designed for userspace NFS servers. It allows opening a file using a **File Handle**—a filesystem-specific blob of bytes that uniquely identifies an inode.
|
||||
|
||||
### The Handle mechanism
|
||||
1. **Dumping**: CRIU reads the file handle for a watch from `/proc/$pid/fdinfo/$fd`. (CRIU developers upstreamed patches to the Linux kernel to ensure this information is exposed).
|
||||
2. **Restoring**: During restoration, CRIU takes this handle and calls `open_by_handle_at()`. This returns an `O_PATH` file descriptor pointing to the original inode, even if its original path is unknown.
|
||||
3. **Re-attaching**: CRIU then uses this `O_PATH` descriptor to re-establish the inotify or fanotify watch, effectively "tricking" the kernel into watching the correct inode.
|
||||
|
||||
## Strategy 2: Irmap (Inode Reverse Mapping)
|
||||
|
||||
Not all filesystems support file handles (e.g., some older or specialized filesystems). In these cases, CRIU must resort to a brute-force approach called **Irmap**.
|
||||
|
||||
The Irmap engine maintains a cache that maps `(device, inode)` pairs back to their filesystem paths.
|
||||
1. **Scanning**: Irmap recursively scans "known" directories (like configuration paths or application homes) and records every name-to-inode mapping it finds.
|
||||
2. **Lookup**: When CRIU needs a path for a specific inode, it queries the Irmap cache.
|
||||
3. **Pre-dump Integration**: To minimize the performance impact of filesystem scanning, CRIU can perform this scan during a **pre-dump** while the application is still running. The results are saved to an `irmap-cache.img` file and reused during the final dump.
|
||||
|
||||
## Filesystem Specifics
|
||||
|
||||
* **Tmpfs**: This filesystem pins its dentries in memory. For tmpfs, paths are almost always available via `/proc` and do not require handles or Irmap.
|
||||
* **OverlayFS**: Due to its layered nature, OverlayFS can have complex handle behaviors. CRIU includes specific logic to navigate these layers during handle resolution.
|
||||
|
||||
## See also
|
||||
* [Dumping File Descriptors](dumping-files.md)
|
||||
* [FSNotify (Inotify and Fanotify)](fsnotify.md)
|
||||
* [Irmap](irmap.md)
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
# CRIU: Under the Hood
|
||||
|
||||
This directory contains technical documentation detailing the internal implementation of CRIU, the kernel APIs it leverages, and the complex algorithms used to achieve checkpoint and restore of various Linux resources.
|
||||
|
||||
## Core Architecture & Lifecycle
|
||||
|
||||
* [Checkpoint and Restore Overview](checkpointrestore.md): High-level view of the C/R process.
|
||||
* [Freezing the Process Tree](freezing-the-tree.md): How CRIU stops the application using the freezer cgroup or signals.
|
||||
* [Parasite Code](parasite-code.md): Injection and execution of code within the victim's address space.
|
||||
* [Restorer Context](restorer-context.md): The environment in which the restorer blob executes.
|
||||
* [Stages of Restore](stages-of-restoring.md): Detailed breakdown of the multi-stage restoration process.
|
||||
* [Final States](final-states.md): The state of processes after restore.
|
||||
* [Technologies Used](technologies.md): Overview of kernel technologies CRIU depends on.
|
||||
* [Kerndat](kerndat.md): How CRIU probes and caches kernel feature support.
|
||||
|
||||
## Memory Management
|
||||
|
||||
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md): The primary algorithms for memory C/R.
|
||||
* [Memory Changes Tracking](memory-changes-tracking.md): Using dirty bits (soft-dirty) for iterative migration.
|
||||
* [Pagemap Cache](pagemap-cache.md): Optimizing access to `/proc/pid/pagemap`.
|
||||
* [Copy-on-Write Memory](copy-on-write-memory.md): Handling shared and private COW mappings.
|
||||
* [Shared Memory](shared-memory.md): Restoration of SysV IPC and POSIX shared memory.
|
||||
* [Memory Images Deduplication](memory-images-deduplication.md): Saving space in image files.
|
||||
* [Optimizing Pre-dump Algorithm](optimizing-pre-dump-algorithm.md): Strategies for minimizing downtime.
|
||||
* [Userfaultfd](userfaultfd.md): Lazy migration and post-copy restoration.
|
||||
|
||||
## Files, Mounts & I/O
|
||||
|
||||
* [Dumping Files](dumping-files.md): General overview of file descriptor C/R.
|
||||
* [How hard is it to open a file?](how-hard-is-it-to-open-a-file.md): The complexities of reconstructing file states.
|
||||
* [How to open a file without open() syscall](how-to-open-a-file-without-open-system-call.md): Using `linkat` and other tricks for inaccessible files.
|
||||
* [How to assign needed FD to a file](how-to-assign-needed-file-descriptor-to-a-file.md): Re-mapping FDs to match original values.
|
||||
* [Invisible Files](invisible-files.md): Handling unlinked but open files.
|
||||
* [FD Info Engine](fdinfo-engine.md): Parsing `/proc/pid/fdinfo`.
|
||||
* [Service Descriptors](service-descriptors.md): Managing CRIU's internal FDs to avoid collisions.
|
||||
* [Mount Points](mount-points.md): Basic mount restoration.
|
||||
* [Mount V2](mount-v2.md): Modern mount restoration using `open_tree` and `move_mount`.
|
||||
* [Mounts V2 Virtuozzo](mounts-v2-virtuozzo.md): Extensions for Virtuozzo-specific mount features.
|
||||
* [Filesystem Peculiarities](filesystems-pecularities.md): Handling `/dev`, `/proc`, `sysfs`, etc.
|
||||
* [IRM](irmap.md): Inode-to-path mapping (irmap).
|
||||
* [KCMP Trees](kcmp-trees.md): Using `kcmp` to deduplicate shared resources.
|
||||
* [Validate Files on Restore](validate-files-on-restore.md): Ensuring file consistency.
|
||||
* [FSNotify](fsnotify.md): Checkpointing inotify and fanotify marks.
|
||||
* [AIO](aio.md): Checkpointing asynchronous I/O contexts.
|
||||
|
||||
## Networking
|
||||
|
||||
* [TCP Connections](tcp-connection.md): Using TCP Repair mode for zero-loss socket migration.
|
||||
* [Unix Sockets](unix-sockets.md): Reconnecting stream and dgram unix sockets.
|
||||
* [Sockets](sockets.md): General socket restoration (Netlink, Raw, etc.).
|
||||
* [Change IP Address](change-ip-address.md): Handling network configuration changes during migration.
|
||||
* [MAC-VLAN](mac-vlan.md): Support for MAC-VLAN interfaces.
|
||||
* [TUN/TAP](tun-tap.md): Virtual network device restoration.
|
||||
|
||||
## Process & Resource Management
|
||||
|
||||
* [PID Restore](pid-restore.md): Algorithms for restoring tasks with specific PIDs.
|
||||
* [PIDFD](pidfd.md): Checkpointing and restoring pidfds.
|
||||
* [PIDFD Store](pidfd-store.md): Internal management of pidfds.
|
||||
* [Zombies](zombies.md): Handling processes in the `EXIT_ZOMBIE` state.
|
||||
* [32-bit Tasks C/R](32bit-tasks-cr.md): Specifics for IA32/compat mode tasks.
|
||||
* [Pending Signals](pending-signals.md): Capturing and re-queuing signals.
|
||||
* [Restartable Sequences (rseq)](restartable-sequences.md): Handling the `rseq` kernel feature.
|
||||
* [vDSO](vdso.md): Handling the virtual dynamic shared object across kernel versions.
|
||||
* [TTYs](ttys.md): The complex state of terminal devices and PTY pairs.
|
||||
* [CGroups](cgroups.md): Restoring cgroup hierarchy and membership.
|
||||
|
||||
## Security & Kernel Features
|
||||
|
||||
* [AppArmor](apparmor.md): Handling AppArmor profiles during dump and restore.
|
||||
* [ARM64 GCS](arm64-gcs.md): Guarded Control Stack support on AArch64.
|
||||
* [BPF Maps](bpf-maps.md): Experimental support for checkpointing BPF map data.
|
||||
* [Code Blobs](code-blobs.md): Management of PIE blobs (parasite, restorer).
|
||||
|
||||
## Comparison & External Tools
|
||||
|
||||
* [Comparison to other C/R projects](comparison-to-other-cr-projects.md): How CRIU differs from DMTCP, BLCR, etc.
|
||||
* [DMTCP](dmtcp.md): Specific notes on DMTCP integration or comparison.
|
||||
* [FAQ](faq.md): Frequently Asked Questions about CRIU internals.
|
||||
|
||||
---
|
||||
*Generated by Gemini CLI as part of the Documentation Audit (March 2026).*
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
# Invisible and Nameless Files
|
||||
|
||||
In Linux, a file can remain accessible to a process even if it no longer has a visible path in the filesystem. This occurs when a file is unlinked (deleted) while still open or when its path becomes inaccessible due to mount shadowing. This document explains how CRIU detects and reconstructs these "invisible" files.
|
||||
|
||||
## How Files Lose Their Paths
|
||||
|
||||
### 1. Unlinked while Open
|
||||
The most common case is when an application opens a file and then immediately deletes it:
|
||||
```c
|
||||
int fd = open("/tmp/secret", O_RDWR);
|
||||
unlink("/tmp/secret");
|
||||
```
|
||||
The file data persists in the kernel as long as the file descriptor remains open, but it no longer exists in the filesystem directory structure.
|
||||
|
||||
### 2. Virtual Filesystem Deletion
|
||||
On virtual filesystems like `/proc`, if a process dies, its entries (e.g., `/proc/$PID/cmdline`) disappear. However, if another process still has an open file descriptor to one of these entries, the file remains alive but "nameless."
|
||||
|
||||
### 3. Mount Shadowing (Overmounts)
|
||||
If a process opens a file in `/mnt/data` and then a new filesystem is mounted over `/mnt`, the original file becomes inaccessible via its path.
|
||||
|
||||
## CRIU's Detection and Reconstruction Strategies
|
||||
|
||||
CRIU uses the `/proc/$pid/fd/` and `/proc/$pid/fdinfo/` interfaces to identify open files and their expected paths.
|
||||
|
||||
### Ghost Files (Link Count = 0)
|
||||
If a file has a link count of zero (`st_nlink == 0`), it is truly deleted.
|
||||
* **Dumping**: CRIU reads the entire content of the file and stores it within the image directory as a "ghost file."
|
||||
* **Restoring**: During restoration, CRIU recreates the file in a temporary location, opens it, and then immediately unlinks it to restore the original unlinked state.
|
||||
* **Optimization**: For large sparse files, CRIU can use the `--ghost-fiemap` option to only capture the data blocks, significantly reducing image size.
|
||||
|
||||
### Link-Remap (Link Count > 0)
|
||||
If a file has a positive link count but its expected path is missing or points to a different file, it means the specific name used to open the file was deleted, but other hard links still exist.
|
||||
* **Strategy**: CRIU uses `linkat()` with the `AT_EMPTY_PATH` flag to create a temporary name for the file on the same filesystem. This allows it to be re-opened via a path during restoration.
|
||||
* **Option**: This behavior is enabled via the `--link-remap` flag.
|
||||
|
||||
### Virtual File Remap (The PID Helper)
|
||||
For deleted `/proc` entries, CRIU cannot use ghost files or `linkat()`. Instead:
|
||||
1. It records the PID of the original process that the `/proc` entry referred to.
|
||||
2. During restoration, it creates a temporary **TASK_HELPER** process with that specific PID.
|
||||
3. The restored application opens the `/proc/$PID/...` entry of this helper.
|
||||
4. The helper is terminated once all restoration tasks are complete.
|
||||
|
||||
### Filesystem-Specific Handling
|
||||
|
||||
* **NFS**: CRIU detects "Silly Rename" files (`.nfsXXX`) and handles them via the link-remap mechanism.
|
||||
* **OverlayFS**: Since `linkat()` may fail on OverlayFS if the file resides on a read-only lower layer, CRIU automatically falls back to the ghost file strategy in these cases.
|
||||
* **Devpts**: Files on `devpts` (like PTYs) are managed by the kernel and are restored using specific PTY master/slave allocation logic rather than file-based reconstruction.
|
||||
|
||||
## Technical Details
|
||||
|
||||
* **--ghost-limit**: By default, CRIU limits ghost files to **1 MB** to prevent excessive disk usage. This can be increased via the `--ghost-limit` option.
|
||||
* **--evasive-devices**: Allows CRIU to proceed even if a character or block device path has changed, provided the device numbers (`st_rdev`) match.
|
||||
|
||||
## See also
|
||||
* [Dumping File Descriptors](dumping-files.md)
|
||||
* [Filesystem Peculiarities](filesystems-pecularities.md)
|
||||
* [Mount Points](mount-points.md)
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# Irmap (Inode Reverse Mapping)
|
||||
|
||||
Irmap is CRIU's engine for resolving an `(inode, device)` pair back into a filesystem path. This is primarily required for restoring **fsnotify** (inotify and fanotify) instances, which internally reference inodes but do not preserve the paths used to create them.
|
||||
|
||||
## The Problem
|
||||
|
||||
When an application creates an inotify watch, the kernel resolves the path to an inode and attaches the watch to it. The original path string is then discarded by the kernel. During a checkpoint, CRIU can see which inode is being watched but needs a valid path to recreate that watch during restoration.
|
||||
|
||||
## How Irmap Works
|
||||
|
||||
Irmap uses a combination of predefined hints and brute-force scanning to build a reverse mapping cache.
|
||||
|
||||
### 1. Heuristic Hints
|
||||
CRIU starts by scanning "known" locations where applications typically place watches, such as:
|
||||
- `/etc` (configuration files)
|
||||
- `/var/log` (log monitoring)
|
||||
- `/var/spool`
|
||||
- D-Bus and Polkit service paths (`/usr/share/dbus-1/services`, etc.)
|
||||
- `/lib/udev`
|
||||
- The root directory (`/`)
|
||||
|
||||
### 2. User-Defined Scan Paths
|
||||
Users can provide additional directories to scan via the command line to help CRIU find application-specific files more quickly:
|
||||
```bash
|
||||
criu dump --irmap-scan-path /path/to/my/app ...
|
||||
```
|
||||
These paths are prioritized and scanned before the default hints.
|
||||
|
||||
### 3. Caching and Pre-dump
|
||||
Scanning large filesystems can be slow and resource-intensive. To mitigate this:
|
||||
- **irmap-cache.img**: Scan results are stored in this image file within the images directory.
|
||||
- **Pre-dump Optimization**: CRIU can perform the irmap scan during a `pre-dump` while the application is still running. This populates the cache early, significantly reducing the time the application must remain frozen during the final dump.
|
||||
- **Validation**: On subsequent runs, CRIU loads the cache and re-validates entries individually (checking if the inode/device still matches the path) rather than performing a full re-scan.
|
||||
|
||||
## Support for Filesystems
|
||||
|
||||
* **Standard Filesystems**: Works well on most local filesystems (ext4, xfs, etc.).
|
||||
* **Tmpfs**: Paths are generally available via `/proc` and don't strictly require Irmap, though it can still be used.
|
||||
* **OverlayFS**: Irmap has historically had difficulties with OverlayFS due to how inodes are reported across different layers. In modern kernels, **open_by_handle_at** (leveraging file handles exposed in `/proc/$pid/fdinfo`) is the preferred and more reliable alternative to Irmap.
|
||||
|
||||
## See also
|
||||
* [FSNotify](fsnotify.md)
|
||||
* [Re-opening nameless files](how-to-open-a-file-without-open-system-call.md)
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
# Shared Object Detection (Kcmp Trees)
|
||||
|
||||
CRIU must frequently determine if system resources (such as file descriptions, memory mappings, or namespaces) are shared between different processes. While some objects have unique kernel-provided IDs (like inode numbers for files on disk), many do not. This document explains how CRIU uses the `kcmp()` system call and red-black trees to efficiently detect these shared objects.
|
||||
|
||||
## The Challenge
|
||||
|
||||
Comparing every resource in every process against every other process would result in $O(N^2)$ complexity, where $N$ is the total number of resources (e.g., 100 tasks with 100 files each = 10,000 files, or 50 million pairs). This is prohibitively slow.
|
||||
|
||||
## The Solution: `kcmp()` and Pointer Comparison
|
||||
|
||||
The `kcmp()` system call identifies whether two kernel objects are the same. Crucially, its return value is not a simple boolean; it returns the result of an internal kernel pointer comparison:
|
||||
* **0**: The objects are identical.
|
||||
* **1**: The first object's pointer is "less than" the second.
|
||||
* **2**: The first object's pointer is "greater than" the second.
|
||||
* **-1**: Error.
|
||||
|
||||
This ordering information allows CRIU to use **red-black trees** to sort and search for objects with $O(N \log N)$ complexity.
|
||||
|
||||
## Two-Level Red-Black Trees
|
||||
|
||||
To further optimize performance and minimize the number of expensive `kcmp()` system calls, CRIU uses a two-level tree structure:
|
||||
|
||||
### Level 1: Fast ID (genid)
|
||||
CRIU first calculates a "generation ID" (`genid`) using cheap, locally available metadata. For regular files, this is derived from the device ID, inode number, and current file position.
|
||||
* Objects are inserted into a primary red-black tree ordered by `genid`.
|
||||
* If two objects have different `genid`s, they are guaranteed to be different, and no system call is needed.
|
||||
|
||||
### Level 2: Sub-tree (kcmp)
|
||||
If two objects have identical `genid`s, they *might* be the same.
|
||||
* CRIU then descends into a sub-tree associated with that `genid`.
|
||||
* In this sub-tree, objects are ordered using the `kcmp()` system call.
|
||||
* If `kcmp()` returns 0, the objects are confirmed as shared.
|
||||
|
||||
## Supported Object Types
|
||||
|
||||
CRIU uses `kcmp()` for various object types, including:
|
||||
* **KCMP_FILE**: Individual file descriptions.
|
||||
* **KCMP_VM**: Virtual memory address spaces.
|
||||
* **KCMP_FILES**: The entire file descriptor table.
|
||||
* **KCMP_FS**: Filesystem information (umask, root, cwd).
|
||||
* **KCMP_SIGHAND**: Signal handler tables.
|
||||
* **KCMP_IO**: I/O context.
|
||||
* **KCMP_SYSV_SEM**: System V semaphore undo lists.
|
||||
* **KCMP_EPOLL_TFD**: Specific descriptors within an epoll interest list.
|
||||
|
||||
## See also
|
||||
* [Dumping File Descriptors](dumping-files.md)
|
||||
* [Copy-on-write memory](copy-on-write-memory.md)
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
# Kerndat (Kernel Data)
|
||||
|
||||
**Kerndat** is a CRIU module responsible for detecting the capabilities and features of the currently running Linux kernel. Since CRIU's functionality depends heavily on specific kernel system calls and behaviors, runtime detection is essential for ensuring compatibility and selecting the most efficient algorithms.
|
||||
|
||||
## Feature Detection
|
||||
|
||||
CRIU performs a wide array of checks during initialization. These include:
|
||||
* **System Call Availability**: Checking for `kcmp()`, `userfaultfd()`, `memfd_create()`, `clone3()`, `openat2()`, `membarrier()`, and more.
|
||||
* **Filesystem Features**: Verifying `pagemap` functionality, `PAGEMAP_SCAN` support, and anonymous shared mapping behaviors.
|
||||
* **Namespace Support**: Detecting Time namespaces, CGroup namespaces, and namespace-specific identifiers.
|
||||
* **Architecture-Specific Quirks**: Identifying known CPU bugs or features, such as the x86 FPU/XSAVE ptrace bug.
|
||||
|
||||
The results of these checks are stored in a global `kdat` structure, which other CRIU modules query to determine how to proceed during dump and restore operations.
|
||||
|
||||
## Persistent Caching
|
||||
|
||||
Executing hundreds of kernel feature checks can be time-consuming. To speed up subsequent CRIU invocations, the results are cached on disk.
|
||||
|
||||
* **Cache Location**:
|
||||
* **Root**: `/run/criu.kdat` (typically stored on `tmpfs` to ensure it is cleared on reboot).
|
||||
* **Non-root**: `$XDG_RUNTIME_DIR/criu.kdat`.
|
||||
* **Lifecycle**: CRIU attempts to load this cache during `kerndat_init()`. If the cache is missing or stale (e.g., if the CRIU binary has been updated with new checks), CRIU performs a full detection and saves the new results back to the cache file.
|
||||
|
||||
## Kerndat vs. Inventory
|
||||
|
||||
It is important to distinguish between **kerndat** and the **inventory image** (`inventory.img`):
|
||||
* **Kerndat**: Captures the capabilities of the **host kernel**. It is system-wide and typically survives across different CRIU operations on the same host.
|
||||
* **Inventory**: Captures critical metadata about a **specific checkpoint**. It is stored within the images directory and includes the CRIU version used for the dump, the host's LSM type (SELinux/AppArmor), and the root task's original IDs.
|
||||
|
||||
## Inspection
|
||||
|
||||
To see the features detected by CRIU on your current system, use the check command:
|
||||
```bash
|
||||
criu check --extra
|
||||
```
|
||||
This command triggers a kerndat initialization and prints the status of various required and optional kernel features, allowing you to verify that your environment is ready for CRIU.
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# Mac-VLAN
|
||||
|
||||
Mac-VLAN is a Linux network driver that allows creating multiple virtual interfaces with unique MAC addresses on top of a single physical interface. These virtual interfaces act as standalone devices on the network, each with its own IP and MAC address.
|
||||
|
||||
## Checkpoint and Restore of Mac-VLAN
|
||||
|
||||
CRIU identifies Mac-VLAN interfaces by monitoring netlink messages (specifically `RTM_NEWLINK`) and inspecting their attributes.
|
||||
|
||||
### 1. Checkpointing
|
||||
During a dump, CRIU extracts the following attributes for each Mac-VLAN device:
|
||||
- **Parent Interface**: The physical device (or "upper" link) that the Mac-VLAN is built upon (identified via `IFLA_LINK`).
|
||||
- **Mode**: The specific Mac-VLAN operational mode (e.g., `bridge`, `private`, `vepa`, `passthru`), extracted from `IFLA_MACVLAN_MODE`.
|
||||
- **Flags**: Any additional configuration flags associated with the interface (`IFLA_MACVLAN_FLAGS`).
|
||||
- **MAC Address**: The unique hardware address of the virtual interface.
|
||||
|
||||
### 2. Restoration
|
||||
To recreate a Mac-VLAN interface exactly as it was, CRIU performs the following:
|
||||
- **Link Creation**: It sends an `RTM_NEWLINK` netlink message with the kind set to `"macvlan"`, specifying the original mode and the link to the parent device.
|
||||
- **Index Preservation**: To ensure that any application sockets bound to the interface index remain valid, CRIU uses the `IFLA_NEW_IFINDEX` attribute. This allows CRIU to request the exact same interface index that the device possessed before the checkpoint. (This kernel feature was originally developed specifically to support CRIU).
|
||||
- **Namespace Migration**: Once created, the interface is moved into the target network namespace for the restored process.
|
||||
|
||||
## External Interface Mapping
|
||||
|
||||
Since the parent physical interface may have a different name or index on the destination host during migration, CRIU provides the `--external` option to map these dependencies:
|
||||
|
||||
```bash
|
||||
# Example mapping of an internal macvlan interface to a host physical interface
|
||||
criu restore --external macvlan[eth0]:phys0 ...
|
||||
```
|
||||
|
||||
This tells CRIU that the Mac-VLAN interface which was originally attached to `eth0` should now be attached to the physical interface `phys0` on the current host.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Networking](networking.md)
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
# Memory Changes Tracking
|
||||
|
||||
Memory changes tracking (also known as "dirty memory tracking") is a critical feature in CRIU that enables efficient **live migration** with minimal downtime. By identifying and capturing only the memory pages that have been modified since a previous snapshot, CRIU can perform iterative dumps while the application continues to run.
|
||||
|
||||
## The Problem: Memory Dump Latency
|
||||
|
||||
During a standard checkpoint, CRIU freezes the process tree and dumps its entire memory state to disk. For memory-intensive applications (like large databases), this process can take several seconds, during which the application is completely unresponsive. This "freeze time" is directly proportional to the amount of memory used by the application.
|
||||
|
||||
## The Solution: Iterative Dumps
|
||||
|
||||
To minimize freeze time, CRIU supports an iterative migration scheme:
|
||||
1. **Initial Pre-dump**: Capture a full snapshot of the application's memory while it is still running.
|
||||
2. **Subsequent Pre-dumps**: Periodically capture only those pages that have been modified (made "dirty") since the last pre-dump.
|
||||
3. **Final Dump**: Freeze the processes and capture the final set of dirty pages. Since most memory was already transferred in previous steps, the final freeze time is significantly reduced.
|
||||
|
||||
## Kernel Mechanisms for Tracking
|
||||
|
||||
CRIU relies on two primary kernel mechanisms to track dirty pages:
|
||||
|
||||
### 1. The Soft-Dirty Bit
|
||||
Linux maintains a "soft-dirty" bit for each Page Table Entry (PTE).
|
||||
* **Resetting**: CRIU enables tracking by writing "4" to `/proc/$pid/clear_refs`, which clears the soft-dirty bit for all pages in the task's address space.
|
||||
* **Tracking**: Any subsequent write to a page causes the kernel to set its soft-dirty bit.
|
||||
* **Reading**: CRIU identifies dirty pages by reading the bit from the process's `/proc/$pid/pagemap` interface.
|
||||
|
||||
### 2. ioctl(PAGEMAP_SCAN)
|
||||
Reading the entire `/proc/$pid/pagemap` file can be slow for very large address spaces. Modern kernels (v6.7+) support the `PAGEMAP_SCAN` ioctl, which allows CRIU to:
|
||||
* **Efficient Scanning**: Identify dirty pages across a large address space in a single kernel call.
|
||||
* **Filtering**: Directly filter for specific page categories (e.g., only dirty and present pages).
|
||||
* **Atomic Reset**: Optionally clear the soft-dirty bit while scanning, ensuring no writes are missed between scanning and resetting.
|
||||
|
||||
CRIU automatically detects and uses `PAGEMAP_SCAN` if available, falling back to manual `/proc` parsing on older kernels.
|
||||
|
||||
## Implementation in CRIU
|
||||
|
||||
Iterative migration is managed through the `pre-dump` command:
|
||||
|
||||
1. **Chained Images**: Each pre-dump creates a set of image files in a new directory. These directories are linked together using the `--prev-images-dir` option.
|
||||
2. **Consolidated Restore**: During restoration, CRIU traverses the chain of images from newest to oldest. For any given memory address, it restores the most recent version of the page found in the image stack.
|
||||
3. **Page Server**: To avoid writing iterative dumps to disk, they can be sent over the network to a **page server** on the destination host.
|
||||
|
||||
## See also
|
||||
* [Iterative Migration](iterative-migration.md)
|
||||
* [Memory Images Deduplication](memory-images-deduplication.md)
|
||||
* [Page Server](page-server.md)
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
# Memory Dumping and Restoring
|
||||
|
||||
Dumping and restoring the memory of a process tree is one of the most critical and complex tasks performed by CRIU. This document details the mechanisms, optimizations, and kernel interfaces involved in this process.
|
||||
|
||||
## The Virtual Memory Layout (VMAs)
|
||||
|
||||
A process's address space is composed of several Virtual Memory Areas (VMAs). CRIU identifies these areas by parsing `/proc/$pid/smaps` and `/proc/$pid/map_files/`.
|
||||
* **Metadata**: Each VMA's start address, end address, protection flags (read, write, execute), and sharing status (private or shared) are recorded in the `mm-$id.img` file.
|
||||
* **Backing Store**: CRIU also records whether a VMA is anonymous (backed by RAM/swap) or file-backed.
|
||||
|
||||
## The Dumping Process
|
||||
|
||||
Capturing memory contents while maintaining consistency and performance requires a multi-stage approach.
|
||||
|
||||
### 1. Parasite Injection
|
||||
CRIU cannot efficiently read a process's private memory from the outside. Instead, it injects **parasite code** into the target task. This code runs within the task's own address space and context, allowing it direct access to all memory regions.
|
||||
|
||||
### 2. Zero-Copy Dumping (vmsplice)
|
||||
To transfer memory from the parasite to the CRIU dumper with minimal overhead, CRIU uses a zero-copy mechanism:
|
||||
1. **Pipe Setup**: CRIU creates a pipe and sends one end to the parasite via a Unix domain socket.
|
||||
2. **vmsplice**: The parasite uses the `vmsplice()` system call with the `SPLICE_F_GIFT` flag. This effectively "gifts" the memory pages to the kernel's pipe buffer without copying the data in userspace.
|
||||
3. **Splice to Image**: The CRIU dumper then uses `splice()` to move the data from the pipe directly into the image file (`pages-$id.img`) or to a network socket (for the page server).
|
||||
|
||||
### 3. Page Deduplication and Skipping
|
||||
CRIU avoids dumping unnecessary data to save time and space:
|
||||
* **Unchanged File Pages**: Read-only, file-backed pages (like library code) that have not been modified are not dumped. CRIU simply records the file and offset to re-map them during restoration.
|
||||
* **Dirty Tracking**: Using the **soft-dirty bit** (or `PAGEMAP_SCAN`), CRIU can identify and dump only those pages that have changed since a previous pre-dump.
|
||||
|
||||
---
|
||||
|
||||
## The Restoration Process
|
||||
|
||||
Restoring memory involves reconstructing the exact address space layout the application had at the moment of the checkpoint.
|
||||
|
||||
### 1. Re-mapping VMAs
|
||||
During the early stages of restoration, each process calls `mmap()` to recreate its VMAs based on the data in `mm-$id.img`.
|
||||
* **Anonymous Memory**: Mapped as private and anonymous.
|
||||
* **File Mappings**: Re-mapped from their original files on disk.
|
||||
|
||||
### 2. Filling Memory Contents
|
||||
CRIU then repopulates the mappings with the data stored in the `pages-$id.img` files. For efficiency, CRIU uses its own optimized I/O routines to read the images and fill the memory regions.
|
||||
|
||||
### 3. COW Preservation
|
||||
CRIU uses a specialized strategy to ensure that memory shared via `fork()` (Copy-on-Write) remains shared after restoration. This minimizes the total physical memory footprint of the restored process tree. See [COW Memory](copy-on-write-memory.md) for details.
|
||||
|
||||
## Advanced Migration Techniques
|
||||
|
||||
* **Page Server**: During live migration, memory pages are sent over the network to a page server on the destination host, avoiding expensive disk I/O.
|
||||
* **Lazy Migration (Userfaultfd)**: CRIU can restore a process immediately without its memory and then load pages on demand as the application accesses them. This is powered by the `userfaultfd` kernel feature and is essential for reducing initial downtime.
|
||||
|
||||
## See also
|
||||
* [Memory Changes Tracking](memory-changes-tracking.md)
|
||||
* [Copy-on-write Memory](copy-on-write-memory.md)
|
||||
* [Userfaultfd](userfaultfd.md)
|
||||
* [Page Server](page-server.md)
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
# Memory Images Deduplication
|
||||
|
||||
During iterative migration, CRIU produces multiple snapshots of a process's memory. Since most memory pages remain unchanged between iterations, saving every page in every snapshot would result in significant disk space waste and increased migration time. CRIU uses several deduplication techniques to address this.
|
||||
|
||||
## How Deduplication Works
|
||||
|
||||
Deduplication relies on identifying pages that are identical to those in a previous snapshot (the "parent" image).
|
||||
|
||||
### 1. The `in_parent` Flag
|
||||
The `pagemap-$id.img` file describes the virtual memory layout. Each entry (`pagemap_entry`) can include an `in_parent` flag:
|
||||
* **If `false`**: The page's contents are stored in the current `pages-$id.img` file.
|
||||
* **If `true`**: The page's contents are identical to the one in the parent image. CRIU does not write the data to the current `pages-$id.img`, saving both disk space and I/O time.
|
||||
|
||||
### 2. Detection via Soft-Dirty
|
||||
During a `pre-dump`, CRIU uses the kernel's **soft-dirty bit** to identify which pages have been modified.
|
||||
* If a page was present in the previous iteration and its soft-dirty bit is **not set**, CRIU knows the content remains unchanged.
|
||||
* It marks the page as `in_parent` in the current pagemap image and skips dumping its data.
|
||||
|
||||
## Auto-Deduplication (`--auto-dedup`)
|
||||
|
||||
CRIU provides an advanced `--auto-dedup` mode that optimizes both the dumping and restoration processes.
|
||||
|
||||
### During Dump
|
||||
When `--auto-dedup` is enabled during a dump, CRIU actively manages the relationship between the current and parent image sets to ensure maximum deduplication efficiency. It traverses the previous images to verify which regions can be safely referenced rather than re-dumped.
|
||||
|
||||
### During Restore (Disk Space Optimization)
|
||||
A unique and powerful feature of `--auto-dedup` during restoration is **online disk space reclamation**:
|
||||
* As CRIU reads pages from the `pages-$id.img` files to restore the process's memory, it uses the `fallocate(FALLOC_FL_PUNCH_HOLE)` system call on the image files.
|
||||
* This "punches holes" in the images, effectively freeing the underlying physical disk blocks as soon as the data has been loaded into RAM.
|
||||
* This is critical for systems with limited disk space when restoring from a large number of iterative pre-dumps, as it prevents the total image size from exceeding the available storage.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
* **Image Chaining**: Deduplication requires a chain of images established via the `--prev-images-dir` option, allowing CRIU to look back through multiple layers of snapshots.
|
||||
* **Sparse File Support**: The hole-punching mechanism leverages the host filesystem's support for sparse files, ensuring that the restored environment remains efficient.
|
||||
|
||||
## See also
|
||||
* [Memory Changes Tracking](memory-changes-tracking.md)
|
||||
* [Iterative Migration](iterative-migration.md)
|
||||
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
# Checkpoint and Restore of Mount Points
|
||||
|
||||
CRIU provides deep support for capturing and reconstructing Linux mount namespaces and the complex hierarchies of mount points within them. This includes support for bind mounts, shared propagation, and external dependencies.
|
||||
|
||||
## Key Information Captured
|
||||
|
||||
For every mount namespace, CRIU parses `/proc/$pid/mountinfo` to extract:
|
||||
1. **Mount Hierarchy**: The parent-child relationships between mount points.
|
||||
2. **Filesystem Details**: Device IDs, filesystem types, and the mount source.
|
||||
3. **Root and Target**: The specific directory within the filesystem being mounted and its destination in the process's view.
|
||||
4. **Propagation State**: Whether a mount is `shared`, `slave`, `private`, or `unbindable`.
|
||||
5. **Mount Options**: Flags such as `ro`, `nodev`, `noexec`, and `nosuid`.
|
||||
|
||||
## The Restoration Challenge
|
||||
|
||||
Restoring mounts is one of CRIU's most difficult tasks because it must recreate the exact same state that the kernel built up over time. This requires:
|
||||
* **Dependency Sorting**: Mounts must be recreated in the correct order (e.g., a parent must exist before its child can be mounted).
|
||||
* **Source Resolution**: CRIU must be able to access the original filesystem source.
|
||||
* **Propagation Reconstruction**: Shared and slave relationships must be established in the correct sequence to ensure future mount events propagate as expected.
|
||||
|
||||
## Mount V2: The Modern Engine
|
||||
|
||||
CRIU includes an advanced restoration engine called **Mount V2** (`--mount-v2`). This engine uses a more robust algorithm to handle:
|
||||
* **Complex Overmounts**: Scenarios where multiple mounts are stacked on the same directory.
|
||||
* **Circular Dependencies**: Resolving cases where mounts depend on each other in non-trivial ways.
|
||||
* **Namespace Sharing**: Efficiently handling processes that share the same mount namespace.
|
||||
|
||||
## External and Auto-detected Mounts
|
||||
|
||||
Sometimes, the source of a mount point is located outside the container or process tree being checkpointed (e.g., a host directory bind-mounted into a container).
|
||||
|
||||
### 1. External Mounts (`--external`)
|
||||
Users can manually specify how to handle these external dependencies by mapping the mount's identifier to a path on the destination host:
|
||||
```bash
|
||||
criu restore --external mnt[ID]:/new/host/path ...
|
||||
```
|
||||
|
||||
### 2. Auto-detection
|
||||
CRIU can often automatically identify external bind mounts by comparing the mount points in the target process with those in its own mount namespace. This simplifies migration by reducing the need for manual mapping.
|
||||
|
||||
## Common Issues
|
||||
|
||||
* **Unsupported Filesystems**: Some specialized or virtual filesystems may not support standard checkpointing. These often require plugins or must be marked as external.
|
||||
* **Hidden Sources**: If a bind mount's source is overmounted and no longer visible, CRIU may fail to identify how to recreate it without the Mount V2 engine or manual hints.
|
||||
|
||||
## See also
|
||||
* [Mount V2 Details](mount-v2.md)
|
||||
* [Filesystem Peculiarities](filesystems-pecularities.md)
|
||||
* [Invisible Files (Overmounts)](invisible-files.md)
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# Mount Points 2.0 (Legacy)
|
||||
|
||||
> **Note**: This document describes an early design iteration for mount restoration. The current and much more advanced implementation is documented in [Mount V2](mount-v2.md).
|
||||
|
||||
For detailed information on the modern mount restoration algorithm, including the use of detached mounts and `move_mount`, please refer to:
|
||||
* [Mount V2 Overview](mount-v2.md)
|
||||
* [Mount V2 Detailed Algorithm](mounts-v2-virtuozzo.md)
|
||||
* [Mount Points (General)](mount-points.md)
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# Mount V2: Advanced Mount Restoration
|
||||
|
||||
Introduced in CRIU v3.16, **Mount V2** is a sophisticated restoration engine that leverages modern Linux kernel APIs to handle complex mount hierarchies, propagation groups, and overmounts with high reliability.
|
||||
|
||||
## Why Mount V2 was Necessary
|
||||
|
||||
The original mount restoration mechanism (Mount V1) relied on sequential, path-based `mount()` calls. This approach had several critical flaws:
|
||||
1. **Overmount Sensitivity**: If a directory was already covered by another mount, performing a path-based mount on it could fail or target the wrong filesystem.
|
||||
2. **Circular Dependencies**: Resolving mounts that depend on each other in non-linear ways was difficult and often resulted in ordering failures.
|
||||
3. **Propagation Complexity**: Establishing `shared` and `slave` relationships required creating dummy mount points and performing specific sequences of `mount --make-shared/slave` calls, which was fragile in complex scenarios.
|
||||
|
||||
## How Mount V2 Works
|
||||
|
||||
Mount V2 moves away from path-based mounting, instead using **File Descriptor-based** mounting provided by newer kernel system calls.
|
||||
|
||||
### 1. Detached Mounts
|
||||
CRIU creates each required mount as a **detached mount**. These mounts exist in the kernel but are not yet attached to any visible path in the filesystem.
|
||||
* **New Filesystems**: Created using `fsopen()` and `fsmount()`.
|
||||
* **Bind Mounts**: Created using `open_tree()` with the `OPEN_TREE_CLONE` flag to create an unattached clone of an existing path.
|
||||
|
||||
### 2. Precise Propagation Grouping
|
||||
Using the `move_mount()` syscall with the `MOVE_MOUNT_SET_GROUP` flag (introduced in kernel v5.15), CRIU can explicitly assign a detached mount to a specific **shared or slave propagation group**. This eliminates the need for dummy mounts and ensures that the propagation state is perfectly restored as recorded in the images.
|
||||
|
||||
### 3. Tree Construction via File Descriptors
|
||||
CRIU constructs the entire mount hierarchy by attaching child mounts to their parents using their respective file descriptors. Since this happens "off-line" (outside of any mount namespace), it is immune to path shadowing, path resolution errors, or overmounting issues.
|
||||
|
||||
### 4. Atomic Final Attachment
|
||||
Once the complete hierarchy is assembled as a tree of detached mounts, CRIU performs a final `move_mount()` to attach the root of this reconstructed tree into the target mount namespace at the desired destination path.
|
||||
|
||||
## Kernel Requirements
|
||||
|
||||
Mount V2 requires a modern kernel that supports:
|
||||
* `fsopen()`, `fsmount()`, `move_mount()` (Kernel v5.2+)
|
||||
* `open_tree()` (Kernel v5.3+)
|
||||
* `MOVE_MOUNT_SET_GROUP` (Kernel v5.15+)
|
||||
|
||||
CRIU automatically detects these features during the [Kerndat](kerndat.md) phase. It will fall back to the older Mount V1 engine if these calls are unavailable, though many modern container layouts now effectively require Mount V2 for a successful restore.
|
||||
|
||||
## See also
|
||||
* [Mount Points](mount-points.md)
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Kerndat](kerndat.md)
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
# Mount V2: Detailed Algorithm
|
||||
|
||||
The Mount V2 engine (originally developed by Virtuozzo and later merged into upstream CRIU) is designed to resolve complex issues with restoring sharing groups, over-mounted files, and cross-namespace bind mounts. This document provides a technical breakdown of its operation.
|
||||
|
||||
## 1. Mount Image Processing Stage
|
||||
|
||||
During initialization, CRIU processes the mount images for all namespaces to build an internal model of the filesystem state:
|
||||
- **Hierarchy Construction**: Build a per-namespace mount tree based on parent IDs.
|
||||
- **Bind Grouping**: Group mounts by superblock equality into "bind" lists to identify shared underlying filesystems.
|
||||
- **Sharing Groups**: Organize shared and slave groups into a tree structure (e.g., where a parent's `shared_id` matches a child's `master_id`).
|
||||
- **The Root Yard**: Create a helper mount (`root_yard_mp`) at a temporary location (e.g., `/tmp/.criu.mntns.XXXXXX/`). All mount trees from all namespaces are initially merged as subdirectories of this "root yard."
|
||||
|
||||
## 2. Pre-Fork Mounting Stage
|
||||
|
||||
This stage is executed from the init task in a dedicated "service" mount namespace before the target process tree is forked:
|
||||
1. **Plain Mounting**: CRIU walks the merged mount tree and creates all mounts in a "plain" (unattached) and "private" state.
|
||||
2. **Source Resolution**: For each mount, CRIU identifies its source (a real filesystem, a bind mount from another already-mounted superblock, or an external source).
|
||||
3. **Cross-Namespace Handling**: By maintaining all mounts within a single service namespace during this stage, CRIU can easily handle bind mounts that cross namespace boundaries.
|
||||
|
||||
## 3. Propagation and Shared Group Restoration
|
||||
|
||||
CRIU restores complex propagation relationships using modern kernel APIs:
|
||||
- **Slavery and Sharing**: For each sharing group, CRIU identifies the "master" mount. It uses the `move_mount()` system call with the `MOVE_MOUNT_SET_GROUP` flag (or the legacy `MS_SET_GROUP` mechanism) to establish slave/shared relationships precisely as they existed during the dump.
|
||||
- **Settings Replication**: Once the sharing state is established for the primary mount in a group, all other members of the group inherit these settings.
|
||||
|
||||
## 4. Namespace Transition and Final Positioning
|
||||
|
||||
For each target mount namespace being restored:
|
||||
1. **Unshare**: CRIU calls `unshare(CLONE_NEWNS)` to create a fresh, empty mount namespace.
|
||||
2. **Tree Positioning**: Move the "plain" mounts from the root yard into their final hierarchical positions within the new namespace using `move_mount()`.
|
||||
3. **Pivot Root**: Execute `pivot_root()` to switch to the new namespace root, effectively hiding the temporary "yard" and finalizing the mount hierarchy.
|
||||
|
||||
## 5. Post-Fork Fixups
|
||||
|
||||
Certain mounts cannot be fully restored until the process tree is established:
|
||||
- **Delayed Procfs**: `proc` mounts for nested PID namespaces must wait until the target PID namespace is created. CRIU enters these namespaces after forking to perform the final mounts.
|
||||
- **Internal Yards**: In some cases, temporary `tmpfs` mounts ("internal yards") are used within a namespace to hold mounts that must be moved or adjusted after the process tree is fully alive.
|
||||
|
||||
## See also
|
||||
* [Mount V2 Overview](mount-v2.md)
|
||||
* [Mount Points](mount-points.md)
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
# NFS mount points
|
||||
|
||||
When C/R-ing NFS mount points there a chicken-and-egg problem.
|
||||
|
||||
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# Optimized Pre-dump Algorithm
|
||||
|
||||
Pre-dumping is the process of capturing dirty memory pages while an application continues to run, aiming to minimize the final "freeze time" during live migration. CRIU provides two primary modes for pre-dumping: `read` and `splice`.
|
||||
|
||||
## Traditional vs. Optimized Pre-dump
|
||||
|
||||
### The `read` Mode (Traditional)
|
||||
In this mode, CRIU uses the `process_vm_readv` system call to read memory from the target process.
|
||||
* **Workflow**: Tasks are briefly frozen to identify dirty pages and reset the soft-dirty bit, then resumed. CRIU then reads the pages from the running process's address space.
|
||||
* **Challenge**: Reading memory while a process is running can lead to minor inconsistencies if the process modifies a page *while* it is being read (see [Memory Consistency](#memory-consistency) below). Furthermore, `process_vm_readv` requires the target process to be alive and its memory mappings to remain stable during the read.
|
||||
|
||||
### The `splice` Mode (Optimized & Default)
|
||||
The `splice` mode (enabled via `--pre-dump-mode=splice`) uses a zero-copy "gift" mechanism to further reduce freeze time and improve reliability.
|
||||
|
||||
#### How `splice` Mode Works:
|
||||
1. **Brief Freeze**: CRIU seizes the tasks and injects the parasite code.
|
||||
2. **vmsplice "Gifting"**: The parasite identifies dirty pages and calls `vmsplice()` with the `SPLICE_F_GIFT` flag. This flag tells the kernel that the process is "giving" these pages to a pipe.
|
||||
3. **Immediate Resume**: Once the `vmsplice()` calls are complete (which is extremely fast as no data is actually copied), the parasite is removed, and the tasks are resumed immediately.
|
||||
4. **Parallel Draining**: While the tasks are running, the main CRIU process "drains" the data from the pipes and writes it to the image files or sends it to the page server.
|
||||
|
||||
#### Why `splice` is Better:
|
||||
* **Minimized Downtime**: The "freeze" duration is reduced to just the time needed for the parasite to execute the `vmsplice()` system calls, rather than the time needed to transfer memory data over the network or to disk. This scheme relies entirely on `vmsplice()` being extremely fast. Because the target process is frozen during these calls, minimizing this duration is critical to the primary goal of pre-dumping: reducing process downtime during live migration and making the migration process almost invisible to the application.
|
||||
* **Zero-Copy Transfer**: By gifting pages directly from the target process to the pipe, `splice` mode avoids copying memory to CRIU user-space buffers (unlike `read` mode which uses `process_vm_readv` to copy data). While this zero-copy mechanism does not use COW (meaning intermediate dumps can be inconsistent if pages are modified after resume), CRIU's iterative design handles this inconsistency (see below) while maximizing transfer performance.
|
||||
|
||||
## Memory Consistency
|
||||
|
||||
Because the target process is resumed while CRIU is still writing the memory data (in both `read` and `splice` modes), intermediate pre-dump images may contain inconsistent memory states.
|
||||
|
||||
This inconsistency is expected and handled by CRIU's iterative design:
|
||||
1. **Tracking Changes**: CRIU uses the kernel's soft-dirty tracker to monitor memory writes after the process is resumed.
|
||||
2. **Subsequent Dumps**: Any page modified after it has been pre-dumped is marked dirty again and will be captured in the next pre-dump iteration or during the final dump.
|
||||
3. **Restoring Consistency**: During restore, CRIU applies the dump images in sequence (from oldest pre-dump to the final dump). The final dump is taken while the process is fully frozen, ensuring that the final state of all memory pages is consistent.
|
||||
|
||||
## Usage
|
||||
|
||||
The optimized `splice` mode is the default in modern CRIU. It can be explicitly requested using the `--pre-dump-mode` option:
|
||||
```bash
|
||||
criu pre-dump --pre-dump-mode splice ...
|
||||
```
|
||||
|
||||
## See also
|
||||
* [Memory Changes Tracking](memory-changes-tracking.md)
|
||||
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
|
||||
* [Iterative Migration](iterative-migration.md)
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# Pagemap Cache
|
||||
|
||||
When dumping the memory of a process, CRIU must frequently query the kernel to determine which virtual memory pages are currently present in RAM, swapped out, or modified (dirty). This information is typically retrieved from the `/proc/$pid/pagemap` file. However, reading and parsing this file repeatedly for every Virtual Memory Area (VMA) is inefficient. To solve this, CRIU implements a high-performance **Pagemap Cache**.
|
||||
|
||||
## The Performance Problem
|
||||
|
||||
The `/proc/$pid/pagemap` file is a 64-bit-per-page binary stream. For a process with a large address space, this file can be several megabytes in size. While a single sequential read is fast, CRIU needs this data across multiple stages of the dump (e.g., initial size estimation, private memory dumping, shared memory dumping, and iterative pre-dumps). Performing multiple full reads and frequent `lseek()` calls into this file introduces significant overhead, especially for applications with thousands of small VMAs.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
The pagemap cache (`struct pmc`) optimizes access through several advanced techniques:
|
||||
|
||||
### 1. Sliding Window Caching
|
||||
Instead of reading the entire pagemap at once, CRIU uses a sliding window (typically **2MB** in size, defined as `PMC_SIZE`).
|
||||
* When a VMA is accessed that is not currently in the cache (a cache miss), the cache "refills" itself by reading the pagemap for the required range.
|
||||
* **Greedy Prefetching**: If the current VMA is small, the cache tries to fill the remainder of the 2MB window by pre-reading information for subsequent, adjacent VMAs. This significantly reduces the total number of `read()` system calls and minimizes the overhead of kernel-side page table walks.
|
||||
|
||||
### 2. ioctl(PAGEMAP_SCAN) Integration
|
||||
On modern kernels (v6.7+), the pagemap cache leverages the `PAGEMAP_SCAN` ioctl. This interface is far more efficient than the legacy `/proc` file:
|
||||
* **Bulk Retrieval**: It allows CRIU to fetch information for multiple, non-contiguous page ranges in a single kernel call.
|
||||
* **Kernel-Side Filtering**: CRIU can instruct the kernel to only return information for specific categories of pages (e.g., pages that are both present in RAM and marked as "soft-dirty"), further reducing the amount of data transferred and processed in userspace.
|
||||
|
||||
### 3. Cache Invalidation
|
||||
To ensure consistency, the pagemap cache is per-process and is strictly managed:
|
||||
* The cache is typically populated while the target process is **frozen** to ensure a stable view of memory.
|
||||
* The cache is invalidated whenever the process state might have changed or when the dumper transitions between different memory processing phases.
|
||||
|
||||
## Debugging and Control
|
||||
|
||||
The pagemap cache can be disabled for troubleshooting or performance comparison by setting the `CRIU_PMC_OFF` environment variable.
|
||||
|
||||
## See also
|
||||
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
|
||||
* [Memory Changes Tracking](memory-changes-tracking.md)
|
||||
* [Optimizing Pre-dump Algorithm](optimizing-pre-dump-algorithm.md)
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
# Parasite Code Injection and Execution
|
||||
|
||||
The **parasite code** is a specialized binary blob that CRIU injects into the address space of a target process during a checkpoint. Its primary purpose is to extract internal task state—such as private memory contents, credentials, and signal handlers—that is not available via standard kernel interfaces like `/proc`.
|
||||
|
||||
## The Infection Process
|
||||
|
||||
Infection is a multi-stage operation managed by the **Compel** sub-project, leveraging the `ptrace` system call to take control of the target process.
|
||||
|
||||
### 1. Seizing the Task
|
||||
CRIU stops the target task using `PTRACE_SEIZE` followed by `PTRACE_INTERRUPT`. This ensures a non-disruptive stop without delivering signals to the application, maintaining transparency.
|
||||
|
||||
### 2. Bootstrap Payload
|
||||
CRIU identifies the task's current instruction pointer (`RIP`/`PC`) and uses `PTRACE_POKEDATA` to temporarily inject a small bootstrap payload. This payload is typically designed to execute a system call (such as `mmap` or `memfd_create`) to allocate a dedicated memory region for the full parasite blob.
|
||||
|
||||
### 3. Memory Exchange Optimization
|
||||
To maximize efficiency and avoid thousands of slow `ptrace` calls, CRIU uses a **memory exchange** technique:
|
||||
* The parasite's memory region is often backed by a file descriptor (e.g., `memfd`).
|
||||
* CRIU maps this same file descriptor into its own address space.
|
||||
* This allows the CRIU coordinator to write the parasite code, Global Offset Table (GOT), and arguments directly into the target's memory at local memory speeds.
|
||||
|
||||
### 4. Relocation and GOT Patching
|
||||
Since the parasite is a Position-Independent Executable (PIE), CRIU must patch its GOT table with the actual addresses where the blob was mapped in the target process's address space.
|
||||
|
||||
### 5. Starting the Daemon
|
||||
CRIU sets the task's instruction pointer to the entry point of the parasite and resumes execution using `PTRACE_CONT`. The parasite initializes its own stack, sets up signal handling for its own internal use, and enters **daemon mode**.
|
||||
|
||||
## Execution and Communication
|
||||
|
||||
The parasite runs as a daemon within the target task's context, communicating with the main CRIU process via a Unix domain socket.
|
||||
|
||||
### Control Loop
|
||||
The parasite enters a loop where it waits for commands from the CRIU coordinator. Each command follows a **Request-Response** pattern:
|
||||
1. **Request**: CRIU sends a command ID (e.g., `PARASITE_CMD_DUMP_PAGES`) and any necessary arguments through the socket.
|
||||
2. **Execution**: The parasite executes the requested action within the task's context (e.g., calling `vmsplice` on its own memory).
|
||||
3. **Response**: The parasite sends an acknowledgment (ACK) and optional data back to CRIU.
|
||||
|
||||
### Supported Actions
|
||||
* **Memory Dumping**: Efficiently transfers memory pages to CRIU using the `vmsplice()` system call.
|
||||
* **Credential Extraction**: Captures UIDs, GIDs, and capability sets.
|
||||
* **Timer and Signal State**: Reads interval timers and signal action tables that are not visible through `/proc`.
|
||||
* **Thread Coordination**: In multi-threaded processes, the parasite coordinates state collection across all threads.
|
||||
|
||||
## Cleanup and Cure
|
||||
|
||||
Once the state capture is complete, CRIU performs a "cure" operation to return the process to its original state:
|
||||
1. CRIU sends the `PARASITE_CMD_FINI` command to the daemon.
|
||||
2. The parasite unmaps its allocated memory and prepares to exit.
|
||||
3. CRIU restores the original register state (including the instruction pointer) and the original code bytes that were overwritten during the bootstrap phase.
|
||||
4. CRIU detaches from the task, allowing it to resume normal operation or terminating it as requested.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Code Blobs](code-blobs.md)
|
||||
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
# Pending Signals
|
||||
|
||||
In Linux, a signal is marked as **pending** if it has been delivered to a task but has not yet been handled (e.g., because the signal is blocked or the task is currently stopped). CRIU provides full support for capturing and restoring these pending signal queues, ensuring that the application's signal state remains perfectly consistent across a checkpoint.
|
||||
|
||||
## Checkpoint and Restore of Pending Signals
|
||||
|
||||
CRIU manages pending signals using specialized `ptrace` interfaces and signal injection system calls.
|
||||
|
||||
### 1. Checkpointing (Dumping)
|
||||
During a dump, CRIU must extract both the list of pending signals and the detailed metadata associated with each one (the `siginfo_t` structure).
|
||||
|
||||
* **PTRACE_PEEKSIGINFO**: CRIU uses this system call (introduced in Linux kernel v3.10 specifically to support CRIU) to read the signal queues of the target task without actually delivering them.
|
||||
* **Private Signals**: Signals delivered to a specific thread are read using standard peeking.
|
||||
* **Shared Signals**: Signals delivered to the entire process (which can be handled by any thread) are read by adding the `PTRACE_PEEKSIGINFO_SHARED` flag.
|
||||
* **Batch Processing**: CRIU reads signals in batches (typically 32 at a time) to efficiently capture entire queues, which is common in high-throughput applications.
|
||||
* **Signal Mask**: In addition to the pending signals, CRIU uses `PTRACE_GETSIGMASK` to capture the set of signals currently blocked by each thread. This mask is essential because it determines why the signals were pending in the first place.
|
||||
|
||||
### 2. Restoration
|
||||
To recreate the pending state, CRIU re-injects the captured signals into the newly created process tree before it begins normal execution.
|
||||
|
||||
* **rt_sigqueueinfo()**: For process-wide (shared) signals, CRIU uses this system call to send a signal to a process with the original `siginfo_t` data.
|
||||
* **rt_tgsigqueueinfo()**: For thread-specific (private) signals, CRIU uses this variant to target a specific thread ID (TID) within a process.
|
||||
* **Preserving siginfo**: These system calls allow CRIU to pass the exact original `siginfo_t` structure (including the sender's PID, UID, and any signal-specific data), ensuring the restored task sees the identical signal context.
|
||||
|
||||
## Shared vs. Private Pending Signals
|
||||
|
||||
* **Multi-threaded Handling**: In multi-threaded applications, signals are carefully tracked:
|
||||
* **Shared signals** are stored in the process leader's `core.img`.
|
||||
* **Private signals** are stored in the `core.img` corresponding to each individual thread.
|
||||
* **Restore Order**: Signals are restored while the task is still under CRIU's control, ensuring that they remain pending until the task is finally resumed and its original signal mask is applied.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Parasite Code](parasite-code.md)
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# PID Restoration
|
||||
|
||||
A critical requirement for successful checkpoint/restore is ensuring that each process and thread is restored with its original **Process ID (PID)** and **Thread ID (TID)**. Applications frequently rely on these IDs for inter-process communication, signal delivery, and as keys for shared resources (such as System V IPC).
|
||||
|
||||
## Restoration Mechanisms
|
||||
|
||||
CRIU employs two primary methods to request specific PIDs from the Linux kernel during restoration.
|
||||
|
||||
### 1. The Legacy Interface: `ns_last_pid`
|
||||
On older kernels, Linux does not provide a direct way to request a specific PID during a `fork()` or `clone()` call. Instead, CRIU uses the `/proc/sys/kernel/ns_last_pid` interface:
|
||||
1. CRIU acquires a global lock (`lock_last_pid`) to minimize the chance of other processes interfering.
|
||||
2. It writes `N-1` to `/proc/sys/kernel/ns_last_pid`.
|
||||
3. It calls `fork()`.
|
||||
4. The kernel assigns the next available PID, which should be `N`.
|
||||
|
||||
**Limitations**:
|
||||
* **Race Conditions**: Other processes on the system (outside of CRIU's control) might fork and "steal" the intended PID between the write and the fork.
|
||||
* **Performance**: Repeatedly writing to the `/proc` filesystem and calling `fork()` is slow, especially for large process trees.
|
||||
* **Nesting Complexity**: Handling nested PID namespaces with this interface requires recursively entering namespaces and managing the legacy interface at each level.
|
||||
|
||||
### 2. The Modern Interface: `clone3()` with `set_tid`
|
||||
Introduced in Linux kernel v5.5, the `clone3()` system call provides a much more robust and efficient mechanism via the `set_tid` array in the `clone_args` structure.
|
||||
* **Atomic Assignment**: CRIU explicitly specifies the desired PID directly during the creation call.
|
||||
* **No Races**: The PID assignment is atomic with process creation, eliminating the risk of PID theft.
|
||||
* **Efficiency**: Offers significant performance improvements, particularly during the restoration of large, multi-threaded applications.
|
||||
* **Full Hierarchy Support**: CRIU can pass an array of PIDs to `set_tid`, allowing it to simultaneously set the process's identity in all nested PID namespaces.
|
||||
|
||||
## Implementation in CRIU
|
||||
|
||||
CRIU includes architecture-specific assembly wrappers (`RUN_CLONE3_RESTORE_FN`) to safely execute these calls during the critical restoration phase.
|
||||
|
||||
* **Automatic Selection**: CRIU automatically detects the presence of `clone3()` and `set_tid` support during the [Kerndat](kerndat.md) phase. If the modern interface is available, it is prioritized.
|
||||
* **Thread Restoration**: Individual threads are restored using the same mechanisms, ensuring that their TIDs match the original state.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Kerndat](kerndat.md)
|
||||
* [Restorer Context](restorer-context.md)
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
# Pidfd Store: Reliable Process Identification
|
||||
|
||||
The **Pidfd Store** is an internal CRIU mechanism used during iterative migration to reliably identify processes across multiple pre-dump iterations. It leverages the Linux kernel's `pidfd` interface to eliminate the risks associated with PID reuse.
|
||||
|
||||
## The Problem: PID Reuse
|
||||
|
||||
In an iterative migration workflow, CRIU performs multiple `pre-dump` operations. Each iteration captures memory pages that have changed since the previous snapshot. To do this safely, CRIU must ensure that it is still talking to the *exact same process* it was in the previous iteration.
|
||||
|
||||
If a process dies between iterations and the kernel assigns its old PID to a new, unrelated process, a naive check based only on the PID would fail to detect this change. Performing an incremental dump on a new process using the state of an old one would lead to corrupted images and a failed restoration.
|
||||
|
||||
## How the Pidfd Store Works
|
||||
|
||||
The Pidfd Store allows CRIU to maintain a persistent, race-free handle for every process in the tree.
|
||||
|
||||
### 1. Capturing Pidfds
|
||||
During the first pre-dump, CRIU calls `pidfd_open()` for every task it captures. Unlike a numeric PID, a **pidfd** is a file descriptor that refers to a specific process *instance*. If that process terminates, its pidfd becomes invalid and will never refer to a subsequent process, even if the numeric PID is reused.
|
||||
|
||||
### 2. Persistent Storage via "The Socket Trick"
|
||||
CRIU often operates as a service, receiving commands via RPC. To keep pidfds alive between independent RPC calls, CRIU uses a clever "socket trick":
|
||||
* CRIU creates a Unix domain socket and connects it to itself.
|
||||
* It "sends" the captured pidfds into this socket using the `SCM_RIGHTS` mechanism.
|
||||
* The Linux kernel stores these file descriptors in the socket's internal buffer. Because the socket is connected to itself, the descriptors remain queued in the kernel until CRIU explicitly reads them back.
|
||||
|
||||
### 3. Identity Verification
|
||||
In each subsequent `pre-dump` or the final `dump` command:
|
||||
1. CRIU "drains" the pidfds from its internal storage socket.
|
||||
2. It builds a hash table mapping PIDs to these stable pidfd handles.
|
||||
3. Before capturing state for a PID, CRIU verifies the task against the stored pidfd.
|
||||
4. If the pidfd is still valid, CRIU knows it is the same process and can safely perform an incremental memory dump.
|
||||
5. If the pidfd is invalid or missing, CRIU detects a **PID reuse** event and treats the process as entirely new, performing a full dump to maintain consistency.
|
||||
|
||||
## Kernel Requirements
|
||||
|
||||
The Pidfd Store requires modern kernel features (automatically detected via [Kerndat](kerndat.md)):
|
||||
* `pidfd_open()` (Kernel v5.3+)
|
||||
* `pidfd_getfd()` (Kernel v5.6+, used to transfer the storage socket between service components).
|
||||
|
||||
## See also
|
||||
* [Memory Changes Tracking](memory-changes-tracking.md)
|
||||
* [Iterative Migration](iterative-migration.md)
|
||||
* [Kerndat](kerndat.md)
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
# Pidfd Support
|
||||
|
||||
A **pidfd** is a file descriptor that refers to a specific process. Unlike traditional numeric PIDs, which can be reused by the kernel once a process terminates, a pidfd is a stable and race-free handle. It remains valid as long as the descriptor is open, even after the process it refers to has died. CRIU provides full support for checkpointing and restoring pidfds owned by applications.
|
||||
|
||||
## How CRIU Handles Pidfds
|
||||
|
||||
CRIU treats pidfds as a specialized type of file descriptor. During a dump, it captures both the target of the pidfd and its configuration.
|
||||
|
||||
### 1. Checkpointing (Dumping)
|
||||
When CRIU encounters a pidfd in a process's file descriptor table:
|
||||
* **Target Identification**: It parses `/proc/$pid/fdinfo/$fd` to determine the numeric PID that the pidfd currently refers to.
|
||||
* **Tree Validation**: CRIU verifies that this target PID is part of the process tree being checkpointed. This ensures that the process will be available for re-binding during restoration.
|
||||
* **Metadata Capture**: CRIU records the target process's namespace-local PID and any flags associated with the pidfd (such as `O_NONBLOCK` or `O_CLOEXEC`).
|
||||
|
||||
### 2. Restoration
|
||||
Restoring a pidfd involves recreating a handle that points to the equivalent process in the newly restored tree.
|
||||
|
||||
* **Alive Processes**: If the target process is alive, CRIU simply calls the `pidfd_open()` system call on the restored PID of that task.
|
||||
* **Dead Processes**: A unique feature of pidfds is that they can be held open even after the target process has exited. To restore this state, CRIU:
|
||||
1. Creates a temporary "helper" process.
|
||||
2. Opens a pidfd to this helper.
|
||||
3. Terminates the helper process.
|
||||
This leaves the restored application with a valid pidfd that refers to a dead process, perfectly mimicking the original state.
|
||||
|
||||
## Kernel Evolution: From Anonymous Inodes to `pidfs`
|
||||
|
||||
The underlying implementation of pidfds in the Linux kernel has changed over time:
|
||||
* **Pre-v6.9**: Pidfds were implemented using anonymous inodes. In `/proc/$pid/fd`, they appeared as `anon_inode:[pidfd]`.
|
||||
* **v6.9 and later**: Pidfds are now part of a dedicated **pidfs** filesystem. They appear in `/proc` as `pidfd:[N]`.
|
||||
|
||||
CRIU automatically detects these kernel differences and handles both formats transparently, ensuring that pidfds are correctly identified and restored regardless of the host kernel version.
|
||||
|
||||
## Current Limitations
|
||||
* **PIDFD_THREAD**: Support for pidfds that target specific threads (created with the `PIDFD_THREAD` flag) is currently not implemented.
|
||||
|
||||
## See also
|
||||
* [Pidfd Store (Iterative Migration)](pidfd-store.md)
|
||||
* [PID Restoration](pid-restore.md)
|
||||
* [Kerndat Feature Detection](kerndat.md)
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# Restartable Sequences (rseq)
|
||||
|
||||
Restartable Sequences (rseq) is a Linux kernel feature (introduced in v4.18) that enables high-performance userspace operations on per-CPU data without requiring atomic instructions or traditional locking. Each thread registers a `struct rseq`, and the kernel ensures that if a thread is preempted or interrupted while inside a critical section, it is "restarted" by jumping to a predefined abort handler.
|
||||
|
||||
## The Challenge of C/R with rseq
|
||||
|
||||
Checkpointing and restoring rseq is exceptionally delicate because the kernel's rseq state is tightly coupled with process execution.
|
||||
|
||||
1. **Dumping Sensitivity**: If an infected thread is allowed to run even briefly (e.g., to execute parasite code), the kernel's `rseq_handle_notify_resume` hook may be triggered. This would cause the kernel to "fix up" the rseq state, clearing critical section pointers in userspace memory and losing the very state CRIU needs to capture.
|
||||
2. **Restoration Morphing**: During restoration, CRIU "morphs" into the target process. If the CRIU binary itself was compiled with rseq support (common in modern distributions), it may have an active rseq registration that must be carefully managed before the memory layout is swapped.
|
||||
|
||||
## How CRIU Handles rseq
|
||||
|
||||
CRIU provides robust support for rseq, ensuring that threads interrupted within a critical section correctly restart after restoration.
|
||||
|
||||
### 1. Checkpointing (Dumping)
|
||||
CRIU captures the rseq configuration without disturbing the thread's execution state:
|
||||
|
||||
* **PTRACE_GET_RSEQ_CONF**: CRIU uses this ptrace command (Kernel v5.13+) to retrieve the address, size, and signature of the `struct rseq` registered for each thread.
|
||||
* **External Peeking**: To avoid triggering kernel fixups, CRIU **does not** use its standard parasite code to read rseq-related memory. Instead, it uses `PTRACE_PEEKDATA` to read the `struct rseq` and `struct rseq_cs` (critical section descriptor) directly from the outside while the task is frozen.
|
||||
* **Critical Section Detection**: By reading the `rseq_cs` pointer within the `struct rseq`, CRIU identifies if a thread was in the middle of a sequence at the time of the snapshot.
|
||||
|
||||
### 2. Restoration
|
||||
The restoration process involves two critical rseq-related steps:
|
||||
|
||||
* **Unregistering Restorer rseq**: Before CRIU performs the final "morphing" (unmapping its own memory and mapping the application's memory), it must explicitly **unregister** any rseq area used by the CRIU process itself. Failing to do so would cause the kernel to attempt to update a `cpu_id` field in memory that has been unmapped, resulting in an immediate segmentation fault.
|
||||
* **Re-establishing Application rseq**: Once the application's memory layout and thread registers are restored, CRIU calls the `rseq()` system call for each thread. It re-registers the original `struct rseq` at its original address.
|
||||
* **Automatic Restart**: Because the `rseq_cs` pointer is restored as part of the thread's memory, the kernel will detect the active critical section upon the first resumption and automatically trigger the application's restart/abort logic, ensuring data integrity.
|
||||
|
||||
## Kernel Requirements
|
||||
|
||||
* **rseq support**: Linux Kernel v4.18+
|
||||
* **PTRACE_GET_RSEQ_CONF**: Linux Kernel v5.13+ (Required for reliable automated detection).
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Parasite Code](parasite-code.md)
|
||||
* [Restorer Context](restorer-context.md)
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
# Restorer Context
|
||||
|
||||
The **Restorer Context** refers to the final stage of the restoration process, where a CRIU process "morphs" itself into the target application. This critical transition is performed by a specialized [PIE](code-blobs.md) blob known as the **Restorer PIE**.
|
||||
|
||||
## Why a Dedicated Context is Necessary
|
||||
|
||||
During the final stage of restoration, CRIU must accomplish two conflicting goals:
|
||||
1. **Memory Swapping**: It must unmap all of CRIU's own code, stack, and data to completely clear the address space for the application.
|
||||
2. **Memory Re-mapping**: It must map the application's original memory regions (VMAs) back into their exact original addresses.
|
||||
|
||||
While these operations are occurring, some code must remain in the address space to execute the necessary `munmap()` and `mmap()` system calls. The Restorer PIE is designed to reside in a temporary "safe hole" in the address space—a range that does not conflict with either CRIU's temporary mappings or the application's final layout.
|
||||
|
||||
## The Restoration Workflow
|
||||
|
||||
1. **Preparation**: The root CRIU process identifies the restorer code and prepares it for distribution.
|
||||
2. **Forking**: The process tree is recreated. Since the restorer code is mapped in the root task before forking, all child processes share the same physical memory for the restorer via standard Copy-on-Write (COW).
|
||||
3. **Safe Hole Detection**: Each restored process scans its target memory layout (from the `mm.img` file) to find a contiguous area large enough to hold the restorer code and its stack.
|
||||
4. **Remapping**: Each process uses `mremap()` to move the shared restorer blob to its specific safe hole.
|
||||
5. **Execution Jump**: The process jumps from the main CRIU code into the restorer PIE.
|
||||
6. **Cleanup and Reconstruction**: The restorer PIE unmaps CRIU, recreates the application's original mappings, and populates them with data from the image files.
|
||||
7. **Final Transition (Sigreturn)**: The very last step is calling `sigreturn()`. The restorer prepares a special signal frame on the stack containing the application's original register state (including the instruction pointer). The kernel then loads this state, effectively resuming the application from the exact point of the checkpoint.
|
||||
|
||||
## Technical Characteristics
|
||||
|
||||
### Freestanding PIE
|
||||
Because the restorer runs in an environment where standard libraries have been unmapped, it is a **freestanding** Position-Independent Executable. It contains its own minimal assembly-level system call wrappers and does not depend on `glibc` or any external runtime.
|
||||
|
||||
### Conflict Avoidance
|
||||
The algorithm for finding the "safe hole" is architecture-specific. It must account for various kernel-mapped regions like the vDSO, the stack, and potential guard pages to ensure that the restorer code never overlaps with memory that the application needs.
|
||||
|
||||
## See also
|
||||
* [Code Blobs](code-blobs.md)
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
# Service Descriptors (Service FDs)
|
||||
|
||||
During dump and restore operations, CRIU requires numerous internal file descriptors (FDs) to manage logs, images, RPC communication, and transport sockets. Because the application being checkpointed or restored may use any arbitrary FD number, CRIU must ensure its internal descriptors never conflict with those of the application. To achieve this, CRIU uses the **Service FD Engine**.
|
||||
|
||||
## The Protected Range
|
||||
|
||||
CRIU avoids FD collisions by placing its internal descriptors in a "protected" range at the very top of the process's file descriptor table.
|
||||
|
||||
* **Lifting Limits**: Upon startup, CRIU attempts to lift its `RLIMIT_NOFILE` resource limit (using `rlimit_unlimit_nofile()`) to a very high value (typically 1,048,576 or higher).
|
||||
* **Top-Down Allocation**: Service FDs are allocated starting from the maximum allowed FD number and working downwards. This strategy places them as far as possible from the range typically used by applications (which usually start from 0 and work upwards).
|
||||
|
||||
## Service FD Engine Mechanisms
|
||||
|
||||
The engine (`criu/servicefd.c`) provides a robust abstraction for managing these descriptors through several key techniques:
|
||||
|
||||
### 1. Per-Process Isolation in Shared Tables
|
||||
In scenarios where multiple processes share the same file descriptor table (e.g., threads or processes created with `CLONE_FILES`), CRIU assigns a unique `service_fd_id` to each task. The engine uses this ID to offset the service FD range, ensuring that even tasks sharing an FD table have distinct, non-overlapping slots for their internal CRIU descriptors.
|
||||
|
||||
### 2. Descriptor Relocation
|
||||
When CRIU opens a file for its own use (such as an image file or the log), the kernel initially assigns it the lowest available FD number (e.g., FD 3). CRIU then uses `fcntl(F_DUPFD_CLOEXEC)` or `dup3()` to "move" that descriptor to its designated high-range slot and immediately closes the original low-numbered descriptor.
|
||||
|
||||
### 3. Protection Flags and Safety
|
||||
During critical phases of restoration—specifically when the application's FDs are being "planted" into their final numeric slots—CRIU sets a global `sfds_protected` flag. While this flag is set, the service FD engine is "locked." Any attempt by the code to modify or close a service descriptor will trigger an immediate safety crash (BUG), preventing accidental corruption of the restoration state.
|
||||
|
||||
## Common Service FD Types
|
||||
|
||||
The engine manages various types of descriptors, each with a specific role:
|
||||
* **LOG_FD**: The descriptor for the main CRIU log file.
|
||||
* **IMG_FD**: The descriptor used for accessing image files.
|
||||
* **RPC_SK**: The socket used for RPC communication with external management tools.
|
||||
* **TRANSPORT_FD**: Sockets used to "send" and "receive" FDs between processes via `SCM_RIGHTS`.
|
||||
* **PROC_FD**: A stable handle to the `/proc` filesystem.
|
||||
* **CGROUP_YARD**: A descriptor for the temporary directory used during cgroup restoration.
|
||||
|
||||
## See also
|
||||
* [Dumping File Descriptors](dumping-files.md)
|
||||
* [Descriptor Assignment](how-to-assign-needed-file-descriptor-to-a-file.md)
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# Shared Memory
|
||||
|
||||
CRIU provides comprehensive support for capturing and reconstructing the various ways processes share memory in Linux. This includes anonymous shared regions, file-backed shared mappings, and System V IPC segments.
|
||||
|
||||
## Types of Shared Memory
|
||||
|
||||
CRIU categorizes shared memory into three primary types, each with a dedicated restoration strategy:
|
||||
|
||||
### 1. Shared Anonymous Mappings
|
||||
Created via `mmap(..., MAP_SHARED | MAP_ANONYMOUS, ...)`, these regions have no persistent backing file on disk but are shared between a parent and its children after a `fork()`, or between unrelated processes that inherit the mapping.
|
||||
|
||||
* **Identification**: CRIU identifies these regions by parsing `/proc/$pid/maps`. For shared anonymous regions, the kernel assigns a unique **internal inode number** (often appearing in the `inode` column of maps). CRIU uses this inode number as a `shmid` to group and identify identical mappings across the entire process tree.
|
||||
* **Restoration via memfd**: During restoration, CRIU uses the `memfd_create()` system call to create an anonymous, RAM-backed file.
|
||||
* One process (the designated "master" for that specific `shmid`) creates the `memfd`, populates it with the memory contents captured in `pages-shmem.img`, and maps it.
|
||||
* All other processes that shared the original region map the same `memfd` file descriptor, ensuring that any subsequent writes are visible to all participants, just as they were before the checkpoint.
|
||||
|
||||
### 2. Shared File Mappings
|
||||
Created via `mmap(..., MAP_SHARED, fd, ...)`, these regions are backed by a regular file on the filesystem.
|
||||
|
||||
* **Mechanism**: CRIU records the file's unique identity (device and inode), the offset within the file, and the mapping length.
|
||||
* **Restoration**: Each process re-opens the original file (or a restored version of it) and calls `mmap()` with the `MAP_SHARED` flag. The Linux kernel's standard page cache mechanism automatically handles the sharing and synchronization between processes.
|
||||
|
||||
### 3. System V IPC Shared Memory
|
||||
Managed via the legacy `shmget()` and `shmat()` APIs, these segments are part of the kernel's IPC subsystem.
|
||||
|
||||
* **Mechanism**: CRIU captures the segment's metadata (key, ID, permissions, size) and its full data contents during the dump.
|
||||
* **Restoration**: CRIU recreates the IPC segments using `shmget()` with the original parameters and repopulates the data. The restored processes then attach to these segments using `shmat()`, ensuring that IPC-based communication continues seamlessly.
|
||||
|
||||
## Advanced Coordination Features
|
||||
|
||||
CRIU leverages modern kernel features to handle complex sharing accurately:
|
||||
* **kcmp**: Used to definitively verify if two memory mappings in different processes refer to the same underlying kernel object (via `KCMP_VM`), ensuring that shared resources are only dumped once.
|
||||
* **Futex Synchronization**: During restoration, CRIU uses futexes to coordinate between the "master" process (which populates shared memory) and "slave" processes, ensuring that no process starts execution until the shared memory state is fully consistent.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
|
||||
* [Kcmp Trees](kcmp-trees.md)
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
# Network Sockets
|
||||
|
||||
CRIU provides extensive support for checkpointing and restoring a wide variety of Linux network sockets, including Unix domain sockets, IPv4/IPv6 (TCP, UDP, RAW), Netlink, and Packet sockets.
|
||||
|
||||
## Key Information Captured
|
||||
|
||||
To faithfully restore a socket, CRIU must capture its full kernel state:
|
||||
1. **Identity**: Family (AF_INET, AF_UNIX, etc.), type (SOCK_STREAM, SOCK_DGRAM), and protocol (TCP, UDP, etc.).
|
||||
2. **Addresses**: Local binding addresses and, for connected sockets, the remote peer address and port.
|
||||
3. **Socket Options**: A wide range of options (e.g., `SO_KEEPALIVE`, `SO_REUSEADDR`, `TCP_NODELAY`, buffer sizes) are captured and reapplied.
|
||||
4. **Queues**: Data currently residing in the send and receive buffers is extracted and re-injected upon restoration.
|
||||
5. **State**: Whether the socket is listening, connected, or in a transitional state (like `FIN_WAIT` or `CLOSE_WAIT` for TCP).
|
||||
|
||||
## The Dumping Process
|
||||
|
||||
CRIU combines information from multiple sources to build a complete picture of each socket.
|
||||
|
||||
### 1. sock_diag
|
||||
The primary source of truth is the **sock_diag** kernel module. CRIU sends Netlink requests to `sock_diag` to retrieve detailed internal state for most socket families. This provides protocol-level information that is not available via standard userspace APIs.
|
||||
|
||||
### 2. SCM_RIGHTS and Parasite
|
||||
For deeper inspection—such as peeking at socket queues or enabling TCP repair mode—CRIU uses its **parasite code** to send the actual socket file descriptor to the CRIU process via a Unix domain socket using the `SCM_RIGHTS` mechanism. This allows the CRIU coordinator to perform `ioctl`, `getsockopt`, and `recv(MSG_PEEK)` calls directly on a local copy of the socket.
|
||||
|
||||
## Restoration Strategies
|
||||
|
||||
### TCP Repair Mode
|
||||
Restoring a TCP connection without disrupting the peer (and without sending any packets) is a major challenge. CRIU uses a specialized kernel feature called **TCP Repair Mode**:
|
||||
1. CRIU creates a new socket and immediately puts it into repair mode.
|
||||
2. While in this mode, CRIU can manually set the sequence numbers, window sizes, and other protocol-level state to match the captured dump.
|
||||
3. It populates the send and receive queues with the dumped data.
|
||||
4. Finally, it takes the socket out of repair mode, allowing the connection to resume as if it were never interrupted.
|
||||
|
||||
### Unix Sockets and SCM_RIGHTS
|
||||
Unix sockets are unique because they can be used to transfer other file descriptors. CRIU captures these "in-flight" descriptors (files that have been sent but not yet received) and ensures they are correctly re-queued for the restored process.
|
||||
|
||||
## Supported Socket Families
|
||||
|
||||
* **AF_UNIX**: Full support for Stream, Datagram, and Sequential Packet types, including abstract and file-backed names.
|
||||
* **AF_INET / AF_INET6**:
|
||||
* **TCP**: Full connection state restoration via Repair Mode.
|
||||
* **UDP / UDPLITE**: Captures addresses, options, and queues.
|
||||
* **RAW**: Captures protocol settings and binding state.
|
||||
* **AF_NETLINK**: Captures the state of Netlink sockets used for kernel communication (e.g., for routing or audit).
|
||||
* **AF_PACKET**: Supports capturing packet filters (BPF) and specific interface bindings.
|
||||
|
||||
## See also
|
||||
* [TCP Connection Details](tcp-connection.md)
|
||||
* [Unix Sockets and SCM_RIGHTS](unix-sockets.md)
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Kerndat Feature Detection](kerndat.md)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# Stages of Restoration
|
||||
|
||||
Restoring a complex process tree is a multi-step operation coordinated by a central CRIU process and executed across the newly created process tree. Each stage is synchronized to ensure that dependencies (such as shared files and parent-child relationships) are met and security invariants are maintained.
|
||||
|
||||
## The Synchronization Mechanism
|
||||
|
||||
CRIU uses a global state machine (defined as `CR_STATE_*` constants) to coordinate between the main CRIU process and the tasks being restored. Tasks use **futexes** in shared memory to signal the completion of their work in each stage and wait for the coordinator to signal the transition to the next stage.
|
||||
|
||||
## Stage 1: Root Task Initiation (`CR_STATE_ROOT_TASK`)
|
||||
The main CRIU process performs initial image analysis, resolves shared resources, and prepares the restorer code blobs. It then forks the **root task** of the tree being restored. The root task performs initial pre-checks and begins its environmental setup.
|
||||
|
||||
## Stage 2: Namespace Preparation (`CR_STATE_PREPARE_NAMESPACES`)
|
||||
The root task (and specialized helpers) initializes the required namespaces (Mount, Network, IPC, UTS, Time). This ensures that all subsequent processes in the tree are created within the correct containerized environment from the moment of their birth.
|
||||
|
||||
## Stage 3: Process Tree Forking (`CR_STATE_FORKING`)
|
||||
The process tree is recursively forked until all processes are recreated.
|
||||
* **PID Restoration**: Processes are created with their original PIDs using the `clone3()` system call or the `ns_last_pid` interface.
|
||||
* **Transport Setup**: Each task creates an abstract Unix domain socket to "receive" shared file descriptors from its designated "master" peers.
|
||||
|
||||
## Stage 4: Main Resource Restoration (`CR_STATE_RESTORE`)
|
||||
This is the primary stage where the bulk of the application state is reconstructed:
|
||||
* **Files and Sockets**: File descriptors are opened locally or received via `SCM_RIGHTS`.
|
||||
* **Memory Mapping**: VMAs are recreated via `mmap()`.
|
||||
* **Restorer Jump**: Each task "morphs" by jumping from the main CRIU code into the freestanding **Restorer PIE** blob.
|
||||
* **Threads**: Individual application threads are recreated within each process.
|
||||
|
||||
## Stage 5: Signal Synchronization (`CR_STATE_RESTORE_SIGCHLD`)
|
||||
Tasks restore their original `SIGCHLD` handlers. This stage serves as a critical synchronization point to transition from CRIU's internal error-tracking (which relies on `SIGCHLD` to detect failed restoration steps in children) to the application's original signal handling logic.
|
||||
|
||||
## Stage 6: Security and Credentials (`CR_STATE_RESTORE_CREDS`)
|
||||
For security reasons, this is the final stage before the application resumes execution. CRIU ensures that sensitive attributes are restored in a specific order:
|
||||
1. **Credentials**: UIDs, GIDs, and Capability sets are applied.
|
||||
2. **Seccomp**: Security filters are enabled only after the final credentials are in place.
|
||||
3. **Process Attributes**: The "dumpable" status and parent-death signals (`pdeath_sig`) are re-established.
|
||||
|
||||
By delaying these steps until the very end, CRIU prevents potential security vulnerabilities where a partially-restored process could be intercepted or manipulated while in a transitional state.
|
||||
|
||||
## Stage 7: Resumption (`CR_STATE_COMPLETE`)
|
||||
The tasks execute their final `sigreturn()` call from within the Restorer PIE. This restores the original register state (including the instruction pointer) and jumps the CPU back into the application's code. The process tree is now fully restored and running.
|
||||
|
||||
## See also
|
||||
* [Restorer Context](restorer-context.md)
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [PID Restoration](pid-restore.md)
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# TCP Connection Checkpoint and Restore
|
||||
|
||||
Checkpointing and restoring established TCP connections is one of CRIU's most advanced features. It allows migrating live applications without dropping active network sessions, provided that the network infrastructure (such as IP routing, virtual IPs, or NAT) supports the transition.
|
||||
|
||||
## The Challenge
|
||||
|
||||
Standard TCP is managed entirely by the kernel's network stack. Under normal circumstances, userspace cannot:
|
||||
1. Read or set internal sequence numbers.
|
||||
2. Directly populate the kernel's send and receive buffers.
|
||||
3. Transition a socket between states (e.g., from `SYN_SENT` to `ESTABLISHED`) without performing an actual network handshake.
|
||||
|
||||
Attempting to restore a connection without specific kernel support would lead to immediate sequence number mismatches and connection resets (RST) from the remote peer.
|
||||
|
||||
## The Solution: TCP Repair Mode
|
||||
|
||||
To address these limitations, CRIU developers implemented **TCP Repair Mode** in the Linux kernel. When a socket is placed into repair mode, the TCP state machine is suspended, and the kernel allows userspace to manipulate its internal parameters directly.
|
||||
|
||||
### Checkpointing (Dumping)
|
||||
1. **Network Locking**: Before capturing the socket state, CRIU "locks" the connection using **iptables** or **nftables**. This ensures the kernel drops any incoming packets from the peer, preventing the connection state from changing while CRIU is performing the dump.
|
||||
2. **Enable Repair**: CRIU puts the socket into repair mode (`TCP_REPAIR`).
|
||||
3. **State Capture**: Using the `libsoccr` library, CRIU extracts:
|
||||
* **Sequence Numbers**: The current positions in the data stream (`TCP_QUEUE_SEQ`).
|
||||
* **TCP Options**: Window scaling factors, timestamps, and SACK settings (`TCP_REPAIR_OPTIONS`).
|
||||
* **Window Parameters**: Send and receive window sizes and offsets (`TCP_REPAIR_WINDOW`).
|
||||
* **Queue Data**: The actual bytes currently residing in the kernel's send and receive buffers.
|
||||
4. **Silent Close**: Once the state is captured, the socket is closed while still in repair mode. This is crucial as it prevents the kernel from sending `FIN` or `RST` packets to the peer, keeping the connection "alive" from the peer's perspective.
|
||||
|
||||
### Restoration
|
||||
1. **Socket Creation**: CRIU creates a new socket and immediately enables repair mode.
|
||||
2. **Binding**: The socket is bound to the original local IP address and port.
|
||||
3. **State Injection**: captured parameters (sequences, windows, options) are applied to the new socket using `setsockopt`.
|
||||
4. **Queue Re-population**: The send and receive buffers are re-filled with the original data.
|
||||
5. **Activation**: CRIU takes the socket out of repair mode. The kernel now considers the connection to be in the exact state it was at the moment of the checkpoint.
|
||||
6. **Network Unlocking**: Finally, the network locks are removed. The application resumes, and the next packet sent or received will have perfectly consistent sequence numbers.
|
||||
|
||||
## Network Locking Methods
|
||||
|
||||
CRIU supports multiple strategies to manage the network during migration:
|
||||
* **nftables** (Preferred): Uses the modern `nft` API to create efficient, temporary rules.
|
||||
* **iptables**: Uses traditional `iptables` commands to drop packets for the specific 4-tuple.
|
||||
* **Skip**: Allows external orchestration (e.g., by an SDN controller) to handle packet buffering and redirection.
|
||||
|
||||
## See also
|
||||
* [Network Sockets](sockets.md)
|
||||
* [Changing IP Addresses](change-ip-address.md)
|
||||
* [Kerndat Feature Detection](kerndat.md)
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
# Foundational Technologies
|
||||
|
||||
CRIU relies on a wide array of advanced Linux kernel features and userspace libraries to perform transparent checkpoint and restore.
|
||||
|
||||
## Kernel Technologies
|
||||
|
||||
### Core C/R Capabilities
|
||||
* **kcmp()**: A system call used to identify shared resources (files, memory mappings, namespaces) between processes by performing internal kernel pointer comparisons.
|
||||
* **clone3()**: A modern process creation interface that allows CRIU to atomically request specific PIDs and TIDs, even across nested PID namespaces.
|
||||
* **prctl() Extensions**:
|
||||
* `PR_SET_MM`: Allows the restorer to reconstruct a process's original memory layout (code, data, heap, etc.).
|
||||
* `PR_GET_TID_ADDRESS`: Captures the address used for `set_tid_address`.
|
||||
* `PR_SET_THP_DISABLE`: Preserves the status of Transparent Huge Pages.
|
||||
* **ptrace() Extensions**:
|
||||
* `PTRACE_SEIZE` & `PTRACE_INTERRUPT`: Enables non-disruptive task stopping.
|
||||
* `PTRACE_GETSIGMASK` & `PTRACE_SETSIGMASK`: Captures and restores thread signal masks.
|
||||
* `PTRACE_PEEKSIGINFO`: Reads pending signal queues without delivering them.
|
||||
* `PTRACE_GET_RSEQ_CONF`: Retrieves Restartable Sequences (rseq) registration details.
|
||||
|
||||
### Resource Introspection
|
||||
* **/proc Filesystem**:
|
||||
* `/proc/$pid/map_files`: Provides stable handles to files mapped into a process's memory.
|
||||
* `/proc/$pid/fdinfo`: Exposes internal state for file descriptors, including positions, flags, and socket handles.
|
||||
* `ioctl(PAGEMAP_SCAN)`: Efficiently identifies dirty and present pages in large address spaces.
|
||||
* **sock_diag**: A netlink-based interface used to retrieve detailed protocol-level state for sockets (TCP, UDP, Unix, etc.).
|
||||
|
||||
### Advanced Subsystems
|
||||
* **TCP Repair Mode**: A specialized socket state that allows CRIU to capture and restore the full internal state of TCP connections without sending network packets.
|
||||
* **Userfaultfd**: Enables **Lazy Migration** by allowing CRIU to handle page faults in userspace and load memory pages on-demand.
|
||||
* **Mount V2 APIs**: Uses `fsopen()`, `fsmount()`, `open_tree()`, and `move_mount()` to robustly reconstruct complex filesystem hierarchies and propagation groups.
|
||||
* **Netfilter (nftables/iptables)**: Used to "lock" network connections during migration to prevent state changes.
|
||||
|
||||
## Userspace Technologies
|
||||
|
||||
### Compel
|
||||
[Compel](../compel.md) is a dedicated sub-project that provides the infrastructure for **Parasite Injection**. It allows CRIU to execute self-contained code (PIE) within the context of a target process to capture internal state.
|
||||
|
||||
### Google Protocol Buffers (protobuf)
|
||||
CRIU uses [Protocol Buffers](https://developers.google.com/protocol-buffers/) as the standard serialization format for all image files. This ensures a structured, extensible, and cross-version compatible way to store process state.
|
||||
|
||||
### ZDTM (Zero-Downtime Migration)
|
||||
[ZDTM](zdtm-test-suite.md) is CRIU's comprehensive test suite. It includes hundreds of tests that verify the functional correctness of C/R across various architectures and kernel versions.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Memory Changes Tracking](memory-changes-tracking.md)
|
||||
* [Mount V2](mount-v2.md)
|
||||
* [PID Restoration](pid-restore.md)
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
# TTY (Teletype) Support
|
||||
|
||||
CRIU provides support for checkpointing and restoring various types of Linux terminals (TTYs), with a primary focus on **Unix98 Pseudoterminals (PTYs)**.
|
||||
|
||||
## Key Information Captured
|
||||
|
||||
For each TTY instance, CRIU captures a comprehensive set of kernel metadata:
|
||||
1. **Identity**: The TTY type (PTY, Console, Serial, or Virtual Terminal), subtype (Master or Slave), and its unique kernel index.
|
||||
2. **Configuration**: Detailed `termios` settings (baud rate, parity, control characters) and window size parameters (`winsize`).
|
||||
3. **Ownership and Permissions**: The original UID/GID and mode of the TTY device node.
|
||||
4. **Process Context**: Controlling terminal status, Session ID (SID), and Foreground Process Group (PGRP).
|
||||
5. **Extended State**: Lock status (`TIOCGLCKTRMIOS`), exclusive mode settings, and packet mode (`TIOCPKT`) flags.
|
||||
|
||||
## The PTY Index Challenge
|
||||
|
||||
A major challenge in restoring PTYs is that the Linux kernel assigns indices (e.g., the `N` in `/dev/pts/N`) sequentially when `/dev/ptmx` is opened. Standard userspace APIs do not allow requesting a specific index.
|
||||
|
||||
### The "Sequential Opening" Strategy
|
||||
To ensure each PTY is restored with its original index, CRIU employs a specialized "brute-force" technique:
|
||||
1. **Looping Open**: CRIU enters a loop, repeatedly calling `open("/dev/ptmx")`.
|
||||
2. **Index Verification**: After each open, it queries the assigned index using the `TIOCGPTN` ioctl.
|
||||
3. **Consuming Indices**: If the assigned index is lower than the target index, CRIU **keeps the file descriptor open**. This prevents the kernel from reassigning that index.
|
||||
4. **Target Match**: Once the kernel assigns the correct original index, CRIU uses that descriptor as the restored master PTY.
|
||||
5. **Cleanup**: All "placeholder" descriptors opened during the loop are then closed, freeing those indices for the rest of the system.
|
||||
|
||||
## Restoration Workflow
|
||||
|
||||
1. **Master Peer Reconstruction**: A designated process recreates the master PTY using the sequential opening strategy.
|
||||
2. **Slave Peer Attachment**: Slave processes open the corresponding `/dev/pts/N` devices. Because the master was created with the correct index, these slaves automatically link to the correct peer.
|
||||
3. **State Application**: Termios, window sizes, and device ownership are applied to the newly opened descriptors.
|
||||
4. **Controlling Terminal Re-binding**: CRIU re-establishes the relationship between each process and its controlling terminal using the `TIOCSCTTY` ioctl.
|
||||
|
||||
## Current Limitations
|
||||
|
||||
* **Buffered Data**: Captured TTY input and output queues (data that was sent but not yet read) are currently not fully restored. CRIU ensures the *interface* is restored, but the application may see a reset of buffered streams.
|
||||
* **Legacy BSD PTYs**: Support for older BSD-style PTYs is not implemented, as the modern Linux kernel does not provide the necessary introspection to reliably pair these devices.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Descriptor Assignment](how-to-assign-needed-file-descriptor-to-a-file.md)
|
||||
* [Kerndat Feature Detection](kerndat.md)
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# TUN/TAP Interface Support
|
||||
|
||||
CRIU supports checkpointing and restoring Linux TUN/TAP virtual network interfaces. These devices are frequently used in VPN clients, virtualization platforms (like QEMU), and container networking.
|
||||
|
||||
## How CRIU Handles TUN/TAP
|
||||
|
||||
CRIU manages TUN/TAP as a combination of a **Network Interface** (the link visible to the kernel) and a **File Descriptor** (the handle used by the application to send and receive packets).
|
||||
|
||||
### 1. Checkpointing (Dumping)
|
||||
During a dump, CRIU identifies TUN/TAP descriptors and collects their full kernel state:
|
||||
* **Device Attributes**: The interface name, type (TUN for L3 or TAP for L2), and operational flags (e.g., `IFF_NO_PI`, `IFF_VNET_HDR`).
|
||||
* **Persistency**: Whether the device is persistent (`IFF_PERSIST`), meaning it survives even when no process has it open.
|
||||
* **Buffer Sizes**: Captures the send buffer size (`TUNGETSNDBUF`) and the virtual network header size (`TUNGETVNETHDRSZ`).
|
||||
* **Multi-Queue State**: CRIU identifies if multiple file descriptors are attached to different queues of the same TUN/TAP device, allowing for parallel I/O.
|
||||
* **Ownership**: Captures the UID and GID associated with the TUN/TAP device.
|
||||
|
||||
### 2. Restoration
|
||||
To recreate the TUN/TAP environment exactly as it was, CRIU performs the following:
|
||||
* **Interface Creation**: Recreates the virtual link or attaches to an existing persistent one using `TUNSETIFF`.
|
||||
* **Index Preservation**: Uses the `TUNSETIFINDEX` ioctl to ensure the restored interface has the exact same numeric index as the original. This is critical for applications that have cached the interface index.
|
||||
* **Queue Re-attachment**: For multi-queue devices, CRIU uses `TUNSETIFF` in combination with `TUNSETQUEUE` to correctly re-link each restored file descriptor to its original queue.
|
||||
* **State Application**: Restores the original buffer sizes, ownership, and persistent status. If a device was not originally persistent, CRIU explicitly drops the persistency after the application has attached to it.
|
||||
|
||||
## Current Limitations
|
||||
|
||||
* **Packet Filters (BPF)**: Capturing a TAP interface with a complex BPF filter attached is currently **not supported**. The kernel does not provide a robust way to extract the filter program and re-attach it during restoration without the original application context.
|
||||
* **In-flight Packets**: Data currently residing in the kernel's internal TUN/TAP queues (packets sent by the application but not yet processed by the virtual device, or vice versa) is not preserved across a checkpoint.
|
||||
|
||||
## See also
|
||||
* [Network Sockets](sockets.md)
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Kerndat Feature Detection](kerndat.md)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# Unix Domain Sockets
|
||||
|
||||
CRIU supports checkpointing and restoring Unix domain sockets (AF_UNIX), including Stream, Datagram, and Sequential Packet types. Unix sockets are unique because they can be bound to paths in the filesystem and are frequently used to transfer file descriptors between processes.
|
||||
|
||||
## Key Challenges
|
||||
|
||||
1. **Path and Inode Decoupling**: A Unix socket's address (its bind path) and the actual socket file on disk are not intrinsically linked in the kernel. If a socket file is moved or unlinked after `bind()`, the socket still reports its original address.
|
||||
2. **In-flight Descriptors**: Unix sockets can contain "in-flight" file descriptors sent via `SCM_RIGHTS` that have been sent by one process but not yet received by the peer.
|
||||
3. **Cross-Namespace Bindings**: Sockets in one mount namespace may be bound to paths that are only visible or reachable from another mount namespace.
|
||||
|
||||
## CRIU's Solution: `SIOCUNIXFILE`
|
||||
|
||||
To reliably restore Unix sockets, CRIU developers upstreamed the `SIOCUNIXFILE` ioctl to the Linux kernel. This ioctl allows CRIU to:
|
||||
* Retrieve an `O_PATH` file descriptor to the actual socket file on disk, regardless of its current name or overmounting status in the filesystem.
|
||||
* By obtaining this `O_PATH` descriptor, CRIU can definitively identify the exact mount point and inode of the socket file, ensuring it can be recreated in the correct location during restoration.
|
||||
|
||||
## Dumping Workflow
|
||||
|
||||
1. **Identity and State**: CRIU uses the `sock_diag` netlink interface to retrieve the socket's type, state, and peer ID.
|
||||
2. **Peer Linking**: For connected or related sockets (like those created via `socketpair()`), CRIU uses the peer information to link them together in the process tree model.
|
||||
3. **File Handle Retrieval**: For sockets bound to the filesystem, CRIU uses `SIOCUNIXFILE` to get a handle to the socket file and records its location.
|
||||
4. **Queue and FD Capture**: Send and receive queues are peeked to capture pending data. Crucially, any file descriptors currently residing in the socket's queues are also captured and dumped.
|
||||
|
||||
## Restoration Workflow
|
||||
|
||||
1. **Socket Creation**: CRIU recreate the socket using the original family, type, and protocol.
|
||||
2. **Address Binding**:
|
||||
* CRIU creates a temporary "yard" (a `tmpfs` mount) to safely recreate socket files without interfering with the host filesystem.
|
||||
* It creates the required directory structure and uses symlinks to ensure the `bind()` call targets the correct path.
|
||||
3. **Peer Connection**: For connected stream sockets, one peer performs a `bind()` and `listen()`, while the other calls `connect()`. CRIU's file restoration engine coordinates this to ensure the server end is ready before the client attempts to connect.
|
||||
4. **State and Data Injection**: Socket options and pending data are restored.
|
||||
5. **Descriptor Redelivery**: In-flight file descriptors are re-injected into the socket's queue using the `SCM_RIGHTS` mechanism, ensuring the application receives them upon resumption.
|
||||
|
||||
## External Unix Sockets
|
||||
|
||||
If a socket is connected to a process *outside* the tree being checkpointed, CRIU cannot capture the peer's state. These are **External Sockets**.
|
||||
* Restoration will fail by default for these sockets to prevent inconsistent states.
|
||||
* Users can explicitly allow these connections using the `--external unix[ID]` option, which tells CRIU to treat the socket as a persistent external dependency.
|
||||
|
||||
## See also
|
||||
* [Network Sockets](sockets.md)
|
||||
* [External UNIX socket](external-unix-socket.md)
|
||||
* [Descriptor Assignment](how-to-assign-needed-file-descriptor-to-a-file.md)
|
||||
* [Kerndat Feature Detection](kerndat.md)
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
# Userfaultfd and Lazy Migration
|
||||
|
||||
**Userfaultfd** is a powerful Linux kernel feature that allows a userspace process (a "monitor") to handle page faults for other processes. CRIU leverages this feature to implement **Lazy Migration**, which significantly reduces the initial downtime when migrating memory-intensive applications.
|
||||
|
||||
## Lazy Migration Overview
|
||||
|
||||
In a traditional migration, the destination host must receive the entire memory dump (potentially many gigabytes) before the application can resume. This "freeze time" can be several seconds or even minutes for large applications.
|
||||
|
||||
With **Lazy Migration**:
|
||||
1. CRIU captures only the minimal process state (registers, file descriptors, etc.) and essential memory pages.
|
||||
2. The process tree is resumed immediately on the destination host with most of its memory regions mapped but empty.
|
||||
3. Memory pages are transferred from the source host only when the application actually tries to access them ("on-demand").
|
||||
|
||||
## How it Works: The Lazy Pages Daemon
|
||||
|
||||
CRIU implements lazy migration through a dedicated background process called the **Lazy Pages Daemon**.
|
||||
|
||||
### 1. The Handover
|
||||
During the restoration process, each process in the tree:
|
||||
* Opens a `userfaultfd` file descriptor.
|
||||
* Registers its memory regions with the kernel for tracking.
|
||||
* Sends the descriptor to the Lazy Pages Daemon via a Unix domain socket using the `SCM_RIGHTS` mechanism.
|
||||
* Resumes execution of the application code via `sigreturn`.
|
||||
|
||||
### 2. Handling Page Faults
|
||||
When the application accesses a page that hasn't been loaded yet, the kernel pauses the faulting thread and sends a message to the Lazy Pages Daemon.
|
||||
1. **Notification**: The daemon receives a `UFFD_EVENT_PAGEFAULT` message containing the faulting address.
|
||||
2. **Retrieval**: The daemon fetches the required page contents, either from the local `pages.img` images or from a remote **Page Server** on the source host.
|
||||
3. **Injection**: The daemon uses the `UFFDIO_COPY` (to fill data) or `UFFDIO_ZEROPAGE` (to fill zeros) ioctl to inject the page into the application's address space.
|
||||
4. **Resumption**: Once the kernel confirms the page is filled, it automatically resumes the paused thread.
|
||||
|
||||
## Advanced Features: Non-Cooperative UFFD
|
||||
|
||||
CRIU utilizes "non-cooperative" kernel features to maintain consistency if the application modifies its memory layout while being lazily restored:
|
||||
* **UFFD_FEATURE_EVENT_FORK**: If the process calls `fork()`, the kernel notifies the daemon, which then begins monitoring the new child process.
|
||||
* **UFFD_FEATURE_EVENT_REMAP**: If the process moves memory using `mremap()`, the daemon updates its internal mapping table to ensure it continues to fetch the correct data for the new addresses.
|
||||
* **UFFD_FEATURE_EVENT_UNMAP / REMOVE**: Handles scenarios where the application releases memory.
|
||||
|
||||
## Benefits and Trade-offs
|
||||
|
||||
* **Reduced Downtime**: Applications resume in milliseconds, regardless of their total memory size.
|
||||
* **Network Jitter**: The application may experience minor stalls (latency spikes) during the initial phase as pages are fetched over the network.
|
||||
* **Source Dependency**: The source host and the Page Server must remain alive and connected until the entire memory state has been successfully transferred to the destination.
|
||||
|
||||
## See also
|
||||
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
|
||||
* [Page Server](page-server.md)
|
||||
* [Kerndat Feature Detection](kerndat.md)
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# File Validation on Restore
|
||||
|
||||
CRIU can verify that regular files and shared libraries being restored on the destination host are identical to the ones captured during the checkpoint. This is a critical security and stability feature, as mismatching libraries (e.g., a different version of `libc.so`) can lead to immediate application crashes or subtle data corruption due to changed offsets and symbols.
|
||||
|
||||
## How File Validation Works
|
||||
|
||||
File validation is managed via the `--file-validation` option. CRIU automatically captures metadata for all regular, file-backed mappings during the dump and stores it in the image files.
|
||||
|
||||
### Supported Validation Methods
|
||||
|
||||
CRIU supports two primary methods for validating files:
|
||||
|
||||
#### 1. Build-ID (Default)
|
||||
Most modern Linux executables and shared libraries include a **GNU Build-ID**—a unique, compiler-generated hash stored in a dedicated ELF note section (`NT_GNU_BUILD_ID`).
|
||||
* **Dumping**: CRIU identifies ELF files by checking their magic numbers. For each ELF file, it maps at most the first **1 MB** of the file (defined as `BUILD_ID_MAP_SIZE`) and extracts the Build-ID hash.
|
||||
* **Restoring**: During restoration, CRIU performs the same extraction on the file residing on the target host. If the resulting hash does not match the one stored in the image, CRIU aborts the restoration to prevent corruption.
|
||||
* **Fallback**: If a file is not an ELF or lacks a Build-ID, CRIU automatically falls back to validating the file by its size.
|
||||
|
||||
#### 2. File Size (`filesize`)
|
||||
A simpler and faster validation method that only compares the total size of the file in bytes.
|
||||
* **Advantage**: Minimal overhead as it only requires a `stat()` call.
|
||||
* **Disadvantage**: Less reliable than Build-ID, as different versions of a file can occasionally have identical sizes.
|
||||
|
||||
## Usage and Configuration
|
||||
|
||||
File validation is enabled by default using the `buildid` method. You can explicitly configure the behavior using the `--file-validation` flag:
|
||||
|
||||
```bash
|
||||
# Explicitly use Build-ID validation
|
||||
criu restore --file-validation buildid ...
|
||||
|
||||
# Use only file size validation
|
||||
criu restore --file-validation filesize ...
|
||||
```
|
||||
|
||||
## Security and Integrity
|
||||
|
||||
File validation ensures that the restored process tree runs against the same binary environment it was captured in. This prevents "library injection" scenarios where an attacker might try to force a restored process to run against malicious versions of its original dependencies. It also ensures that internal pointers (such as function addresses) remain valid, as they are often tied to specific library versions.
|
||||
|
||||
## See also
|
||||
* [Dumping File Descriptors](dumping-files.md)
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Filesystem Peculiarities](filesystems-pecularities.md)
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
# vDSO and VVAR Handling
|
||||
|
||||
The **vDSO** (virtual Dynamic Shared Object) and **VVAR** (virtual VARiable) areas are specialized memory regions mapped by the Linux kernel into every process. They enable high-performance userspace execution of specific system calls (such as `gettimeofday()` or `clock_gettime()`) by providing direct access to kernel-maintained code and data without the overhead of a full context switch.
|
||||
|
||||
## The Challenge of C/R
|
||||
|
||||
The vDSO is uniquely challenging for checkpoint/restore because its contents and memory layout are determined by the **host kernel**.
|
||||
1. **Address Dependencies**: Applications frequently cache the addresses of vDSO functions. These must remain identical after restoration.
|
||||
2. **ABI and Kernel Compatibility**: If a process is migrated to a different kernel version, the vDSO code from the original host might be incompatible with the new host's internal kernel-to-userspace data interfaces.
|
||||
|
||||
## CRIU's Restoration Strategy
|
||||
|
||||
CRIU uses two primary strategies to handle vDSO migration, automatically selecting the best one based on kernel capabilities detected during the [Kerndat](kerndat.md) phase.
|
||||
|
||||
### 1. The Proxy (Patching) Method
|
||||
This is the fallback approach used when the kernel does not support mapping the vDSO at an arbitrary address:
|
||||
* **Checkpoint**: CRIU captures the original vDSO contents and parses its ELF symbol table to identify the offsets of essential functions (e.g., `__vdso_gettimeofday`, `__vdso_time`).
|
||||
* **Restoration**:
|
||||
1. CRIU maps the original vDSO binary at its original virtual address.
|
||||
2. It identifies the **new vDSO** provided by the current host kernel.
|
||||
3. For each essential symbol, CRIU locates the corresponding function in the new vDSO.
|
||||
4. CRIU **patches** the code in the original vDSO with a "trampoline" (a small jump instruction) that redirects execution to the equivalent function in the new host's vDSO.
|
||||
* **Result**: The application continues to call the memory addresses it originally linked against, but it transparently executes the code optimized for the current host kernel.
|
||||
|
||||
### 2. The `arch_prctl` Method (Modern)
|
||||
On modern kernels (v4.18+ for x86_64), CRIU uses a significantly more efficient mechanism:
|
||||
* CRIU uses the `arch_prctl()` system call with the `ARCH_MAP_VDSO_64` (or `ARCH_MAP_VDSO_32`) flag to instruct the kernel to map its **current, native** vDSO directly at the application's original virtual address.
|
||||
* **Advantage**: This eliminates the complexity of ELF patching and ensures the application always uses the most optimal, native code path for the host kernel.
|
||||
|
||||
## VVAR Handling
|
||||
|
||||
The **VVAR** area contains the raw data (such as the current clock value) that the vDSO code reads.
|
||||
* VVAR is a data-only region and is not executable.
|
||||
* CRIU identifies the VVAR mapping during the dump and ensures it is correctly re-established on the destination host, usually adjacent to the restored vDSO.
|
||||
* When using the `arch_prctl` method, the kernel automatically manages the associated VVAR mapping when the vDSO is moved.
|
||||
|
||||
## See also
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
* [Kerndat Feature Detection](kerndat.md)
|
||||
* [Restorer Context](restorer-context.md)
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
# Zombie Processes
|
||||
|
||||
CRIU supports checkpointing and restoring **zombie processes** (tasks that have terminated but have not yet been reaped by their parent). These processes are a vital part of a process tree's state, as they maintain exit codes that the parent may eventually need to read.
|
||||
|
||||
## How CRIU Handles Zombies
|
||||
|
||||
Zombie processes are unique because they have no active memory, no file descriptors, and no CPU state. However, they still occupy an entry in the kernel's process table and maintain an identity via their PID.
|
||||
|
||||
### 1. Checkpointing (Dumping)
|
||||
During the dump phase, CRIU identifies zombie tasks by checking their state in `/proc/$pid/stat`.
|
||||
* **State Capture**: CRIU records the zombie's PID and its original **exit code**.
|
||||
* **Minimal Footprint**: Because zombies have no address space, CRIU does not attempt to inject parasite code or dump memory for them.
|
||||
|
||||
### 2. Restoration
|
||||
Restoring a zombie process involves recreating a task and immediately forcing it into a terminated state without allowing its parent to reap it.
|
||||
|
||||
* **The Helper Technique**: CRIU forks a new process using the original PID (via `clone3` or `ns_last_pid`).
|
||||
* **Immediate Termination**: This process immediately calls the `exit()` system call with the captured exit code.
|
||||
* **Parent Coordination**: The parent process of the zombie (which is also being restored) is managed to ensure it does not accidentally reap the new zombie before the restoration is complete.
|
||||
* **Result**: This leaves the new process in the zombie state, perfectly matching the original environment's PID table.
|
||||
|
||||
## See also
|
||||
* [Process Tree Final States](final-states.md)
|
||||
* [PID Restoration](pid-restore.md)
|
||||
* [Checkpoint/Restore Architecture](checkpointrestore.md)
|
||||
147
GEMINI.md
147
GEMINI.md
|
|
@ -1,147 +0,0 @@
|
|||
# CRIU (Checkpoint/Restore In User-space)
|
||||
|
||||
CRIU is a tool for saving the state of a running application to a set of files
|
||||
(checkpointing) and restoring it back to a live state. It is primarily used for
|
||||
live migration of containers, in-place updates, and fast application startup.
|
||||
|
||||
It is implemented as a command-line tool called `criu`. The two primary commands
|
||||
are `dump` and `restore`.
|
||||
|
||||
- `dump`: Saves a process tree and all its related resources (file
|
||||
descriptors, IPC, sockets, namespaces, etc.) into a collection of image
|
||||
files.
|
||||
- `restore`: Restores processes from image files to the same state they were
|
||||
in before the dump.
|
||||
|
||||
## Quick Start
|
||||
|
||||
To get a feel for `criu`, you can try checkpointing and restoring a simple
|
||||
process.
|
||||
|
||||
1. **Run a simple process:**
|
||||
Open a terminal and run a command that will run for a while. Find its PID.
|
||||
```bash
|
||||
sleep 1000 &
|
||||
[1] 12345
|
||||
```
|
||||
|
||||
2. **Dump the process:**
|
||||
As root, use `criu dump` with the process ID (`-t`) and a directory for the
|
||||
image files (`-D`).
|
||||
```bash
|
||||
sudo criu dump -t 12345 -D /tmp/sleep_images -v4 --shell-job
|
||||
```
|
||||
The `sleep` process will no longer be running.
|
||||
|
||||
3. **Restore the process:**
|
||||
Use `criu restore` to bring the process back to life from the images.
|
||||
```bash
|
||||
sudo criu restore -D /tmp/sleep_images -v4 --shell-job
|
||||
```
|
||||
The `sleep` process will be running again as if nothing happened.
|
||||
|
||||
# For Developers and Contributors
|
||||
|
||||
This section contains more technical details about CRIU's internals and
|
||||
development process.
|
||||
|
||||
## Dump Process
|
||||
|
||||
On dump, CRIU uses available kernel interfaces to collect information about
|
||||
processes. For properties that can only be retrieved from within the process
|
||||
itself, CRIU injects a binary blob (called a "parasite") into the process's
|
||||
address space and executes it in the context of one of the process's threads.
|
||||
This injection is handled by a subproject called **Compel**.
|
||||
|
||||
## Restore Process
|
||||
|
||||
On restore, CRIU reads the image files to reconstruct the processes. The goal is
|
||||
to restore them to the exact state they were in before the dump. The restore
|
||||
process is divided into several stages (defined as `CR_STATE_*` in
|
||||
`./criu/include/restorer.h`).
|
||||
|
||||
The main `criu` process acts as a coordinator. It first restores resources with
|
||||
inter-process dependencies (file descriptors, sockets, shared memory,
|
||||
namespaces, etc.). It then forks the process tree and sets up namespaces.
|
||||
Finally, it restores process-specific resources like file descriptors and memory
|
||||
mappings.
|
||||
|
||||
A key step involves a small, self-contained binary called the "restorer". All
|
||||
restored processes switch to executing this code, which unmaps the CRIU-specific
|
||||
memory and restores the application's original memory mappings. On the final
|
||||
step, the restorer calls `sigreturn` on a prepared signal frame to resume the
|
||||
process with the state it had at the moment of the dump.
|
||||
|
||||
## Compel
|
||||
|
||||
Compel is a subproject responsible for generating the binary blobs used for the
|
||||
parasite code (for dumping) and the restorer code (for restoring). It provides a
|
||||
library for injecting and executing this code within the target process's
|
||||
address space. It is a separate project because the logic for generating and
|
||||
injecting Position-Independent Executable (PIE) code is complex and
|
||||
self-contained.
|
||||
|
||||
## Coding Style
|
||||
|
||||
The C code in the CRIU project follows the
|
||||
[Linux Kernel Coding Style](https://www.kernel.org/doc/html/latest/process/coding-style.html).
|
||||
Here are some of the main points:
|
||||
|
||||
- **Indentation**: Use tabs, which are set to 8 characters.
|
||||
- **Line Length**: The preferred line limit is 80 characters, but it can be
|
||||
extended to 120 if it improves code readability.
|
||||
- **Braces**:
|
||||
- The opening brace for a function goes on a new line.
|
||||
- The opening brace for a block (like `if`, `for`, `while`, `switch`) goes
|
||||
on the same line.
|
||||
- **Spaces**: Use spaces around operators (`+`, `-`, `*`, `/`, `%`, `<`, `>`,
|
||||
`=`, etc.).
|
||||
- **Naming**: Use descriptive names for functions and variables.
|
||||
- **Comments**: Use C-style comments (`/* ... */`). For multi-line comments,
|
||||
the preferred format is:
|
||||
```c
|
||||
/*
|
||||
* This is a multi-line
|
||||
* comment.
|
||||
*/
|
||||
```
|
||||
|
||||
## Code Layout
|
||||
|
||||
The code is organized into the following directories:
|
||||
|
||||
- `./compel`: The Compel sub-project.
|
||||
- `./criu`: The main `criu` tool source code.
|
||||
- `./images`: Protobuf descriptions for the image files.
|
||||
- `./test`: All tests.
|
||||
- `./test/zdtm`: The Zero-Downtime Migration (ZDTM) test suite.
|
||||
- `./test/zdtm.py`: The executor script for ZDTM tests.
|
||||
- `./scripts`: Helper scripts.
|
||||
- `./scripts/build`: Docker image files used for CI and cross-compilation
|
||||
checks.
|
||||
- `./crit`: A tool to inspect and manipulate CRIU image files.
|
||||
- `./soccr`: A library for TCP socket checkpoint/restore.
|
||||
|
||||
## Tests
|
||||
|
||||
The main test suite is ZDTM. Here is an example of how to run a single test:
|
||||
|
||||
```bash
|
||||
sudo ./test/zdtm.py run -t zdtm/static/env00
|
||||
```
|
||||
|
||||
Each ZDTM test has three stages: preparation, C/R, and results checks. During
|
||||
the test, a process calls `test_daemon()` to signal it is ready for C/R, then
|
||||
calls `test_waitsig()` to wait for the C/R stage to complete. After being
|
||||
restored, the test checks that all its resources are still in a valid state.
|
||||
|
||||
## AI-assisted contributions
|
||||
|
||||
Add an `Assisted-by` tag to each commit message, placed after the
|
||||
commit message body and before the `Signed-off-by` line:
|
||||
|
||||
```
|
||||
Assisted-by: AGENT_NAME:MODEL_VERSION
|
||||
```
|
||||
|
||||
Do not add `Signed-off-by` tags on behalf of the user.
|
||||
38
INSTALL.md
38
INSTALL.md
|
|
@ -1,31 +1,11 @@
|
|||
## Building CRIU from source code
|
||||
|
||||
First, you need to install compile-time dependencies. Check [Installation dependencies](https://criu.org/Installation#Dependencies) for more info.
|
||||
|
||||
To compile CRIU, run:
|
||||
```
|
||||
make
|
||||
```
|
||||
This should create the `./criu/criu` executable.
|
||||
|
||||
To change the default behaviour of CRIU, the following variables can be passed
|
||||
to the make command:
|
||||
|
||||
* **NETWORK_LOCK_DEFAULT**, can be set to one of the following
|
||||
values: `NETWORK_LOCK_IPTABLES`, `NETWORK_LOCK_NFTABLES`,
|
||||
`NETWORK_LOCK_SKIP`. CRIU defaults to `NETWORK_LOCK_IPTABLES`
|
||||
if nothing is specified. If another network locking backend is
|
||||
needed, `make` can be called like this:
|
||||
`make NETWORK_LOCK_DEFAULT=NETWORK_LOCK_NFTABLES`
|
||||
|
||||
## Installing CRIU from source code
|
||||
|
||||
Once CRIU is built one can easily setup the complete CRIU package
|
||||
(which includes executable itself, CRIT tool, libraries, manual
|
||||
and etc) simply typing
|
||||
```
|
||||
make install
|
||||
```
|
||||
|
||||
make install
|
||||
|
||||
this command accepts the following variables:
|
||||
|
||||
* **DESTDIR**, to specify global root where all components will be placed under (empty by default);
|
||||
|
|
@ -36,17 +16,17 @@ this command accepts the following variables:
|
|||
* **LIBDIR**, to specify directory where to put libraries (guess the correct path by default).
|
||||
|
||||
Thus one can type
|
||||
```
|
||||
make DESTDIR=/some/new/place install
|
||||
```
|
||||
|
||||
make DESTDIR=/some/new/place install
|
||||
|
||||
and get everything installed under `/some/new/place`.
|
||||
|
||||
## Uninstalling CRIU
|
||||
|
||||
To clean up previously installed CRIU instance one can type
|
||||
```
|
||||
make uninstall
|
||||
```
|
||||
|
||||
make uninstall
|
||||
|
||||
and everything should be removed. Note though that if some variable (**DESTDIR**, **BINDIR**
|
||||
and such) has been used during installation procedure, the same *must* be passed with
|
||||
uninstall action.
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
Andrey Vagin <avagin@gmail.com> (chief)
|
||||
Mike Rapoport <rppt@kernel.org>
|
||||
Dmitry Safonov <0x7f454c46@gmail.com>
|
||||
Adrian Reber <areber@redhat.com>
|
||||
Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
|
||||
Radostin Stoyanov <rstoyanov@fedoraproject.org>
|
||||
Alexander Mikhalitsyn <alexander@mihalicyn.com>
|
||||
|
||||
Pavel Emelyanov <ovzxemul@gmail.com> (retired)
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
## Introduction
|
||||
|
||||
Dear maintainer. Thank you for investing the time and energy to help
|
||||
make CRIU as useful as possible. Maintaining a project is difficult,
|
||||
sometimes unrewarding work. Sure, you will contribute cool features
|
||||
to the project, but most of your time will be spent reviewing patches,
|
||||
cleaning things up, documenting, answering questions, justifying design
|
||||
decisions - while everyone else will just have fun! But remember -- the
|
||||
quality of the maintainers work is what distinguishes the good projects
|
||||
from the great. So please be proud of your work, even the unglamorous
|
||||
parts, and encourage a culture of appreciation and respect for *every*
|
||||
aspect of improving the project -- not just the hot new features.
|
||||
|
||||
Being a maintainer is a time consuming commitment and should not be
|
||||
taken lightly. This document is a manual for maintainers old and new.
|
||||
It explains what is expected of maintainers, how they should work, and
|
||||
what tools are available to them.
|
||||
|
||||
This is a living document - if you see something out of date or missing,
|
||||
speak up!
|
||||
|
||||
## What are a maintainer's responsibility?
|
||||
|
||||
Part of a healthy project is to have active maintainers to support the
|
||||
community in contributions and perform tasks to keep the project running.
|
||||
It is every maintainer's responsibility to:
|
||||
|
||||
* Keep the community a friendly place
|
||||
* Deliver prompt feedback and decisions on pull requests and mailing
|
||||
list threads
|
||||
* Encourage other members to help each other, especially in cases the
|
||||
maintainer is overloaded or feels the lack of needed expertise
|
||||
* Make sure the changes made respects the philosophy, design and
|
||||
roadmap of the project
|
||||
|
||||
## How are decisions made?
|
||||
|
||||
CRIU is an open-source project with an open design philosophy. This
|
||||
means that the repository is the source of truth for EVERY aspect of the
|
||||
project. *If it's part of the project, it's in the repo. It's in the
|
||||
repo, it's part of the project.*
|
||||
|
||||
All decisions affecting CRIU, big and small, follow the same 3 steps:
|
||||
|
||||
* Submit a change. Anyone can do this
|
||||
|
||||
* Discuss it. Anyone can and is encouraged to do this
|
||||
|
||||
* Accept or decline it. Only maintainers do this
|
||||
|
||||
*I'm a maintainer, should I make pull requests / send patches too?*
|
||||
|
||||
Yes. Nobody should ever push to the repository directly. All changes
|
||||
should be made through submitting (and accepting) the change.
|
||||
|
||||
### Two-steps decision making ###
|
||||
|
||||
Since CRIU is extremely complex piece of software we try double hard
|
||||
not to make mistakes, that would be hard to fix in the future. In order
|
||||
to facilitate this, the "final" decision is made in two stages:
|
||||
|
||||
* We definitely want to try something out
|
||||
|
||||
* We think that the attempt was successful
|
||||
|
||||
Respectively, new features get accepted first into the *criu-dev* branch and
|
||||
after they have been validated they are merged into the *master* branch. Yet,
|
||||
urgent bug fixes may land directly in the master branch. If a change in
|
||||
the criu-dev branch is considered to be bad (whatever it means), then it
|
||||
can be reverted without propagation to the master branch. Reverting from
|
||||
the master branch is expected not to happen at all, but if such an
|
||||
extraordinary case occurs, the impact of this step, especially the question
|
||||
of backward compatibility, should be considered in the most careful manner.
|
||||
|
||||
## Who decides what?
|
||||
|
||||
All decisions can be expressed as changes to the repository (either in the
|
||||
form of pull requests, or patches sent to the mailing list), and maintainers
|
||||
make decisions by merging or rejecting them. Review and approval or
|
||||
disagreement can be done by anyone and is denoted by adding a respective
|
||||
comment in the pull request. However, merging the change into either branch
|
||||
only happens after approvals from maintainers.
|
||||
|
||||
In order for a patch to be merged into the criu-dev branch at least two
|
||||
maintainers should accept it. In order for a patch to be merged into the
|
||||
master branch the majority of maintainers should decide that (then prepare
|
||||
a pull request, submit it, etc.).
|
||||
|
||||
Overall the maintainer system works because of mutual respect across the
|
||||
maintainers of the project. The maintainers trust one another to make
|
||||
decisions in the best interests of the project. Sometimes maintainers
|
||||
can disagree and this is part of a healthy project to represent the point
|
||||
of views of various people. In the case where maintainers cannot find
|
||||
agreement on a specific change the role of a Chief Maintainer comes into
|
||||
play.
|
||||
|
||||
### Chief maintainer
|
||||
|
||||
The chief maintainer for the project is responsible for overall architecture
|
||||
of the project to maintain conceptual integrity. Large decisions and
|
||||
architecture changes should be reviewed by the chief maintainer.
|
||||
|
||||
Also the chief maintainer has the veto power on any change submitted
|
||||
to any branch. Naturally, a change in the criu-dev branch can be reverted
|
||||
after a chief maintainer veto, a change in the master branch must be
|
||||
carefully reviewed by the chief maintainer and vetoed in advance.
|
||||
|
||||
### How are maintainers added (and removed)?
|
||||
|
||||
The best maintainers have a vested interest in the project. Maintainers
|
||||
are first and foremost contributors that have shown they are committed to
|
||||
the long term success of the project. Contributors wanting to become
|
||||
maintainers are expected to be deeply involved in contributing code,
|
||||
patches review, and paying needed attention to the issues in the project.
|
||||
Just contributing does not make you a maintainer, it is about building trust
|
||||
with the current maintainers of the project and being a person that they can
|
||||
rely on and trust to make decisions in the best interest of the project.
|
||||
|
||||
When a contributor wants to become a maintainer or nominate someone as a
|
||||
maintainer, one can submit a "nomination", which technically is the
|
||||
respective modification to the `MAINTAINERS` file. When a maintainer feels
|
||||
they is unable to perform the required duties, or someone else wants to draw
|
||||
the community attention to this fact, one can submit a "(self-)removing"
|
||||
change.
|
||||
|
||||
The final vote to add or to remove a maintainer is to be approved by the
|
||||
majority of current maintainers (with the chief maintainer having veto power
|
||||
on that too).
|
||||
|
||||
One might have noticed, that the chief maintainer (re-)assignment is not
|
||||
regulated by this document. That's true :) However, this can be done. If
|
||||
the community decides that the chief maintainer needs to be changed the
|
||||
respective "decision making rules" are to be prepared, submitted and
|
||||
accepted into this file first.
|
||||
|
||||
Good luck!
|
||||
407
Makefile
407
Makefile
|
|
@ -1,157 +1,112 @@
|
|||
#
|
||||
# Import the build engine first
|
||||
__nmk_dir=$(CURDIR)/scripts/nmk/scripts/
|
||||
export __nmk_dir
|
||||
|
||||
#
|
||||
# No need to try to remake our Makefiles
|
||||
Makefile: ;
|
||||
Makefile.%: ;
|
||||
scripts/%.mak: ;
|
||||
$(__nmk_dir)%.mk: ;
|
||||
|
||||
#
|
||||
# Import the build engine
|
||||
include $(__nmk_dir)include.mk
|
||||
include $(__nmk_dir)macro.mk
|
||||
|
||||
ifeq ($(origin HOSTCFLAGS), undefined)
|
||||
HOSTCFLAGS := $(CFLAGS) $(USERCFLAGS)
|
||||
endif
|
||||
CFLAGS += $(USERCFLAGS)
|
||||
export CFLAGS
|
||||
|
||||
HOSTCFLAGS ?= $(CFLAGS)
|
||||
export HOSTCFLAGS
|
||||
|
||||
#
|
||||
# Supported Architectures
|
||||
ifneq ($(filter-out x86 arm aarch64 ppc64 s390 mips loongarch64 riscv64,$(ARCH)),)
|
||||
$(error "The architecture $(ARCH) isn't supported")
|
||||
endif
|
||||
|
||||
# The PowerPC 64 bits architecture could be big or little endian.
|
||||
# They are handled in the same way.
|
||||
ifeq ($(SUBARCH),ppc64)
|
||||
error := $(error ppc64 big endian is not yet supported)
|
||||
endif
|
||||
# Where we live.
|
||||
SRC_DIR := $(CURDIR)
|
||||
export SRC_DIR
|
||||
|
||||
#
|
||||
# Architecture specific options.
|
||||
ifeq ($(ARCH),arm)
|
||||
ARMV := $(shell echo $(SUBARCH) | sed -nr 's/armv([[:digit:]]).*/\1/p; t; i7')
|
||||
|
||||
ifeq ($(ARMV),6)
|
||||
ARCHCFLAGS += -march=armv6
|
||||
endif
|
||||
|
||||
ifeq ($(ARMV),7)
|
||||
ARCHCFLAGS += -march=armv7-a+fp
|
||||
endif
|
||||
|
||||
ifeq ($(ARMV),8)
|
||||
# Running 'setarch linux32 uname -m' returns armv8l on aarch64.
|
||||
# This tells CRIU to handle armv8l just as armv7hf. Right now this is
|
||||
# only used for compile testing. No further verification of armv8l exists.
|
||||
ARCHCFLAGS += -march=armv7-a
|
||||
ARMV := 7
|
||||
endif
|
||||
|
||||
DEFINES := -DCONFIG_ARMV$(ARMV) -DCONFIG_VDSO_32
|
||||
|
||||
PROTOUFIX := y
|
||||
# For simplicity - compile code in Arm mode without interwork.
|
||||
# We could choose Thumb mode as default instead - but a dirty
|
||||
# experiment shows that with 90Kb PIEs Thumb code doesn't save
|
||||
# even one page. So, let's stick so far to Arm mode as it's more
|
||||
# universal around all different Arm variations, until someone
|
||||
# will find any use for Thumb mode. -dima
|
||||
CFLAGS_PIE := -marm
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),aarch64)
|
||||
DEFINES := -DCONFIG_AARCH64
|
||||
CC_MBRANCH_PROT := $(shell $(CC) -c -x c /dev/null -mbranch-protection=none -o /dev/null >/dev/null 2>&1 && echo "-mbranch-protection=none")
|
||||
CFLAGS_PIE := $(CC_MBRANCH_PROT)
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),ppc64)
|
||||
LDARCH := powerpc:common64
|
||||
DEFINES := -DCONFIG_PPC64 -D__SANE_USERSPACE_TYPES__
|
||||
ifneq ($(filter-out x86 arm arm64 ppc64,$(ARCH)),)
|
||||
$(error "The architecture $(ARCH) isn't supported")
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),x86)
|
||||
SRCARCH := x86
|
||||
LDARCH := i386:x86-64
|
||||
VDSO := y
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),arm)
|
||||
SRCARCH := arm
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),arm64)
|
||||
ARCH := aarch64
|
||||
SRCARCH := aarch64
|
||||
VDSO := y
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),ppc64)
|
||||
SRCARCH := ppc64
|
||||
LDARCH := powerpc:common64
|
||||
VDSO := y
|
||||
endif
|
||||
|
||||
LDARCH ?= $(SRCARCH)
|
||||
|
||||
export SRCARCH LDARCH VDSO
|
||||
|
||||
SRCARCH ?= $(ARCH)
|
||||
LDARCH ?= $(SRCARCH)
|
||||
|
||||
export SRCARCH LDARCH VDSO
|
||||
|
||||
UNAME-M := $(shell uname -m)
|
||||
export UNAME-M
|
||||
|
||||
ifeq ($(ARCH),arm)
|
||||
ARMV := $(shell echo $(UNAME-M) | sed -nr 's/armv([[:digit:]]).*/\1/p; t; i7')
|
||||
DEFINES := -DCONFIG_ARMV$(ARMV)
|
||||
|
||||
ifeq ($(ARMV),6)
|
||||
USERCFLAGS += -march=armv6
|
||||
endif
|
||||
|
||||
ifeq ($(ARMV),7)
|
||||
USERCFLAGS += -march=armv7-a
|
||||
endif
|
||||
|
||||
PROTOUFIX := y
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),x86)
|
||||
DEFINES := -DCONFIG_X86_64
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),mips)
|
||||
DEFINES := -DCONFIG_MIPS
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),loongarch64)
|
||||
DEFINES := -DCONFIG_LOONGARCH64
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),riscv64)
|
||||
DEFINES := -DCONFIG_RISCV64
|
||||
endif
|
||||
|
||||
#
|
||||
# CFLAGS_PIE:
|
||||
# The PowerPC 64 bits architecture could be big or little endian.
|
||||
# They are handled in the same way.
|
||||
#
|
||||
# Ensure with -fno-optimize-sibling-calls that we don't create GOT
|
||||
# (Global Offset Table) relocations with gcc compilers that don't have
|
||||
# commit "S/390: Fix 64 bit sibcall".
|
||||
ifeq ($(ARCH),s390)
|
||||
ARCH := s390
|
||||
DEFINES := -DCONFIG_S390
|
||||
CFLAGS_PIE := -fno-optimize-sibling-calls
|
||||
ifeq ($(ARCH),ppc64)
|
||||
ifeq ($(UNAME-M),ppc64)
|
||||
error := $(error ppc64 big endian not yet supported)
|
||||
endif
|
||||
|
||||
DEFINES := -DCONFIG_PPC64
|
||||
endif
|
||||
|
||||
CFLAGS_PIE += -DCR_NOGLIBC
|
||||
export CFLAGS_PIE
|
||||
|
||||
LDARCH ?= $(ARCH)
|
||||
export LDARCH
|
||||
export PROTOUFIX DEFINES
|
||||
export PROTOUFIX DEFINES USERCFLAGS
|
||||
|
||||
#
|
||||
# Independent options for all tools.
|
||||
DEFINES += -D_FILE_OFFSET_BITS=64
|
||||
DEFINES += -D_LARGEFILE64_SOURCE
|
||||
DEFINES += -D_GNU_SOURCE
|
||||
|
||||
WARNINGS := -Wall -Wformat-security -Wdeclaration-after-statement -Wstrict-prototypes
|
||||
CFLAGS += $(USERCFLAGS)
|
||||
|
||||
# -Wdangling-pointer results in false warning when we add a list element to
|
||||
# local list head variable. It is false positive because before leaving the
|
||||
# function we always check that local list head variable is empty, thus
|
||||
# insuring that pointer to it is not dangling anywhere, but gcc can't
|
||||
# understand it.
|
||||
# Note: There is similar problem with kernel list, where this warning is also
|
||||
# disabled: https://github.com/torvalds/linux/commit/49beadbd47c2
|
||||
WARNINGS += -Wno-dangling-pointer -Wno-unknown-warning-option
|
||||
WARNINGS := -Wall -Wformat-security
|
||||
|
||||
CFLAGS-GCOV := --coverage -fno-exceptions -fno-inline -fprofile-update=atomic
|
||||
CFLAGS-GCOV := --coverage -fno-exceptions -fno-inline
|
||||
export CFLAGS-GCOV
|
||||
|
||||
ifeq ($(ARCH),mips)
|
||||
WARNINGS := -rdynamic
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),loongarch64)
|
||||
WARNINGS += -Wno-implicit-function-declaration
|
||||
endif
|
||||
|
||||
ifneq ($(GCOV),)
|
||||
LDFLAGS += -lgcov
|
||||
CFLAGS += $(CFLAGS-GCOV)
|
||||
endif
|
||||
|
||||
ifneq ($(NETWORK_LOCK_DEFAULT),)
|
||||
CFLAGS += -DNETWORK_LOCK_DEFAULT=$(NETWORK_LOCK_DEFAULT)
|
||||
endif
|
||||
|
||||
ifeq ($(ASAN),1)
|
||||
CFLAGS-ASAN := -fsanitize=address
|
||||
export CFLAGS-ASAN
|
||||
CFLAGS += $(CFLAGS-ASAN)
|
||||
endif
|
||||
|
||||
ifneq ($(WERROR),0)
|
||||
WARNINGS += -Werror
|
||||
endif
|
||||
|
|
@ -169,20 +124,17 @@ ifeq ($(GMON),1)
|
|||
export GMON GMONLDOPT
|
||||
endif
|
||||
|
||||
AFLAGS += -D__ASSEMBLY__
|
||||
CFLAGS += $(USERCFLAGS) $(ARCHCFLAGS) $(WARNINGS) $(DEFINES) -iquote include/
|
||||
HOSTCFLAGS += $(WARNINGS) $(DEFINES) -iquote include/
|
||||
export AFLAGS CFLAGS USERCLFAGS HOSTCFLAGS
|
||||
CFLAGS += $(WARNINGS) $(DEFINES) -iquote include/
|
||||
|
||||
# Default target
|
||||
all: criu lib crit cuda_plugin
|
||||
all: criu lib
|
||||
.PHONY: all
|
||||
|
||||
#
|
||||
# Version headers.
|
||||
include Makefile.versions
|
||||
|
||||
VERSION_HEADER := criu/include/version.h
|
||||
VERSION_HEADER := $(SRC_DIR)/criu/include/version.h
|
||||
GITID_FILE := .gitid
|
||||
GITID := $(shell if [ -d ".git" ]; then git describe --always; fi)
|
||||
|
||||
|
|
@ -217,50 +169,50 @@ endif
|
|||
$(Q) echo "#define CRIU_GITID \"$(GITID)\"" >> $@
|
||||
$(Q) echo "#endif /* __CR_VERSION_H__ */" >> $@
|
||||
|
||||
criu-deps += $(VERSION_HEADER)
|
||||
|
||||
#
|
||||
# Setup proper link for asm headers in common code.
|
||||
include/common/asm: include/common/arch/$(ARCH)/asm
|
||||
$(call msg-gen, $@)
|
||||
$(Q) ln -s ./arch/$(ARCH)/asm $@
|
||||
$(VERSION_HEADER): include/common/asm
|
||||
|
||||
criu-deps += include/common/asm
|
||||
#
|
||||
# piegen tool might be disabled by hands. Don't use it until
|
||||
# you know what you're doing.
|
||||
ifneq ($(filter ia32 x86 ppc64,$(ARCH)),)
|
||||
ifneq ($(PIEGEN),no)
|
||||
piegen-y := y
|
||||
export piegen-y
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Configure variables.
|
||||
export CONFIG_HEADER := include/common/config.h
|
||||
ifeq ($(filter tags etags cscope clean lint indent fetch-clang-format help mrproper,$(MAKECMDGOALS)),)
|
||||
include Makefile.config
|
||||
else
|
||||
# To clean all files, enable make/build options here
|
||||
export CONFIG_COMPAT := y
|
||||
export CONFIG_GNUTLS := y
|
||||
export CONFIG_HAS_LIBBPF := y
|
||||
export CONFIG_LZ4 := y
|
||||
CONFIG_HEADER_REL := criu/include/config.h
|
||||
export CONFIG_HEADER := $(SRC_DIR)/$(CONFIG_HEADER_REL)
|
||||
ifeq ($(filter clean mrproper,$(MAKECMDGOALS)),)
|
||||
include $(SRC_DIR)/Makefile.config
|
||||
endif
|
||||
|
||||
#
|
||||
# Protobuf images first, they are not depending
|
||||
# on anything else.
|
||||
$(eval $(call gen-built-in,images))
|
||||
criu-deps += images/built-in.o
|
||||
|
||||
#
|
||||
# Compel get used by CRIU, build it earlier
|
||||
include Makefile.compel
|
||||
.PHONY: .FORCE
|
||||
|
||||
#
|
||||
# Next the socket CR library
|
||||
#
|
||||
SOCCR_A := soccr/libsoccr.a
|
||||
soccr/Makefile: ;
|
||||
soccr/%: $(CONFIG_HEADER) .FORCE
|
||||
SOCCR_CONFIG := $(SRC_DIR)/soccr/config.h
|
||||
$(SOCCR_CONFIG): $(CONFIG_HEADER)
|
||||
$(Q) test -f $@ || ln -s ../$(CONFIG_HEADER_REL) $@
|
||||
soccr/%: $(SOCCR_CONFIG) .FORCE
|
||||
$(Q) $(MAKE) $(build)=soccr $@
|
||||
soccr/built-in.o: $(CONFIG_HEADER) .FORCE
|
||||
soccr/built-in.o: $(SOCCR_CONFIG) .FORCE
|
||||
$(Q) $(MAKE) $(build)=soccr all
|
||||
$(SOCCR_A): |soccr/built-in.o
|
||||
criu-deps += $(SOCCR_A)
|
||||
|
||||
#
|
||||
# CRIU building done in own directory
|
||||
|
|
@ -270,69 +222,47 @@ criu-deps += $(SOCCR_A)
|
|||
#
|
||||
# But note that we're already included
|
||||
# the nmk so we can reuse it there.
|
||||
criu/Makefile: ;
|
||||
criu/Makefile.packages: ;
|
||||
criu/Makefile.crtools: ;
|
||||
criu/%: $(criu-deps) .FORCE
|
||||
criu/%: images/built-in.o $(VERSION_HEADER) $(CONFIG_HEADER) .FORCE
|
||||
$(Q) $(MAKE) $(build)=criu $@
|
||||
criu: $(criu-deps)
|
||||
criu: images/built-in.o $(SOCCR_A) $(VERSION_HEADER) $(CONFIG_HEADER)
|
||||
$(Q) $(MAKE) $(build)=criu all
|
||||
.PHONY: criu
|
||||
|
||||
unittest: $(criu-deps)
|
||||
$(Q) $(MAKE) $(build)=criu unittest
|
||||
.PHONY: unittest
|
||||
|
||||
|
||||
#
|
||||
# Libraries next once criu is ready
|
||||
# Libraries next once criu it ready
|
||||
# (we might generate headers and such
|
||||
# when building criu itself).
|
||||
lib/Makefile: ;
|
||||
lib/%: criu .FORCE
|
||||
$(Q) $(MAKE) $(build)=lib $@
|
||||
lib: criu
|
||||
$(Q) $(MAKE) $(build)=lib all
|
||||
.PHONY: lib
|
||||
|
||||
clean mrproper:
|
||||
subclean:
|
||||
$(Q) $(MAKE) -C Documentation clean
|
||||
$(Q) $(RM) .gitid
|
||||
.PHONY: subclean
|
||||
|
||||
clean: subclean
|
||||
$(Q) $(MAKE) $(build)=images $@
|
||||
$(Q) $(MAKE) $(build)=criu $@
|
||||
$(Q) $(MAKE) $(build)=soccr $@
|
||||
$(Q) $(MAKE) $(build)=lib $@
|
||||
$(Q) $(MAKE) $(build)=crit $@
|
||||
$(Q) $(MAKE) $(build)=compel $@
|
||||
$(Q) $(MAKE) $(build)=compel/plugins $@
|
||||
.PHONY: clean mrproper
|
||||
.PHONY: clean
|
||||
|
||||
clean-amdgpu_plugin:
|
||||
$(Q) $(MAKE) -C plugins/amdgpu clean
|
||||
.PHONY: clean-amdgpu_plugin
|
||||
|
||||
clean-cuda_plugin:
|
||||
$(Q) $(MAKE) -C plugins/cuda clean
|
||||
.PHONY: clean-cuda_plugin
|
||||
|
||||
clean-top:
|
||||
$(Q) $(MAKE) -C Documentation clean
|
||||
$(Q) $(MAKE) -C soccr/test clean
|
||||
$(Q) $(MAKE) $(build)=test/compel clean
|
||||
$(Q) $(RM) .gitid
|
||||
.PHONY: clean-top
|
||||
|
||||
clean: clean-top clean-amdgpu_plugin clean-cuda_plugin
|
||||
|
||||
mrproper-top: clean-top clean-amdgpu_plugin clean-cuda_plugin
|
||||
# mrproper depends on clean in nmk
|
||||
mrproper: subclean
|
||||
$(Q) $(MAKE) $(build)=images $@
|
||||
$(Q) $(MAKE) $(build)=criu $@
|
||||
$(Q) $(MAKE) $(build)=soccr $@
|
||||
$(Q) $(MAKE) $(build)=lib $@
|
||||
$(Q) $(RM) $(CONFIG_HEADER)
|
||||
$(Q) $(RM) $(SOCCR_CONFIG)
|
||||
$(Q) $(RM) $(VERSION_HEADER)
|
||||
$(Q) $(RM) $(COMPEL_VERSION_HEADER)
|
||||
$(Q) $(RM) include/common/asm
|
||||
$(Q) $(RM) compel/include/asm
|
||||
$(Q) $(RM) cscope.*
|
||||
$(Q) $(RM) tags TAGS
|
||||
.PHONY: mrproper-top
|
||||
|
||||
mrproper: mrproper-top
|
||||
.PHONY: mrproper
|
||||
|
||||
#
|
||||
# Non-CRIU stuff.
|
||||
|
|
@ -343,25 +273,13 @@ docs:
|
|||
.PHONY: docs
|
||||
|
||||
zdtm: all
|
||||
$(Q) $(MAKE) -C test/zdtm all
|
||||
$(Q) MAKEFLAGS= $(MAKE) -C test/zdtm all
|
||||
.PHONY: zdtm
|
||||
|
||||
test: zdtm
|
||||
$(Q) $(MAKE) -C test
|
||||
$(Q) MAKEFLAGS= $(MAKE) -C test
|
||||
.PHONY: test
|
||||
|
||||
amdgpu_plugin: criu
|
||||
$(Q) $(MAKE) -C plugins/amdgpu all
|
||||
.PHONY: amdgpu_plugin
|
||||
|
||||
cuda_plugin: criu
|
||||
$(Q) $(MAKE) -C plugins/cuda all
|
||||
.PHONY: cuda_plugin
|
||||
|
||||
crit: lib
|
||||
$(Q) $(MAKE) -C crit
|
||||
.PHONY: crit
|
||||
|
||||
#
|
||||
# Generating tar requires tag matched CRIU_VERSION.
|
||||
# If not found then simply use GIT's describe with
|
||||
|
|
@ -382,26 +300,26 @@ endif
|
|||
tar-name := $(shell echo $(head-name) | sed -e 's/^v//g')
|
||||
criu-$(tar-name).tar.bz2:
|
||||
git archive --format tar --prefix 'criu-$(tar-name)/' $(head-name) | bzip2 > $@
|
||||
dist tar: criu-$(tar-name).tar.bz2 ;
|
||||
dist tar: criu-$(tar-name).tar.bz2
|
||||
@true
|
||||
.PHONY: dist tar
|
||||
|
||||
TAGS_FILES_REGEXP := . -name '*.[hcS]' ! -path './.*' \( ! -path './test/*' -o -path './test/zdtm/lib/*' \)
|
||||
tags:
|
||||
$(call msg-gen, $@)
|
||||
$(Q) $(RM) tags
|
||||
$(Q) $(FIND) $(TAGS_FILES_REGEXP) -print | xargs $(CTAGS) -a
|
||||
$(Q) $(FIND) . -name '*.[hcS]' ! -path './.*' ! -path './test/*' -print | xargs $(CTAGS) -a
|
||||
.PHONY: tags
|
||||
|
||||
etags:
|
||||
$(call msg-gen, $@)
|
||||
$(Q) $(RM) TAGS
|
||||
$(Q) $(FIND) $(TAGS_FILES_REGEXP) -print | xargs $(ETAGS) -a
|
||||
$(Q) $(FIND) . -name '*.[hcS]' ! -path './.*' ! -path './test/*' -print | xargs $(ETAGS) -a
|
||||
.PHONY: etags
|
||||
|
||||
|
||||
cscope:
|
||||
$(call msg-gen, $@)
|
||||
$(Q) $(FIND) $(TAGS_FILES_REGEXP) ! -type l -print > cscope.files
|
||||
$(Q) $(FIND) . -name '*.[hcS]' ! -path './.*' ! -path './test/*' ! -type l -print > cscope.files
|
||||
$(Q) $(CSCOPE) -bkqu
|
||||
.PHONY: cscope
|
||||
|
||||
|
|
@ -415,19 +333,17 @@ gcov:
|
|||
.PHONY: gcov
|
||||
|
||||
docker-build:
|
||||
$(MAKE) -C scripts/build/ x86_64
|
||||
$(MAKE) -C scripts/build/ x86_64
|
||||
.PHONY: docker-build
|
||||
|
||||
docker-test:
|
||||
docker run --rm --privileged -v /lib/modules:/lib/modules --network=host --cgroupns=host criu-x86_64 \
|
||||
./test/zdtm.py run -a --keep-going --ignore-taint
|
||||
docker run --rm -it --privileged criu-x86_64 ./test/zdtm.py run -a -x tcp6 -x tcpbuf6 -x static/rtc -x cgroup
|
||||
.PHONY: docker-test
|
||||
|
||||
help:
|
||||
@echo ' Targets:'
|
||||
@echo ' all - Build all [*] targets'
|
||||
@echo ' * criu - Build criu'
|
||||
@echo ' * crit - Build crit'
|
||||
@echo ' zdtm - Build zdtm test-suite'
|
||||
@echo ' docs - Build documentation'
|
||||
@echo ' install - Install CRIU (see INSTALL.md)'
|
||||
|
|
@ -440,85 +356,10 @@ help:
|
|||
@echo ' cscope - Generate cscope database'
|
||||
@echo ' test - Run zdtm test-suite'
|
||||
@echo ' gcov - Make code coverage report'
|
||||
@echo ' unittest - Run unit tests'
|
||||
@echo ' lint - Run code linters'
|
||||
@echo ' indent - Indent C code'
|
||||
@echo ' amdgpu_plugin - Make AMD GPU plugin'
|
||||
@echo ' cuda_plugin - Make NVIDIA CUDA plugin'
|
||||
.PHONY: help
|
||||
|
||||
ruff:
|
||||
@ruff --version
|
||||
ruff check ${RUFF_FLAGS} --config=scripts/ruff.toml \
|
||||
test/zdtm.py \
|
||||
test/inhfd/*.py \
|
||||
test/others/rpc/config_file.py \
|
||||
test/others/action-script/check_actions.py \
|
||||
test/others/pycriu/*.py \
|
||||
lib/pycriu/criu.py \
|
||||
lib/pycriu/__init__.py \
|
||||
lib/pycriu/images/pb2dict.py \
|
||||
lib/pycriu/images/images.py \
|
||||
scripts/criu-ns \
|
||||
scripts/magic-gen.py \
|
||||
test/others/criu-ns/run.py \
|
||||
crit/*.py \
|
||||
crit/crit/*.py \
|
||||
test/others/crit/*.py \
|
||||
scripts/uninstall_module.py \
|
||||
coredump/ coredump/coredump \
|
||||
scripts/github-indent-warnings.py \
|
||||
contrib/criu-service-client/test/*.py \
|
||||
contrib/compression-benchmark/ \
|
||||
test/others/compression/ \
|
||||
soccr/test/run.py \
|
||||
soccr/test/tcp-test.py
|
||||
|
||||
shellcheck:
|
||||
shellcheck --version
|
||||
shellcheck scripts/*.sh
|
||||
shellcheck scripts/ci/*.sh
|
||||
shellcheck contrib/apt-install contrib/dependencies/*.sh
|
||||
shellcheck -x test/others/crit/*.sh
|
||||
shellcheck -x test/others/libcriu/*.sh
|
||||
shellcheck -x test/others/crit/*.sh test/others/criu-coredump/*.sh
|
||||
shellcheck -x test/others/config-file/*.sh
|
||||
shellcheck -x test/others/action-script/*.sh
|
||||
shellcheck -x contrib/criu-service-client/test/*.sh
|
||||
shellcheck -x test/others/compression/*/*.sh
|
||||
|
||||
codespell:
|
||||
codespell
|
||||
|
||||
lint: ruff shellcheck codespell
|
||||
# Do not append \n to pr_perror, pr_pwarn or fail
|
||||
! git --no-pager grep -E '^\s*\<(pr_perror|pr_pwarn|fail)\>.*\\n"'
|
||||
# Do not use %m with pr_* or fail
|
||||
! git --no-pager grep -E '^\s*\<(pr_(err|perror|warn|pwarn|debug|info|msg)|fail)\>.*%m'
|
||||
# Do not use errno with pr_perror, pr_pwarn or fail
|
||||
! git --no-pager grep -E '^\s*\<(pr_perror|pr_pwarn|fail)\>\(".*".*errno'
|
||||
# End pr_(err|warn|msg|info|debug) with \n
|
||||
! git --no-pager grep -En '^\s*\<pr_(err|warn|msg|info|debug)\>.*);$$' | grep -v '\\n'
|
||||
# No EOL whitespace for C files
|
||||
! git --no-pager grep -E '\s+$$' \*.c \*.h
|
||||
.PHONY: lint ruff shellcheck codespell
|
||||
|
||||
codecov: SHELL := $(shell command -v bash)
|
||||
codecov:
|
||||
curl -Os https://uploader.codecov.io/latest/linux/codecov
|
||||
chmod +x codecov
|
||||
./codecov
|
||||
.PHONY: codecov
|
||||
|
||||
fetch-clang-format: .FORCE
|
||||
$(E) ".clang-format"
|
||||
$(Q) scripts/fetch-clang-format.sh
|
||||
|
||||
BASE ?= "HEAD~1"
|
||||
OPTS ?= "--quiet"
|
||||
indent:
|
||||
git clang-format --style file --extensions c,h $(OPTS) $(BASE)
|
||||
.PHONY: indent
|
||||
lint:
|
||||
flake8 --config=scripts/flake8.cfg test/zdtm.py
|
||||
|
||||
include Makefile.install
|
||||
|
||||
|
|
|
|||
|
|
@ -1,77 +0,0 @@
|
|||
COMPEL_BIN := ./compel/compel-host
|
||||
export COMPEL_BIN
|
||||
|
||||
COMPEL_VERSION_HEADER := compel/include/version.h
|
||||
|
||||
$(COMPEL_VERSION_HEADER): Makefile.versions
|
||||
$(call msg-gen, $(COMPEL_VERSION_HEADER))
|
||||
$(Q) echo "/* Autogenerated, do not edit */" > $(COMPEL_VERSION_HEADER)
|
||||
$(Q) echo "#ifndef COMPEL_SO_VERSION_H__" >> $(COMPEL_VERSION_HEADER)
|
||||
$(Q) echo "#define COMPEL_SO_VERSION_H__" >> $(COMPEL_VERSION_HEADER)
|
||||
$(Q) echo "#define COMPEL_SO_VERSION \"$(COMPEL_SO_VERSION)\"" >> $(COMPEL_VERSION_HEADER)
|
||||
$(Q) echo "#define COMPEL_SO_VERSION_MAJOR " $(COMPEL_SO_VERSION_MAJOR) >> $(COMPEL_VERSION_HEADER)
|
||||
$(Q) echo "#define COMPEL_SO_VERSION_MINOR " $(COMPEL_SO_VERSION_MINOR) >> $(COMPEL_VERSION_HEADER)
|
||||
$(Q) echo "#define COMPEL_SO_VERSION_SUBLEVEL " $(COMPEL_SO_VERSION_SUBLEVEL) >> $(COMPEL_VERSION_HEADER)
|
||||
$(Q) echo "#endif /* COMPEL_SO_VERSION_H__ */" >> $(COMPEL_VERSION_HEADER)
|
||||
|
||||
compel/include/asm:
|
||||
$(call msg-gen, $@)
|
||||
$(Q) ln -s ../arch/$(ARCH)/src/lib/include $@
|
||||
|
||||
compel-deps += compel/include/asm
|
||||
compel-deps += $(COMPEL_VERSION_HEADER)
|
||||
compel-deps += $(CONFIG_HEADER)
|
||||
compel-deps += include/common/asm
|
||||
compel-plugins += compel/plugins/std.lib.a compel/plugins/fds.lib.a
|
||||
|
||||
LIBCOMPEL_SO := libcompel.so
|
||||
LIBCOMPEL_A := libcompel.a
|
||||
export LIBCOMPEL_SO LIBCOMPEL_A
|
||||
|
||||
#
|
||||
# Compel itself.
|
||||
compel/Makefile: ;
|
||||
compel/%: $(compel-deps) $(compel-plugins) .FORCE
|
||||
$(Q) $(MAKE) $(build)=compel $@
|
||||
|
||||
criu-deps += compel/compel-host-bin
|
||||
|
||||
#
|
||||
# Make sure the host program is ready after the
|
||||
# library and plugins are built.
|
||||
compel/compel-host-bin: | compel/$(LIBCOMPEL_A) $(compel-plugins)
|
||||
$(COMPEL_BIN): compel/compel-host-bin
|
||||
|
||||
#
|
||||
# Plugins
|
||||
compel/plugins/Makefile: ;
|
||||
compel/plugins/%: $(compel-deps) .FORCE
|
||||
$(Q) $(MAKE) $(build)=compel/plugins $@
|
||||
|
||||
#
|
||||
# GNU make 4.x supports targets matching via wide
|
||||
# match targeting, where GNU make 3.x series is not,
|
||||
# so we have to write them here explicitly.
|
||||
compel/plugins/std.lib.a: $(compel-deps) .FORCE
|
||||
$(Q) $(MAKE) $(build)=compel/plugins $@
|
||||
|
||||
compel/plugins/shmem.lib.a: $(compel-deps) compel/plugins/std.lib.a .FORCE
|
||||
$(Q) $(MAKE) $(build)=compel/plugins $@
|
||||
|
||||
compel/plugins/fds.lib.a: $(compel-deps) compel/plugins/std.lib.a .FORCE
|
||||
$(Q) $(MAKE) $(build)=compel/plugins $@
|
||||
|
||||
compel/compel: compel/built-in.o compel/$(LIBCOMPEL_A) | $(compel-deps)
|
||||
$(call msg-link, $@)
|
||||
$(Q) $(CC) $(CFLAGS) $^ $(WRAPFLAGS) $(LDFLAGS) -rdynamic -o $@
|
||||
|
||||
#
|
||||
# And compel library.
|
||||
LIBCOMPEL_SO_CFLAGS += $(CFLAGS) -rdynamic -Wl,-soname,$(LIBCOMPEL_SO).$(COMPEL_SO_VERSION_MAJOR)
|
||||
compel/$(LIBCOMPEL_SO): compel/$(LIBCOMPEL_A)
|
||||
$(call msg-link, $@)
|
||||
$(Q) $(CC) -shared $(LIBCOMPEL_SO_CFLAGS) -o $@ -Wl,--whole-archive $^ -Wl,--no-whole-archive $(LDFLAGS)
|
||||
|
||||
compel-install-targets += compel/$(LIBCOMPEL_SO)
|
||||
compel-install-targets += compel/compel
|
||||
compel-install-targets += $(compel-plugins)
|
||||
111
Makefile.config
111
Makefile.config
|
|
@ -1,16 +1,10 @@
|
|||
include $(__nmk_dir)utils.mk
|
||||
include $(__nmk_dir)msg.mk
|
||||
include scripts/feature-tests.mak
|
||||
|
||||
# This is a kludge for $(info ...) to not eat spaces.
|
||||
S :=
|
||||
include $(SRC_DIR)/scripts/feature-tests.mak
|
||||
|
||||
ifeq ($(call try-cc,$(FEATURE_TEST_LIBBSD_DEV),-lbsd),true)
|
||||
LIBS_FEATURES += -lbsd
|
||||
FEATURE_DEFINES += -DCONFIG_HAS_LIBBSD
|
||||
else
|
||||
$(info Note: Building without setproctitle() support.)
|
||||
$(info $S Install libbsd-devel (RPM) / libbsd-dev (DEB) to fix.)
|
||||
endif
|
||||
|
||||
ifeq ($(call pkg-config-check,libselinux),y)
|
||||
|
|
@ -18,107 +12,44 @@ ifeq ($(call pkg-config-check,libselinux),y)
|
|||
FEATURE_DEFINES += -DCONFIG_HAS_SELINUX
|
||||
endif
|
||||
|
||||
ifeq ($(call pkg-config-check,libbpf),y)
|
||||
LIBS_FEATURES += -lbpf
|
||||
FEATURE_DEFINES += -DCONFIG_HAS_LIBBPF
|
||||
export CONFIG_HAS_LIBBPF := y
|
||||
endif
|
||||
|
||||
ifeq ($(call pkg-config-check,libdrm),y)
|
||||
export CONFIG_AMDGPU := y
|
||||
LIBDRM_CFLAGS := $(shell $(PKG_CONFIG) --cflags libdrm)
|
||||
ifeq ($(call try-cc,$(FEATURE_TEST_DRM_COLOR_CTM_3X4),,$(LIBDRM_CFLAGS)),true)
|
||||
export CONFIG_HAS_DRM_COLOR_CTM_3X4 := y
|
||||
FEATURE_DEFINES += -DHAVE_DRM_COLOR_CTM_3X4
|
||||
endif
|
||||
$(info Note: Building with amdgpu_plugin.)
|
||||
else
|
||||
$(info Note: Building without amdgpu_plugin.)
|
||||
$(info $S Install libdrm-devel (RPM) or libdrm-dev (DEB) to fix.)
|
||||
endif
|
||||
|
||||
ifeq ($(NO_GNUTLS)x$(call pkg-config-check,gnutls),xy)
|
||||
LIBS_FEATURES += -lgnutls
|
||||
export CONFIG_GNUTLS := y
|
||||
FEATURE_DEFINES += -DCONFIG_GNUTLS
|
||||
else
|
||||
$(info Note: Building without GnuTLS support.)
|
||||
$(info $S Install gnutls-devel (RPM) or gnutls-dev (DEB) to fix.)
|
||||
endif
|
||||
|
||||
ifeq ($(NO_LZ4)x$(call pkg-config-check,liblz4),xy)
|
||||
LIBS_FEATURES += -llz4
|
||||
export CONFIG_LZ4 := y
|
||||
FEATURE_DEFINES += -DCONFIG_LZ4
|
||||
else
|
||||
$(info Note: Building without LZ4 compression support.)
|
||||
endif
|
||||
|
||||
ifeq ($(call pkg-config-check,libnftables),y)
|
||||
LIB_NFTABLES := $(shell $(PKG_CONFIG) --libs libnftables)
|
||||
ifeq ($(call try-cc,$(FEATURE_TEST_NFTABLES_LIB_API_0),$(LIB_NFTABLES)),true)
|
||||
LIBS_FEATURES += $(LIB_NFTABLES)
|
||||
FEATURE_DEFINES += -DCONFIG_HAS_NFTABLES_LIB_API_0
|
||||
else ifeq ($(call try-cc,$(FEATURE_TEST_NFTABLES_LIB_API_1),$(LIB_NFTABLES)),true)
|
||||
LIBS_FEATURES += $(LIB_NFTABLES)
|
||||
FEATURE_DEFINES += -DCONFIG_HAS_NFTABLES_LIB_API_1
|
||||
else
|
||||
$(info Warn: Building without nftables support (incompatible API version).)
|
||||
endif
|
||||
else
|
||||
$(info Warn: Building without nftables support.)
|
||||
$(info $S Install nftables-devel (RPM) or libnftables-dev (DEB) to fix.)
|
||||
endif
|
||||
|
||||
export LIBS += $(LIBS_FEATURES)
|
||||
|
||||
ifneq ($(PLUGINDIR),)
|
||||
FEATURE_DEFINES += -DCR_PLUGIN_DEFAULT="\"$(PLUGINDIR)\""
|
||||
endif
|
||||
|
||||
CONFIG_FILE = .config
|
||||
CONFIG_FILE = $(SRC_DIR)/.config
|
||||
|
||||
$(CONFIG_FILE):
|
||||
touch $(CONFIG_FILE)
|
||||
|
||||
ifeq ($(ARCH),x86)
|
||||
# CONFIG_COMPAT is only for x86 now, no need for compile-test other archs
|
||||
ifeq ($(call try-asm,$(FEATURE_TEST_X86_COMPAT)),true)
|
||||
export CONFIG_COMPAT := y
|
||||
FEATURE_DEFINES += -DCONFIG_COMPAT
|
||||
else
|
||||
$(info Note: Building without ia32 C/R, missing ia32 support in gcc.)
|
||||
$(info $S It may be related to missing gcc-multilib in your)
|
||||
$(info $S distribution, or you may have Debian with buggy toolchain.)
|
||||
$(info $S See https://github.com/checkpoint-restore/criu/issues/315.)
|
||||
endif
|
||||
endif
|
||||
|
||||
export DEFINES += $(FEATURE_DEFINES)
|
||||
export CFLAGS += $(FEATURE_DEFINES)
|
||||
|
||||
FEATURES_LIST := TCP_REPAIR PTRACE_PEEKSIGINFO \
|
||||
SETPROCTITLE_INIT TCP_REPAIR_WINDOW MEMFD_CREATE \
|
||||
OPENAT2 NO_LIBC_RSEQ_DEFS
|
||||
FEATURES_LIST := TCP_REPAIR STRLCPY STRLCAT PTRACE_PEEKSIGINFO \
|
||||
SETPROCTITLE_INIT MEMFD TCP_REPAIR_WINDOW
|
||||
|
||||
# $1 - config name
|
||||
define gen-feature-test
|
||||
ifeq ($$(call try-cc,$$(FEATURE_TEST_$(1)),$$(LIBS_FEATURES),$$(DEFINES)),true)
|
||||
$(Q) echo '#define CONFIG_HAS_$(1)' >> $$@
|
||||
else
|
||||
$(Q) echo '// CONFIG_HAS_$(1) is not set' >> $$@
|
||||
$(Q) @echo '#define CONFIG_HAS_$(1)' >> $$@
|
||||
$(Q) @echo '' >> $$@
|
||||
endif
|
||||
endef
|
||||
|
||||
define config-header-rule
|
||||
$(CONFIG_HEADER): scripts/feature-tests.mak $(CONFIG_FILE)
|
||||
$(call msg-gen, $$@)
|
||||
$(Q) echo '#ifndef __CR_CONFIG_H__' > $$@
|
||||
$(Q) echo '#define __CR_CONFIG_H__' >> $$@
|
||||
$(Q) echo '' >> $$@
|
||||
$(CONFIG_HEADER): $(SRC_DIR)/scripts/feature-tests.mak $(CONFIG_FILE)
|
||||
$$(call msg-gen, $$@)
|
||||
$(Q) @echo '#ifndef __CR_CONFIG_H__' > $$@
|
||||
$(Q) @echo '#define __CR_CONFIG_H__' >> $$@
|
||||
$(Q) @echo '' >> $$@
|
||||
$(call map,gen-feature-test,$(FEATURES_LIST))
|
||||
$(Q) cat $(CONFIG_FILE) | sed -n -e '/^[^#]/s/^/#define CONFIG_/p' >> $$@
|
||||
$(Q) echo '#endif /* __CR_CONFIG_H__ */' >> $$@
|
||||
$(Q) @cat $(CONFIG_FILE) | sed -n -e '/^[^#]/s/^/#define CONFIG_/p' >> $$@
|
||||
ifeq ($$(VDSO),y)
|
||||
$(Q) @echo '#define CONFIG_VDSO' >> $$@
|
||||
$(Q) @echo '' >> $$@
|
||||
endif
|
||||
ifeq ($$(piegen-y),y)
|
||||
$(Q) @echo '#define CONFIG_PIEGEN' >> $$@
|
||||
$(Q) @echo '' >> $$@
|
||||
endif
|
||||
$(Q) @echo '#endif /* __CR_CONFIG_H__ */' >> $$@
|
||||
endef
|
||||
|
||||
$(eval $(config-header-rule))
|
||||
|
|
|
|||
|
|
@ -1,60 +1,28 @@
|
|||
#
|
||||
# Installation paths.
|
||||
PREFIX ?= /usr/local
|
||||
BINDIR ?= $(PREFIX)/bin
|
||||
SBINDIR ?= $(PREFIX)/sbin
|
||||
MANDIR ?= $(PREFIX)/share/man
|
||||
INCLUDEDIR ?= $(PREFIX)/include
|
||||
LIBEXECDIR ?= $(PREFIX)/libexec
|
||||
RUNDIR ?= /run
|
||||
PLUGINDIR ?= $(PREFIX)/lib/criu
|
||||
PREFIX := /usr/local
|
||||
BINDIR := $(PREFIX)/bin
|
||||
SBINDIR := $(PREFIX)/sbin
|
||||
MANDIR := $(PREFIX)/share/man
|
||||
LIBDIR := $(PREFIX)/lib
|
||||
INCLUDEDIR := $(PREFIX)/include
|
||||
LIBEXECDIR := $(PREFIX)/libexec
|
||||
|
||||
#
|
||||
# For recent Debian/Ubuntu with multiarch support.
|
||||
DEB_HOST_MULTIARCH := $(shell dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null)
|
||||
ifneq "$(DEB_HOST_MULTIARCH)" ""
|
||||
LIBDIR ?= $(PREFIX)/lib/$(DEB_HOST_MULTIARCH)
|
||||
LIBDIR := $(PREFIX)/lib/$(DEB_HOST_MULTIARCH)
|
||||
else
|
||||
#
|
||||
# For most other systems
|
||||
ifeq "$(shell uname -m)" "x86_64"
|
||||
LIBDIR ?= $(PREFIX)/lib64
|
||||
LIBDIR := $(PREFIX)/lib64
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# LIBDIR falls back to the standard path.
|
||||
LIBDIR ?= $(PREFIX)/lib
|
||||
|
||||
export PREFIX BINDIR SBINDIR MANDIR RUNDIR
|
||||
export LIBDIR INCLUDEDIR LIBEXECDIR PLUGINDIR
|
||||
|
||||
# Detect externally managed Python environment (PEP 668).
|
||||
PYTHON_EXTERNALLY_MANAGED := $(shell $(PYTHON) -c 'import os, sysconfig; print(int(os.path.isfile(os.path.join(sysconfig.get_path("stdlib"), "EXTERNALLY-MANAGED"))))')
|
||||
PIP_BREAK_SYSTEM_PACKAGES ?= 0
|
||||
|
||||
# If Python environment is externally managed and PIP_BREAK_SYSTEM_PACKAGES is not set, skip pip install.
|
||||
SKIP_PIP_INSTALL := 0
|
||||
ifeq ($(PYTHON_EXTERNALLY_MANAGED),1)
|
||||
ifeq ($(PIP_BREAK_SYSTEM_PACKAGES),0)
|
||||
|
||||
SKIP_PIP_INSTALL := 1
|
||||
$(info Warn: Externally managed python environment)
|
||||
$(info Consider using PIP_BREAK_SYSTEM_PACKAGES=1)
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
# Default flags for pip install:
|
||||
# --ignore-installed: Overwrite already installed pycriu/crit packages
|
||||
# --no-build-isolation: Use current Python environment to build pycriu/crit packages
|
||||
# --no-deps: Don't install any dependencies
|
||||
# --no-index: Don't use PyPI index to find packages
|
||||
# --progress-bar: Cleaner output
|
||||
# --upgrade: Treat the install as an upgrade when replacing the installed version
|
||||
PIPFLAGS ?= --ignore-installed --no-build-isolation --no-deps --no-index --progress-bar off --upgrade
|
||||
|
||||
export SKIP_PIP_INSTALL PIPFLAGS
|
||||
export PREFIX BINDIR SBINDIR MANDIR
|
||||
export LIBDIR INCLUDEDIR LIBEXECDIR
|
||||
|
||||
install-man:
|
||||
$(Q) $(MAKE) -C Documentation install
|
||||
|
|
@ -64,37 +32,16 @@ install-lib: lib
|
|||
$(Q) $(MAKE) $(build)=lib install
|
||||
.PHONY: install-lib
|
||||
|
||||
install-crit: lib
|
||||
$(Q) $(MAKE) $(build)=crit install
|
||||
.PHONY: install-crit
|
||||
|
||||
install-criu: criu
|
||||
$(Q) $(MAKE) $(build)=criu install
|
||||
.PHONY: install-criu
|
||||
|
||||
install-amdgpu_plugin: amdgpu_plugin
|
||||
$(Q) $(MAKE) -C plugins/amdgpu install
|
||||
.PHONY: install-amdgpu_plugin
|
||||
|
||||
install-cuda_plugin: cuda_plugin
|
||||
$(Q) $(MAKE) -C plugins/cuda install
|
||||
.PHONY: install-cuda_plugin
|
||||
|
||||
install-compel: $(compel-install-targets)
|
||||
$(Q) $(MAKE) $(build)=compel install
|
||||
$(Q) $(MAKE) $(build)=compel/plugins install
|
||||
.PHONY: install-compel
|
||||
|
||||
install: install-man install-lib install-crit install-criu install-compel install-amdgpu_plugin install-cuda_plugin ;
|
||||
install: install-man install-lib install-criu
|
||||
@true
|
||||
.PHONY: install
|
||||
|
||||
uninstall:
|
||||
$(Q) $(MAKE) -C Documentation $@
|
||||
$(Q) $(MAKE) $(build)=lib $@
|
||||
$(Q) $(MAKE) $(build)=crit $@
|
||||
$(Q) $(MAKE) $(build)=criu $@
|
||||
$(Q) $(MAKE) $(build)=compel $@
|
||||
$(Q) $(MAKE) $(build)=compel/plugins $@
|
||||
$(Q) $(MAKE) -C plugins/amdgpu $@
|
||||
$(Q) $(MAKE) -C plugins/cuda $@
|
||||
.PHONY: uninstall
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#
|
||||
# CRIU version.
|
||||
CRIU_VERSION_MAJOR := 4
|
||||
CRIU_VERSION_MINOR := 2
|
||||
CRIU_VERSION_MAJOR := 2
|
||||
CRIU_VERSION_MINOR := 12
|
||||
CRIU_VERSION_SUBLEVEL :=
|
||||
CRIU_VERSION_EXTRA :=
|
||||
CRIU_VERSION_NAME := CRIUTIBILITY
|
||||
CRIU_VERSION_NAME := Vulcanite Rook
|
||||
CRIU_VERSION := $(CRIU_VERSION_MAJOR)$(if $(CRIU_VERSION_MINOR),.$(CRIU_VERSION_MINOR))$(if $(CRIU_VERSION_SUBLEVEL),.$(CRIU_VERSION_SUBLEVEL))$(if $(CRIU_VERSION_EXTRA),.$(CRIU_VERSION_EXTRA))
|
||||
|
||||
export CRIU_VERSION_MAJOR CRIU_VERSION_MINOR CRIU_VERSION_SUBLEVEL
|
||||
|
|
@ -12,7 +12,7 @@ export CRIU_VERSION_EXTRA CRIU_VERSION_NAME CRIU_VERSION
|
|||
|
||||
#
|
||||
# C library for CRIU.
|
||||
CRIU_SO_VERSION_MAJOR := 2
|
||||
CRIU_SO_VERSION_MAJOR := 1
|
||||
CRIU_SO_VERSION_MINOR := 0
|
||||
|
||||
export CRIU_SO_VERSION_MAJOR CRIU_SO_VERSION_MINOR
|
||||
|
|
@ -23,9 +23,3 @@ SOCCR_SO_VERSION_MAJOR := 1
|
|||
SOCCR_SO_VERSION_MINOR := 0
|
||||
|
||||
export SOCCR_SO_VERSION_MAJOR SOCCR_SO_VERSION_MINOR
|
||||
|
||||
COMPEL_SO_VERSION_MAJOR := 1
|
||||
COMPEL_SO_VERSION_MINOR := 0
|
||||
COMPEL_SO_VERSION_SUBLEVEL := 0
|
||||
|
||||
export COMPEL_SO_VERSION_MAJOR COMPEL_SO_VERSION_MINOR COMPEL_SO_VERSION_SUBLEVEL
|
||||
|
|
|
|||
77
README.md
77
README.md
|
|
@ -1,71 +1,24 @@
|
|||
[](
|
||||
https://github.com/checkpoint-restore/criu/actions/workflows/ci.yml)
|
||||
[](
|
||||
https://circleci.com/gh/checkpoint-restore/criu)
|
||||
## CRIU (Checkpoint and Restore in Userspace)
|
||||
|
||||
<p align="center"><img src="Documentation/logo.svg" width="256px"/></p>
|
||||
|
||||
## CRIU -- A project to implement checkpoint/restore functionality for Linux
|
||||
|
||||
CRIU (stands for Checkpoint and Restore in Userspace) is a utility to checkpoint/restore Linux tasks.
|
||||
|
||||
Using this tool, you can freeze a running application (or part of it) and checkpoint
|
||||
it to a hard drive as a collection of files. You can then use the files to restore and run the
|
||||
An utility to checkpoint/restore tasks. Using this tool, you can freeze a
|
||||
running application (or part of it) and checkpoint it to a hard drive as a
|
||||
collection of files. You can then use the files to restore and run the
|
||||
application from the point it was frozen at. The distinctive feature of the CRIU
|
||||
project is that it is mainly implemented in user space. There are some more projects
|
||||
doing C/R for Linux, and so far CRIU [appears to be](https://criu.org/Comparison_to_other_CR_projects)
|
||||
the most feature-rich and up-to-date with the kernel.
|
||||
project is that it is mainly implemented in user space.
|
||||
|
||||
CRIU project is (almost) the never-ending story, because we have to always keep up with the
|
||||
Linux kernel supporting checkpoint and restore for all the features it provides. Thus we're
|
||||
looking for contributors of all kinds -- feedback, bug reports, testing, coding, writing, etc.
|
||||
Please refer to [CONTRIBUTING.md](CONTRIBUTING.md) if you would like to get involved.
|
||||
The project home is at http://criu.org.
|
||||
|
||||
The project [started](https://criu.org/History) as the way to do live migration for OpenVZ
|
||||
Linux containers, but later grew to more sophisticated and flexible tool. It is currently
|
||||
used by (integrated into) OpenVZ, LXC/LXD, Docker, and other software, project gets tremendous
|
||||
help from the community, and its packages are included into many Linux distributions.
|
||||
|
||||
The project home is at http://criu.org. This wiki contains all the knowledge base for CRIU we have.
|
||||
Pages worth starting with are:
|
||||
- [Installation instructions](http://criu.org/Installation)
|
||||
- [Kernel configuration, compilation, etc](http://criu.org/Installation)
|
||||
- [A simple example of usage](http://criu.org/Simple_loop)
|
||||
- [Examples of more advanced usage](https://criu.org/Category:HOWTO)
|
||||
- Troubleshooting can be hard, some help can be found [here](https://criu.org/When_C/R_fails), [here](https://criu.org/What_cannot_be_checkpointed) and [here](https://criu.org/index.php?title=FAQ)
|
||||
- [More sophisticated example with graphical app](http://criu.org/VNC)
|
||||
|
||||
### Checkpoint and restore of simple loop process
|
||||
<p align="center"><a href="https://asciinema.org/a/232445"><img src="https://asciinema.org/a/232445.png" width="572px" height="412px"/></a></p>
|
||||
### A video tour on basic CRIU features
|
||||
[](https://asciinema.org/a/7fnt2prsumvxiwf3ng61fgct3)
|
||||
|
||||
## Advanced features
|
||||
### How to contribute
|
||||
|
||||
As main usage for CRIU is live migration, there's a library for it called P.Haul. Also the
|
||||
project exposes two cool core features as standalone libraries. These are libcompel for parasite code
|
||||
injection and libsoccr for TCP connections checkpoint-restore.
|
||||
|
||||
### Live migration
|
||||
|
||||
True [live migration](https://criu.org/Live_migration) using CRIU is possible, but doing
|
||||
all the steps by hands might be complicated. The [phaul sub-project](https://criu.org/P.Haul)
|
||||
provides a Go library that encapsulates most of the complexity. This library and the Go bindings
|
||||
for CRIU are stored in the [go-criu](https://github.com/checkpoint-restore/go-criu) repository.
|
||||
|
||||
|
||||
### Parasite code injection
|
||||
|
||||
In order to get state of the running process CRIU needs to make this process execute
|
||||
some code, that would fetch the required information. To make this happen without
|
||||
killing the application itself, CRIU uses the [parasite code injection](https://criu.org/Parasite_code)
|
||||
technique, which is also available as a standalone library called [libcompel](https://criu.org/Compel).
|
||||
|
||||
### TCP sockets checkpoint-restore
|
||||
|
||||
One of the CRIU features is the ability to save and restore state of a TCP socket
|
||||
without breaking the connection. This functionality is considered to be useful by
|
||||
itself, and we have it available as the [libsoccr library](https://criu.org/Libsoccr).
|
||||
|
||||
## Licence
|
||||
|
||||
The project is licensed under GPLv2 (though files sitting in the lib/ directory are LGPLv2.1).
|
||||
|
||||
All files in the images/ directory are licensed under the Expat license (so-called MIT).
|
||||
See the images/LICENSE file.
|
||||
* [How to submit patches](http://criu.org/How_to_submit_patches);
|
||||
* Send all bug reports to [mailing
|
||||
list](https://lists.openvz.org/mailman/listinfo/criu);
|
||||
* Spread the word about CRIU in [social networks](http://criu.org/Contacts);
|
||||
|
|
|
|||
17
compel/.gitignore
vendored
17
compel/.gitignore
vendored
|
|
@ -1,17 +0,0 @@
|
|||
arch/x86/plugins/std/sys-exec-tbl-64.c
|
||||
arch/x86/plugins/std/syscalls-64.S
|
||||
arch/arm/plugins/std/syscalls/syscalls.S
|
||||
arch/aarch64/plugins/std/syscalls/syscalls.S
|
||||
arch/s390/plugins/std/syscalls/syscalls.S
|
||||
arch/ppc64/plugins/std/syscalls/syscalls.S
|
||||
arch/mips/plugins/std/syscalls/syscalls-64.S
|
||||
arch/loongarch64/plugins/std/syscalls/syscalls-64.S
|
||||
arch/riscv64/plugins/std/syscalls/syscalls.S
|
||||
include/version.h
|
||||
plugins/include/uapi/std/asm/syscall-types.h
|
||||
plugins/include/uapi/std/syscall-64.h
|
||||
plugins/include/uapi/std/syscall-codes-64.h
|
||||
plugins/include/uapi/std/syscall-codes.h
|
||||
plugins/include/uapi/std/syscall.h
|
||||
plugins/include/uapi/std/syscall-aux.h
|
||||
plugins/include/uapi/std/syscall-aux.S
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue