Terminamos la lección anterior señalando una costura que llevamos ignorando todo el módulo. Cuando recorremos /var/lib/meteora/lecturas/2026-08-31.dat componente a componente, damos por hecho que el árbol es una cosa homogénea. No lo es. / es un ext4 sobre una partición del primer NVMe; /var/lib/meteora es otro ext4, sobre el RAID 1 /dev/md0; /run es tmpfs y vive en la RAM; /proc no tiene ningún dispositivo detrás y sus ficheros se inventan en el momento de leerlos. Cuatro sistemas de archivos radicalmente distintos, con estructuras internas incompatibles, y sin embargo la resolución de rutas camina de uno a otro sin enterarse.

Esta lección explica cómo se consigue eso, y lo hace en dos mitades que se complementan. La primera es de administración: cómo se trocea un dispositivo de bloques en particiones, cómo LVM añade una capa de flexibilidad encima, cómo se crea un sistema de archivos y —la operación central— qué ocurre exactamente al ejecutar mount, con /etc/fstab campo a campo y las opciones que protegen de verdad. La segunda es de arquitectura: el Sistema de Archivos Virtual (VFS), la capa de indirección del núcleo que hace que el mismo open() funcione sobre un SSD, sobre la RAM y sobre un servidor al otro lado de la red.

Al terminar sabrás particionar y montar un servidor con criterio, entender por qué separar /var de / no es manía sino prevención, resolver el "target is busy" que todo el mundo sufre, y explicar con precisión por qué /proc/cpuinfo se comporta como un fichero sin serlo.

Contenido

  1. Del dispositivo de bloques a la partición: MBR y GPT
  2. Esquema de particionado de un servidor y por qué separar /var
  3. Ver lo que hay: lsblk, fdisk -l y blkid
  4. LVM: volúmenes físicos, grupos de volúmenes y volúmenes lógicos
  5. Instantáneas de LVM para copiar /var/lib/meteora en caliente
  6. Crear el sistema de archivos con mkfs
  7. El montaje: qué ocurre exactamente al ejecutar mount
  8. Identificación estable: UUID, etiquetas y /etc/fstab campo a campo
  9. Opciones de montaje y qué protege cada una
  10. Desmontar, "target is busy" y cómo resolverlo
  11. Montajes bind y espacios de nombres de montaje
  12. El Sistema de Archivos Virtual (VFS) y sus cuatro objetos
  13. Sistemas de archivos virtuales y en memoria
  14. Sistemas de archivos en red: NFS y SMB

Del dispositivo de bloques a la partición: MBR y GPT

En el módulo 2 dejamos el disco como un vector de bloques direccionables por LBA. Una partición es simplemente un rango contiguo de ese vector declarado como una unidad independiente: "del LBA 2048 al 1050623, esto es una cosa". Nada más. La partición no impone formato ni contenido; solo delimita.

¿Por qué particionar en lugar de usar el disco entero? Por cuatro razones que siguen siendo válidas: aislar el llenado (si /var/log se desborda, no debe impedir que puedas iniciar sesión), aplicar políticas distintas de montaje a cada zona, usar sistemas de archivos distintos según la carga (04-01), y satisfacer los requisitos de arranque (la UEFI exige una partición FAT32; el cifrado de disco necesita /boot sin cifrar).

La tabla de particiones vive en los primeros sectores del disco, y hay dos formatos. MBR (Master Boot Record), de 1983, ocupa los primeros 512 bytes: 446 para el código de arranque, 64 para la tabla —4 entradas de 16 bytes— y 2 para la firma 0x55AA. GPT (GUID Partition Table), parte de UEFI, usa una cabecera en el LBA 1 y un array de entradas de 128 bytes, con una copia completa al final del disco.

MBR GPT
Año 1983 1998
Tamaño máximo de disco 2 TiB (LBA de 32 bits × 512 B) 8 ZiB
Particiones primarias 4 128 (por defecto en Linux)
Particiones extendidas Necesarias para pasar de 4 No existen: todas son iguales
Redundancia de la tabla Ninguna Copia al final del disco
Suma de verificación No CRC32 de cabecera y entradas
Identificación Número de partición GUID único por partición y por disco
Etiquetas de partición No Sí, 36 caracteres
Tipo de partición 1 byte (83, 82, 8e...) GUID de 16 bytes
Arranque BIOS heredada UEFI (y BIOS con bios_grub)
Protección heredada MBR protector en el LBA 0

Tres diferencias importan de verdad. El límite de 2 TiB de MBR es infranqueable: inicio y tamaño se guardan en 32 bits de sectores de 512 bytes, y 2³² × 512 = 2 TiB, así que cualquier disco de 4 u 8 TB exige GPT. La redundancia: en MBR, corromper 512 bytes destruye la tabla y el acceso a todo; GPT guarda una copia íntegra al final y verifica ambas con CRC32, de modo que gdisk reconstruye una a partir de la otra —la diferencia entre "he perdido el disco" y "he tardado un minuto"—. Y el MBR protector: GPT escribe en el LBA 0 un MBR falso con una partición de tipo 0xEE que cubre todo el disco, para que una herramienta antigua lo vea como ocupado y no lo formatee alegremente.

Regla actual: usa GPT siempre, salvo que necesites arrancar una BIOS heredada muy antigua.

Esquema de particionado de un servidor y por qué separar /var

Este es el esquema real de meteo-01, con dos NVMe de 512 GB en RAID 1 (02-05) más el volumen de datos:

Partición Tamaño Tipo Punto de montaje Sistema de archivos
/dev/nvme0n1p1 512 MiB EFI System /boot/efi FAT32
/dev/nvme0n1p2 1 GiB Linux /boot ext4
/dev/nvme0n1p3 40 GiB Linux / ext4
/dev/nvme0n1p4 20 GiB Linux /var ext4
/dev/nvme0n1p5 8 GiB Linux swap swap
/dev/md0 196 GiB RAID 1 /var/lib/meteora ext4 (noatime)

Y ahora la justificación, que es lo que importa. Separar /var de / no es un ritual heredado: previene un modo de fallo concreto y frecuente.

/var contiene todo lo que crece sin control: logs, colas de correo, cachés, bases de datos, imágenes de contenedores. Si comparte partición con / y un log se desboca, ningún proceso puede crear temporales, systemd no puede escribir su estado, sudo puede fallar al no poder registrar, la shell no guarda historial ni ficheros de bloqueo, y —lo grave— no puedes iniciar sesión, porque tu perfil necesita escribir.

Esa última consecuencia es todo el argumento: un / lleno es un servidor que no te deja entrar a arreglarlo. Con /var separado, un log desbocado llena /var, fallan los servicios de esa partición, y / conserva espacio para que puedas conectarte, diagnosticar y borrar. Es también la razón del -m 5 que ext4 reserva por defecto para root (04-01) y de que en / no debas bajarlo.

El mismo razonamiento, aplicado al resto: /boot mantiene el núcleo accesible aunque / esté cifrado o dañado; /home impide que un usuario llene el sistema y permite reinstalar sin perder datos; /tmp montado noexec,nosuid corta muchos exploits; y /var/lib/meteora aísla datos irrecuperables en su propio RAID, con su propio mkfs y su noatime.

El contraargumento honesto: las particiones fijas desperdician espacio/ con 30 GiB libres no ayuda a /var lleno— y son difíciles de redimensionar. Esa es exactamente la carencia que LVM viene a resolver.

Ver lo que hay: lsblk, fdisk -l y blkid

Tres herramientas, tres puntos de vista. Nunca formatees ni particiones sin haber mirado las tres.

lsblk muestra el árbol de dispositivos de bloques: qué contiene qué.

$ lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT
NAME          SIZE TYPE  FSTYPE            MOUNTPOINT
nvme0n1     476,9G disk
├─nvme0n1p1   512M part  vfat              /boot/efi
├─nvme0n1p3    40G part  ext4              /
├─nvme0n1p4    20G part  ext4              /var
└─nvme0n1p6   196G part  linux_raid_member
  └─md0       196G raid1 ext4              /var/lib/meteora
nvme1n1     476,9G disk
└─nvme1n1p1   196G part  linux_raid_member
  └─md0       196G raid1 ext4              /var/lib/meteora

Lo valioso es la jerarquía: se ve que md0 está formado por dos particiones de discos distintos y que es él, y no ellas, quien lleva el ext4. TYPE distingue disk, part, raid1, lvm y crypt. Y un campo vacío en MOUNTPOINT significa que no está montado, que es lo primero que hay que comprobar antes de tocar nada.

fdisk -l entra en la tabla de particiones:

$ sudo fdisk -l /dev/nvme0n1
Disco /dev/nvme0n1: 476,94 GiB, 512110190592 bytes, 1000215216 sectores
Tamaño de sector (lógico/físico): 512 bytes / 512 bytes
Tipo de etiqueta de disco: gpt

Dispositivo        Comienzo      Final   Sectores Tamaño Tipo
/dev/nvme0n1p1         2048    1050623    1048576   512M Sistema EFI
/dev/nvme0n1p2      1050624    3147775    2097152     1G Sistema de ficheros de Linux
/dev/nvme0n1p3      3147776   87033855   83886080    40G Sistema de ficheros de Linux

Lo que aporta y lsblk no: Tipo de etiqueta de disco: gpt (confirma el formato), los LBA exactos de inicio y fin, y el tamaño de sector lógico/físico. El comienzo en el sector 2048 no es casual: alinea la primera partición a 1 MiB, lo que garantiza que los bloques de 4 KiB del sistema de archivos coincidan con los sectores físicos del disco y con las páginas de borrado del SSD. Una partición mal alineada provoca ciclos leer-modificar-escribir en cada operación y puede costar el 30 % del rendimiento; hoy las herramientas alinean solas, pero conviene saber por qué está ese 2048 ahí.

blkid identifica el contenido: qué sistema de archivos hay y con qué UUID.

$ sudo blkid
/dev/nvme0n1p1: UUID="A1B2-C3D4" TYPE="vfat" PARTLABEL="EFI System"
/dev/nvme0n1p3: UUID="c4e8f1a0-...-3b7d" TYPE="ext4" PARTUUID="8f2a..."
/dev/md0: LABEL="meteora-datos" UUID="9f3a1c22-7d4e-4a51-b7c8-2e5f0a1d6b93" TYPE="ext4"

Ahí está el UUID que usaremos en /etc/fstab, y la etiqueta meteora-datos que pusimos con mkfs -L en 04-01. Ojo con la distinción: UUID identifica el sistema de archivos (lo escribe mkfs en el superbloque) y PARTUUID identifica la partición (lo escribe la tabla GPT). Reformatear cambia el UUID pero no el PARTUUID.

LVM: volúmenes físicos, grupos de volúmenes y volúmenes lógicos

El problema de las particiones fijas es que decides los tamaños el día de la instalación, cuando menos sabes, y cambiarlos después es arriesgado. LVM (Logical Volume Manager) inserta una capa de indirección que lo resuelve, con tres niveles:

graph TB
    PV1["PV: /dev/sdb1 — 500 GB"] --> VG
    PV2["PV: /dev/sdc1 — 500 GB"] --> VG
    VG["<b>VG 'datos' — 1 TB</b><br/>reserva única de extents de 4 MiB"]
    VG --> LV1["LV lv_meteora — 600 GB<br/>ext4 → /var/lib/meteora"]
    VG --> LV2["LV lv_backup — 200 GB<br/>ext4 → /srv/backup"]
    VG --> LV3["200 GB SIN ASIGNAR<br/>(margen para crecer)"]
  • PV (physical volume): un dispositivo de bloques —partición, disco entero o RAID— entregado a LVM.
  • VG (volume group): la unión de varios PV en una reserva única de espacio, dividida en extents de 4 MiB.
  • LV (logical volume): un dispositivo de bloques virtual construido con extents del VG. Sobre él se hace mkfs y se monta, exactamente igual que sobre una partición.

La creación completa, y después la ampliación en caliente, sin desmontar ni parar el servicio:

sudo pvcreate /dev/sdb1 /dev/sdc1              # 1. declarar los PV
sudo vgcreate datos /dev/sdb1 /dev/sdc1        # 2. crear el VG 'datos' (1 TB)
sudo lvcreate -L 600G -n lv_meteora datos      # 3. crear un LV de 600 GB
sudo mkfs.ext4 /dev/datos/lv_meteora           # 4. formatearlo

sudo lvextend -L +100G /dev/datos/lv_meteora   # 5. +100 GB al volumen lógico
sudo resize2fs /dev/datos/lv_meteora           # 6. y al sistema de archivos

Dos pasos porque son dos capas: lvextend agranda el dispositivo virtual y resize2fs extiende el ext4 para que ocupe el espacio nuevo. El orden importa: al ampliar, primero el volumen y luego el sistema de archivos; al reducir, al revés —primero resize2fs para encoger el ext4 y después lvreduce—, porque si reduces el volumen antes que el sistema de archivos, cortas datos y los pierdes. lvresize -r hace ambos pasos en el orden correcto y es la forma segura de hacerlo. Una nota que conecta con 04-01: ext4 se puede reducir; XFS no, porque xfs_growfs solo crece; es un argumento fuerte a favor de ext4 cuando no sabes cómo evolucionarán tus volúmenes.

Capacidad Particiones fijas LVM
Redimensionar en caliente Muy difícil y arriesgado Sí, un comando
Un volumen sobre varios discos No
Añadir un disco a un volumen existente No (vgextend + lvextend)
Instantáneas No
Mover datos entre discos en caliente No (pvmove)
Complejidad y capas que pueden fallar Mínima Mayor

Instantáneas de LVM para copiar /var/lib/meteora en caliente

Aquí está la funcionalidad que resuelve un problema real de Meteora. Copiar /var/lib/meteora/lecturas/2026-09-01.dat mientras el ingestor escribe en él produce una copia inconsistente: el principio del fichero es de las 03:00 y el final de las 03:04, con una estructura Lectura posiblemente cortada por la mitad. Parar el servicio media hora cada noche no es aceptable.

Una instantánea (snapshot) de LVM congela el estado de un volumen en un instante:

# 1. Crear la instantánea (instantáneo: menos de un segundo)
sudo lvcreate -L 20G -s -n snap_meteora /dev/datos/lv_meteora

# 2. Montarla en solo lectura
sudo mkdir -p /mnt/snap
sudo mount -o ro /dev/datos/snap_meteora /mnt/snap

# 3. Copiar con calma: el contenido está congelado, el servicio sigue vivo
sudo tar czf /srv/backup/meteora-$(date +%F).tar.gz -C /mnt/snap .

# 4. Desmontar y ELIMINAR la instantánea
sudo umount /mnt/snap
sudo lvremove -y /dev/datos/snap_meteora

Cómo funciona: la instantánea no copia nada al crearse. Es una tabla vacía más una regla de copia en la primera escritura (copy-on-write): cuando el ingestor escribe en un bloque del volumen original, LVM primero copia el contenido antiguo a la zona de la instantánea y después deja escribir. Así, quien lee la instantánea ve el estado congelado y quien lee el original ve el actual.

Y ahora la advertencia, que es la parte que la gente ignora y luego lamenta:

Coste Detalle
Penalización de escritura Cada escritura nueva sobre un bloque no copiado se convierte en leer + escribir + escribir. La caída típica es del 20-40 %, y con muchas instantáneas activas se multiplica
Espacio finito La instantánea tiene un tamaño fijo (los 20 GB del ejemplo). Almacena los bloques originales de todo lo que cambie mientras viva
Desbordamiento = pérdida Si se llena, la instantánea se invalida por completo y la copia se pierde. El volumen original no sufre, pero tu copia sí
Vida corta Cuanto más tiempo viva, más cambios acumula y más lento va todo. Se crea, se usa y se elimina

Dimensionarla es aritmética: si Meteora escribe 17,3 MB al día y la copia tarda 20 minutos, cambiarán unos 240 KB, así que 20 GB dan margen de sobra incluso para un pico anómalo. La vigilancia se hace con lvs, mirando la columna Data%; si se acerca al 100 %, hay que ampliarla con lvextend ya:

$ sudo lvs
  LV            VG     Attr       LSize   Origin      Data%
  lv_meteora    datos  owi-aos--- 600,00g
  snap_meteora  datos  swi-aos---  20,00g lv_meteora   0,12

Un matiz de honestidad técnica: la instantánea congela los bloques del dispositivo, no la memoria. Si el ingestor tenía datos en la caché de páginas sin volcar, la instantánea no los tiene. Por eso la copia perfecta lleva un paso previo: pedir al servicio que haga fsync() (o enviarle SIGHUP), ejecutar sync, y entonces crear la instantánea. Lo veremos al hablar de fsync en Gestión de Archivos, y las garantías de consistencia son el tema de Asignación de Espacio, Journaling e Integridad.

Crear el sistema de archivos con mkfs

mkfs escribe sobre el dispositivo las estructuras que estudiamos en 04-01: superbloque, descriptores de grupo, mapas de bits y tabla de inodos. No pregunta y no avisa: si el dispositivo es el equivocado, los datos anteriores dejan de ser accesibles al instante.

Las opciones que de verdad se usan, y qué decide cada una:

Opción Qué hace Cuándo tocarla
-b 4096 Tamaño de bloque Bajar a 1024 con millones de ficheros pequeños (04-01)
-i N Un inodo por cada N bytes Subirlo con pocos ficheros grandes; bajarlo con muchos pequeños
-N N Número exacto de inodos Cuando sabes la cifra exacta
-m N Porcentaje reservado para root 5 % en /; 1 % o 0 % en volúmenes de datos
-L etiqueta Etiqueta del sistema de archivos Siempre: facilita /etc/fstab y el diagnóstico
-O car Activar/desactivar características extent, dir_index, metadata_csum, ^has_journal
-E stride=,stripe_width= Alinear con la geometría del RAID Con RAID 5/6, marca diferencias reales
-n Simulacro: no escribe nada Antes de cada mkfs real

El procedimiento seguro, con el simulacro incluido:

lsblk /dev/md0 ; sudo blkid /dev/md0 ; findmnt --source /dev/md0   # 1-3. verificar
sudo mkfs.ext4 -n -b 4096 -i 1048576 -m 1 -L meteora-datos /dev/md0   # 4. simulacro
sudo mkfs.ext4    -b 4096 -i 1048576 -m 1 -L meteora-datos /dev/md0   # 5. de verdad

Los tres primeros comandos responden "¿es el dispositivo correcto?", "¿qué contiene ahora?" y "¿está montado?" en cinco segundos, y evitan el accidente más caro de la administración de sistemas. El paso 4 con -n imprime exactamente lo que haría —número de inodos, de bloques, posiciones de los superbloques de respaldo— sin tocar nada.

El montaje: qué ocurre exactamente al ejecutar mount

Llegamos a la operación central. Montar es injertar el árbol de un sistema de archivos en un punto del árbol global, de modo que la resolución de rutas cruce de uno a otro sin notarlo.

sudo mount /dev/md0 /var/lib/meteora

Los pasos que ejecuta el núcleo, en orden:

  1. Resolver el punto de montaje. /var/lib/meteora se convierte en un inodo, con el algoritmo de 04-02. Debe existir y ser un directorio; si no, ENOTDIR o ENOENT.
  2. Abrir el dispositivo y leer su superbloque, que en ext4 empieza en el byte 1024: de ahí salen el tamaño de bloque, el número de inodos, la posición de la tabla de inodos, el UUID, las características activas y el estado.
  3. Comprobar el estado. Si dice "sucio" —no se desmontó bien—, se dispara la recuperación desde el diario (04-05). Si exige características que este núcleo no soporta, se rechaza el montaje.
  4. Crear un objeto superblock en memoria, la representación viva del sistema de archivos, con sus operaciones (leer inodo, escribir inodo, estadísticas...).
  5. Crear una estructura vfsmount que asocia ese superblock con el inodo del punto de montaje.
  6. Enganchar la dentry. A partir de ahora, cuando la resolución de rutas llegue a la dentry de /var/lib/meteora, verá la marca de "aquí hay un montaje" y saltará al inodo raíz del nuevo sistema de archivos.
  7. Registrarlo en la tabla de montajes, visible en /proc/mounts.

El paso 6 es la clave de todo, y explica el comportamiento más desconcertante del montaje:

Montar sobre un directorio no vacío no borra su contenido: lo oculta. Los ficheros siguen ahí, intactos, pero la ruta ya no llega a ellos porque el paso 6 desvía la resolución.

Se comprueba fácilmente:

sudo touch /var/lib/meteora/OCULTO.txt
ls /var/lib/meteora                       # → OCULTO.txt
sudo mount /dev/md0 /var/lib/meteora
ls /var/lib/meteora                       # → lecturas/  archivo/   (¡sin OCULTO.txt!)
sudo umount /var/lib/meteora
ls /var/lib/meteora                       # → OCULTO.txt  (¡ha vuelto!)

De ahí un incidente clásico: alguien escribe datos en /var/lib/meteora antes de montar el volumen, luego monta, y esos datos desaparecen de la vista mientras siguen ocupando espacio invisible en /. Para verlos sin desmontar existe el truco del bind mount del apartado 11.

La tabla de montajes:

$ cat /proc/mounts
/dev/nvme0n1p3 / ext4 rw,relatime 0 0
/dev/nvme0n1p4 /var ext4 rw,relatime 0 0
/dev/md0 /var/lib/meteora ext4 rw,noatime 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
tmpfs /run tmpfs rw,nosuid,nodev,size=1608040k,mode=755 0 0
tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0
devtmpfs /dev devtmpfs rw,nosuid,size=4096k,nr_inodes=2003417 0 0

/proc/mounts es la verdad del núcleo, con las opciones realmente en vigor. mount sin argumentos muestra lo mismo, y findmnt lo presenta en árbol: acepta un punto de montaje o un dispositivo, filtra por tipo (-t ext4) y devuelve un código de salida útil para scripts, así que es la herramienta a usar.

Identificación estable: UUID, etiquetas y /etc/fstab campo a campo

Un problema real: los nombres /dev/sdX no son estables. Se asignan en el orden en que el núcleo detecta los discos, que depende de la velocidad de arranque de cada controlador, del orden de los puertos y de si hay un USB conectado; el disco que hoy es /dev/sdb puede ser /dev/sdc mañana, y una entrada de fstab que lo nombre montará el volumen equivocado o fallará el arranque. Las cuatro formas de identificar un dispositivo:

Forma Qué identifica Estabilidad Ejemplo
/dev/sdb1 Nombre del núcleo Mala Cambia con el orden de detección
LABEL= Etiqueta del sistema de archivos Buena, pero puede duplicarse LABEL=meteora-datos
UUID= Sistema de archivos, por mkfs Excelente UUID=9f3a1c22-7d4e-...
PARTUUID= Partición, por GPT Excelente, sobrevive al formateo PARTUUID=8f2a...

Usa UUID= en /etc/fstab. Es lo que hacen todos los instaladores modernos. La única precaución: el UUID cambia al reformatear, así que tras un mkfs hay que actualizar fstab o el sistema no arrancará.

El /etc/fstab real de meteo-01:

# <sistema de archivos>                        <punto>            <tipo> <opciones>                      <dump> <pass>
UUID=c4e8f1a0-2b19-4d7c-9e35-6a80f2c13b7d      /                  ext4   defaults                         0      1
UUID=A1B2-C3D4                                 /boot/efi          vfat   umask=0077,shortname=winnt       0      2
UUID=7d3e9b41-05fa-4c28-8b16-d9e4a7c0f582      /boot              ext4   defaults,nosuid,nodev,noexec     0      2
UUID=b81f6c30-9a24-4e5d-af73-1c206e8b4d95      /var               ext4   defaults,nosuid,nodev            0      2
UUID=9f3a1c22-7d4e-4a51-b7c8-2e5f0a1d6b93      /var/lib/meteora   ext4   noatime,nosuid,nodev,noexec      0      2
UUID=3f8a2c17-6d40-4b91-a5e8-7c1b09d3e264      none               swap   sw                               0      0
tmpfs                                          /tmp               tmpfs  rw,nosuid,nodev,noexec,size=2G   0      0

Los seis campos, uno a uno:

  1. Origen. Qué montar: UUID, etiqueta, dispositivo, o un nombre arbitrario para los sistemas virtuales (tmpfs, proc).
  2. Punto de montaje. Dónde. Para swap, none.
  3. Tipo. ext4, vfat, tmpfs, swap, nfs... o auto para que mount lo deduzca leyendo el superbloque.
  4. Opciones, separadas por comas y sin espacios. Es el campo del apartado siguiente.
  5. dump. Reliquia de la utilidad dump de los años 80. Hoy siempre 0.
  6. pass. Orden de comprobación con fsck al arrancar: 1 para la raíz, 2 para las demás (se comprueban en paralelo si están en discos distintos) y 0 para no comprobar —obligatorio en tmpfs y sistemas de red, que no tienen fsck—.

El error más peligroso de todo este módulo vive en fstab: una línea mal escrita puede impedir que la máquina arranque, dejándola en modo de emergencia sin acceso remoto. El procedimiento seguro es innegociable:

sudo cp /etc/fstab /etc/fstab.bak      # 1. copia de seguridad
sudo nano /etc/fstab                   # 2. editar
sudo findmnt --verify --verbose        # 3. VALIDAR sintaxis, UUID y opciones
sudo mount -a                          # 4. montar lo pendiente: si falla, lo dice AQUÍ

findmnt --verify comprueba que los UUID y los puntos de montaje existen y que las opciones son válidas sin montar nada. mount -a intenta montarlo todo: si hay un error, aparece ahora, con la máquina viva, y no en el arranque. Y si algo sale mal de todos modos, la opción nofail evita que el fallo de una entrada bloquee el arranque —muy recomendable en discos externos y montajes de red—.

Opciones de montaje y qué protege cada una

Las opciones del cuarto campo son una de las herramientas de endurecimiento más baratas que existen: cuestan cero rendimiento y cierran clases enteras de ataque.

Opción Qué hace De qué protege
defaults rw,suid,dev,exec,auto,nouser,async Nada: es el conjunto permisivo por omisión
ro Solo lectura Modificaciones accidentales o maliciosas; obligatorio en medios forenses
rw Lectura y escritura (Por defecto)
noexec Prohíbe ejecutar binarios Que se ejecute un programa subido a un directorio de datos o a /tmp
nosuid Ignora los bits setuid/setgid Escalada de privilegios con un binario setuid colocado ahí (04-06)
nodev Ignora los ficheros de dispositivo Que alguien cree un /dev/sda propio y lea el disco crudo saltándose los permisos
noatime No actualiza el atime Escrituras inútiles (04-01)
relatime Atime perezoso (Por defecto desde 2009)
sync Escrituras síncronas Pérdida de datos ante corte; cuesta muchísimo rendimiento
nofail No bloquea el arranque si falla Que un disco ausente deje la máquina en modo de emergencia
errors=remount-ro Ante un error de E/S, remonta en solo lectura Que un disco moribundo siga corrompiendo datos

El trío noexec,nosuid,nodev es la receta estándar para cualquier volumen que contenga solo datos. nosuid es el más importante: sin él, un atacante con permiso de escritura puede colocar una copia de /bin/bash con el bit setuid de root y obtener una shell de superusuario; con nosuid el núcleo ignora ese bit y el ataque no funciona —una palabra en fstab frente a una escalada a root—. nodev cierra la vía análoga con dispositivos: sin él se podría crear un fichero de dispositivo con el mayor/menor de /dev/sda y leer el disco entero saltándose los permisos. Y noexec impide ejecutar binarios desde ahí, aunque no es una barrera fuerte: un script sigue corriendo con bash script.sh y un binario con /lib/ld-linux.so.2 ./binario, así que úsalo como capa de defensa, no como muro.

Por eso /var/lib/meteora se monta con noatime,nosuid,nodev,noexec: contiene datos, nunca programas, así que las cuatro opciones son gratis y cierran tres vectores. Aplicar el mismo trío a /tmp, /var y /home es una de las mejores relaciones esfuerzo/beneficio de la administración de sistemas, y volveremos sobre ello en el módulo 5. Las opciones se pueden cambiar en caliente con mount -o remount,ro /var/lib/meteora (y rw para volver), que es justo lo que hace el núcleo con errors=remount-ro al detectar un error de E/S: congelar las escrituras para no empeorar el daño.

Desmontar, "target is busy" y cómo resolverlo

umount desmonta: vuelca las escrituras pendientes, sincroniza el superbloque, lo marca como limpio (decisivo para 04-05) y desengancha el punto de montaje. Pero:

$ sudo umount /var/lib/meteora
umount: /var/lib/meteora: target is busy.

Un sistema de archivos está ocupado si algún proceso lo está usando, y "usando" incluye cuatro casos que la gente olvida:

  1. Tiene un fichero abierto dentro (04-04).
  2. Tiene su cwd dentro (04-02).
  3. Tiene un fichero mapeado en memoria con mmap() (02-04).
  4. Hay otro montaje encima de un subdirectorio suyo.

El diagnóstico, con dos herramientas complementarias:

$ sudo lsof +f -- /var/lib/meteora
COMMAND    PID    USER   FD   TYPE DEVICE     SIZE/OFF   NODE NAME
meteo-api 2841 meteora  cwd    DIR    9,0         4096 1180928 /var/lib/meteora
meteo-api 2841 meteora    7r   REG    9,0     17280000 1180934 .../2026-08-31.dat
agregador 2903 meteora  mem    REG    9,0     17280000 1180934 .../2026-08-31.dat

En lsof, la columna FD es la clave: cwd es directorio de trabajo, mem es fichero mapeado, y un número (7r) es un descriptor abierto. fuser -vm /var/lib/meteora dice lo mismo con letras: c (cwd), e (ejecutable en uso), f (fichero abierto), r (raíz) y m (mapeado).

Las soluciones, en orden de preferencia:

sudo systemctl stop meteo-api agregador   # 1. LO CORRECTO: parar quien lo usa
sudo umount /var/lib/meteora

sudo umount -l /var/lib/meteora           # 2. perezoso: desengancha ya, libera después
sudo umount -f /mnt/nfs-remoto            # 3. forzar (montajes de red colgados)
sudo fuser -km /var/lib/meteora           # 4. ÚLTIMO RECURSO: matar a quien lo usa

Sobre las tres últimas, con honestidad. umount -l (lazy) desengancha el punto de montaje inmediatamente de la jerarquía, pero mantiene el sistema de archivos vivo hasta que se cierre el último descriptor: las rutas dejan de funcionar al instante, pero el dispositivo sigue en uso, así que si tu objetivo era desconectarlo o formatearlo, aún no puedes. umount -f está pensado para NFS con el servidor caído, donde los procesos están bloqueados en estado D; en un sistema local puede dejar escrituras sin volcar. Y fuser -k envía SIGKILL, sin dar oportunidad de guardar nada: comprueba antes con fuser -vm a quién vas a matar.

Un cuarto caso, poco conocido pero frecuente: si el sistema de archivos parece libre y aun así está ocupado, mira si tienes otro montaje encima (un bind mount, un contenedor, un overlay) con findmnt -R /var/lib/meteora, que muestra el subárbol de montajes recursivamente.

Montajes bind y espacios de nombres de montaje

Un montaje bind hace visible un directorio ya existente en un segundo punto del árbol. No copia nada ni crea un enlace: es el mismo sistema de archivos montado dos veces.

sudo mkdir -p /srv/publicacion/datos
sudo mount --bind /var/lib/meteora/lecturas /srv/publicacion/datos

Ahora las dos rutas llevan a los mismos inodos. La diferencia con un enlace simbólico es sustancial:

Enlace simbólico Montaje bind
Qué es Un fichero con una ruta dentro Una entrada en la tabla de montajes
Sobrevive al reinicio Sí (está en el disco) No (salvo entrada en fstab)
Funciona dentro de un chroot No (la ruta apunta fuera)
Lo ve un proceso confinado Puede romperse
Opciones distintas al original No : se puede remontar en solo lectura

Esa última fila es la más útil en la práctica: puedes exponer un directorio de datos a un servicio solo para lectura, sin tocar el original, y de paso resolver el enigma del apartado 7 —ver lo que quedó oculto bajo un montaje— sin desmontar nada:

sudo mount -o remount,bind,ro /srv/publicacion/datos   # solo esta vista es de lectura
sudo mount --bind / /mnt/raiz-real     # monta la raíz REAL, sin montajes encima
ls /mnt/raiz-real/var/lib/meteora      # → OCULTO.txt, el fichero escondido
sudo umount /mnt/raiz-real

El servicio que sirve /srv/publicacion/datos no puede escribir; el ingestor, que usa la ruta original, sí. Es el mecanismo detrás de ReadOnlyPaths= de systemd (módulo 7) y de los volúmenes de solo lectura de Docker.

Los montajes bind son, además, la puerta de entrada a un concepto mayor: los espacios de nombres de montaje (mount namespaces). Linux permite que cada proceso tenga su propia tabla de montajes, de modo que /var/lib/meteora signifique cosas distintas para dos procesos de la misma máquina. Es la base de los contenedores, que lo combinan con pivot_root, sistemas de archivos por capas (overlayfs) y cgroups; se ve completo en Contenedores: Namespaces y cgroups. Aquí basta con quedarse con que la tabla de montajes no es necesariamente global, y que /proc/<pid>/mountinfo dice cuál ve cada proceso.

El Sistema de Archivos Virtual (VFS) y sus cuatro objetos

Hemos llegado a la pieza que lo explica todo. Considera este programa:

int a = open("/var/lib/meteora/lecturas/2026-08-31.dat", O_RDONLY);  /* ext4 en NVMe */
int b = open("/dev/shm/meteora-cache",                   O_RDONLY);  /* tmpfs en RAM */
int c = open("/proc/2841/status",                        O_RDONLY);  /* inventado    */
int d = open("/mnt/historico/2025-01-01.dat",            O_RDONLY);  /* NFS por red  */

read(a, buf, 4096);   read(b, buf, 4096);   read(c, buf, 4096);   read(d, buf, 4096);

Cuatro sistemas de archivos incompatibles: uno con inodos y extents en un SSD, otro que vive en la caché de páginas, otro que genera el contenido en el momento de la lectura ejecutando código del núcleo, y otro que traduce cada operación en paquetes de red. Y sin embargo, las mismas cuatro líneas de código funcionan sobre los cuatro.

Eso lo hace posible el VFS (Virtual File System), una capa de abstracción dentro del núcleo:

graph TB
    APP["Proceso en modo usuario<br/>open() read() write() close()"]
    SC["Interfaz de llamadas al sistema (01-06)"]
    VFS["<b>VFS — Sistema de Archivos Virtual</b><br/>superblock · inode · dentry · file"]
    E4["ext4 / XFS"]
    TMP["tmpfs"]
    PROC["procfs / sysfs"]
    NFS["NFS"]
    PC["Caché de páginas (02-04)"]
    BIO["Capa de bloques y planificador (02-05)"]
    DRV["Controlador NVMe (02-07)"]
    HW["/dev/md0 — RAID 1"]
    RAM["RAM"]
    NET["Pila de red → servidor remoto"]
    APP --> SC --> VFS
    VFS --> E4
    VFS --> TMP
    VFS --> PROC
    VFS --> NFS
    E4 --> PC
    TMP --> RAM
    PROC -->|genera al vuelo| RAM
    NFS --> NET
    PC --> BIO --> DRV --> HW

La idea es exactamente la del polimorfismo en programación orientada a objetos, implementada en C con tablas de punteros a función. El VFS define qué operaciones existen; cada sistema de archivos aporta su implementación. Cuando llega un read(), el VFS no sabe leer nada: mira la tabla de operaciones del fichero y llama al puntero correspondiente, que apunta a ext4_file_read_iter, a shmem_file_read_iter o a la función del módulo de procfs.

Los cuatro objetos del VFS, que conviene tener claros porque explican comportamientos concretos:

Objeto Representa Uno por... Estructura Dónde lo has visto
superblock Un sistema de archivos montado Montaje struct super_block Se crea en el paso 4 de mount
inode Un fichero concreto Fichero struct inode El inodo de 04-01, en memoria
dentry Un nombre dentro de un directorio Componente de ruta struct dentry La caché de dentries de 04-02
file Un fichero abierto por un proceso open() struct file El descriptor, tema de 04-04

Las relaciones entre ellos responden preguntas que quizá te hayas hecho. Varias dentries pueden apuntar al mismo inode: eso son los enlaces duros, dos nombres y un fichero. Varios file pueden apuntar al mismo inode: dos procesos que abren el mismo fichero tienen objetos file distintos —cada uno con su desplazamiento y su modo— sobre un solo inode, y de ahí sale todo el comportamiento de descriptores, fork y dup de 04-04. Y el inode del VFS no es el inodo del disco, sino su representación en memoria común a todos los sistemas de archivos: un fichero de procfs tiene inode del VFS aunque en el disco no exista nada.

Un ejemplo de la tabla de operaciones, simplificado del núcleo real:

struct file_operations {                    /* lo que el VFS ESPERA de cualquier FS */
    ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
    ssize_t (*write_iter)(struct kiocb *, struct iov_iter *);
    int     (*fsync)     (struct file *, loff_t, loff_t, int);
    int     (*mmap)      (struct file *, struct vm_area_struct *);
};

const struct file_operations ext4_file_operations = {   /* lo que APORTA ext4 */
    .read_iter = ext4_file_read_iter,   .write_iter = ext4_file_write_iter,
    .fsync     = ext4_sync_file,        .mmap       = ext4_file_mmap,
};

read() en modo usuario acaba, tras el cambio a modo núcleo de 01-06, en vfs_read(), que hace esencialmente file->f_op->read_iter(...). Una indirección por puntero a función, y ahí es donde el camino se bifurca hacia ext4, tmpfs o NFS.

Lo que el VFS aporta, resumido: una sola implementación de las llamadas al sistema para todos los sistemas de archivos; cachés compartidas (páginas, dentries, inodos) que benefician a todos; la posibilidad de añadir un sistema de archivos nuevo como módulo sin tocar el resto del núcleo; y la transparencia que permite que una ruta cruce de ext4 a tmpfs a mitad de camino sin que ningún programa se entere. Es la misma filosofía de máquina extendida de 01-01, aplicada una capa más abajo.

Sistemas de archivos virtuales y en memoria

Con el VFS entendido, los sistemas de archivos "raros" dejan de serlo. Todos implementan la misma interfaz; lo que cambia es de dónde sacan los datos.

Sistema Montado en Dónde están los datos Persistente Para qué
procfs /proc Se generan al leer No Procesos y parámetros del núcleo
sysfs /sys Se generan al leer No Modelo de dispositivos, controladores
devtmpfs /dev RAM No Ficheros de dispositivo, poblado por el núcleo
tmpfs /run, /dev/shm, /tmp Caché de páginas + swap No Datos volátiles rápidos
cgroupfs /sys/fs/cgroup Se generan al leer No Límites de recursos (06-02)
overlayfs Variable Dos capas superpuestas Depende Imágenes de contenedores

procfs es el más peculiar: sus ficheros no existen. Cuando ejecutas cat /proc/2841/status, el read() llega vía VFS a una función del núcleo que recorre el task_struct del proceso 2841 y formatea texto sobre la marcha. Por eso ls -l /proc/2841/status muestra tamaño 0 —el núcleo no sabe cuántos bytes producirá hasta generarlos— y por eso el contenido cambia entre dos lecturas consecutivas. Todo lo que hemos usado del módulo 2 y 3 —/proc/<pid>/maps, /proc/<pid>/stack, /proc/<pid>/fd, /proc/mounts— es esto: una interfaz de consulta al núcleo disfrazada de ficheros, para poder usarla con cat, grep y awk en lugar de con una API especial. Es una de las mejores ideas de Linux.

tmpfs es un sistema de archivos completo cuyo almacén es la caché de páginas. Es rapidísimo, porque una escritura es una copia en RAM; es volátil, y eso es una característica y no un defecto —es por lo que /run/meteora/lecturas.fifo y /run/meteora/api.sock están ahí (04-02)—; crece y encoge dinámicamente hasta el límite de size=; y puede irse a swap bajo presión de memoria, a diferencia de un disco RAM clásico que la inmoviliza.

$ df -h /dev/shm /run /tmp
tmpfs            7,7G   132M  7,5G   2% /dev/shm
tmpfs            1,6G   1,8M  1,6G   1% /run
tmpfs            2,0G    24K  2,0G   1% /tmp

Y aquí se cierra un círculo del módulo 3. La caché de Meteora, /dev/shm/meteora-cache, la creamos con shm_open() + mmap() como memoria compartida POSIX. Ahora ya se ve qué es realmente: shm_open() es un open() sobre un fichero de tmpfs montado en /dev/shm, y mmap() mapea sus páginas en varios procesos. La memoria compartida POSIX en Linux está implementada sobre el sistema de archivos, y por eso puedes hacerle ls -l, chmod y rm como a cualquier otro fichero:

$ ls -l /dev/shm/
-rw-r----- 1 meteora meteora 134217728 sep  1 12:41 meteora-cache

128 MiB de caché que son, a la vez, un fichero y un segmento de memoria compartida. No hay contradicción: es el VFS haciendo su trabajo.

Sistemas de archivos en red: NFS y SMB

El VFS permite algo más ambicioso: que el sistema de archivos esté en otra máquina. El cliente implementa las operaciones del VFS traduciéndolas a peticiones de red.

NFS SMB / CIFS
Origen Sun, 1984 IBM/Microsoft, 1983
Mundo natural UNIX y Linux Windows
Modelo de permisos UID/GID de UNIX ACL de Windows y usuarios de dominio
Estado en el servidor Sin estado hasta NFSv3; con estado en v4 Con estado
Autenticación Confianza en el UID (o Kerberos en v4) Usuario y contraseña, Kerberos
Bloqueo de ficheros Problemático (protocolo aparte hasta v4) Integrado
Puerto típico 2049 445

Montarlos es como montar cualquier otra cosa, lo que es precisamente la gracia del VFS:

sudo mount -t nfs -o vers=4,hard,timeo=600 nas.meteora.local:/export/historico /mnt/historico
sudo mount -t cifs -o credentials=/etc/smb.cred,uid=990,gid=990 //nas/datos /mnt/datos

Los tres problemas que hay que conocer antes de usarlos en producción:

1. La latencia lo cambia todo. Un stat() local cuesta microsegundos; sobre NFS, una ida y vuelta de red: entre 0,1 y 5 ms. Un ls -l de un directorio con 1.000 ficheros hace 1.000 stat(), lo que en local son milisegundos y sobre NFS pueden ser cinco segundos. La causa nunca es el ancho de banda, sino el número de idas y vueltas.

2. La semántica no es la misma. POSIX garantiza que un write() completado es visible de inmediato para cualquier otro proceso; NFS usa coherencia débil, cachea atributos y datos, y otro cliente puede tardar segundos en ver el cambio. Peor aún, el bloqueo de ficheros (flock, que veremos en 04-04) es notoriamente frágil sobre NFS. Regla práctica: no pongas sobre NFS nada que dependa de bloqueos o de escrituras coordinadas entre máquinas, bases de datos en particular.

3. hard frente a soft. Con hard (por defecto), si el servidor deja de responder los procesos se quedan bloqueados indefinidamente en estado D, sin responder ni a SIGKILL: el cuadro clínico del módulo 3 y el motivo del detector hung task de 03-06. La alternativa soft devuelve error tras un tiempo límite, pero puede corromper datos si el error llega a mitad de una escritura. Lo equilibrado es hard más intr (o NFSv4, que permite interrumpir), y montar siempre con nofail.

Meteora usa NFS solo para el archivo histórico de solo lectura en /mnt/historico: datos que ya no cambian, sin bloqueos, sin escrituras concurrentes. /var/lib/meteora, donde el ingestor escribe constantemente, está en almacenamiento local sobre RAID 1, y ahora ya tienes los tres motivos técnicos por los que esa decisión es la correcta.

Errores Comunes y Consejos

Usar /dev/sdX en /etc/fstab. Los nombres del núcleo cambian con el orden de detección. Usa UUID= siempre, y recuerda que el UUID cambia al reformatear.

Editar fstab sin validar. Una línea mal escrita deja la máquina en modo de emergencia en el siguiente arranque, y si es un servidor remoto, sin acceso. Copia de seguridad, findmnt --verify y mount -a antes de reiniciar. Siempre.

Escribir en el punto de montaje antes de montar. Los ficheros quedan ocultos bajo el montaje, ocupando espacio invisible en la partición de abajo. Comprueba con un bind mount de /.

Formatear el dispositivo equivocado. mkfs no pregunta. Los tres comandos de verificación (lsblk, blkid, findmnt --source) más el simulacro con -n cuestan diez segundos y evitan el accidente más caro de la profesión.

Reducir un volumen lógico en el orden equivocado. Al ampliar: lvextend y después resize2fs. Al reducir: resize2fs primero y después lvreduce. Invertirlo al reducir corta datos. Usa lvresize -r, que lo hace bien solo.

Dejar instantáneas de LVM vivas indefinidamente. Cuestan un 20-40 % de rendimiento de escritura y, si se llenan, se invalidan y pierdes la copia. Crear, usar y eliminar.

Recurrir a umount -l como respuesta refleja al "target is busy". Oculta el problema: el sistema de archivos sigue en uso aunque haya desaparecido del árbol. Diagnostica primero con lsof o fuser, y para el servicio.

Montar sistemas de archivos de red sin nofail. Un NAS apagado bloquea el arranque del servidor. Y con hard, un servidor caído deja procesos en D que no mueren ni con kill -9.

Consejo: monta los volúmenes de datos con nosuid,nodev,noexec —tres palabras que cierran tres vectores de ataque— y usa findmnt en lugar de mount a secas, que muestra el árbol, filtra, verifica y devuelve códigos de salida útiles en scripts.

Ejercicios

Ejercicio 1: diagnosticar el árbol de montajes

En una máquina cualquiera, ejecuta lsblk -f, findmnt, blkid y cat /proc/mounts, y responde: (a) ¿cuántos sistemas de archivos hay montados y cuántos tienen un dispositivo real detrás?; (b) ¿qué opciones tiene /tmp y qué protege cada una?; (c) ¿cuánta RAM están consumiendo los tmpfs ahora mismo?; (d) crea un fichero en /dev/shm y localiza dónde aparece su memoria en free -h. Explica el resultado de (d) con lo que sabes del VFS y de la caché de páginas.

Ejercicio 2: diseñar el particionado y el fstab de un servidor

Vas a instalar un meteo-02 con un NVMe de 1 TB y dos discos SATA de 4 TB para el histórico. Diseña el esquema completo: tabla de particiones (justificando MBR o GPT), particiones con sus tamaños y sistemas de archivos, uso o no de LVM, y el /etc/fstab íntegro con los seis campos y las opciones de montaje justificadas una a una. Explica qué protege cada separación y qué pasaría si no la hicieras. El servidor ejecutará los tres servicios de Meteora y guardará cinco años de histórico.

Ejercicio 3: copia consistente con instantáneas

/var/lib/meteora está sobre un volumen lógico de 600 GB y el ingestor escribe sin parar. Escribe el script completo de copia de seguridad nocturna que produzca una copia consistente sin parar el servicio: dimensionamiento justificado de la instantánea, la secuencia de comandos con su control de errores, la comprobación de que la instantánea no se ha desbordado, y la limpieza garantizada aunque el script falle a la mitad. Explica además por qué sync antes de crear la instantánea no basta del todo y qué haría falta para una copia perfecta.

Soluciones

Solución 1

(a) wc -l < /proc/mounts da el total y grep -c '^/dev/' /proc/mounts los que tienen dispositivo real. En un sistema típico salen entre 25 y 40 montajes, de los cuales solo 3 a 6 tienen un dispositivo real; todo lo demás es procfs, sysfs, tmpfs, devtmpfs, cgroupfs, devpts, securityfs... El sistema de archivos que ves es mayoritariamente una construcción en memoria, y esa es la mejor demostración práctica de para qué sirve el VFS.

(b) findmnt /tmp da algo como rw,nosuid,nodev,noexec,relatime,size=2097152k. nosuid impide la escalada con un binario setuid depositado ahí —/tmp es escribible por todos, así que es el sitio natural para intentarlo—; nodev impide crear un /dev/sda casero y leer el disco crudo; noexec impide ejecutar directamente un binario descargado (aunque no bloquea bash script.sh); y size=2G limita cuánta RAM puede consumir.

(c) df -h -t tmpfs: la columna "Usados" de cada tmpfs es RAM ocupada ahora mismo, y suele rondar unos cientos de MiB entre /run, /dev/shm y /tmp.

(d)

free -h                                    # anota "buff/cache" y "disponible"
dd if=/dev/zero of=/dev/shm/prueba bs=1M count=512 status=none
free -h                                    # buff/cache sube ~512 MiB
ls -l /dev/shm/prueba                      # el fichero existe y mide 536870912
rm /dev/shm/prueba
free -h                                    # baja de nuevo

Explicación. tmpfs no tiene dispositivo: sus páginas son páginas de la caché de páginas (02-04), así que free las contabiliza en buff/cache. La diferencia con una caché normal es crucial: las páginas de tmpfs no se pueden descartar, porque no hay copia en ningún disco del que releerlas; solo pueden irse a swap. Por eso un tmpfs sin size= puede llegar a agotar la memoria del sistema y disparar el OOM killer de 02-04, y por eso todos los tmpfs del sistema llevan un límite.

Solución 2

Tabla de particiones: GPT, porque los discos de 4 TB superan el límite de 2 TiB de MBR; además aporta redundancia y CRC.

Dispositivo Tamaño FS Punto Justificación
nvme0n1p1 512 MiB vfat /boot/efi Exigido por UEFI
nvme0n1p2 1 GiB ext4 /boot Núcleos; fuera de LVM para simplificar el arranque
nvme0n1p3 16 GiB swap Con 32 GB de RAM, media para presión puntual
nvme0n1p4 resto LVM PV Todo lo demás bajo LVM, para poder redimensionar
lv_root 40 GiB ext4 / Sistema base con holgura
lv_var 40 GiB ext4 /var Logs y colas aisladas de /
lv_meteora 600 GiB ext4 /var/lib/meteora Datos activos, con margen
sin asignar ~300 GiB Deliberado: reserva para ampliar donde haga falta
md1 (RAID 1, 4 TB) 3,6 TiB ext4 /srv/historico Cinco años de histórico con redundancia

Dejar espacio sin asignar en el VG es una decisión de diseño, no un descuido: como LVM amplía en caliente, es mejor repartir cuando sepas dónde hace falta que adivinar el día de la instalación.

UUID=<efi>       /boot/efi         vfat   umask=0077,shortname=winnt              0 2
UUID=<boot>      /boot             ext4   defaults,nosuid,nodev,noexec            0 2
/dev/vg0/lv_root /                 ext4   defaults,errors=remount-ro              0 1
/dev/vg0/lv_var  /var              ext4   defaults,nosuid,nodev                   0 2
/dev/vg0/lv_met  /var/lib/meteora  ext4   noatime,nosuid,nodev,noexec             0 2
/dev/md1         /srv/historico    ext4   noatime,nosuid,nodev,noexec,nofail      0 2
UUID=<swap>      none              swap   sw                                      0 0
tmpfs            /tmp              tmpfs  rw,nosuid,nodev,noexec,size=4G          0 0

Justificación de las opciones no obvias: errors=remount-ro en / hace que un error de E/S pase el volumen a solo lectura en lugar de seguir corrompiéndose; nosuid,nodev en /var porque no hay motivo legítimo para un binario setuid ahí, pero sin noexec porque algunos gestores de paquetes ejecutan cosas desde /var/lib; noexec sí en /var/lib/meteora y /srv/historico, que son datos puros; pass=1 solo en /, 2 en el resto y 0 en swap y tmpfs, que no tienen fsck; nofail en /srv/historico para que un RAID que no ensamble no impida arrancar; y /tmp como tmpfs de 4 GB, rápido, autolimpiante y con límite para que no agote la RAM.

Qué pasaría sin las separaciones. Sin /var separado, un log desbocado llenaría / y no podrías iniciar sesión para arreglarlo. Sin /var/lib/meteora separado, no podrías aplicarle noatime ni un mkfs afinado. Sin /boot separado, cifrar el disco raíz sería mucho más complicado.

Solución 3

Dimensionamiento. La instantánea almacena los bloques originales de todo lo que cambie mientras viva. Meteora escribe unos 17,3 MB al día, es decir 720 KB/hora; si la copia tarda 30 minutos, cambiarán unos 360 KB. Con 10 GB hay un factor de seguridad de 28.000× frente a un pico anómalo, y sigue siendo el 1,6 % del volumen. Sobredimensionar aquí es barato; quedarse corto significa perder la copia.

#!/bin/bash
set -euo pipefail
VG=datos ; LV=lv_meteora ; SNAP=snap_backup ; MNT=/mnt/snap
DEST=/srv/backup/meteora-$(date +%F).tar.gz

limpiar() {                                  # limpieza GARANTIZADA, pase lo que pase
    mountpoint -q "$MNT" && umount "$MNT" || true
    lvs "$VG/$SNAP" &>/dev/null && lvremove -y "$VG/$SNAP" || true
}
trap limpiar EXIT

systemctl reload meteora-ingestor    # 1. SIGHUP: cerrar y reabrir con fsync (03-03)
sync                                 #    volcar la caché de páginas al dispositivo
lvcreate -L 10G -s -n "$SNAP" "/dev/$VG/$LV"        # 2. instantánea (<1 segundo)
mkdir -p "$MNT" && mount -o ro "/dev/$VG/$SNAP" "$MNT"   # 3. montar en solo lectura
tar czf "$DEST" -C "$MNT" .                              # 4. copiar con calma

USO=$(lvs --noheadings -o data_percent "/dev/$VG/$SNAP" | tr -d ' %' | cut -d. -f1)
if [ "$USO" -ge 90 ]; then           # 5. ¿se desbordó durante la copia?
    echo "AVISO: instantánea al ${USO}% — la copia puede ser inválida" >&2
    exit 1
fi
echo "Copia correcta en $DEST (instantánea al ${USO}%)"

Las tres decisiones importantes del script: set -euo pipefail aborta al primer error en lugar de continuar con una copia incompleta; trap limpiar EXIT garantiza que la instantánea se elimina aunque el script falle o lo maten —sin esto, una instantánea olvidada penaliza las escrituras durante días y acaba desbordándose—; y la comprobación posterior de data_percent avisa si la instantánea se llenó durante la copia, que es lo que convierte el script en una copia de seguridad y no en una ilusión.

Por qué sync no basta del todo. sync vuelca la caché de páginas del núcleo al dispositivo, así que la instantánea recoge todo lo que el núcleo tenía pendiente. Pero no vacía los búferes de espacio de usuario: si el ingestor usa FILE* de la biblioteca C, puede tener datos en su propio búfer que aún no han llegado ni siquiera al núcleo (04-04). De ahí el systemctl reload previo, que le pide cerrar y reabrir sus ficheros con fsync(). La copia perfecta requiere además que la aplicación tenga un punto consistente —una transacción cerrada, un fichero de día completo— y no solo bytes volcados; con un formato de registros de 24 bytes añadidos al final, cualquier corte deja como mucho una lectura incompleta, que el lector detecta por el tamaño. Es la diferencia entre consistencia de bytes y consistencia de aplicación, y volveremos sobre ella en 04-05.

Conclusión

Una partición es un rango contiguo de LBA declarado como unidad independiente, y la tabla que las describe es MBR o GPT. La elección ya no es opinable: MBR topa en 2 TiB y 4 particiones primarias y no tiene redundancia; GPT llega a 8 ZiB, admite 128 particiones, guarda una copia de la tabla al final del disco verificada con CRC32 y protege del formateo accidental con un MBR protector. Se particiona para aislar el llenado, aplicar políticas distintas, usar sistemas de archivos distintos y satisfacer los requisitos de arranque, y la separación de /var tiene un argumento demoledor: un / lleno es un servidor en el que no puedes entrar a arreglarlo. LVM añade la capa que a las particiones les falta: PV, VG y LV permiten ampliar en caliente (lvextend + resize2fs, en ese orden; al revés para reducir), repartir un volumen entre discos y mover datos sin parar nada; y sus instantáneas resuelven la copia consistente de /var/lib/meteora sin detener el ingestor, a cambio de un 20-40 % de penalización de escritura y del riesgo de invalidarse si se llenan.

El montaje es la operación central del módulo: resolver el punto de montaje, leer el superbloque, comprobar el estado, crear el superblock y el vfsmount en memoria y enganchar la dentry para que la resolución de rutas salte al nuevo árbol. De ese último paso salen dos hechos: que montar sobre un directorio no vacío oculta su contenido sin borrarlo, y que la tabla de montajes de /proc/mounts es la verdad del sistema. La identificación estable es con UUID=, nunca con /dev/sdX, y /etc/fstab tiene seis campos donde pass vale 1 en la raíz, 2 en el resto y 0 en lo que no tiene fsck — con el procedimiento obligatorio de copia de seguridad, findmnt --verify y mount -a antes de reiniciar.

Las opciones de montaje son endurecimiento gratuito: nosuid corta la escalada por binario setuid, nodev impide leer el disco crudo saltándose los permisos, noexec añade una capa más, y errors=remount-ro detiene el daño de un disco moribundo. Por eso /var/lib/meteora va con noatime,nosuid,nodev,noexec. El "target is busy" tiene cuatro causas —fichero abierto, cwd, mmap y montaje encima—, se diagnostica con lsof o fuser -vm, y se resuelve parando el servicio: umount -l desengancha pero no libera, y fuser -k mata sin avisar. Los montajes bind exponen un mismo árbol en dos puntos con opciones distintas, permiten ver lo oculto bajo un montaje y son la antesala de los espacios de nombres de montaje de 06-02.

Y la explicación de fondo de todo es el VFS: cuatro objetos —superblock por montaje, inode por fichero, dentry por nombre, file por apertura— y tablas de punteros a función que hacen que vfs_read() acabe en ext4_file_read_iter, en shmem_file_read_iter o en el cliente NFS según el caso. Gracias a él, /proc puede generar sus ficheros al leerlos —de ahí el tamaño 0 y el contenido cambiante—, tmpfs puede ser un sistema de archivos cuyo almacén es la caché de páginas —y por eso /dev/shm/meteora-cache es a la vez un fichero y memoria compartida POSIX—, y NFS puede poner un sistema de archivos al otro lado de la red, con sus tres pegas: latencia por ida y vuelta, coherencia débil que rompe los bloqueos, y hard que deja procesos en D cuando el servidor cae.

Ya tenemos el mapa completo del almacenamiento: sabemos qué es un fichero, cómo se le pone nombre, y cómo se ensambla el árbol por el que lo alcanzamos. Lo que no hemos hecho todavía es usarlo desde un programa. ¿Qué ocurre exactamente cuando open() devuelve el número 3? ¿Por qué padre e hijo comparten el desplazamiento tras un fork pero dos open del mismo fichero no? ¿Cómo implementa la shell la redirección > y ese 2>&1 que todo el mundo copia sin entender? ¿Y cómo se asegura el agregador de que las medias horarias que publica nunca se lean a medio escribir?

Es lo que veremos en Gestión de Archivos.

Fundamentos de Sistemas Operativos

Módulo 1: Introducción a los Sistemas Operativos

Módulo 2: Gestión de Recursos

Módulo 3: Concurrencia

Módulo 4: Estructuras de Archivos

Módulo 5: Protección y Seguridad del Sistema

Módulo 6: Virtualización y Contenedores

Módulo 7: Administración y Diagnóstico en la Práctica

© Copyright 2026. Todos los derechos reservados