AnimaTier
AnimaTier is a two-phase file-tiering daemon that moves cold blocks from a hot SSD tier down to a slow btrfs "cold" subvolume, then promotes hot files back up when a real user re-accesses them. AnimaTier is part of the Anima OS ecosystem and is engineered to coexist with the beesdedup beesd deduplication engine -- without ever letting beesd's hash-scan storm flip a file into the wrong tier.
- Two-tier design (SSD → cold, cold → SSD) with quarantine and age gates
beesd/bees/bee*noise filtering so dedup doesn't fight the heuristic- Size (
-size) and age (mtime > N days) minimisers for cold migration - Configurable quarantine window before promotion back to hot tier
- Zero-touch operation via
systemdtimer, idempotent install script - Sourceable module design with exported
_at_*function wrappers (fully testable without root or any real files) shunit2-based test harness covering every phase transition- AGPL-3.0-or-later licensed, created by animaios
The Anima OS collection is a celebration of tinkering — a personal ecosystem of daemons, scripts, and tools that make a home btrfs storage system feel alive. AnimaTier is the data-gravity agent: it watches files decay into silence, lets the SSD breathe, and yanks them back the moment you open them.
curl -fsSL https://raw.githubusercontent.com/animaios/animatier/main/install.sh | sudo bashgit clone https://github.com/animaios/animatier.git
cd animatier
sudo ./install.shinstall.sh will:
- Copy
animatier.shinto/usr/local/bin/animatier.sh. - Drop the
systemdservice + timer unit into/usr/lib/systemd/system/. - Create a
/etc/animatier/animatier.conffrom a commented sample if missing. - Run
systemctl daemon-reload(andenable --now animatier.timerif a system bus is available).
All behaviour is environment-driven. Write overrides in
/etc/animatier/animatier.conf, e.g.:
# /etc/animatier/animatier.conf
ANIMATIER_SOURCE_DIR=/home/vi
ANIMATIER_TARGET_DIR=/cold/home-slow
ANIMATIER_LOG_FILE=/var/log/animatier.log
ANIMATIER_DAYS_TO_COLD=7
ANIMATIER_MIN_SIZE=10M
ANIMATIER_QUARANTINE_HOURS=24
ANIMATIER_QUARANTINE_MAX_KB_PER_SEC=300
ANIMATIER_OWNER=vi
ANIMATIER_GROUP=vi
ANIMATIER_PROC_DIR=/proc
ANIMATIER_DRY_RUN=0Environment variables win over the defaults; the config file is only sourced when present.
For every regular file older than DAYS_TO_COLD days and larger than
ANIMATIER_MIN_SIZE:
- Directory prune: skip
.cache,.config,.local,.mozilla,.thunderbird,.rustup,.cargo,.steam. - Symlink skip: any path that is already a link (migration marker) is ignored.
- Active-file skip: if
fuserreports open handles and any accessor is not a bee pod, bail. - User-access skip: if
atime − mtime > 5sand a non-bee process is holding the file, bail. - Age gate:
NOW − mtime < DAYS_TO_COLD × 86400→ bail. - Migrate with
rsync -a --remove-source-files, stampuser.tiering.moved_atviasetfattr, drop a symlink in place. - Log
[COLD] <rel-path>.
For every regular file on the cold tier:
- Symlink check: promotion only happens when a symlink exists at the source tier pointing at the cold location.
- Active-file skip: same as Phase 1.
- Quarantine:
NOW − moved_at < QUARANTINE_HOURS × 3600→ bail. This is the safety valve that keeps newly-migrated files on the cheap disk until the heat is definitely real. - Post-write access gate:
atime ≤ mtime + 5→ bail. - Bees filter: if only bees/beesd/bee* opens the file, log
[HOT:bees-filtered]and continue -- we never promote because of a dedup storm. - Pull file back with
rsync -a --remove-source-files, log[HOT] <rel-path>.
The deduplication engine bees walks every file on a btree to hash blocks.
Without this guard its periodic scans would raise every file's atime and
make every cold file look hot. AnimaTier reads
ANIMATIER_PROC_DIR/<pid>/comm for every process reported by fuser and
demotes the entire accessor set to non-bee before making any tiering
decision. The filter treats any process whose comm starts with bees,
beesd, or bee* as benign.
bash tests/test_animatier.shThe harness vendors shunit2 (and install.sh pulls it down if missing).
Tests stub out every _at_* wrapper so they exercise the phase logic directly
— no root, no btrfs, no beesd required.
fanotify-based real-time signals instead of polling.- LLM-assisted decay scoring for warmer/cooler classification.
- Agentic tiering -- let a small sidekick agent decide custom zones.
- Prometheus-compatible telemetry for observation lovers.
AGPL-3.0-or-later. See LICENSE for the full text.