Snapper 2.0 (or just Snapper) is a snapshot mechanism for the virtual memory space of the persistent operating system PhantomOS. It uses the a logging file system (e.g. ext4) to ensure that file operations (e.g. modification or deletion) are resistant to OS crashes mid-way through the operation.
A vital property of Snapper is that it needs to be disk space efficient in order not to bloat the file system. This is done by utilizing a mapping from the virtual pages (from now on referred only as pages) to a file containing their contents. Thus if a page remains unchanged its contents will still be mapped to a file from a previous snapshot, hence no new file needs to be created.
- Genode + Goa
- Lwext4 Plugin (optional)
Install the requirements. This pre-built container image comes with all the dependencies needed for Genode:
git clone -b sculpt-25.04 https://github.com/genodelabs/genode.git
git clone https://github.com/genodelabs/goa.git genode/goa
git clone --depth 1 https://github.com/rumenmitov/snapper genode/repos/snapper
# If you want to use ext4 for the file-system:
git clone -b 25.05-2025-07-07 --depth 1 https://codeberg.org/jws/genode-wundertuete.git genode/repos/wundertuete
# Start the container
podman run -d --name genode --cap-add SYS_PTRACE -v $PWD/genode:/genode -w /genode docker.io/rmitov/genode:25.05 tail -f /dev/nullFollow the following steps inside the container.
❗ Make sure to setup Genode’s build directory before continuing! ❗
Add the following to <genode>/build/x86_64/etc/build.conf:
REPOSITORIES += $(GENODE_DIR)/repos/wundertuete # optional REPOSITORIES += $(GENODE_DIR)/repos/snapper
# You may need to run this command twice, if it fails the first time.
goa update-goa 25.04 || (echo "Could not update goa to required version!" && exit 1)
/genode/tool/ports/prepare_port lwext4
DEPOT_DIR=/genode/repos/snapper/var/depot goa depot-dir
DEPOT_DIR=/genode/repos/snapper/var/depot FORCE_VERSION=2025-07-09 /genode/tool/depot/create rumen/bin/x86_64/vfs_lwext4
mkdir /genode/repos/snapper/raw
# NOTE: seek=16 will make the file only 16MB. If you want to run larger workloads increase this number.
dd if=/dev/zero of=/genode/repos/snapper/raw/snapper_block.raw bs=1M seek=16 count=0
mkfs.ext4 -O^metadata_csum -F /genode/repos/snapper/raw/snapper_block.rawIf you are using the container, the following should be run inside the container.
NOTE The runtime file pkg/snapper/runtime is made to persist changes made to the block storage during the execution of the program. pkg/snapper itself does not make any changes; the runtime file exists for potential future debugging purposes.
For a non-persistent runtime, see pkg/snappertests/runtime.
cd /genode/repos/snapper
goa run --pkg snapperThis will run the main Snapper binary. If instead you want to run the tests:
goa run --pkg snappertests
To specify the number of snapshot objects that should be in the test simulation (TESTS defaults to 1000):
TESTS=50 goa run --pkg snappertests
cd /genode
make -C build/x86_64 run/snapper KERNEL=linux BOARD=linuxOr, to run the tests:
make -C build/x86_64 run/snappertests KERNEL=linux BOARD=linux
To (optionally) specify how many test objects to create (see Running With Goa for more details):
TESTS=50 make -C build/x86_64 run/snappertests KERNEL=linux BOARD=linux
NOTE: On subsequent runs, if you want to change
TESTS, you have torm -rf /genode/build/x86_64/test/snapper/before running.
The Snapper library is available for most run scripts and Goa projects. First run:
./<genode-dir>/depot/tool/extract rumen/src/snap
- For run scripts just add
lib/snapto the build artifacts. - For Goa, add
rumen/api/snap/2025-08-05to the archives file.
To run benchmarks on Snapper, see pkg/snapperbench/README.org.
Snapper should be configurable through Genode’s XML. The configuration options are stored inSnapper::Config:
| OPTION | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
| verbose | bool | false | Whether to print verbose output. |
| threshold | unsigned int | 100 | The maximum number of files in a snapshot sub-directory. |
| integrity | bool | true | If true, crash the system on failed integrity checks, |
| otherwise log a warning. | |||
| redundancy | unsigned int | 3 | After reaching this reference count, a redundant file |
| copy will be created for subsequent snapshot. | |||
| max_snapshots | unsigned int | 0 | The maximum number of complete snapshots inside |
| <snapper-root>. | |||
| min_snapshots | unsigned int | 0 | The minimum number of generations that need to be present |
| for a purge to be possible. | |||
| expiration | unsigned int | 0 | How many seconds a generation should be kept. |
| (seconds) | |||
| bufsize | size_t | 1024 * 1024 | The size of the dataspace which will transfer the payload |
| (bytes) | to the snapper component. |
