
🌐 También en: English · Deutsch · Français
HP3, mi HPE MicroServer Gen10 Plus v2, vuelve a funcionar con Debian 13 y OpenZFS. Por qué volvió a dejar Windows es una historia para otro artículo. Este va de la restauración posterior y de un ajuste que llevaba escondido a plena vista durante dos sistemas operativos y dos artículos del blog.
El plan era aburrido, como debe ser una restauración: un pool RAIDZ1 nuevo sobre los mismos tres SSD WD Red SA500, datasets por usuario y luego unos 1,7 TB copiados de vuelta desde un disco USB con rsync. El mismo reparto de siempre: yo decido, y mi coadministrador de IA (Claude) ejecuta los comandos y vigila las cifras. Y fueron precisamente las cifras las que empezaron a no cuadrar.
🐌 Siete megabytes por segundo. Por SSD.
La copia avanzaba a paso de tortuga, a 25–35 MB/s. La estimación hablaba de unas dieciséis horas. Hasta cosas pequeñas como zfs create o zpool status se quedaban colgadas durante minutos, esperando a que el siguiente grupo de transacciones terminara de sincronizarse. Entonces zpool iostat -l mostró el problema real:
$ zpool iostat -vl storage 5 1
bandwidth total_wait disk_wait
read write read write read write
storage 3.42K 22.7M 1ms 233ms 1ms 65ms
raidz1-0 3.42K 22.7M 1ms 233ms 1ms 65ms
ata-WD_Red_SA500_..._00458 1.14K 7.57M 1ms 262ms 1ms 68ms
ata-WD_Red_SA500_..._01387 1.14K 7.58M 1ms 258ms 1ms 72ms
ata-WD_Red_SA500_..._02050 1.14K 7.58M 1ms 181ms 1ms 57ms
$ cat /proc/pressure/io
some avg10=94.05 avg60=90.06 avg300=80.24
full avg10=88.82 avg60=84.62 avg300=75.87Unos 7,5 MB/s por disco con 65 ms de latencia, y la máquina pasaba alrededor del 90 % de su tiempo esperando E/S. Son SSD SATA especificados para bastante más de 500 MB/s de escritura secuencial. 65 ms es terreno de discos mecánicos. Peor, en realidad: un disco duro decente lo hace mejor.
🕵️ Sospechoso número uno: TRIM, y esto ya me había pasado
TRIM fue el primer sospechoso, y no solo en teoría. Ya me había mordido una vez. La primera vez que pasé estos SSD de Windows a Linux, instalé Debian sobre discos que habían estado cifrados con BitLocker. Las cifras eran igual de horribles que ahora, y aquella vez la solución fue un TRIM. Así que cuando volvieron los mismos síntomas, saltó el déjà vu.
La razón de que BitLocker y los SSD sean tan mala combinación al reinstalar está en cómo ve el mundo un SSD. No tiene ni idea de lo que es un archivo. Solo conoce bloques lógicos, y un bloque está «en uso» desde el momento en que se escribe algo en él hasta que alguien dice explícitamente «este ya lo puedes olvidar». Ese alguien es TRIM (o discard, en términos de Linux). Un sistema de archivos lo envía cuando borra archivos. Un mkfs o un zpool create recién hecho encima de datos antiguos no lo hace necesariamente para todo el disco.
BitLocker lo empeora todo al máximo. Los datos cifrados son indistinguibles del ruido aleatorio, así que dentro de la unidad no hay nada que comprimir ni deduplicar. Y cuando un volumen lleva un tiempo cifrado y en uso, gran parte de la memoria flash contiene lo que el SSD tiene que tratar como datos valiosos. Luego borro el disco con un sistema operativo nuevo. La tabla de particiones es nueva, el sistema de archivos es nuevo, pero nadie le dice al SSD que todos esos bloques antiguos ya son basura. Desde su punto de vista, la unidad sigue llena.
Eso duele, porque la flash no se puede sobrescribir en el sitio. Se escribe por páginas y se borra en bloques mucho más grandes. Una unidad que cree estar llena ya no tiene bloques borrados de antemano. Para cada escritura nueva, su recolector de basura tiene que encontrar primero un bloque, copiar a otro sitio las páginas todavía «válidas» (el viejo ruido cifrado), borrar el bloque y solo entonces escribir los datos nuevos. Una escritura del host se convierte en varias internas (amplificación de escritura). El rendimiento se desploma, la latencia se dispara y, encima, la unidad se desgasta más rápido.
La forma correcta, que apunto aquí para que mi yo del futuro la siga de verdad: antes de entregar SSD usados a un sistema de archivos nuevo, hay que descartarlos por completo. Esto destruye todo lo que hay en el disco, y de eso se trata:
# Before zpool create / mkfs — irreversibly wipes the drive!
blkdiscard /dev/disk/by-id/ata-WD_Red_SA500_2.5_2TB_...
# Check that the drive supports TRIM at all (non-zero DISC-GRAN/DISC-MAX):
lsblk --discard /dev/sdXEn un SSD SATA sin actividad, blkdiscard suele tardar entre unos segundos y unos pocos minutos para toda la unidad. Hacerlo después con zpool trim en un pool en uso también funciona. ZFS solo descarta el espacio que no usa. Pero es más lento, compite con la E/S real y solo ayuda desde el momento en que se ejecuta.
Hay una tercera opción que no vi hasta más tarde, mientras rebuscaba en la BIOS otra cosa (ver más abajo): el RBSU de HPE trae integrados SATA Secure Erase y SATA Sanitize. Son la versión de firmware de la misma idea. La propia unidad lo tira todo, incluidas sus propias tablas de asignación, y vuelve como el primer día, con todos los bloques libres. Para SSD que de todas formas se van a borrar, es probablemente el reinicio más limpio que existe, y no necesita ningún sistema operativo en marcha. La misma advertencia, en letra más grande: borra la unidad por completo.
Esta vez me había saltado ese paso, así que lanzamos un zpool trim storage completo en mitad de la restauración. Cuarenta minutos después iba por el 2 %, y la copia apenas era más rápida. TRIM era parte del problema, pero no la parte que había convertido los SSD en disqueteras. También fallaba algo más básico. Y cuando sabes qué era, un TRIM arrastrándose al 2 % también empieza a tener sentido.
💡 Sospechoso número dos: una palabra en sysfs
$ for d in sda sdb sdc sdd; do echo "$d $(cat /sys/block/$d/queue/write_cache)"; done
sda write through
sdb write through
sdc write through
sdd write through
$ hdparm -W /dev/disk/by-id/ata-WD_Red_SA500_2.5_2TB_...
write-caching = 0 (off)Write through. La caché de escritura de las propias unidades estaba desactivada. Todo SSD tiene un pequeño búfer de DRAM: recibe las escrituras entrantes, responde «hecho» y luego las escribe en la flash en trozos grandes y eficientes. Sin él, la unidad tiene que completar cada escritura en la flash antes de responder. Para un SSD es más o menos la peor forma de trabajar, porque la flash se escribe en páginas grandes y se borra en bloques aún más grandes. Muchas escrituras pequeñas y separadas significan escrituras lentas y desgaste adicional.
¿Quién la desactivó? Debian no, no toca ese ajuste. El registro del kernel lo responde, dos segundos después del encendido, mucho antes de que se haya ejecutado nada en el espacio de usuario:
$ dmesg | grep -i "write cache"
[ 2.101312] sd 2:0:0:0: [sda] Write cache: disabled, read cache: enabled
[ 2.101316] sd 3:0:0:0: [sdc] Write cache: disabled, read cache: enabled
[ 2.101332] sd 5:0:0:0: [sdd] Write cache: disabled, read cache: enabled
[ 2.101407] sd 4:0:0:0: [sdb] Write cache: disabled, read cache: enabled
[ 3.644946] sd 6:0:0:0: [sde] Write cache: enabled, read cache: enabled ← USB stick
[ 530.822448] sd 7:0:0:0: [sdf] Write cache: enabled, read cache: enabled ← USB diskLos cuatro SSD SATA internos arrancan con disabled, mientras que los dos dispositivos USB arrancan con enabled. Las unidades SATA vienen de fábrica con la caché de escritura activada, así que algo la desactiva durante el POST, y ese algo es el firmware del servidor. Por lo visto, HPE pone por defecto «caché de escritura de la unidad desactivada» en las unidades SATA, y según resultó, no deja cambiarlo (más sobre esto abajo). Las pruebas apuntan claramente a la plataforma, no a Linux.
⚡ Un comando después
$ for d in /dev/disk/by-id/ata-WD_Red_SA500_2.5_2TB_*[0-9]; do hdparm -W1 "$d"; done
setting drive write-caching to 1 (on)
write-caching = 1 (on)
...| Caché de escritura desactivada | Caché de escritura activada | |
|---|---|---|
| Rendimiento de la restauración con rsync | 25–35 MB/s | 85–95 MB/s |
| Presión de E/S (PSI, some avg60) | ~90 % | ~30–45 % |
| Duración estimada de la restauración | ~16 horas | ~6 horas |
| Cuello de botella | los SSD | el disco USB de 2,5″ desde el que copiaba |
En directo, en mitad de la copia, sin reiniciar. Los SSD pasaron de ser el problema a estar esperando a un disco duro USB portátil. Cuando terminó la restauración, hice además un benchmark limpio.
📊 El benchmark limpio: los mismos discos, un interruptor
Con la restauración terminada y el pool otra vez en reposo (unos 1,3 TB ocupados, TRIM todavía en pausa), repetí las mismas pruebas con dd que en el artículo original del NAS, dos veces: una con la caché de escritura de las unidades desactivada de nuevo y otra con ella activada. Esta vez me tomé en serio las lecciones de aquel artículo: un dataset de pruebas propio con compression=off, un archivo de 1 GiB de datos aleatorios servido desde la RAM (/dev/shm) para que /dev/urandom no se convierta en el cuello de botella, fsync al final y lecturas con O_DIRECT para que la ARC no maquille las cifras de lectura.
zfs create -o compression=off storage/bench
head -c 1G /dev/urandom > /dev/shm/rand.bin
dd if=/dev/shm/rand.bin of=/storage/bench/t bs=1M conv=fsync # buffered + fsync
dd if=/dev/shm/rand.bin of=/storage/bench/t bs=1M oflag=direct conv=fsync # O_DIRECT
dd if=/dev/shm/rand.bin of=/storage/bench/t4k bs=4k count=5000 oflag=direct,dsync
dd if=/storage/bench/t of=/dev/null bs=1M iflag=direct # read| Prueba | Caché desactivada | Caché activada | Factor |
|---|---|---|---|
| Escritura secuencial 1M, con búfer + fsync | 8 MB/s | 547 MB/s | ~68× |
| Escritura secuencial 1M, O_DIRECT | 2 MB/s | 239 MB/s | ~120× |
| Escritura 4K, O_DIRECT + dsync | 292 kB/s | 334 kB/s | ~1× |
| Lectura secuencial 1M, O_DIRECT | 972 MB/s | 865 MB/s | – |
Dos megabytes por segundo. En SSD. El primer intento usaba un archivo de 4 GiB, como el artículo original. Con la caché desactivada llegaba a 3 MB/s y habría tardado bastante más de media hora, así que lo reduje a 1 GiB. Eso ya es un resultado en sí mismo.
Lo que dice de verdad la tabla:
- Las escrituras se multiplican por 70 a 120. Eso ya no es una mejora de ajuste fino. Es la diferencia entre «roto» y «funciona».
- Las lecturas no cambian. Claro que no, es una caché de escritura. La pequeña diferencia es ruido entre ejecuciones.
- Las escrituras síncronas de 4K no mejoran en absoluto, y es lo correcto. Con
dsync, cada escritura de 4K termina con un vaciado de caché, así que la caché se vacía tan rápido como se llena. Para cargas con muchas escrituras síncronas (bases de datos, NFS con sync, máquinas virtuales), la respuesta no es la caché de la unidad. Es un dispositivo de registro separado para ZFS (SLOG) o SSD con protección ante cortes de corriente. La caché de escritura no es magia. Solo evita que la unidad haga cada escritura de la forma más costosa posible. - Comparadas con el artículo original (138 MB/s con búfer, 15,4 MB/s con O_DIRECT), las cifras sin caché son hoy todavía peores. Sospecho que ahí actúa el segundo problema de este artículo: entonces las unidades eran nuevas, esta vez estaban llenas de datos antiguos de BitLocker y el TRIM aún no se había ejecutado. Faltaban dos cosas, y cada una empeora la otra.
🔙 La parte en la que releo mi propio blog
Aquí viene lo un poco embarazoso. Son los mismos tres SSD en la misma máquina sobre los que ya he escrito dos veces. Las dos veces las cifras me estaban diciendo exactamente esto, y las dos veces encontré una explicación plausible y seguí adelante.
Primer fallo: Building a RAIDZ1 NAS on Debian 13 with OpenZFS. Medí 138 MB/s de escritura con búfer y 15,4 MB/s con O_DIRECT, unas nueve veces más lento. Incluso escribí que «me sorprendió lo suficiente como para comprobarlo dos y tres veces». Luego lo expliqué con la agrupación en grupos de transacciones de ZFS: las escrituras con búfer se juntan en escrituras de franja completa, y O_DIRECT se salta eso. Esa parte es cierta. Pero la explicación era demasiado cómoda. Con la caché de la unidad desactivada, cada escritura no agrupada tiene que esperar a la propia flash, y eso es lo que convierte «algo más lento» en «nueve veces más lento». Hasta la cifra «buena» merecía una segunda mirada: 138 MB/s repartidos entre tres SSD SATA no es para tirar cohetes.
Segundo fallo: Enough YAML for Now, en el lado de Windows. Paridad de Storage Spaces sobre los mismos discos: 88 MiB/s de escritura secuencial, 461 IOPS de escritura aleatoria y una latencia en el percentil 99 de más de un segundo. Le eché la culpa a la paridad: «Las lecturas son geniales. Las escrituras son… paridad». El coste de lectura-modificación-escritura de la paridad es real. Pero también ejecuté DiskSpd con -Sh, que desactiva a propósito la caché de escritura de la unidad durante la prueba. El benchmark medía «sin caché de escritura» por diseño, y resulta que así funcionaba el servidor cada día de todos modos. El peor caso y la realidad diaria eran lo mismo, y nunca me pregunté por qué.
Dos sistemas operativos, dos benchmarks, dos explicaciones que sonaban razonables, un ajuste que nadie comprobó. La lección no es «los benchmarks mienten». Es que comparé las cifras con mis expectativas sobre el software y nunca con la hoja de datos del hardware. 15 MB/s de escritura en un SSD deberían haber sido una señal de alarma, fuera cual fuera el sistema de archivos que hubiera encima.
🛡️ ¿Es seguro activarla?
Es la pregunta obvia: si HPE la desactiva, quizá haya un motivo.
Hay un motivo, y en su mayor parte no se aplica aquí. La caché de la unidad es RAM volátil. Si se va la corriente, se pierde lo que haya en ella que aún no esté en la flash. Los SSD empresariales tienen condensadores para esto («power-loss protection»); los SSD de consumo y de NAS normalmente no. Además, un servidor HPE clásico usa una controladora RAID Smart Array con su propia caché respaldada por batería. En ese diseño, la caché de la unidad es en el mejor de los casos redundante y en el peor un riesgo, así que desactivarla es la opción prudente. Para un fabricante que no sabe qué sistema operativo, sistema de archivos o controladora vas a usar, «desactivada» es el valor por defecto seguro.
En un sistema de archivos moderno, una caché de escritura es segura porque el sistema de archivos le dice a la unidad cuándo los datos tienen que estar en almacenamiento estable. En cada punto importante, ZFS, ext4 y NTFS envían un vaciado de caché y no dan nada por confirmado hasta que la unidad lo confirma. Además, ZFS funciona con copia en escritura, así que tras un fallo tienes o bien el último estado coherente o bien el nuevo, nunca una mezcla. El único peligro real es una unidad que confirma vaciados que nunca ha hecho (firmware barato y dudoso) o, en Windows, marcar «Desactivar el vaciado de búfer de caché de escritura de Windows en el dispositivo». Esa casilla es de verdad la casilla de «me gusta vivir peligrosamente».
Y en mi caso, los tres servidores HP están de todos modos detrás de un SAI. Lo que sigue en la lista de pendientes es que HP3 se apague limpiamente cuando la batería se esté agotando (NUT). Un SAI que se queda sin batería mientras el servidor sigue escribiendo solo aplaza el corte.
💾 SSD, discos duros y el PC que tienes bajo la mesa
- Los SSD son los que más sufren. La flash se escribe por páginas y se borra por bloques. Sin caché, la unidad no puede agrupar las escrituras pequeñas, así que cada una cuesta más tiempo y más desgaste. Así se llega a 7,5 MB/s.
- Los discos duros también pierden, sobre todo en escritura aleatoria, porque la unidad ya no puede reordenar las peticiones para minimizar el movimiento del cabezal. La escritura secuencial sufre menos.
- Los PC de sobremesa normales casi siempre están bien. Las BIOS de consumo no tocan ese ajuste, y Windows deja activado «Habilitar la caché de escritura en el dispositivo» para las unidades internas. Mi jump host, una placa de sobremesa corriente, indica
write backtanto para su disco duro de 8 TB como para su SSD NVMe. NVMe también tiene una caché de escritura volátil, controlada por el sistema operativo y activada por defecto. - Las unidades USB en Windows son la excepción que seguramente ya has notado. Por defecto están en «Extracción rápida», en la que Windows renuncia por su parte a la caché de escritura diferida para que puedas sacar el pendrive sin expulsarlo. Es una de las razones por las que las copias grandes a USB suelen parecer más lentas en Windows que en Linux.
Compruébalo tú mismo:
# Linux
cat /sys/block/*/queue/write_cache
dmesg | grep -i "write cache"
hdparm -W /dev/sdX # SATA
# Windows (PowerShell)
Get-PhysicalDisk | Get-StorageAdvancedProperty # IsDeviceCacheEnabled, IsPowerProtected🔧 Para que se mantenga
hdparm -W1 es volátil: la unidad lo restablece en el siguiente ciclo de encendido, y el firmware la vuelve a desactivar en cada arranque. Así que la corrección también tiene que aplicarse en cada arranque. De momento, eso es una regla de udev:
# /etc/udev/rules.d/69-ssd-write-cache.rules
# HPE firmware disables the SATA SSD write cache at boot (write through).
# ZFS and ext4 issue cache flushes, so enabling it is safe.
ACTION=="add|change", KERNEL=="sd[a-z]", SUBSYSTEM=="block", ENV{ID_BUS}=="ata", \
ATTR{queue/rotational}=="0", RUN+="/usr/sbin/hdparm -W1 /dev/%k"Solo afecta a las unidades ATA internas no rotativas, así que el SSD del sistema también la recibe y los dispositivos USB quedan al margen.
¿No sería la BIOS un sitio mejor? En teoría, sí: un ajuste del firmware se aplica antes de que cargue cualquier sistema operativo, sobrevive a una reinstalación y cubre también instaladores y sistemas de rescate. Así que reinicié en el RBSU (F9) y me puse a buscar. En System Configuration → BIOS/Platform Configuration → Storage Options → SATA Controller Options, el MicroServer Gen10 Plus v2 tiene exactamente tres entradas:
- Embedded SATA Configuration: SATA AHCI Support
- SATA Secure Erase
- SATA Sanitize
Eso es todo. Ni «Drive Write Cache» ni nada en las opciones de rendimiento. En modo AHCI, el firmware desactiva la caché y no te da forma de cambiarlo. (Las controladoras Smart Array sí tienen una «Physical Drive Write Cache Policy», pero pasar esta máquina a un modo RAID para llegar a ese ajuste ocultaría los discos a Linux y se llevaría el pool de ZFS por delante. No es una opción.) Así que la regla de udev no es un cinturón de seguridad junto a la solución de verdad. Es la solución, aplicada por el sistema operativo en cada arranque, porque nadie más lo hará.
Eso también significa que tiene que formar parte de la instalación, no ser algo que hay que recordar después. Si la próxima reinstalación olvida este único archivo, volvemos a 7,5 MB/s, y probablemente a otro artículo del blog.
Los otros dos servidores HP tienen casi con toda seguridad el mismo valor por defecto. Les tocará en cuanto decida qué hago con ellos.
🎯 Conclusión
Escribí dos artículos llenos de benchmarks cuidadosos: datos comprimibles frente a incomprimibles, ARC frente a caché de páginas, los archivos de prueba llenos de ceros de DiskSpd. Fueron buenas lecciones, y todas iban de que el software me mentía. Mientras tanto, el hardware era totalmente sincero: una palabra en sysfs, una línea en dmesg y una lección sobre TRIM que ya había aprendido una vez tras la instalación con BitLocker y que olvidé enseguida. Nunca miré.
La próxima vez que una cifra me parezca rara, la primera pregunta no será «¿cómo explica esto mi sistema de archivos?», sino «¿qué se supone que debe hacer este hardware?». Un SSD SATA a 15 MB/s no es una curiosidad interesante del sistema de archivos. Es un ajuste, o un TRIM que falta, o en mi caso ambas cosas. 🔍💾
Mi lista de comprobación para reutilizar SSD en un servidor a partir de ahora:
- Primero, descartar.
blkdiscarden cada SSD usado antes de crear el pool (o SATA Secure Erase / Sanitize en la BIOS), sobre todo si tuvo BitLocker u otro cifrado de disco completo. - Incluir la regla de udev en la instalación en las máquinas HPE en modo AHCI. La BIOS no lo arreglará por ti.
- Comprobar la caché de escritura.
dmesg | grep -i "write cache"y/sys/block/*/queue/write_cache. Lo esperado es «write back». - Comparar con la hoja de datos, no con tus expectativas sobre el sistema de archivos.
- Solo entonces, hacer benchmarks, con datos incomprimibles y en un pool en reposo.
📚 Más de esta serie: el NAS RAIDZ1 (en inglés)
- Building a RAIDZ1 NAS on Debian 13 with OpenZFS: Datasets, Compression, and the Lies dd Told Me
- RAIDZ1 NAS Addendum: How Scrub and Trim Actually Get Scheduled — and the Alert That Wasn’t
- Everybody Smile — We’re Taking a Snapshot! Moving From rdiff-backup to ZFS on the RAIDZ1 NAS
- Second Addendum: ZED Watches My Pool’s Health, Not Its Waistline






