Cuando formateas una partición, no estás eligiendo solo un “formato de disco”: estás eligiendo una política de gestión de datos. Un filesystem es la capa que decide cómo se organizan los metadatos de inodos, cómo se agrupan los bloques físicos, qué ocurre cuando el sistema se apaga a mitad de una escritura, y con qué latencia se responde a un open(2). La elección importa, y no hay una respuesta universal.
Los tres que vas a encontrar en producción real en Linux son ext4, XFS y Btrfs. Cada uno parte de un modelo de diseño distinto, lo que explica tanto sus fortalezas como sus límites.
Por qué existen tres opciones y no una sola
ext4 es la evolución directa de ext2 y ext3, el filesystem de referencia en Debian desde hace más de una década. Añade journaling de metadatos (heredado de ext3), extents en lugar de mapas de bloques indirectos, y allocación retardada. El journaling garantiza que tras un crash el filesystem quede en un estado consistente: antes de escribir los metadatos definitivos, los registra en un área dedicada llamada journal; si el sistema cae, el kernel puede repasar ese log y completar o deshacer la operación. Los extents sustituyen el esquema de bloques indirectos de ext2 (que escalaba mal con archivos grandes) por rangos contiguos descritos como (bloque_inicio, longitud), reduciendo la fragmentación y el overhead en archivos de varios gigabytes.
XFS viene de SGI y está diseñado desde el inicio para I/O masivo y concurrencia alta. Su unidad interna es la allocation group: el espacio del disco se divide en grupos independientes, cada uno con su propio árbol B+ de inodos y espacio libre. Esto permite que múltiples hilos hagan allocación en paralelo sin bloquearse entre sí, algo que ext4 no puede hacer con la misma eficiencia porque su allocador es global. XFS también tiene un journal, pero es exclusivamente de metadatos y está optimizado para throughput. La contrapartida clásica de XFS es que fsck en un filesystem dañado es más costoso y menos recuperable que en ext4, y que no soporta reducir el tamaño del sistema de ficheros una vez creado.
Btrfs (B-tree filesystem) es el que rompe el esquema: en lugar de separar filesystem y gestión de volúmenes, integra ambos. Su estructura interna es un árbol B-tree copy-on-write (CoW) que cubre metadatos y datos. Eso habilita snapshots atómicos sin coste de copia, checksums de datos y metadatos (lo que ext4 y XFS no hacen en datos), compresión transparente en escritura, y RAID por software gestionado internamente. El CoW tiene un coste real: la fragmentación se acumula en workloads de escritura aleatoria intensiva, y hay escenarios de producción —bases de datos con O_DIRECT, VMs con imágenes raw— donde el comportamiento no es predecible sin benchmarking previo. Las features de RAID5/6 de Btrfs llevan años marcadas como experimentales y no deberías usarlas en producción todavía.
Cuándo usar cada uno: ext4 para el disco del sistema operativo y para workloads genéricos donde necesitas madurez y comportamiento predecible; XFS cuando tienes escrituras concurrentes pesadas, archivos grandes (logs, media, bases de datos de analítica), o necesitas escalar en número de inodos sin penalización; Btrfs cuando los snapshots son un requisito operativo y el workload lo soporta —servidores de ficheros, entornos de desarrollo, sistemas con rollback frecuente.
Lo que se rompe si eliges mal: poner Btrfs bajo PostgreSQL con su patrón de escritura aleatoria sin deshabilitar CoW en el directorio de datos (chattr +C) genera fragmentación patológica y degradación progresiva de rendimiento. Usar ext4 para un servidor con millones de ficheros pequeños sin ajustar el número de inodos al formatear deja el filesystem sin inodos disponibles aunque quede espacio libre. XFS en un sistema que necesitas reducir de tamaño te obliga a backup y reformat completo.
Ejemplo: crear, inspeccionar y verificar los tres filesystems
El escenario: tienes tres particiones nuevas en un disco secundario (/dev/sdb1, /dev/sdb2, /dev/sdb3). Vamos a formatearlas, tunear las opciones más relevantes, montarlas con opciones no triviales, e inspeccionar el estado interno de cada una.
#!/bin/bash
# Requiere: util-linux, e2fsprogs, xfsprogs, btrfs-progs
# apt install e2fsprogs xfsprogs btrfs-progs
# ── ext4 ─────────────────────────────────────────────────────────────────────
# -m 1: reservar solo 1% para root (el 5% por defecto tiene sentido en /,
# no en un volumen de datos donde el espacio es prioritario)
# -E lazy_itable_init=0: inicializar tabla de inodos completamente ahora,
# no en background; más lento al formatear, pero evita I/O sorpresivo posterior
# -L datos-ext4: etiqueta, útil para montaje por LABEL= en fstab
mkfs.ext4 -m 1 -E lazy_itable_init=0 -L datos-ext4 /dev/sdb1
# Ver todos los parámetros del superbloque: UUID, journal size, feature flags,
# mount count, last check, etc.
tune2fs -l /dev/sdb1
# Activar compresión de journal (ahorra I/O en journals grandes) y
# habilitar checksum del journal (ext4 feature disponible desde kernel 3.x)
tune2fs -O metadata_csum /dev/sdb1 # ya activo por defecto en Bookworm, pero
# útil para verificar en discos migrados
tune2fs -E journal_async_commit /dev/sdb1 2>/dev/null || true
# journal_async_commit puede no estar disponible en todos los kernels;
# el || true evita que el script pare en ese caso
# Montar con opciones orientadas a rendimiento en datos no críticos:
# noatime: no actualizar atime en cada lectura (enorme ganancia en lecturas)
# data=ordered: modo por defecto — datos escritos antes de metadatos en journal;
# el modo data=writeback es más rápido pero menos seguro
mkdir -p /mnt/datos-ext4
mount -o noatime,data=ordered /dev/sdb1 /mnt/datos-ext4
# ── XFS ──────────────────────────────────────────────────────────────────────
# -f: forzar si el disco tiene restos de filesystem anterior
# -L datos-xfs: etiqueta
# -d agcount=8: número de allocation groups; regla práctica: 1 por CPU
# para maximizar paralelismo de allocación
mkfs.xfs -f -L datos-xfs -d agcount=8 /dev/sdb2
# Inspeccionar metadatos internos del superbloque XFS
xfs_info /dev/sdb2 2>/dev/null || xfs_info /mnt/datos-xfs # antes o después de montar
mkdir -p /mnt/datos-xfs
# largeio: pista al kernel para preferir I/O de bloques grandes (beneficia streaming)
# inode64: permite inodos en cualquier parte del disco, no solo los primeros 4TB
# noatime: igual que en ext4
mount -o noatime,largeio,inode64 /dev/sdb2 /mnt/datos-xfs
# Verificar y reparar XFS (solo con filesystem DESMONTADO o en modo solo lectura)
# xfs_repair -n: modo check sin modificar (equivalente a fsck -n)
# Si el sistema arrancó con el filesystem sucio, xfs_repair lo detecta
# y aplica el log antes de verificar estructuras
umount /mnt/datos-xfs
xfs_repair -n /dev/sdb2 # no modifica nada; quitar -n para reparar de verdad
mount -o noatime,largeio,inode64 /dev/sdb2 /mnt/datos-xfs
# ── Btrfs ────────────────────────────────────────────────────────────────────
# -L datos-btrfs: etiqueta
# --checksum xxhash: checksum de datos y metadatos con xxHash (más rápido que
# crc32c para CPUs modernas sin aceleración hardware de crc)
# Disponible desde kernel 5.5; Bookworm trae 6.1, sin problema
mkfs.btrfs -L datos-btrfs --checksum xxhash /dev/sdb3
mkdir -p /mnt/datos-btrfs
# compress=zstd:3: compresión zstd nivel 3 en escritura; transparente para apps;
# nivel 3 equilibra CPU y ratio; nivel 1 para latencia mínima
# space_cache=v2: mapa de espacio libre en árbol B-tree (v2), más eficiente que v1
# noatime: igual que en los anteriores
mount -o noatime,compress=zstd:3,space_cache=v2 /dev/sdb3 /mnt/datos-btrfs
# Crear un subvolumen (unidad lógica dentro del filesystem, base para snapshots)
btrfs subvolume create /mnt/datos-btrfs/activo
# Snapshot de solo lectura — atómico, coste de espacio casi cero en el momento
# de creación gracias a CoW
btrfs subvolume snapshot -r \
/mnt/datos-btrfs/activo \
/mnt/datos-btrfs/snap-$(date +%Y%m%d-%H%M%S)
# Estado del filesystem: uso real vs. espacio reservado, ratios de compresión,
# distribución de datos y metadatos
btrfs filesystem usage /mnt/datos-btrfs
# Scrub: verificación de integridad comparando datos contra checksums almacenados
# Es la operación de mantenimiento periódico imprescindible en Btrfs
# A diferencia de fsck, se puede ejecutar con el filesystem MONTADO
btrfs scrub start /mnt/datos-btrfs
btrfs scrub status /mnt/datos-btrfs
# ── fsck.ext4: nunca con el filesystem montado ───────────────────────────────
umount /mnt/datos-ext4
# -n: solo lectura, no modifica
# -f: forzar comprobación aunque el filesystem esté marcado como limpio
# -v: verbose — muestra contadores de inodos, bloques, directorios examinados
fsck.ext4 -nfv /dev/sdb1
Qué está pasando debajo de cada decisión
El flag -E lazy_itable_init=0 en mkfs.ext4 merece atención: cuando lo omites, el kernel inicia las tablas de inodos en segundo plano durante las primeras horas de uso del filesystem. En producción eso se traduce en I/O inesperado justo cuando el servidor está en carga, lo que hace difícil distinguir si el rendimiento degradado es un problema real o el init de inodos. Pagarlo al formatear es la opción correcta si el servidor va a entrar en producción poco después.
La opción -d agcount=8 en mkfs.xfs no es decorativa. Cada allocation group de XFS tiene su propio lock para la allocación de bloques e inodos. Con un AG único (el mínimo posible), todos los hilos compiten por el mismo lock y el throughput no escala con CPUs. Con 8 AGs en una máquina de 8 cores, la allocación puede ocurrir en paralelo real. El xfs_info que sigue al formateo te muestra la configuración exacta: tamaño de AG, tamaño de bloque, y si están activas features como reflink o finobt (B-tree de inodos libres, activado por defecto en Bookworm).
Para Btrfs, el --checksum xxhash en lugar del crc32c por defecto tiene implicaciones reales de CPU: en servidores con muchas escrituras pequeñas, el coste de calcular checksums para cada bloque es apreciable. xxHash es significativamente más rápido en software puro, aunque en CPUs Intel/AMD recientes con instrucción crc32 en hardware, crc32c puede ser competitivo. Si vas a usar Btrfs en producción, benchmarca ambos en tu hardware con fio antes de decidir.
El btrfs scrub del ejemplo es la operación de mantenimiento que diferencia Btrfs de ext4 y XFS: lee cada bloque del disco, calcula su checksum, y lo compara con el almacenado. Si tiene un segundo dispositivo en el pool (RAID1), puede autocorregir silenciosamente errores de bit rot. En ext4 y XFS, los checksums solo cubren metadatos (y en ext4, solo con metadata_csum activo); un bit incorrecto en los datos pasa desapercibido. Por eso en entornos donde la integridad de datos a largo plazo es crítica —backups, archivos— Btrfs o ZFS son la única defensa real a nivel de filesystem.
El motivo por el que fsck.ext4 nunca se ejecuta con el filesystem montado no es solo una advertencia de seguridad: el VFS del kernel y el fsck acceden a las estructuras del filesystem sin coordinación entre sí. El fsck puede ver un estado intermedio de una escritura en vuelo y “corregir” estructuras que el kernel estaba modificando correctamente, dejando el filesystem corrupto. En Btrfs, el scrub es seguro en caliente precisamente porque trabaja a través del propio árbol CoW, que garantiza consistencia estructural en todo momento.
[Ubuntu]: En Ubuntu, Btrfs aparece como opción de instalación desde hace varios releases y algunas variantes lo usan por defecto en el root. ZFS está disponible mediante zfsutils-linux con soporte oficial de Canonical desde Ubuntu 20.04. En Debian, ZFS no está en los repositorios principales por incompatibilidad de licencias entre CDDL y GPL, aunque está disponible en contrib como módulo DKMS.
[otras familias]: En RHEL/Fedora, XFS es el filesystem por defecto para el sistema operativo, y Btrfs fue eliminado del soporte de RHEL 8 en adelante; Fedora lo usa por defecto en instalaciones nuevas desde Fedora 33.
N° 87