00 Btrfs mimarisi — B-tree ve CoW
Btrfs (B-tree File System), 2007'de Oracle tarafından başlatılan, mainline 2.6.29'dan itibaren Linux'ta yer alan next-generation dosya sistemidir. Copy-on-Write semantiği, snapshot ve RAID desteği temel tasarım prensipleridir.
B-tree veri yapısı
Btrfs tüm metadata ve veriyi B-tree yapılarında saklar. Her ağaç belirli bir veri türüne hizmet eder ve tüm ağaçlar "tree of tree roots" üst ağacından erişilir.
Copy-on-Write (CoW) mekanizması
Dosya güncelleme (CoW):
┌──────────────────────────────────────────────────┐
│ Mevcut Blok A (offset 0) ← inode işaret eder │
│ [DATA_OLD] │
└──────────────────────────────────────────────────┘
↓ yazma isteği
┌──────────────────────────────────────────────────┐
│ Yeni Blok B (boş alan) ← kopyalanır + değişir│
│ [DATA_NEW] │
└──────────────────────────────────────────────────┘
↓ atomik pointer güncellemesi
inode → Blok B işaret eder
Blok A → extent tree'de serbest bırakılır
CoW avantajları ve dezavantajları
| Avantaj | Dezavantaj |
|---|---|
| Atomic yazma — kısmi yazma riski yok | Parçalanma (fragmentation) artabilir |
| Anlık snapshot — disk alanı sıfır | Büyük DB dosyaları için NoCoW bayrağı gerekir |
| Checksum ile veri bütünlüğü | Metadata overhead daha fazla |
| Crash recovery güçlü | HDD'de seek overhead (SSD ile sorun yok) |
Btrfs gömülü sistemlerde SSD/eMMC/NVMe üzerinde iyi çalışır. HDD üzerinde CoW parçalanması sorun yaratabilir. eMMC üzerinde Btrfs kullanıyorsanız compress=zstd ile hem alan hem de yazma sayısını azaltabilirsiniz.
Bu bölümde
- Btrfs B-tree yapısı tüm metadata ve veriyi ağaç yapılarında saklar
- CoW her yazmayı yeni konuma yazar — atomik güncelleme garantisi
- DB ve büyük dosyalar için
chattr +Cile NoCoW etkinleştirilmeli
01 Subvolume oluşturma ve yönetimi
Subvolume, Btrfs içindeki bağımsız dosya sistemi ağacıdır. Bağımsız mount edilebilir, snapshot alınabilir ve send/receive ile aktarılabilir.
Btrfs kurulumu ve subvolume yapısı
# Btrfs formatla
mkfs.btrfs -L "embedded-data" /dev/mmcblk0p3
# veya çok disk (RAID1)
mkfs.btrfs -d raid1 -m raid1 -L "nas-pool" /dev/sda /dev/sdb
# Geçici mount (subvolume oluşturmak için)
mount /dev/mmcblk0p3 /mnt/btrfs
# Temel subvolume düzeni (ArchLinux tarzı)
btrfs subvolume create /mnt/btrfs/@ # root subvol
btrfs subvolume create /mnt/btrfs/@home # home
btrfs subvolume create /mnt/btrfs/@data # uygulama verisi
btrfs subvolume create /mnt/btrfs/@snapshots # snapshot deposu
btrfs subvolume create /mnt/btrfs/@var_log # /var/log ayrı
# Subvolume listesi
btrfs subvolume list /mnt/btrfs
# Root subvolume ile mount et
umount /mnt/btrfs
mount -o subvol=@ /dev/mmcblk0p3 /
mount -o subvol=@data /dev/mmcblk0p3 /data
Subvolume detay komutları
# Subvolume bilgisi
btrfs subvolume show /data
# ID sorgulama
btrfs subvolume list -p /
# Subvolume sil
btrfs subvolume delete /mnt/btrfs/@old_subvol
# Subvolume'ü varsayılan yap (mount sırasında subvol= gerekmez)
btrfs subvolume set-default 256 / # 256 = subvolume ID
# NoCoW bayrağı (DB, swap dosyaları)
chattr +C /data/postgresql/
lsattr -d /data/postgresql/
/etc/fstab — subvolume mount
# /etc/fstab
UUID=btrfs-uuid / btrfs defaults,subvol=@,compress=zstd:3,noatime 0 0
UUID=btrfs-uuid /data btrfs defaults,subvol=@data,compress=zstd:3,noatime 0 0
UUID=btrfs-uuid /var/log btrfs defaults,subvol=@var_log,noatime 0 0
UUID=btrfs-uuid /.snapshots btrfs defaults,subvol=@snapshots,noatime 0 0
Bu bölümde
- Subvolume bağımsız dosya ağacı — her biri ayrı mount ve snapshot alınabilir
- @, @home, @data, @snapshots düzeni Btrfs best practice'idir
- DB ve swap dosyaları için chattr +C ile CoW devre dışı bırakılmalı
02 Snapshot alma ve yönetimi
Btrfs snapshot'ları anlık olarak alınır ve ilk anda sıfır disk alanı tüketir. CoW sayesinde sadece değişen bloklar yeni alan kaplar.
Snapshot oluşturma
# Yazılabilir snapshot (default)
btrfs subvolume snapshot /data /.snapshots/data-$(date +%Y%m%d-%H%M%S)
# Salt-okunur (read-only) snapshot — OTA için zorunlu
btrfs subvolume snapshot -r /data /.snapshots/data-ro-$(date +%Y%m%d)
# Snapshot listesi
btrfs subvolume list -r / # sadece read-only snapshot'lar
btrfs subvolume list / # tüm subvolume'ler
# Snapshot bilgisi
btrfs subvolume show /.snapshots/data-ro-20260401
# Snapshot sil
btrfs subvolume delete /.snapshots/data-ro-20260301
# Snapshot'tan geri yükle (rollback)
btrfs subvolume snapshot /.snapshots/data-ro-20260401 /data-restored
Otomatik snapshot — snapper entegrasyonu
# snapper kur
apt-get install snapper
# Konfigürasyon oluştur
snapper -c data create-config /data
# Snapshot al
snapper -c data create --description "before-update-$(date +%Y%m%d)"
# Liste
snapper -c data list
# İki snapshot arasındaki fark
snapper -c data diff 1..3
# Belirli snapshot'a rollback
snapper -c data undochange 1..2
# Otomatik temizlik (eski snapshot'ları sil)
snapper -c data cleanup number
Snapshot disk alanı kullanımı
# Toplam Btrfs kullanımı
btrfs filesystem usage /
# Her subvolume/snapshot'ın özel (exclusive) alanı
btrfs filesystem du -s /.snapshots/*
# Paylaşılan (shared) vs özel (exclusive) bloklar
btrfs qgroup show / # quota group istatistikleri
Bu bölümde
- Snapshot -r (read-only) OTA için kullanılmalı — yazılabilir snapshot veriyi değiştirebilir
- İlk snapshot anlık ve sıfır maliyetlidir; fark büyüdükçe alan tüketilir
- snapper otomatik snapshot ve rollback yönetimi sağlar
03 A/B OTA — snapshot akışı
Btrfs snapshot'ları ile A/B güncellemesi geleneksel çift partition gerektirmez. Mevcut rootfs'in snapshot'ı "B slot" olarak kullanılır, güncelleme bu snapshot üzerine uygulanır ve rollback snapshot'a dönmek kadar basittir.
A/B OTA akışı
Mevcut durum: @ subvol (A = çalışan sistem)
1. Güncelleme başlamadan önce snapshot al
btrfs subvol snapshot -r @ /.snapshots/rootfs-v1.2.0
2. @ üzerinde güncellemeyi uygula
(OTA agent paketi indirir, dosyaları günceller)
3. Güncelleme başarılıysa yeni snapshot al
btrfs subvol snapshot -r @ /.snapshots/rootfs-v1.3.0
4. Bir sonraki boot'ta yeni sürümle devam et
5. Güncelleme başarısızsa rollback:
btrfs subvol snapshot /.snapshots/rootfs-v1.2.0 @-rollback
(U-Boot: subvol=@-rollback ile önyükle)
OTA agent scripti
#!/bin/bash
set -euo pipefail
BTRFS_MOUNT="/btrfs_root"
SUBVOL_ACTIVE="@"
SNAP_DIR="@snapshots"
OTA_BUNDLE="$1" # OTA tar.zst paketi
NEW_VERSION="$2" # ör: v1.3.0
# 1. Btrfs kök (topslevol) mount et
mount -o subvolid=5 /dev/mmcblk0p3 "$BTRFS_MOUNT"
# 2. Mevcut sürümü snapshot ile yedekle
PREV_SNAP="$BTRFS_MOUNT/$SNAP_DIR/rootfs-backup-$(date +%Y%m%d-%H%M%S)"
btrfs subvolume snapshot -r \
"$BTRFS_MOUNT/$SUBVOL_ACTIVE" \
"$PREV_SNAP"
echo "Yedek snapshot: $PREV_SNAP"
# 3. OTA paketini uygula
echo "OTA paketi uygulanıyor: $OTA_BUNDLE"
tar -xf "$OTA_BUNDLE" -C "$BTRFS_MOUNT/$SUBVOL_ACTIVE"
# 4. Temel doğrulama
if ! "$BTRFS_MOUNT/$SUBVOL_ACTIVE/usr/bin/version-check" "$NEW_VERSION"; then
echo "Doğrulama başarısız — rollback!"
btrfs subvolume delete "$BTRFS_MOUNT/$SUBVOL_ACTIVE"
btrfs subvolume snapshot "$PREV_SNAP" "$BTRFS_MOUNT/$SUBVOL_ACTIVE"
umount "$BTRFS_MOUNT"
exit 1
fi
# 5. Başarılı — yeni sürüm snapshot'ı oluştur
btrfs subvolume snapshot -r \
"$BTRFS_MOUNT/$SUBVOL_ACTIVE" \
"$BTRFS_MOUNT/$SNAP_DIR/rootfs-$NEW_VERSION"
echo "OTA başarılı: $NEW_VERSION"
umount "$BTRFS_MOUNT"
reboot
Rollback mekanizması
#!/bin/bash
# /usr/sbin/btrfs-rollback.sh <snapshot-ismi>
BTRFS_MOUNT="/btrfs_root"
TARGET_SNAP="$1"
mount -o subvolid=5 /dev/mmcblk0p3 "$BTRFS_MOUNT"
# Mevcut @ subvol'ü geçici olarak yeniden adlandır
btrfs subvolume snapshot -r \
"$BTRFS_MOUNT/@" \
"$BTRFS_MOUNT/@snapshots/rollback-$(date +%Y%m%d-%H%M%S)"
# @ subvolumünü sil
btrfs subvolume delete "$BTRFS_MOUNT/@"
# Hedef snapshot'tan yeni @ oluştur
btrfs subvolume snapshot \
"$BTRFS_MOUNT/@snapshots/$TARGET_SNAP" \
"$BTRFS_MOUNT/@"
echo "Rollback tamamlandı: $TARGET_SNAP"
umount "$BTRFS_MOUNT"
reboot
Bu bölümde
- Btrfs snapshot A/B OTA için çift partition gerektirmez — tek partition yeterli
- Güncelleme öncesi read-only snapshot rollback noktası sağlar
- Doğrulama başarısızsa snapshot'tan @ geri yüklenerek sisteme dönülür
04 btrfs send / receive — delta transfer
btrfs send bir snapshot'ı (veya iki snapshot arasındaki farkı) binary akış olarak dışa aktarır. btrfs receive bu akışı başka bir Btrfs dosya sistemine uygular. Gömülü OTA'da delta güncelleme için kritik araçtır.
Tam ve artımlı transfer
# ── GÖNDERME TARAFI (sunucu / build makinesi) ──
# Tam snapshot transferi (ilk kurulum)
btrfs send /.snapshots/rootfs-v1.0.0 | \
gzip -c > /tmp/rootfs-v1.0.0.btrfs.gz
# Delta (artımlı) transfer: v1.0.0 → v1.1.0
# Her iki snapshot da read-only (-r) olmalı!
btrfs send -p /.snapshots/rootfs-v1.0.0 \
/.snapshots/rootfs-v1.1.0 | \
zstd -c -T4 > /tmp/delta-v1.0.0-v1.1.0.btrfs.zst
# Delta boyutu karşılaştır
du -sh /tmp/rootfs-v1.0.0.btrfs.gz # tam: ~200 MB
du -sh /tmp/delta-v1.0.0-v1.1.0.btrfs.zst # delta: ~8 MB
# ── ALMA TARAFI (hedef cihaz) ──
# İlk kurulum (tam snapshot)
zcat /tmp/rootfs-v1.0.0.btrfs.gz | \
btrfs receive /btrfs_root/@snapshots/
# Delta güncelleme uygula
zstd -d -c /tmp/delta-v1.0.0-v1.1.0.btrfs.zst | \
btrfs receive /btrfs_root/@snapshots/
# SSH üzerinden doğrudan delta transfer
btrfs send -p /.snapshots/rootfs-v1.0.0 \
/.snapshots/rootfs-v1.1.0 | \
ssh root@192.168.1.100 "btrfs receive /.snapshots/"
OTA pipeline — delta güncelleme akışı
Build Sunucusu:
Yeni imaj → Btrfs snapshot → btrfs send -p prev → zstd → delta.btrfs.zst
↓
OTA Sunucusu (HTTP)
↓
Cihaz (wget/curl)
↓
btrfs receive → yeni snapshot
↓
@ subvol güncelle → reboot
Delta boyutu optimizasyonu
Bu bölümde
- btrfs send -p (parent) delta transferi sağlar — tam imaj yerine fark gönderilir
- Delta boyutu güncellemenin büyüklüğüne bağlı — tipik OTA için %2–10 oranında
- SSH pipe ile ağ üzerinden doğrudan aktarım mümkündür
05 Deduplication — duperemove
Deduplication, birden fazla dosya veya snapshot'ta aynı içeriğe sahip blokları tespit edip tek fiziksel kopyaya indirger. Btrfs'te çevrimdışı (offline) ve çevrimiçi (online) dedup desteklenir.
duperemove — offline dedup
# Kur
apt-get install duperemove
# Çalıştır (kuru koşu — sadece raporla)
duperemove -r -d --dry-run /.snapshots/
# Gerçek dedup uygula
duperemove -r -d /.snapshots/
# Birden fazla dizin
duperemove -r -d /data/ /.snapshots/
# Hash veritabanı kullan (tekrarlı çalışma için hızlı)
duperemove -r -d \
--hashfile=/var/lib/duperemove/hashdb \
/.snapshots/
# Thread sayısını sınırla (gömülü)
duperemove -r -d -I 4 --hashfile=/var/lib/duperemove/hashdb /.snapshots/
Btrfs dahili dedup (out-of-band)
# btrfs dedupe ioctls ile kernel tarafı dedup
apt-get install btrfs-compsize bedup
# Aynı içerikli iki dosyayı reflink ile birleştir
cp --reflink=always kaynak.img hedef.img
# Sıkıştırılmış boyutu görüntüle (compsize)
compsize /data/
# Snapshot'lar arasında paylaşılan blokları göster
btrfs filesystem du -s /.snapshots/rootfs-v1.0.0
btrfs filesystem du -s /.snapshots/rootfs-v1.1.0
Snapshot dedup tasarrufu tahmini
| Senaryo | Ham boyut | Dedup sonrası | Tasarruf |
|---|---|---|---|
| 5 benzer rootfs snapshot | 5 × 400 MB = 2 GB | ~420 MB | ~%79 |
| Günlük veri snapshot (1 ay) | 30 × 100 MB = 3 GB | ~150 MB (fark küçükse) | ~%95 |
| Heterojen imajlar | 10 × 200 MB = 2 GB | ~1.5 GB | ~%25 |
Bu bölümde
- duperemove snapshot'lar arasındaki ortak blokları tespit edip alan kurtarır
- --hashfile ile tekrarlı çalışmalarda yalnızca yeni/değişen bloklar taranır
- Benzer rootfs snapshot'larında %70–80 dedup oranı tipiktir
06 Scrub ve data integrity
Btrfs scrub, her bloğu checksum'ıyla karşılaştırarak sessiz veri bozulmalarını (silent corruption) tespit eder ve RAID konfigürasyonunda otomatik onarır.
Scrub çalıştırma
# Scrub başlat (arka planda)
btrfs scrub start /
# Scrub durumunu izle
btrfs scrub status /
# Scrub tamamlanana kadar bekle (foreground)
btrfs scrub start -B /
# Scrub'u duraklat / devam ettir
btrfs scrub cancel /
btrfs scrub resume /
# Tüm bağlı Btrfs FS'leri scrub et
for mount in $(findmnt -t btrfs -n -o TARGET); do
echo "Scrubbing $mount"
btrfs scrub start -B "$mount"
btrfs scrub status "$mount"
done
Scrub sonuç yorumlama
# btrfs scrub status / çıktısı
# scrub status for 91a5d3f2-.....
# scrub started at 2026-04-12 03:00:00
# total bytes scrubbed: 12.34GiB
# error stats:
# read errors: 0
# csum errors: 0 ← 0 olmalı
# uncorrectable errors: 0 ← 0 olmalı
# corrected errors: 0
# unverified errors: 0
# status: finished
# Bozulma varsa kernel log'da görünür
dmesg | grep -i "btrfs.*error\|checksum\|corrected"
Periyodik scrub timer
# /etc/systemd/system/btrfs-scrub.service
[Unit]
Description=Btrfs Scrub — veri bütünlüğü kontrolü
[Service]
Type=oneshot
ExecStart=/usr/sbin/btrfs scrub start -B /
ExecStart=/usr/sbin/btrfs scrub start -B /data
# /etc/systemd/system/btrfs-scrub.timer
[Unit]
Description=Aylık Btrfs Scrub
[Timer]
OnCalendar=monthly
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target
Bu bölümde
- Scrub sessiz bit çürümelerini (bit rot) proaktif olarak tespit eder
- RAID1/5/6 konfigürasyonunda scrub bozuk bloğu otomatik onarır
- Aylık scrub timer gömülü sistemler için yeterlidir
07 Compression — zlib / lzo / zstd
Btrfs şeffaf sıkıştırma, dosyaları yazarken kernel içinde sıkıştırır. Özellikle flash depolamada hem alan tasarrufu hem de daha az yazma ile ömür uzatma sağlar.
Sıkıştırma algoritması karşılaştırması
| Algoritma | Oran | Hız (sıkıştırma) | Hız (açma) | Kullanım |
|---|---|---|---|---|
| zlib (seviye 1–9) | Yüksek | Yavaş | Orta | Arşiv, nadiren erişilen |
| lzo | Düşük–Orta | Çok hızlı | Çok hızlı | Gerçek zamanlı, düşük CPU |
| zstd (seviye 1–15) | Yüksek | Hızlı | Çok hızlı | Genel amaç — önerilen |
| zstd:1 | Orta | Çok hızlı | Çok hızlı | Aktif veri partisyonu |
| zstd:15 | Çok yüksek | Yavaş | Hızlı | Arşiv / snapshot deposu |
Compression mount seçenekleri
# Mount sırasında sıkıştırma etkinleştir
mount -o compress=zstd:3 /dev/mmcblk0p3 /data
# Mevcut dosyaları sıkıştır (yeni yazmalarda otomatik)
btrfs filesystem defragment -r -czstd /data/
# Belirli dizine farklı sıkıştırma (xattr ile)
btrfs property set /data/logs/ compression zstd:8
# Sıkıştırma devre dışı (binary, zaten sıkışık)
btrfs property set /data/videos/ compression ""
# Sıkıştırma oranını görüntüle
compsize /data/
# Örnek çıktı:
# Type Perc Disk Usage Uncompressed Referenced
# TOTAL 62% 384M 621M 631M
# none 100% 21M 21M 21M
# zstd 59% 363M 600M 610M
/etc/fstab compression ayarı
# /etc/fstab — zstd:3 genel amaç için iyi denge
UUID=btrfs-uuid /data btrfs \
defaults,subvol=@data,compress=zstd:3,noatime,discard=async 0 0
UUID=btrfs-uuid /.snapshots btrfs \
defaults,subvol=@snapshots,compress=zstd:10,noatime 0 0
Bu bölümde
- zstd:3 günlük kullanım için oran/hız dengesi açısından önerilen seçimdir
- Snapshot deposu için zstd:10+ daha yüksek sıkıştırma oranı sağlar
- compsize ile gerçek sıkıştırma oranı ölçülür
08 Pratik: Yocto + Btrfs snapshot OTA sistemi
Yocto ile üretilen gömülü Linux imajında Btrfs tabanlı OTA güncelleme altyapısı kurun: snapshot akışı, delta transfer ve rollback prosedürü.
Yocto imaj tarifi
# meta-custom/recipes-core/images/btrfs-ota-image.bb
SUMMARY = "Btrfs snapshot OTA destekli gömülü imaj"
inherit core-image
IMAGE_FEATURES += "ssh-server-openssh"
IMAGE_INSTALL:append = " \
btrfs-tools \
util-linux \
e2fsprogs-mke2fs \
bash \
curl \
zstd \
btrfs-ota-agent \
"
# Btrfs kernel konfigürasyonu
KERNEL_FEATURES:append = " cfg/btrfs.scc"
# WKS disk imaj
WKS_FILE = "btrfs-ota.wks"
WKS disk düzeni
# btrfs-ota.wks
bootloader --ptable gpt --timeout=5
part /boot --source bootimg-partition \
--ondisk mmcblk0 --fstype=vfat --label boot \
--active --align 4 --size 64M
part / --source rootfs \
--ondisk mmcblk0 --fstype=btrfs --label rootfs \
--align 4 --size 1G \
--mkfs-extraopts="-O compress,extra_attr"
İlk boot kurulum scripti
#!/bin/bash
# İlk boot'ta Btrfs subvolume yapısını oluştur
set -e
DEVICE="/dev/mmcblk0p2"
MOUNT="/mnt/btrfs_init"
VERSION=$(cat /etc/os-release | grep VERSION_ID | cut -d= -f2 | tr -d '"')
[ -d "$MOUNT" ] || mkdir -p "$MOUNT"
# Topsevil mount
mount -o subvolid=5 "$DEVICE" "$MOUNT"
# Subvolume yapısını oluştur (sadece ilk boot)
if ! btrfs subvolume list "$MOUNT" | grep -q "@snapshots"; then
btrfs subvolume create "$MOUNT/@snapshots"
# Mevcut root'u @ olarak al
btrfs subvolume snapshot -r "$MOUNT" \
"$MOUNT/@snapshots/rootfs-${VERSION}-initial"
echo "İlk snapshot oluşturuldu: rootfs-${VERSION}-initial"
fi
umount "$MOUNT"
Tam OTA güncelleme döngüsü
## BUILD SUNUCUSU (yocto build makinesi)
# 1. Yeni sürüm derle
bitbake btrfs-ota-image
# 2. Btrfs imajı mount et ve snapshot al
LOOP=$(losetup -f --show tmp/deploy/images/*/rootfs.btrfs)
mount -o subvolid=5 $LOOP /mnt/new_rootfs
btrfs subvolume snapshot -r /mnt/new_rootfs \
/mnt/new_rootfs/@snapshots/rootfs-v1.3.0
# 3. Delta oluştur
btrfs send -p /mnt/prev_rootfs/@snapshots/rootfs-v1.2.0 \
/mnt/new_rootfs/@snapshots/rootfs-v1.3.0 | \
zstd -c -T4 > /ota-server/delta-v1.2.0-v1.3.0.btrfs.zst
## HEDEF CİHAZ
# 4. Delta indir
wget http://ota.example.com/delta-v1.2.0-v1.3.0.btrfs.zst \
-O /tmp/delta.btrfs.zst
# 5. Uygula ve yeniden başlat
/usr/sbin/btrfs-ota-update.sh /tmp/delta.btrfs.zst v1.3.0
# 6. Başarısız olursa rollback
/usr/sbin/btrfs-rollback.sh rootfs-v1.2.0
Bu bölümde
- Yocto + WKS ile Btrfs tabanlı rootfs imajı üretildi
- Build sunucusunda btrfs send -p ile delta paket, cihazda btrfs receive ile uygulandı
- Rollback scripti herhangi bir kayıtlı snapshot'a tek komutla dönmeyi sağlar