Synology: cum am reparat un volum ext4 pe care DSM il declara nereparabil

Un DS920+ cu un volum ext4 de 10,9 TB arata "File system errors" din 30 septembrie 2025. Verificarea din Storage Manager esua de fiecare data cu acelasi mesaj, iar suportul Synology recomanda singura solutie pe care o recomanda intotdeauna: sterge storage pool-ul, creeaza-l din nou, restaureaza din backup. Despre un e2fsck manual spuneau ca sansa de reusita e mica. Cauza reala era o lista de orphan inodes rupta de o pana de curent, iar reparatia a durat cateva ore si nu a pierdut niciun fisier.

Simptomul

In Storage Manager, pool-ul si volumul erau amandoua pe "Warning", data scrubbing-ul blocat ("Unable to run data scrubbing because the storage pool is in abnormal status"), iar in log-ul de sistem, la fiecare incercare:

info  admin: System ran [ext4 filesystem check & repairing] on [Volume 1].
      Exit code: [File system errors cannot be fixed]

Toate cele patru discuri erau SMART-curate (zero sectoare realocate, zero pending, zero erori CRC), iar toate array-urile md raportau [4/4] [UUUU]. Deci nu era hardware.

Ce spune de fapt superblockul

Filesystem state:      clean with errors
Errors behavior:       Continue
FS Error count:        102
First error time:      Tue Sep 30 23:44:04 2025
First error function:  ext4_mb_generate_buddy
Last error time:       Mon Feb  9 16:57:41 2026
Last error function:   ext4_mb_generate_buddy
Last checked:          Sat May 10 17:56:37 2014
Mount count:           257

Last checked din 2014 e detaliul care schimba tot. La finalul unei rulari e2fsck read-write duse pana la capat, codul din e2fsck/unix.c face patru lucruri in acelasi loc: pune s_state = EXT2_VALID_FS, scrie s_lastcheck = now, pune s_mnt_count = 0 si face memset peste tot blocul de contoare de eroare.

Toate patru erau intacte din 2014, data crearii filesystemului. Deci niciun e2fsck nu ajunsese vreodata la capat pe volumul asta, in 12 ani. Verificarile DSM din 2025 si 2026 iesisera devreme, toate.

ext4_mb_generate_buddy

Semnatura erorii e o singura verificare din fs/ext4/mballoc.c:

if (free != grp->bb_free) {
        ext4_grp_locked_error(sb, group, 0, 0,
                              "block bitmap and bg descriptor "
                              "inconsistent: %u vs %u free clusters",
                              free, grp->bb_free);

free e numarul de biti liberi numarati in block bitmap, bb_free e ce scrie in group descriptor. Cele doua contoare nu sunt de acord. Atat. Nu e corupere de inoduri, de directoare sau de date. Iar inode #0 / block #0 din superblock nu sunt inodul zero, sunt sentinele "nu se aplica", pasate literal de apelant.

Ce urmeaza e mai interesant: kernelul marcheaza grupul EXT4_GROUP_INFO_BBITMAP_CORRUPT, dar doar in memorie, si il pune in carantina. Nu se mai aloca nimic din el, iar ext4_free_blocks() face return devreme pentru el, deci fiecare stergere in grupul respectiv pierde definitiv spatiu. Corectia (grp->bb_free = free) nu ajunge niciodata pe disc, fiindca scrierile in grupul ala sunt dezactivate. Rezultat: se re-detecteaza la fiecare mount, la nesfarsit.

Dar asta nu explica esecul verificarii

In e2fsck/problem.c, problemele din pass 5 (PR_5_FREE_BLOCK_COUNT_GROUP, PR_5_BLOCK_BITMAP_HEADER si celelalte) sunt marcate PR_PREEN_OK | PR_PREEN_NOMSG. Adica preen mode le repara singur, tacut. Nu ele opreau verificarea.

Iar superblockul retine doar prima si ultima eroare. Ce oprea e2fsck-ul nu aparea nicaieri in tune2fs.

Unde scrie DSM ce s-a intamplat de fapt

Primul pas a fost sa aflu ce ruleaza Storage Manager. Un poll pe /proc/*/cmdline in timp ce verificarea era pornita din interfata:

while true; do
  for p in /proc/[0-9]*; do
    c=$(cat "$p/cmdline" 2>/dev/null | tr '\0' ' ')
    case "$c" in *fsck*) echo "$(date +%T) ${p##*/} $c";; esac
  done
  sleep 2
done
10:07:38 27575 /sbin/e2fsck -C-1 -pvftt /dev/mapper/cachedev_0

-p = preen. Teoria confirmata direct. Si, mai important, DSM chiar reusea sa demonteze volumul si chiar rula e2fsck read-write. Deci problema nu era ca nu apuca sa porneasca.

Al doilea pas: /usr/syno/lib/systemd/scripts/volume.sh, scriptul care face verificarea la boot, arata unde ajunge output-ul:

/sbin/e2fsck -C-1 -pvf $ThisDev >> /var/log/fsck/${ThisRemap}.log 2>&1

ThisRemap e calea de device cu / inlocuit de ., deci fisierul e /var/log/fsck/mapper.cachedev_0.log. Istoricul complet al fiecarei incercari era acolo, de luni de zile. Ultimele doua linii:

Inodes that were part of a corrupted orphan linked list found.

UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
        (i.e., without -a or -p options)

Bucla

Mesajul corespunde problemei PR_0_ORPHAN_CLEAR_INODE, singura din zona aia care nu are flagul PR_PREEN_OK. Preen ajunge la ea, cheama preenhalt(), iar aia iese cu FSCK_UNCORRECTED (cod 4) direct din interiorul functiei, inainte de blocul de cleanup care ar fi scris s_lastcheck si ar fi sters contoarele. De aici Last checked: 2014.

Lista de orphan inodes e o lista inlantuita din superblock cu fisiere care fusesera unlink-uite dar erau inca deschise de un proces cand s-a intrerupt curentul. Kernelul le elibereaza la urmatorul mount. Doar ca, din fs/ext4/super.c, ext4 sare complet peste procesarea listei cat timp flagul EXT2_ERROR_FS e setat.

Deci:

  1. pana de curent rupe lista de orphan inodes;
  2. se seteaza EXT2_ERROR_FS;
  3. kernelul nu mai proceseaza lista la niciun mount, cat timp flagul e setat;
  4. e2fsck -p refuza sa stearga inodurile fara confirmare si iese cu 4;
  5. flagul nu se sterge niciodata, deci inapoi la pasul 3.

Nu se agraveaza. Dar nu se poate rezolva singura, prin constructie.

De ce s-a rupt lista

Din dmesg, la fiecare boot:

EXT4-fs (md0): mounted filesystem with ordered data mode. Opts: barrier=1
EXT4-fs (dm-1): barriers disabled
EXT4-fs (dm-1): mounted filesystem with writeback data mode.

Synology monteaza partitia de sistem cu barrier=1 si data=ordered, iar volumul de date cu barriers dezactivate si data=writeback. Niciuna nu e default ext4: ambele sunt pasate explicit.

Bitmap-ul si descriptorul se modifica in aceeasi tranzactie de jurnal, deci cu barriers active nu pot diverge. nobarrier scoate insa blkdev_issue_flush dinainte de avansarea cozii jurnalului, iar jbd2 are comentariu explicit in checkpoint.c ca flush-ul ala e necesar pentru corectitudine. Fara el, metadata deja checkpoint-ata poate fi inca in cache-ul volatil al discului cand tranzactiile sunt scoase din log. Cade curentul, se pierde una din cele doua scrieri, si nu mai exista redo nicaieri.

Precizare: data=writeback nu e mecanismul aici. Ala afecteaza ordonarea datelor fata de metadata; bitmap-ul si descriptorul sunt metadata, jurnalizate identic in ordered si writeback. In plus, pe kernel 4.4 md RAID5 nu are PPL (aparut in 4.12), deci si write hole-ul e neacoperit.

Declansatorul, in cazul de fata, a fost un UPS care a cedat.

Reparatia

DSM expune exact ce trebuie, fara sa fie nevoie de synospace --stop-all-spaces (care a marcat pool-ul drept "Crashed" la unii) sau de trucuri cu disable_volumes in synoinfo.conf:

synostgvolume --enum-dep-pkgs /volume1
synostgvolume --stop-package-and-unmount /volume1

Apoi un dry run, care nu scrie nimic:

e2fsck -nvf -C 0 /dev/mapper/cachedev_0

Trei lucruri din output faceau decizia usoara. In lista de diferente de block bitmap, toate intrarile aveau semnul minus. Un -N inseamna "blocul e marcat ocupat pe disc dar niciun inod nu-l revendica", deci se elibereaza; un +N ar fi insemnat directia periculoasa, un fisier care foloseste un bloc pe care bitmap-ul il crede liber. Pass 2, 3 si 4 erau complet goale, fara nicio linie. Si nu exista niciun pass 1B/1C/1D, adica zero blocuri revendicate multiplu.

Motivul pentru care reparatia e sigura sta in cum lucreaza e2fsck: pass 1 reconstruieste block_found_map parcurgand blocurile fiecarui inod, iar pass 5 inlocuieste bitmap-ul de pe disc cu harta calculata. Nu are incredere in bitmap-ul existent, deci nu poate elibera un bloc pe care vreun inod inca il revendica.

Plasa de siguranta e -z, nu e2image: install_image() din misc/e2image.c refuza explicit restaurarea imaginilor raw si qcow2, deci un dump de metadata nu se poate pune inapoi. Fisierul de undo trebuie sa fie pe alt filesystem: un stick formatat ext4, nu FAT32, unde limita de 4 GB pe fisier chiar poate fi atinsa.

e2fsck -yvf -C 0 -z /volumeUSB1/usbshare/vol1-p1.undo /dev/mapper/cachedev_0
e2fsck -yvf -C 0 -z /volumeUSB1/usbshare/vol1-p2.undo /dev/mapper/cachedev_0

A doua trecere e verificarea. Iar la final, ca DSM sa isi actualizeze starea si sa stearga avertismentul din Storage Manager (reboot-ul singur nu e suficient):

synostgvolume --report-ext4-fsck-done \
    --path=/dev/mapper/cachedev_0 --fsck-exit-code=0

Rezultatul

CampInainteDupa
Filesystem stateclean with errorsclean
FS Error count102campul a disparut
Last checked10 mai 201426 iulie 2026
Mount count2570
Blocuri folosite1 319 495 4011 319 396 527

17 inoduri orfane eliberate, 98 874 blocuri recuperate (~386 MB de spatiu fantoma), aproximativ 100 de arbori de extent optimizati. /lost+found nu exista deloc pe volum si a fost creat de e2fsck. A ramas gol, deci niciun inod neatasat de recuperat, niciun fisier pierdut. A doua trecere nu a avut nicio linie "Fix?". Iar dupa reboot, avertismentul warning: mounting fs with errors, running e2fsck is recommended, prezent la fiecare boot din 11 octombrie 2025, a disparut.

Un detaliu de interpretare: in dry run, contoarele counted= ies mult mai mici decat in rularea reala (grupul 47290: counted=14803 fata de counted=31878). Nu e o inconsistenta: cu -n, e2fsck refuza sa elibereze orfanii si le pastreaza blocurile contabilizate. Cele 17 inoduri sterse-dar- neeliberate tineau captiv peste un gigabyte.

Cifra aia nu se scade insa din tabelul de mai sus. "Blocurile folosite" dinainte veneau din contoarele superblockului, adica exact din ce era stricat: in grupurile puse in carantina fiecare stergere se pierdea fara sa fie marcata libera vreodata. Diferenta de 98 874 e intre o contabilitate gresita si una recalculata de la zero de e2fsck, nu un inventar al spatiului eliberat.

Trei capcane DSM

Ce ramane

Mecanismul care a produs coruperea e neschimbat si nu poate fi schimbat persistent: /etc/fstab e regenerat la fiecare boot de /usr/syno/cfgen/s00_synocheckfstab, deci optiunile de mount revin. Pe configuratia asta, un UPS functional nu e optional: e singura aparare ramasa.

Volumul mai are si o particularitate care nu se repara cu fsck: 731 676 672 de inoduri alocate pentru 2 524 173 folosite, adica 0,34%. E rezultatul rularii mke2fs cu raportul implicit de 16 KB per inod pe un volum de 11 TB, si e si motivul pentru care orice verificare completa dureaza: tabela de inoduri singura ocupa in jur de 174 GiB.

Si, cel mai important pentru urmatoarea data: ext4 nu are checksum pe date. Nu exista nicio structura pe disc care sa stie ca un fisier are continut gresit, deci intrebarea "ce fisiere sunt afectate" nu are raspuns pe ext4. Btrfs are, si pe layout redundant Synology documenteaza si repararea automata din copia buna. La urmatoarea inlocuire de discuri, volumul se reface pe Btrfs.

Concluzia practica

"File system errors cannot be fixed" din interfata DSM inseamna e2fsck a iesit cu codul 4, adica erori lasate necorectate. Nu inseamna erori nereparabile. Codul 4 in preen mode inseamna in mod normal exact un lucru: e2fsck a dat peste o problema care cere confirmare umana, si a refuzat sa raspunda singur.

Raspunsul se afla in /var/log/fsck/, la un tail distanta, de luni de zile.

← Toate articolele