# ZFS (sistema de archivos)

ZFS es un sistema de archivos y administrador de volúmenes desarrollado originalmente por Sun Microsystems para su sistema operativo Solaris. El significado original era 'Zettabyte File System', pero ahora es un acrónimo recursivo.
El anuncio oficial de ZFS se produjo en septiembre de 2004. El código fuente del producto final se integró en la rama principal de desarrollo de Solaris el 31 de octubre de 2005 y fue lanzado el 16 de noviembre de 2005 como parte de la compilación 27 de OpenSolaris.
ZFS fue diseñado e implementado por un equipo de Sun liderado por Jeff Bonwick.
ZFS destaca por su gran capacidad, integración de los conceptos anteriormente separados de sistema de ficheros y administrador de volúmenes en un solo producto, nueva estructura sobre el disco, sistemas de archivos ligeros y una administración de espacios de almacenamiento sencilla.

## Espacios de almacenamiento (Storage pools)

A diferencia de los sistemas de ficheros tradicionales que residen encima de un solo dispositivo subyacente y por lo tanto requieren un gestor de volúmenes separado, ZFS se apoya en espacios de almacenamiento virtuales (virtual storage pools).
Los espacios se construyen a partir de uno o más dispositivos virtuales, o vdevs (la forma al que se referencia cualquier tipo de dispositivo de almacenamiento, ya sea local o remoto). Un pool puede ser de tipo simple (uno o más vdevs sin redundancia), mirror (dos o más vdevs en pares, en modalidad espejo), o RAID Z (tres o más vdevs con paridad).
Adicionalmente, uno o más vdevs pueden actuar como caché y/o registro de intentos (ZFS Intent Log, ZIL); usualmente se usan dispositivos más rápidos como SSD para mejorar el rendimiento.

## Sistemas de ficheros ligeros (dataset)

La creación de un nuevo sistema de ficheros (dataset) en el interior de un espacio de almacenamiento ZFS es extremadamente rápida y fácil, mucho más parecida en tiempo y esfuerzo a crear un nuevo directorio en un sistema de archivos tradicional que al tiempo y esfuerzo necesario para crear un nuevo sistema de ficheros en cualquier otro SO tradicional. Estos sistemas de ficheros pueden tener cuotas reservadas y otras capacidades de administración útiles. Entre los usos posibles se encuentra la creación de un sistema de ficheros separado, no sólo un directorio, para cada usuario del sistema.
Para limitar la cantidad de espacio que un dataset puede ocupar, se pueden aplicar cuotas de disco y reserva, y garantizar que habrá espacio disponible para determinado dataset.
Existen dos tipos de dataset:
* filesystem: Es el tipo de dataset por defecto y es el que permite almacenar archivos (regulares y especiales) y directorios. La raíz de un zpool ya es un dataset de tipo filesystem. Se puede establecer el punto de montaje, lo que permite prescindir del archivo fstab.
* zvol: Actúa como un pseudo-dispositivo de bloques accesible desde /dev/zvol. Útil para ser usado como volumen de intercambio (swap) o para ser utilizado como discos virtuales para entornos virtualizados (ya que es más robusto y eficiente que un disco virtual en un archivo regular). Esto es en esencia similar LVM.
Otro tipo de dataset son las Instantáneas (snapshot). Como su nombre lo indica, es la instantánea de un dataset en un momento determinado, útil para conservar versiones antiguas de archivos o zvol. Se nombran agregando un "@" y un nombre arbitrario, a continuación del nombre del dataset (ej: rpool/ROOT/debian-1@Modificado1). bookmark es una variante de las instantáneas, utilizado para transferencia de un dataset entre zpools usando zfs send/zfs recv permitiendo borrar el dataset en el origen (send) pero conservando los datos para el envío (recv).

## Capacidad

128 bits (2$^7$ veces la capacidad de un sistema de ficheros de 64 bits).
Los límites de ZFS están diseñados para ser tan grandes que no se encuentren nunca en la práctica. Respecto a la capacidad del sistema, Jeff Bonwick, el arquitecto jefe de Sun para ZFS, dijo "Llenar un sistema de archivos de 128 bits excedería los límites cuánticos de almacenamiento de la Tierra. No puedes rellenarlo sin hervir los océanos de la Tierra".
Algunos límites teóricos de ZFS son:
* 2$^{48}$ — Número de snapshots en cualquier sistema de ficheros (2 × 10$^{14}$)
* 2$^{48}$ — Número de ficheros en un sistema de ficheros (2 × 10$^{14}$)
* 16 exabytes — Tamaño máximo de un sistema de ficheros.
* 16 exabytes — Tamaño máximo de un fichero.
* 16 exabytes — Tamaño máximo de cualquier atributo.
* 3 × 10$^{23}$ petabytes (293 zettabytes aprox.) — Tamaño máximo de un zpool.
* 2$^{56}$ — Número de atributos de un fichero (realmente limitado a 2$^{48}$ que es el número de ficheros que puede contener un sistema de ficheros ZFS).
* 2$^{56}$ — Número de ficheros en un directorio (realmente limitado a 2$^{48}$ que es el número de ficheros que puede contener un sistema de ficheros ZFS).
* 2$^{64}$ — Número de dispositivos en cualquier zpool.
* 2$^{64}$ — Número de zpools en un sistema.
* 2$^{64}$ — Número de sistemas de ficheros en un zpool.
Como ejemplo de las capacidades expresadas por estos números, si un usuario crease 1000 ficheros por segundo, tardaría unos 9000 años en alcanzar el límite impuesto por el número de ficheros.

## Auto reparación (Self-healing)

En pools de estructura mirror o RAID-Z (paridad simple, doble y triple, equivalentes a RAID 5 y RAID 6 respectivamente pero sin el defecto de «agujero de escritura» (write-hole) que sufren estos últimos), todos los datos son hasheados previamente a su escritura en el bloque lógico del pool (el algoritmo del hash se puede configurar por dataset). Una vez escritos los datos, el hash es comprobado para verificar la correcta inscripción de los mismos. Este hash es asociado a través de un sistema de metadatos al bloque lógico, de tal modo que cuando se accede a los datos del bloque lógico, se hace un chequeo de su integridad (a través de la comparación del hash guardado como metadato y el calculado con los datos del bloque). Si hay discordancia entre los datos, siendo sistemas con redundancia, procede a buscar en el bloque espejo (mirror) o a calcular los datos a través del sistema de paridad empleado (RAID-Z). Si los datos obtenidos con dicha fuente son correctos (equivalencia en los hash calculado y archivado) se procede a la corrección de los datos del bloque dañado, así como al envío de los datos solicitados a la aplicación. Esta característica permite la detección de fallos en discos.

## Modelo transaccional Copy-on-write

ZFS utiliza un modelo transaccional copy-on-write. Todos los punteros a bloques de un sistema de ficheros contienen un checksum de 256 bits sobre el bloque apuntado, que se comprueba al leer el bloque. Los bloques que contienen datos activos no se sobrescriben nunca; en su lugar, se reserva un nuevo bloque, y los datos modificados se escriben en él, y entonces cualquier bloque de metadatos que lo referencie es, de modo similar, reubicado y escrito. Este modelo puede ocasionar una alta fragmentación.
Para reducir la sobrecarga de este proceso, se agregan varias actualizaciones en grupos de transacciones, y se utiliza un «registro de intentos» (ZFS Intent Log o ZIL) cuando se necesitan escrituras síncronas.

## Instantáneas (Snapshots)

Como ZFS no sobrescribe datos, tomar una instantánea simplemente significa no liberar los bloques utilizados por versiones antiguas de los datos. La ventaja es que las instantáneas se toman rápidamente y también son eficientes desde el punto de vista del espacio, pues comparten los datos sin modificar con el sistema de ficheros. Se pueden crear instantáneas tanto de datasets de tipo filesystem como zvol (ver Tipos de dataset).
Se pueden crear instantáneas modificables (llamadas clones), lo que resulta en dos sistemas de ficheros independientes que se crean compartiendo un conjunto común de bloques. A medida que se realizan cambios los bloques del sistema de ficheros divergen, pero los bloques comunes se mantendrán independientemente de cuantos clones existan.

## Bandas de tamaño variable (Dynamic striping)

ZFS permite expandir las bandas de un zpool con o sin redundancia, a medida que se agreguen dispositivos a un pool. En otras palabras, repartirá la carga de escritura de forma equitativa en todos los dispositivos, optimizando los procesos de lectura (leyendo desde distintas ubicaciones de cada bloque en cada dispositivo). Con las bandas de tamaño variable, el rendimiento mejora considerablemente en los pools en modo mirror y RAID Z, eliminando de manera eficaz el problema de write-hole.

## Bloques de tamaño variable

ZFS utiliza bloques de tamaño variable hasta 128K. El código disponible actualmente permite al administrador afinar el tamaño máximo de bloque utilizado, pues ciertas cargas no rinden bien con bloques grandes. También está contemplado un ajuste automático para adecuarse a las características de la carga de trabajo.
Si se activa la compresión se utilizan tamaños de bloque variable, si un bloque se puede comprimir para que quepa en un bloque de tamaño menor, se utiliza el bloque pequeño en el disco, de manera que no sólo se consume menos capacidad sino que se aumenta el throughput de entrada/salida (con el coste de aumentar la sobrecarga de la CPU).

## Capacidades adicionales

* Prioridad I/O explícita con deadline scheduling.
* Ordenación y agregación de I/O globalmente óptima.
* Multiple independent prefetch streams with automatic length and stride detection.
* Parallel, constant-time directory operations.
Para las aplicaciones, ZFS es un sistema de ficheros estándar POSIX; no es necesario ningún cambio en las aplicaciones para guardar datos en ZFS.

## Inconvenientes
### Conjuntos de datos con compresión

Al permitir compresión, si un conjunto de datos está en el límite de su capacidad, el administrador de archivos o el shell podría mostrar discrepancias en el tamaño total de los archivos y el espacio libre. En este caso, la forma correcta de ver el espacio libre de un conjunto de datos es usando las herramientas de ZFS como zfs list dataset (el cual mostrará el espacio real ocupado en el campo ref). Esto ocurre en sistemas no soportados oficialmente por Oracle, como Linux.

### Fragmentación

Dada la naturaleza del sistema copy-on-write, el pool puede sufrir una alta fragmentación, lo que puede ocasionar problemas de rendimiento en unidades mecánicas. Las unidades de estado sólido se ven afectadas de la misma forma, excepto que el rendimiento no se degrada dada la mayor velocidad de lecturas aleatorias).
ZFS no cuenta con una herramienta de desfragmentación integrada. La única forma de desfragmentar un pool es clonar a otro medio, ya sea mediante zpool attach o ZFS send / ZFS recv.