Когда что-то ломается
Файловая система может оказаться в "грязном" состоянии после:
- Power loss / kernel panic во время записи
- Bad sectors на HDD/SSD - storage stack вернул ошибку
- Контроллер дисков соврал про fsync (write-back cache без BBU)
- Corruption памяти (ECC, или её отсутствие)
- Bug в ядре или ФС
- Случайная запись на raw device мимо ФС
Симптомы:
Read-only file systemпосле mount (errors=remount-ro)Structure needs cleaningпри следующем mountInput/output errorпри чтении конкретных файлов- Странности
ls(мусорные имена, файлы пропадают) - Машина залипла на boot'е "checking filesystems..."
Стратегия:
- Стоп. Не писать на повреждённую ФС.
- Backup raw device (
ddилиddrescue) - до любых правок. - Если есть журнал - попытаться replay при mount.
- Если не помогло - offline fsck/repair.
- Если и это не помогло - extract данных utility-средствами.
Journal replay - автоматическая магия
При mount ext4/xfs/btrfs видят, что предыдущий umount был грязным, и проигрывают журнал - применяют закоммиченные но не записанные изменения. Это занимает секунды и решает большинство crash-сценариев.
Что увидишь в dmesg:
EXT4-fs (sda1): recovery required on readonly filesystem
EXT4-fs (sda1): write access will be enabled during recovery
EXT4-fs (sda1): mounted filesystem with ordered data mode
XFS (sdb1): Mounting V5 Filesystem
XFS (sdb1): Starting recovery (logdev: internal)
XFS (sdb1): Ending recovery (logdev: internal)
Если journal recovery упал - тогда fsck.
fsck - frontend
fsck - универсальный wrapper, который смотрит тип ФС и зовёт
правильный инструмент:
| ФС | Реальный binary |
|---|---|
| ext2/3/4 | e2fsck |
| xfs | в fsck это no-op - использовать xfs_repair напрямую |
| btrfs | btrfs check напрямую |
| vfat | dosfsck |
| jfs | jfs_fsck |
# Из fstab автоматом при boot'е
fsck -A # все из fstab (passno > 0)
fsck / # конкретный mountpoint
fsck /dev/sda1 # конкретное устройство
Опции:
| Опция | Что |
|---|---|
-A | все из fstab |
-y | "yes на все" - не безопасно если не знаешь о повреждении |
-n | dry-run, только показать |
-f | force даже на чистой ФС |
-V | verbose |
-C | progress bar |
Главное правило: ФС должна быть размонтирована. Live-fsck
на смонтированной ФС с записями = corruption. Допустимо -n (RO)
на смонтированной для diagnostics.
e2fsck - ext-семейство
umount /dev/sda1
e2fsck -f /dev/sda1 # force, всегда
e2fsck -fy /dev/sda1 # auto-yes (для скриптов и desperate)
e2fsck -fp /dev/sda1 # preen - чинить безопасное, ругаться на остальное
Особые случаи:
# Используем backup-suberblock если основной побит
e2fsck -b 32768 /dev/sda1 # на ext4 с 4K blocks
mke2fs -n /dev/sda1 # покажет где backup'ы (без записи!)
dumpe2fs -h /dev/sda1 | grep -i backup # на здоровой ФС
Что выводит при corruption:
Pass 1: Checking inodes, blocks, and sizes
Inode 12345 has illegal block(s). Clear<y>?
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Файлы, потерявшие имя но имеющие inode, попадают в /lost+found/
по номеру inode'а. Содержимое читаемо, имя нужно восстановить
по содержимому.
xfs_repair - XFS
umount /dev/sdb1
xfs_repair /dev/sdb1 # обычный
xfs_repair -n /dev/sdb1 # dry-run
xfs_repair -L /dev/sdb1 # ZERO LOG - последний шанс!
-L обнуляет журнал, теряя то что не было закоммичено. Делать
только если обычный xfs_repair падает с "log is corrupt or
cannot be read".
XFS не имеет lost+found концепции в том же виде - orphan inode'ы
переподключаются автоматически или удаляются.
btrfs check / btrfs rescue
umount /dev/sdc1
btrfs check /dev/sdc1 # только diagnostics
btrfs check --repair /dev/sdc1 # ОПАСНО - может усугубить!
btrfs check --repair помечен как experimental годами. Используй
только если нечего терять. Сначала btrfs rescue:
btrfs rescue super-recover /dev/sdc1 # восстановить super blocks
btrfs rescue chunk-recover /dev/sdc1 # восстановить chunk tree
btrfs rescue zero-log /dev/sdc1 # как xfs_repair -L
Если ФС не монтируется, попробуй RO:
mount -o ro,recovery,nologreplay /dev/sdc1 /mnt
и спасай данные cp -a или btrfs send.
fstab - passno
Шестое поле fstab говорит когда fsck-it на boot'е:
UUID=... / ext4 defaults 0 1
UUID=... /var ext4 defaults 0 2
UUID=... /tmp tmpfs defaults 0 0
- 0 - не проверять
- 1 - root, проверяется первым
- 2 - проверяется после root, параллельно с другими
2
XFS и btrfs ставят passno=0, потому что fsck для них - no-op (используют свои tools при необходимости).
errors=remount-ro
Опция mount, ставится в fstab:
UUID=... / ext4 defaults,errors=remount-ro 0 1
Когда ядро видит ошибку ФС - вместо panic'а перемонтирует в RO.
Это спасает данные: дальше пишет некуда, можно посмотреть dmesg,
размонтировать (или загрузиться с rescue) и сделать fsck.
Альтернативы: errors=continue (не делать ничего, опасно),
errors=panic (kernel panic, для embedded).
ddrescue для умирающего диска
Когда HDD сыплется и обычный dd падает на bad-секторах:
ddrescue /dev/sda backup.img backup.log
Создаёт image, пропуская проблемные секторы (не зависает на них),
ведёт лог. Повторный запуск дочитывает только проблемные. Перед
любым xfs_repair --L или btrfs check --repair сначала
ddrescue копию.
Восстановление файла
Если файл удалён, но inode не перезаписан:
- ext4:
extundelete /dev/sda1 --restore-file path/to/fileилиe2undel. Размонтируй ФС перед запуском. - xfs:
xfs_undelete(community tool, не всегда работает). - btrfs: можно достать из снапшота если он был.
btrfs restoreиз broken-FS. - Любая: photorec из testdisk-пакета - сигнатурный поиск по типам файлов.
Чем дольше ФС работает после удаления - тем меньше шансов. Размонтировать сразу.
Best practices
- Бэкапы делают fsck не нужным
- errors=remount-ro в fstab всегда
- smartctl -a мониторит S.M.A.R.T. - предсказывает крах
- scrub на btrfs/zfs раз в неделю
- fsck -fp при загрузке у 1-го passno - ловит мелочь
- ddrescue перед repair при подозрении на железо
- Документировать UUID разделов и backup-суперблоков
Когда что-то пошло не так
fsck.xfs ничего не делает- это норма, fsck.xfs - заглушка. Используйxfs_repair.- fsck завис -
xfs_repairна огромной ФС может занять часы. Не трогать. Bad superblock- ext4 backup-superblock черезe2fsck -b $BACKUP /dev/sda1.UUID conflict- послеddкопия ФС имеет тот же UUID.tune2fs -U random /dev/sdb1.- lost+found пустой после fsck - нечего было восстанавливать как orphan, либо ФС была здорова.
- system не загружается из-за fsck-fail - boot из rescue (
init=/bin/sh, USB-live),e2fsck -fy /dev/sdaNруками.