|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +systemd-swap is a dynamic swap management daemon for Linux, written in Rust. It automatically configures optimal swap strategies based on the system's filesystem and requirements, managing zswap, zram, and dynamic swap files (SwapFC). |
| 8 | + |
| 9 | +The project replaces a previous Python implementation with a lightweight (~250 KB) Rust binary that provides: |
| 10 | +- Auto-detection of optimal swap strategy based on filesystem type |
| 11 | +- Zswap (compressed RAM cache) + SwapFC (dynamic swap files) |
| 12 | +- Zram (compressed block device in RAM) with optional writeback to disk |
| 13 | +- Multi-filesystem support: btrfs, ext4, xfs |
| 14 | + |
| 15 | +## Building and Testing |
| 16 | + |
| 17 | +```bash |
| 18 | +# Build the project (requires Rust 1.70+) |
| 19 | +cargo build --release |
| 20 | + |
| 21 | +# Install to system (requires root) |
| 22 | +sudo make install |
| 23 | + |
| 24 | +# Enable and start the service |
| 25 | +sudo systemctl enable --now systemd-swap |
| 26 | + |
| 27 | +# Check service status |
| 28 | +systemctl status systemd-swap |
| 29 | + |
| 30 | +# View detailed swap status (with extra stats as root) |
| 31 | +systemd-swap status |
| 32 | + |
| 33 | +# View logs |
| 34 | +journalctl -u systemd-swap -f |
| 35 | +``` |
| 36 | + |
| 37 | +## Build for Arch Linux/BigLinux |
| 38 | + |
| 39 | +```bash |
| 40 | +cd pkgbuild |
| 41 | +makepkg -si |
| 42 | +``` |
| 43 | + |
| 44 | +## Architecture |
| 45 | + |
| 46 | +### Swap Modes |
| 47 | + |
| 48 | +The daemon operates in one of several modes (auto-detected or manually configured): |
| 49 | + |
| 50 | +1. **auto** (default): Detects filesystem and chooses optimal strategy |
| 51 | + - btrfs/ext4/xfs → zswap+swapfc |
| 52 | + - other filesystems → zram only |
| 53 | + |
| 54 | +2. **zswap+swapfc**: Zswap compresses pages in RAM, SwapFC provides backing swap files |
| 55 | + - Default for btrfs/ext4/xfs systems |
| 56 | + - Zswap shrinker proactively moves cold pages to disk |
| 57 | + - Best desktop performance with efficient memory usage |
| 58 | + |
| 59 | +3. **zram+swapfc**: Zram as primary compressed swap with swap files for overflow |
| 60 | + - Optional zram writeback moves idle pages to disk |
| 61 | + |
| 62 | +4. **zram**: Zram-only mode (no disk swap) |
| 63 | + |
| 64 | +5. **manual**: Explicit configuration via config file flags |
| 65 | + |
| 66 | +### Core Components |
| 67 | + |
| 68 | +**src/main.rs** (479 lines) |
| 69 | +- Entry point with CLI parsing (start/stop/status commands) |
| 70 | +- Swap mode selection logic based on filesystem detection |
| 71 | +- Main daemon loop orchestrating zswap/zram/swapfc |
| 72 | +- Signal handling for graceful shutdown |
| 73 | + |
| 74 | +**src/config.rs** (172 lines) |
| 75 | +- Configuration parser supporting hierarchical config files: |
| 76 | + - `/usr/share/systemd-swap/swap-default.conf` (defaults) |
| 77 | + - `/etc/systemd/swap.conf` (user overrides) |
| 78 | + - `{/usr/lib,/run,/etc}/systemd/swap.conf.d/*.conf` (fragments) |
| 79 | +- Shell variable expansion in config values |
| 80 | +- Type-safe getters for configuration values |
| 81 | + |
| 82 | +**src/swapfc.rs** (558 lines) |
| 83 | +- Dynamic swap file management |
| 84 | +- Creates/removes swap files based on memory pressure |
| 85 | +- Supports both pre-allocated (fallocate) and sparse files |
| 86 | +- Btrfs-specific: subvolume setup, compression mode support |
| 87 | +- Auto-detects filesystem type and validates support (btrfs/ext4/xfs) |
| 88 | + |
| 89 | +**src/zswap.rs** (265 lines) |
| 90 | +- Zswap configuration via `/sys/module/zswap/parameters` |
| 91 | +- Parameter backup/restore on daemon stop |
| 92 | +- Status reporting with debugfs statistics (pool size, compression ratio, etc.) |
| 93 | + |
| 94 | +**src/zram.rs** (380 lines) |
| 95 | +- Zram device creation and configuration |
| 96 | +- Writeback support (CONFIG_ZRAM_WRITEBACK kernel feature) |
| 97 | +- Auto-creation of loop devices for writeback when no partition specified |
| 98 | +- Size parsing: absolute (1G, 512M) or percentage (50%, 100%) |
| 99 | + |
| 100 | +**src/systemd.rs** (145 lines) |
| 101 | +- Systemd integration: sd_notify, swap unit generation |
| 102 | +- Swap unit management via systemctl |
| 103 | + |
| 104 | +**src/meminfo.rs** (300 lines) |
| 105 | +- Memory statistics parsing from `/proc/meminfo` |
| 106 | +- CPU count, RAM size, free RAM/swap percentage calculations |
| 107 | +- Page size detection |
| 108 | + |
| 109 | +**src/helpers.rs** (148 lines) |
| 110 | +- Common utilities: file I/O, directory creation, command execution |
| 111 | +- Root privilege checking |
| 112 | + |
| 113 | +**src/pre-systemd-swap** (124 lines, bash) |
| 114 | +- Pre-service script run before main daemon |
| 115 | +- Btrfs subvolume setup for swap files |
| 116 | +- Disables existing swap partitions |
| 117 | +- Adds fstab entries for swap subvolumes |
| 118 | + |
| 119 | +### Configuration Flow |
| 120 | + |
| 121 | +1. Load defaults from `/usr/share/systemd-swap/swap-default.conf` |
| 122 | +2. Override with `/etc/systemd/swap.conf` |
| 123 | +3. Apply fragments from conf.d directories (etc > run > lib precedence) |
| 124 | +4. Expand shell variables in values |
| 125 | + |
| 126 | +### Filesystem Detection Logic |
| 127 | + |
| 128 | +- Uses `findmnt` to detect filesystem type |
| 129 | +- For swap file paths, checks both the path and its parent |
| 130 | +- Validates filesystem against `SWAPFILE_SUPPORTED_FS` (btrfs/ext4/xfs) |
| 131 | +- Falls back to zram-only for unsupported filesystems |
| 132 | + |
| 133 | +### Pre-allocated vs Sparse Files |
| 134 | + |
| 135 | +By default, SwapFC uses **pre-allocated** files via fallocate (disabled sparse): |
| 136 | +- More stable under memory pressure |
| 137 | +- Reserves disk space upfront |
| 138 | +- Set `swapfc_use_sparse=1` to enable sparse/thin provisioning |
| 139 | + |
| 140 | +### Btrfs-Specific Handling |
| 141 | + |
| 142 | +- Automatically creates `@swapfc` subvolume on btrfs root |
| 143 | +- Optional compression mode: creates loop device over file on compressed subvolume |
| 144 | +- Disables CoW (copy-on-write) for swap files |
| 145 | + |
| 146 | +## File Locations |
| 147 | + |
| 148 | +| Path | Description | |
| 149 | +|------|-------------| |
| 150 | +| `/usr/bin/systemd-swap` | Main Rust binary | |
| 151 | +| `/usr/bin/pre-systemd-swap` | Bash pre-setup script | |
| 152 | +| `/etc/systemd/swap.conf` | User configuration | |
| 153 | +| `/usr/share/systemd-swap/swap-default.conf` | Default configuration | |
| 154 | +| `/run/systemd/swap/` | Runtime state directory | |
| 155 | +| `/swapfc/` | Default swap file location | |
| 156 | +| `/usr/lib/systemd/system/systemd-swap.service` | Main systemd unit | |
| 157 | +| `/usr/lib/systemd/system/pre-systemd-swap.service` | Pre-setup systemd unit | |
| 158 | + |
| 159 | +## Key Configuration Parameters |
| 160 | + |
| 161 | +**swap_mode**: auto | zswap+swapfc | zram+swapfc | zram | manual |
| 162 | + |
| 163 | +**Zswap (for zswap+swapfc mode)**: |
| 164 | +- `zswap_compressor`: zstd (default), lzo, lz4, lzo-rle, lz4hc |
| 165 | +- `zswap_max_pool_percent`: Max RAM % for pool (default: 45) |
| 166 | +- `zswap_shrinker_enabled`: Proactive writeback (default: 1) |
| 167 | + |
| 168 | +**Zram (for zram modes)**: |
| 169 | +- `zram_size`: 1G, 512M, 50%, 100% (default: 80%) |
| 170 | +- `zram_alg`: Compression algorithm (default: zstd) |
| 171 | +- `zram_writeback`: Enable writeback to disk (default: 0) |
| 172 | + |
| 173 | +**SwapFC**: |
| 174 | +- `swapfc_chunk_size`: Per-file size, e.g., 512M, 10% of RAM |
| 175 | +- `swapfc_path`: Location for swap files (default: /swapfc/swapfile) |
| 176 | +- `swapfc_free_ram_perc`: Trigger creation when free RAM < % (default: 35) |
| 177 | +- `swapfc_use_sparse`: Enable sparse files (default: 0) |
| 178 | + |
| 179 | +## Dependencies |
| 180 | + |
| 181 | +- Rust 1.70+ (build time) |
| 182 | +- `libsystemd` (for sd_notify integration) |
| 183 | +- `btrfs-progs` (for btrfs features) |
| 184 | +- `util-linux` (zramctl, losetup, findmnt) |
| 185 | + |
| 186 | +## Testing Configuration Changes |
| 187 | + |
| 188 | +After modifying `/etc/systemd/swap.conf`: |
| 189 | + |
| 190 | +```bash |
| 191 | +sudo systemctl restart systemd-swap |
| 192 | +journalctl -u systemd-swap -f |
| 193 | +systemd-swap status |
| 194 | +``` |
| 195 | + |
| 196 | +## Package Building |
| 197 | + |
| 198 | +The project uses GitHub Actions to trigger builds on push: |
| 199 | +- Webhook dispatches to BigLinux-Package-Build repositories |
| 200 | +- Builds for both x86_64 and aarch64 (ARM) |
| 201 | + |
| 202 | +## Code Style Notes |
| 203 | + |
| 204 | +- Error handling uses `thiserror` crate for typed errors |
| 205 | +- Logging via custom macros: `info!()`, `warn!()`, `error!()`, `debug!()` |
| 206 | +- Systemd integration via `libsystemd` crate |
| 207 | +- Signal handling for graceful shutdown (SIGTERM, SIGINT) |
| 208 | +- Configuration uses lazy string parsing with typed getters |
0 commit comments