# XFS - extents и параллельный I/O _Файловая система · LinuxLab Knowledge Base_ **TL;DR:** XFS - дефолт RHEL 7+: allocation groups (параллельный I/O), extents-based allocation, online grow. **Нельзя уменьшить** - только grow. Идеален для big files, БД, parallel workload. ## Зачем XFS XFS родился у SGI в 1993 для IRIX и больших стораджей. Главные отличия от [ext4](/kb/ext4.md): - **Allocation groups** - ФС разбита на N независимых регионов; разные процессы пишут в разные AG параллельно - **Extent-based** allocation - фрагмент описывается одним extent'ом (start, length), а не списком блоков - **Динамическое выделение inode'ов** - не фиксируется при mkfs - **Delayed allocation** - блоки выделяются при flush, а не при write - **Журналирует только метаданные** - агрессивно - **Online grow** есть, **shrink** - нет С RHEL 7 (2014) - default. Хорошо ложится на БД (PostgreSQL, MySQL), файловые серверы, kvm/qemu-диски, mail-spool с большими mbox. ## Allocation Groups - ключ к параллелизму ФС делится на N равных регионов (по дефолту - по 4 на CPU при mkfs). Каждый AG - почти независимая мини-ФС: свои свободные блоки, свои inode'ы. Это позволяет: - Несколько процессов пишут одновременно в разные AG без блокировок - Allocation решения локальны (близкие inode'ы → близкие блоки) - Быстрый mkfs (форматируешь по AG параллельно) ```bash $ mkfs.xfs /dev/sdb1 meta-data=/dev/sdb1 isize=512 agcount=4, agsize=... ``` Можно переопределить: ```bash mkfs.xfs -d agcount=16 /dev/sdb1 ``` Больше AG = больше параллелизма, но и больше overhead. Default обычно ок. ## Inode - динамические В отличие от [ext4](/kb/ext4.md) (фиксированы при mkfs), XFS выделяет inode'ы по мере необходимости. Никогда не упрёшься в "no space, but free GB". Минусы: inode разбросаны по ФС, директорный обход медленнее на HDD. На SSD неактуально. Размер inode по дефолту 512B (раньше был 256B). Большой inode хорош для встроенных [extended-attributes](/kb/extended-attributes.md) и ACL без выделения отдельных блоков. ```bash mkfs.xfs -i size=1024 /dev/sdb1 # ещё больше места под xattr ``` ## Журналирование XFS журналит **только метаданные**. Данные защищаются delayed allocation + barriers. Журнал лежит во встроенной зоне (можно вынести): ```bash mkfs.xfs -l logdev=/dev/nvme0n1p1,size=128m /dev/sdb1 mount -o logdev=/dev/nvme0n1p1 /dev/sdb1 /mnt/data ``` Обычно log на NVMe ускоряет тяжёлый metadata-load (создание/удаление миллионов файлов). ## Mount-опции ```fstab UUID=... /data xfs defaults,noatime,nodiratime,inode64,logbsize=256k 0 0 ``` | Опция | Что | |-------|-----| | `noatime` | как везде - выкл. atime | | `inode64` (default с RHEL7) | inode'ы могут быть в любой AG; без этого они только в нижних 1 TiB | | `logbsize=256k` | размер log buffer'а; больше = быстрее на metadata-heavy | | `largeio` | optimal-I/O size в st_blksize - подсказка приложениям | | `nobarrier` | **выкл барьеры** - быстрее, но **опасно** на не-battery RAID | | `pquota`, `uquota`, `gquota` | квоты по project/user/group | Барьеры (`barrier=1`) гарантируют, что журнал на диске **до** данных. На HW-RAID с battery-backed cache можно без них (ставь `nobarrier`), но это ответственность за корректность сторадж-стэка. ## Online grow ```bash # Сначала ресайз раздела/LV parted /dev/sdb resizepart 1 100% # или lvextend -L+100G /dev/vg/lv-data # Затем XFS подхватывает xfs_growfs /mnt/data ``` `xfs_growfs` принимает **mountpoint**, не device. ФС должна быть смонтирована. **Shrink невозможен.** Если нужно уменьшить - бэкап, mkfs, restore. Это самое больное место XFS. ## xfs_info, xfs_db ```bash xfs_info /mnt/data # структура: AG count, block size, log xfs_db -r /dev/sdb1 -c "version" # внутренние детали (read-only безопасно) xfs_io -c "stat" /path/to/file # parent inode, extents xfs_io -c "fiemap" file # карта extents xfs_bmap -v file # альтернатива fiemap ``` `xfs_db` - низкоуровневый дебаггер; в RW-режиме можно случайно поломать ФС. ## xfs_repair vs e2fsck XFS делает **journal replay** автоматически при mount. Если этого недостаточно (corruption после crash'а контроллера, bad sectors): ```bash umount /mnt/data xfs_repair /dev/sdb1 # размонтировано обязательно xfs_repair -L /dev/sdb1 # форс с обнулением журнала (РИСК!) ``` `-L` - **последний шанс**: обнуляет log, теряя то что не успело закоммититься. Только если обычный repair падает с "log is corrupt". В отличие от [[ext4|e2fsck]], xfs_repair не правит мелочи на здоровой ФС - он либо нужен, либо нет. ## Quota XFS quota - три измерения: - **uquota** - per user - **gquota** - per group - **pquota** - per **project** (группа inode'ов помеченных одним id) `pquota` уникальна для XFS: можно квотировать произвольное поддерево директорий, не привязанное к user/group: ```bash mount -o pquota /dev/sdb1 /data echo '42:/data/projects/foo' >> /etc/projects echo 'foo:42' >> /etc/projid xfs_quota -x -c 'project -s foo' /data xfs_quota -x -c 'limit -p bhard=10g foo' /data ``` ## XFS vs ext4 | Признак | XFS | [ext4](/kb/ext4.md) | |---------|-----|----------| | Inode | динамические | фиксированные при mkfs | | Параллельный I/O | сильно (AG) | слабее | | Огромные ФС (>16 TiB) | хорошо | хуже из-за structure | | Мелкие файлы | хорошо | хорошо (плотнее упаковка) | | Online resize | grow only | grow + shrink | | Crash recovery | journal replay | journal replay + extensive fsck | | RAM на metadata | больше | меньше | | Default где | RHEL 7+, CentOS, Oracle Linux | Debian/Ubuntu/Mint | Для root-FS на хосте без особых требований - оба ок. Для data-партиции с БД, виртуалками, parallel-load - выбирай XFS. ## Когда что-то пошло не так - **`xfs_growfs: data size unchanged`** - раздел/LV ещё не ресайзнут. Сначала `parted resizepart` или `lvextend`, потом `xfs_growfs`. - **`Structure needs cleaning`** при mount после краша - run `xfs_repair`. Если жалуется на log - `-L` (с понимаем риска). - **fragmentation** - XFS обычно сама не фрагментируется, но при near-full ФС начинает. `xfs_db -c frag /dev/sdb1` (только R/O). `xfs_fsr` - online defrag. - **mkfs на NVME упрямится про block size 4K** - старые xfsprogs не умели; обнови `xfsprogs >= 5.0`. - **Quota не считает project** - забыл `mount -o pquota` или мискс `prjquota` (более старое имя). - **`Cannot allocate memory`** при mount после crash'а - очень большой журнал; нужно больше RAM или вынести log на отдельный диск. ## Команды ```bash sudo mkfs.xfs -L data -f /dev/sdb1 ``` Создать XFS с label; -f нужен если на разделе что-то уже есть ```bash sudo xfs_info /mnt/data ``` Параметры существующей ФС: AG count, block size, log location ```bash sudo xfs_growfs /mnt/data ``` Расширить XFS до полного размера раздела/LV - принимает mountpoint ```bash sudo mount -o noatime,nodiratime,inode64 /dev/sdb1 /mnt/data ``` Mount с типичным набором тюнов для прода ```bash sudo xfs_repair -n /dev/sdb1 ``` Dry-run проверки - покажет проблемы без правки (-n) ```bash sudo xfs_io -c 'fiemap' /path/to/largefile ``` Карта extents - смотреть фрагментацию большого файла ```bash sudo xfs_quota -x -c 'report -h' /data ``` Отчёт по квотам - кто сколько занимает ## См. также - [Файловые системы: ext4, xfs, btrfs, zfs](/kb/filesystems.md) - [ext4 - рабочая лошадь Linux-ФС](/kb/ext4.md) - [btrfs - copy-on-write, subvolumes и снапшоты](/kb/btrfs.md) - [mount и /etc/fstab - подключение ФС](/kb/mount-and-fstab.md) - [fsck и recovery - проверка и восстановление ФС](/kb/fsck-and-recovery.md) - [Kubernetes storage - PV, PVC, StorageClass, CSI](/kb/kubernetes-storage.md)