criu

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:

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.

Level 2: Sub-tree (kcmp)

If two objects have identical genids, they might be the same.

Supported Object Types

CRIU uses kcmp() for various object types, including:

See also