Usando btrfs en Raspberry Pi con Open Media Vault

Una guía para utilizar btrfs como mejora del servidor Open Media Vault montado como NAS casero con nuestra Raspberry Pi.

Montar discos en modo RAID ya lo expliqué en el blog hace tiempo. Sin embargo, a día de hoy es mejor en vez de configurar un RAID USB usando mdadm (que fallará de todos modos tarde o temprano y se dañará incluso con problemas menores de conectividad USB) hacerlo con btrfs.

Así se puede proporcionar integridad de datos y con su modo lineal, va llenando los discos del conjunto de 1 en 1, si se trata de añadir la capacidad de dos o más discos. Esto requiere usar la línea de comandos.

OJO QUE PODEMOS LIARLA, VAMOS A HACER COPIA DE SEGURIDAD E IR CON CUIDADO

 

Entramos en una Terminal por SSH. Instalamos el soporte para btrfs por si no lo tenemos.Y suponiendo que tenemos 2 discos (sda y sdb) lo siguiente creará una configuración lineal de btrfs:

sudo -s
apt install btrfs-tools
parted -s /dev/sda mklabel gpt 
parted -s /dev/sdb mklabel gpt 
partprobe 
mkfs.btrfs -f -d single -m raid1 -L BTRFS_LINEAR /dev/sd[ab]

Los dos comandos parted eliminan las particiones de ambos discos, luego el kernel lee en la tabla de particiones (ahora inexistente) y finalmente creamos una configuración multi disco con btrfs que almacena los datos en forma lineal (comenzando con sda y si está lleno entonces usando sdb)

Además la opción -m raid1 tiene la particularidad de que los metadatos (estructuras del sistema de archivos así como las sumas de comprobación para todos los datos almacenados) están duplicados en ambos discos. Así que incluso si un disco se ve afectado por la corrupción de datos, podemos saberlo con seguridad ya que tenemos dos copias de cada fragmento de metadatos.

Vamos ahora con la parte de montar y utilizar nuestro nuevo sistema de discos.

Montar el disco con Raspbian

Ahora la parte difícil, hemos creado una configuración multi dispositivo btrfs que consiste en sda y sdb. Para poder utilizarlo podemos montar sda o sdb, vale cualquiera ya que el código btrfs busca los discos restantes por su cuenta.

Si vas a usarlos con Raspbian por ejemplo, lo que habría que hacer es modificar fstab más o menos como expliqué en este post, pero con el siguiente texto para nuestro caso montando solo sda por ejemplo en una carpeta ya creada con el nombre /media/btrfs por ejemplo:

sudo -s
mkdir /media/btrfs/
mount /dev/sda /media/btrfs
btrfs filesystem df /media/btrfs/
blkid /dev/sda

La salida será algo así:

NAME FSTYPE LABEL UUID                                 MOUNTPOINT
sda  btrfs        e5b5c118-fb56-4fad-a45d-ff5fad9a649d /media/btrfs

Editamos /etc/fstab:

sudo cp /etc/fstab fstab.old
sudo nano /etc/fstab

Si lo montamos usando el UUID sería de la siguiente forma:

UUID=e5b5c118-fb56-4fad-a45d-ff5fad9a649d /media/btrfs           btrfs   defaults      0  1

O usando el nombre de la unidad, que es más fácil pero tiene sus inconvenientes en caso de que se cambien los nombres de las unidades al cambiarlas de puerto USB. Como ya he dicho, el resto de discos del conjunto se montarán indirectamente de forma automática a partir de ese:

/dev/sda /media/btrfs               btrfs   defaults 0       1

Montar el disco con Open Media Vault

De forma parecida a lo visto con Raspbian pero con la facilidad del entorno de OMV. Así que con nuestra configuración ahora simplemente usamos el interfaz web de OMV para montar sda por ejemplo, sin hacer nada con sdb, y se verá así:

montar disco btrfs en omv

Si desde la Terminal hacemos la siguiente comprobación vemos una incongruencia:

root@raspberrypi:~# lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL /dev/sda 
NAME FSTYPE SIZE MOUNTPOINT LABEL 
sda btrfs 465.8G /srv/dev-disk-by-label-BTRFS_LINEAR BTRFS_LINEAR 
root@raspberrypi:~# df -h | grep '/dev/sd' 
/dev/sda 578G 428M 574G 1% /srv/dev-disk-by-label-BTRFS_LINEAR

Si os fijáis lsblk no detecta bien o no nos informa del espacio combinado de ambos discos. Sin embargo, con df o desde la web de OMV si se ve. Ahora solo queda añadir el nuevo conjunto btrfs creado:

compartir disco btrfs en omv

Lo interesante de usar btrfs viene ahora. Las sumas de comprobación se calcularán de nuevo al leer los datos y se comparan con los metadatos originales que además están guardados por duplicado en los discos del conjunto btrfs. En caso de que se produzca un desajuste (¡corrupción de datos detectada!) se registrará (dmesg y syslog).

Además podemos usar un script que se ejecute una vez al mes desde crontab redirigiendo la salida a un logfile e ir comprobando si todo está OK.

Este script es de Marc Merlin http://marc.merlins.org/perso/btrfs/post_2014-03-19_Btrfs-Tips_-Btrfs-Scrub-and-Btrfs-Filesystem-Repair.html y lo podéis copiar de aquí: https://pastebin.com/bd9yZTMQ

#! /bin/bash

# By Marc MERLIN  2014/03/20
# License: Apache-2.0

which btrfs >/dev/null || exit 0

export PATH=/usr/local/bin:/sbin:$PATH

# bash shortcut for `basename $0`
PROG=${0##*/}
lock=/var/run/$PROG

FILTER='(^Dumping|balancing, usage)'
test -n "$DEVS" || DEVS=$(grep '\' /proc/mounts | awk '{ print $1 }' | sort -u)
for btrfs in $DEVS
do
    tail -n 0 -f /var/log/syslog | grep "BTRFS: " | grep -Ev '(disk space caching is enabled|unlinked .* orphans|turning on discard|device label .* devid .* transid|enabling SSD mode|BTRFS: has skinny extents|BTRFS: device label)' &
    mountpoint="$(grep "$btrfs" /proc/mounts | awk '{ print $2 }' | sort | head -1)"
    logger -s "Quick Metadata and Data Balance of $mountpoint ($btrfs)" >&2
    # Even in 4.3 kernels, you can still get in places where balance
    # won't work (no place left, until you run a -m0 one first)
    btrfs balance start -musage=0 -v $mountpoint 2>&1 | grep -Ev "$FILTER"
    btrfs balance start -musage=20 -v $mountpoint 2>&1 | grep -Ev "$FILTER"
    # After metadata, let's do data:
    btrfs balance start -dusage=0 -v $mountpoint 2>&1 | grep -Ev "$FILTER"
    btrfs balance start -dusage=20 -v $mountpoint 2>&1 | grep -Ev "$FILTER"
    # And now we do scrub. Note that scrub can fail with "no space left
    # on device" if you're very out of balance.
    logger -s "Starting scrub of $mountpoint" >&2
    echo btrfs scrub start -Bd $mountpoint
    ionice -c 3 nice -10 btrfs scrub start -Bd $mountpoint
    pkill -f 'tail -n 0 -f /var/log/syslog'
    logger "Ended scrub of $mountpoint" >&2
done

La salida del script para un disco casi vació, fijaos en la parte del final donde dice 0 errors, sería así:

root@raspberrypi:~# /usr/local/bin/btrfs-scrub.sh 
root: Quick Metadata and Data Balance of /srv/dev-disk-by-label-BTRFS_LINEAR (/dev/sda) 
Done, had to relocate 1 out of 7 chunks 
Done, had to relocate 3 out of 6 chunks 
Done, had to relocate 1 out of 5 chunks 
Done, had to relocate 1 out of 5 chunks 
root: Starting scrub of /srv/dev-disk-by-label-BTRFS_LINEAR 
btrfs scrub start -Bd /srv/dev-disk-by-label-BTRFS_LINEAR 
scrub device /dev/sda (id 1) done 
scrub started at Fri Nov 24 18:33:15 2017 and finished after 159 seconds 
total bytes scrubbed: 3.09GiB with 0 errors 
scrub device /dev/sdb (id 2) done 
scrub started at Fri Nov 24 18:33:15 2017 and finished after 1 seconds 
total bytes scrubbed: 2.56MiB with 0 errors

En caso de que haya errores sabremos en qué archivos y que disco es el que da problemas. Así podemos actuar quitando ese disco del conjunto btrfs y recuperamos de una copia de seguridad, como debe ser.

En la web del Instituto Puig Castellar tienen un montón de buenos Ejemplos de uso de Btrfs.

Extraído del post en el foro de OMV de tkaiser: https://forum.openmediavault.org/index.php/Thread/18991-New-approach-for-Raspberry-Pi-OMV-images/?postID=160915#post160915