Skip to content

Commit b8de7a0

Browse files
committed
Use default without sparse files, and add support to ext4 and xfs
1 parent fbb4111 commit b8de7a0

6 files changed

Lines changed: 320 additions & 103 deletions

File tree

.gitignore

Lines changed: 169 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,169 @@
1-
systemd-swap[_-]*
2-
swap.conf
3-
*.new
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
eggs/
15+
.eggs/
16+
parts/
17+
sdist/
18+
wheels/
19+
share/python-wheels/
20+
*.egg-info/
21+
.installed.cfg
22+
*.egg
23+
MANIFEST
24+
result
25+
26+
feedback.md
27+
VTE-llms.txt
28+
29+
# PyInstaller
30+
# Usually these files are written by a python script from a template
31+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
32+
*.manifest
33+
*.spec
34+
35+
# Installer logs
36+
pip-log.txt
37+
pip-delete-this-directory.txt
38+
39+
# Unit test / coverage reports
40+
htmlcov/
41+
.tox/
42+
.nox/
43+
.coverage
44+
.coverage.*
45+
.cache
46+
nosetests.xml
47+
coverage.xml
48+
*.cover
49+
*.py,cover
50+
.hypothesis/
51+
.pytest_cache/
52+
cover/
53+
54+
# Django stuff:
55+
*.log
56+
local_settings.py
57+
db.sqlite3
58+
db.sqlite3-journal
59+
60+
# Flask stuff:
61+
instance/
62+
.webassets-cache
63+
64+
# Scrapy stuff:
65+
.scrapy
66+
67+
# PyBuilder
68+
.pybuilder/
69+
target/
70+
71+
# Jupyter Notebook
72+
.ipynb_checkpoints
73+
74+
# IPython
75+
profile_default/
76+
ipython_config.py
77+
78+
# pyenv
79+
# For a library or package, you might want to ignore these files since the code is
80+
# intended to run in multiple environments; otherwise, check them in:
81+
# .python-version
82+
83+
# pipenv
84+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
85+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
86+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
87+
# install all needed dependencies.
88+
#Pipfile.lock
89+
90+
# UV
91+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
92+
# This is especially recommended for binary packages to ensure reproducibility, and is more
93+
# commonly ignored for libraries.
94+
#uv.lock
95+
96+
# poetry
97+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
98+
# This is especially recommended for binary packages to ensure reproducibility, and is more
99+
# commonly ignored for libraries.
100+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
101+
#poetry.lock
102+
103+
# pdm
104+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
105+
#pdm.lock
106+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
107+
# in version control.
108+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
109+
.pdm.toml
110+
.pdm-python
111+
.pdm-build/
112+
113+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
114+
__pypackages__/
115+
116+
# Celery stuff
117+
celerybeat-schedule
118+
celerybeat.pid
119+
120+
# SageMath parsed files
121+
*.sage.py
122+
123+
# Environments
124+
.env
125+
.venv
126+
env/
127+
venv/
128+
ENV/
129+
env.bak/
130+
venv.bak/
131+
.direnv/
132+
.serena
133+
134+
# Spyder project settings
135+
.spyderproject
136+
.spyproject
137+
138+
# Rope project settings
139+
.ropeproject
140+
141+
# mkdocs documentation
142+
/site
143+
144+
# mypy
145+
.mypy_cache/
146+
.dmypy.json
147+
dmypy.json
148+
149+
# Pyre type checker
150+
.pyre/
151+
152+
# pytype static type analyzer
153+
.pytype/
154+
155+
# Cython debug symbols
156+
cython_debug/
157+
158+
# PyCharm
159+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
160+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
161+
# and can be added to the global gitignore or merged into this file. For a more nuclear
162+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
163+
#.idea/
164+
165+
# Ruff stuff:
166+
.ruff_cache/
167+
168+
# PyPI configuration file
169+
.pypirc

README.md

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,28 @@ Smart dynamic swap management for Linux, written in Rust.
55
## Features
66

77
- **Auto-detection**: Automatically chooses optimal swap strategy for your filesystem
8-
- **Zswap + SwapFC**: Compressed RAM cache with dynamic btrfs swap files
8+
- **Multi-filesystem**: Supports btrfs, ext4, and xfs for swap files
9+
- **Zswap + SwapFC**: Compressed RAM cache with dynamic swap files
910
- **Zram + SwapFC**: Alternative mode with zram as primary swap
1011
- **Zram writeback**: Move idle pages from zram to disk (kernel 5.4+)
11-
- **Sparse files (thin provisioning)**: Swap files don't pre-allocate disk space
12-
- **Btrfs optimized**: Optional compression mode for swap data
12+
- **Fallback support**: Automatically falls back to zram-only if swap files fail
1313
- **Lightweight**: ~250 KB binary vs ~10 MB Python version
1414

1515
## Swap Modes
1616

1717
| Mode | Description | Best For |
1818
|------|-------------|----------|
19-
| `auto` | Auto-detect: btrfs → zswap+swapfc, other → zram | Most users |
20-
| `zswap+swapfc` | Zswap cache + dynamic swap files | **Desktop (btrfs)** |
19+
| `auto` | Auto-detect: btrfs/ext4/xfs → zswap+swapfc, other → zram | Most users |
20+
| `zswap+swapfc` | Zswap cache + dynamic swap files | **Desktop** |
2121
| `zram+swapfc` | Zram primary + swap files overflow | Memory-constrained |
22-
| `zram` | Zram only (no disk swap) | Non-btrfs systems |
22+
| `zram` | Zram only (no disk swap) | Unsupported filesystems |
2323
| `manual` | Use explicit settings | Advanced users |
2424

2525
### How Each Mode Works
2626

27-
**zswap + swapfc (default for btrfs)**:
27+
**zswap + swapfc (default for btrfs/ext4/xfs)**:
2828
- Zswap compresses pages in RAM before writing to swap
29-
- SwapFC creates swap files as sparse files (thin provisioning)
29+
- SwapFC creates pre-allocated swap files (512MB each)
3030
- Disk space is only used when zswap pool is full
3131
- Best desktop performance with efficient disk usage
3232

@@ -113,12 +113,13 @@ swap_mode=auto
113113

114114
################################################################################
115115
# Zswap (used in zswap+swapfc mode)
116+
# Modern defaults for desktop Linux (kernel 6.x+)
116117
################################################################################
117-
zswap_compressor=zstd # lzo lz4 zstd lzo-rle lz4hc
118-
zswap_max_pool_percent=45 # Max % of RAM for pool
119-
zswap_zpool=zsmalloc # Memory allocator
120-
zswap_shrinker_enabled=1 # Move cold pages to disk
121-
zswap_accept_threshold=80 # Accept threshold after pool full
118+
zswap_compressor=zstd # lzo lz4 zstd lzo-rle lz4hc (zstd = best)
119+
zswap_max_pool_percent=45 # Max % of RAM for pool (20-50 typical)
120+
zswap_zpool=zsmalloc # Memory allocator (default upstream)
121+
zswap_shrinker_enabled=1 # Evict cold pages to disk (default since 6.8)
122+
zswap_accept_threshold=90 # Accept threshold after pool full
122123

123124
################################################################################
124125
# Zram (used in zram modes)
@@ -141,12 +142,10 @@ swapfc_free_ram_perc=35 # Create when free RAM < this %
141142
swapfc_free_swap_perc=25 # Create more when free swap < this %
142143
swapfc_path=/swapfc/swapfile # Path for swap files
143144

144-
# Sparse files (thin provisioning) - ENABLED BY DEFAULT
145-
# Swap files appear full size but only allocate disk space when written.
146-
# Ideal with zswap: pages stay in RAM, disk is only used on writeback.
147-
# swapfc_use_sparse_disable=1 # Uncomment to pre-allocate disk space
145+
# Pre-allocated files (default) - more stable, no loop device needed
146+
swapfc_use_sparse=0 # 0=pre-allocate (default), 1=sparse
148147

149-
# Btrfs compression mode (experimental)
148+
# Btrfs compression mode (experimental) and need use loop device
150149
swapfc_use_btrfs_compression=0 # Double compression: zswap + btrfs
151150
```
152151

@@ -174,21 +173,22 @@ zram_writeback_dev=/dev/sda5
174173

175174
Requires kernel compiled with `CONFIG_ZRAM_WRITEBACK`.
176175

177-
## Sparse Files (Thin Provisioning)
176+
## File Allocation Mode
178177

179-
By default, swap files are created as sparse files:
178+
By default, swap files are **pre-allocated** using `fallocate`:
180179

181-
- Files appear as 512M but start with 0 bytes on disk
182-
- Disk blocks are allocated only when data is actually written
183-
- With zswap, most pages stay compressed in RAM
184-
- Disk is only used when zswap pool is full (writeback)
180+
- Files reserve 512M on disk immediately
181+
- More stable under memory pressure (no loop device needed)
182+
- Better for most desktop and server workloads
185183

186-
To disable and pre-allocate all disk space:
184+
To use sparse files (thin provisioning) instead:
187185

188186
```ini
189-
swapfc_use_sparse_disable=1
187+
swapfc_use_sparse=1
190188
```
191189

190+
Sparse mode creates files that only allocate disk space when written, but requires a loop device which can cause issues under extreme memory pressure.
191+
192192
## File Locations
193193

194194
| Path | Description |

include/swap-default.conf

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ swap_mode=auto
2323
# Requires a backing swap device (swap file or partition).
2424
################################################################################
2525

26-
zswap_compressor=zstd # lzo lz4 zstd lzo-rle lz4hc
27-
zswap_max_pool_percent=50 # Max % of RAM for compressed pool
28-
zswap_zpool=zsmalloc # Memory allocator (zsmalloc better than zbud)
29-
zswap_shrinker_enabled=0 # Proactively move cold pages to swap
26+
zswap_compressor=zstd # lzo lz4 zstd lzo-rle lz4hc (zstd = best balance)
27+
zswap_max_pool_percent=45 # Max % of RAM for compressed pool (20-50 typical)
28+
zswap_zpool=zsmalloc # Memory allocator (zsmalloc = best, default upstream)
29+
zswap_shrinker_enabled=1 # Proactively evict cold pages to disk (default since 6.8)
3030
zswap_accept_threshold=90 # Accept pages again after pool was full (%)
3131

3232
################################################################################
@@ -50,14 +50,16 @@ zram_writeback_dev= # Backing device (partition or empty for auto loop)
5050
zram_writeback_size=1G # Size of auto-created backing file
5151

5252
################################################################################
53-
# SwapFC - Dynamic swap file management (btrfs only)
53+
# SwapFC - Dynamic swap file management
54+
# Supports: btrfs, ext4, xfs (auto-detected)
5455
# Used in zram+swapfc, zswap+swapfc modes, or manual with swapfc_enabled=1
5556
#
56-
# Creates swap files on-demand as memory pressure increases
57+
# Creates swap files on-demand as memory pressure increases.
58+
# If swap file creation fails, automatically falls back to zram-only mode.
5759
################################################################################
5860

5961
# swapfc_chunk_size supports: 1G, 512M, 10% (percentage of RAM)
60-
swapfc_chunk_size=20% # Size of each swap file
62+
swapfc_chunk_size=512M # Size of each swap file (512M = good balance)
6163
swapfc_max_count=32 # Maximum number of swap files
6264
swapfc_min_count=1 # Minimum (1 for zswap backing)
6365
swapfc_free_ram_perc=35 # Create swap when free RAM < this %
@@ -67,11 +69,11 @@ swapfc_priority=50 # Swap priority (decreases per file)
6769
swapfc_path=/swapfc/swapfile # Path for swap files (must be btrfs)
6870
swapfc_frequency=1 # Check interval in seconds
6971

70-
# Sparse files (thin provisioning) - ENABLED BY DEFAULT
71-
# Creates swap files that only allocate disk space when data is actually written.
72-
# This is ideal with zswap: pages stay in RAM until pool is full, then disk is used.
73-
# Uses loop device automatically (required for sparse swap files).
74-
# swapfc_use_sparse_disable=1 # Uncomment to pre-allocate disk space
72+
# File allocation mode:
73+
# - Pre-allocated (default): Uses fallocate, reserves disk space upfront, no loop device
74+
# - Sparse (thin): Uses truncate, only uses disk when written, requires loop device
75+
# Pre-allocated is more stable and avoids potential deadlocks under memory pressure.
76+
swapfc_use_sparse=0 # 0=pre-allocate (stable, default), 1=sparse (loop device)
7577

7678
# Btrfs compression mode: uses loop device over sparse file on compressed btrfs
7779
# This enables swap data to be compressed on disk by btrfs (zstd)

0 commit comments

Comments
 (0)