Aller au contenu
Sylvain Joffraud l4w
Retour

rsync `--link-dest` sans `-H` : les snapshots explosent

Un rsync --link-dest sans -H en aval casse toute la déduplication : sur mon NAS, les snapshots quotidiens des données Nextcloud (108 Go) ne coûtaient que les fichiers modifiés grâce aux hardlinks, mais le script qui recopie le NAS vers un disque externe utilisait rsync -a, sans -H. Chaque snapshot y devenait une copie pleine : 108 Go × N. Le correctif tient en une lettre, puis j’ai simplifié le modèle pour que le problème ne puisse plus revenir.

Deux étages de rsync qui ne parlent pas de la même chose

Le premier étage tourne chaque nuit sur le NAS : un pull des données Nextcloud du serveur srv-a, dans un dossier daté par jour. L’option --link-dest=DIR de rsync crée un hardlink vers le fichier de DIR quand il est inchangé, au lieu de le recopier. Un hardlink est une seconde entrée de répertoire qui pointe vers les mêmes blocs sur le disque : dix snapshots d’un fichier inchangé occupent la place d’un seul.

Le second étage est backup-to-external.sh, qui copie le NAS vers des disques USB externes chiffrés en LUKS (le chiffrement a eu ses propres surprises, racontées dans l’article sur Argon2 et les cibles à 1 GB de RAM). Parmi ses sources, le dossier des homes, qui contient les snapshots du premier étage.

Ses options d’origine :

RSYNC_OPTS=(
  -a
  --info=stats2,progress2
  --modify-window=1
  --bwlimit=15000
  --exclude='.Trash-*/'
  --exclude='lost+found/'
  --exclude='.snapshots/'
)

-a ressemble à « tout préserver ». Ce n’est pas le cas.

Non, et la page de manuel le dit dans le résumé des options (rsync 3.2.7) :

--archive, -a            archive mode is -rlptgoD (no -A,-X,-U,-N,-H)

Et dans la description de --hard-links, -H :

Without this option, hard-linked files in the source are treated as
though they were separate files.

Sur le disque externe, chaque entrée de chaque snapshot devient donc un fichier indépendant, écrit en entier. Les 108 Go dédupliqués sur le NAS se multiplient par le nombre de snapshots présents au moment de la copie.

--link-dest déduplique avec des hardlinks ; un rsync en aval sans -H les transforme en copies. La déduplication ne survit qu’au premier étage.

Combien ça aurait coûté ?

Le commit du correctif note une explosion à 3,5 To. C’est une estimation, pas une mesure sur le disque. Le calcul brut donne le même ordre de grandeur : au moment où je m’en suis aperçu, le NAS contenait 37 snapshots (accumulés parce que la rétention ne tournait plus, voir l’article sur set -e et rsync exit 23), et 37 × 108 Go ≈ 4 To. Même avec la rétention prévue de 3 jours, chaque copie externe aurait embarqué plusieurs fois les 108 Go.

Sur le NAS, rien ne se voyait : du compte un fichier à plusieurs hardlinks une seule fois, et l’espace occupé restait raisonnable. Le problème n’existait qu’en aval, sur un disque branché de temps en temps.

Le correctif : -H, puis plus de snapshots du tout

Première étape, ajouter l’option :

RSYNC_OPTS=(
  --delete  # miroir : purge sur le disque ce qui n existe plus sur le NAS
  -a
  -H  # preserver hardlinks (--link-dest) au lieu de les dupliquer
  --info=stats2,progress2
  --modify-window=1
  --bwlimit=15000
  ...
)

⚠️ D’après le manuel, rsync ne détecte les hardlinks qu’à l’intérieur du même transfert. Ça fonctionne ici parce que tout le dossier des homes, snapshots compris, part en une seule commande. Un rsync par snapshot ne recréerait pas les liens entre eux.

Deuxième étape, le même jour : se demander si ces snapshots servaient à quelque chose. Pour les données Nextcloud et les configurations, la réponse était non : j’ai remplacé les dossiers datés par un miroir unique (--delete), et seuls les dumps de bases gardent 7 jours glissants. Sans snapshots, il n’y a plus de hardlinks à perdre ; -H reste en place pour le jour où un autre dossier en contiendra.

Lessons learned

Questions fréquentes

rsync -a préserve-t-il les hardlinks ?
Non. Le mode archive -a de rsync équivaut à -rlptgoD et n’inclut pas -H : la page de manuel le précise (« no -A,-X,-U,-N,-H »). Sans -H, des fichiers liés par hardlink à la source sont traités comme des fichiers séparés et copiés chacun en entier sur la destination. Il faut ajouter -H explicitement pour les recréer.
Pourquoi mes snapshots rsync --link-dest prennent-ils beaucoup plus de place sur le disque de sauvegarde que sur le NAS ?
Parce que la déduplication de --link-dest repose sur des hardlinks, et qu’un second rsync sans -H ne les reproduit pas. Sur le NAS, un fichier inchangé présent dans dix snapshots n’occupe qu’une fois l’espace disque. Recopié sans -H, il est écrit dix fois. La taille sur la destination devient environ taille des données × nombre de snapshots.
Quelles limites a l’option -H de rsync ?
L’option -H de rsync ne détecte que les hardlinks entre fichiers présents dans le même transfert. Si les snapshots sont copiés par des commandes rsync séparées, un dossier par appel, les liens entre eux ne peuvent pas être retrouvés. Il faut donc synchroniser le dossier parent qui contient tous les snapshots en une seule commande.
Faut-il garder des snapshots datés quand on fait déjà une copie sur disque externe ?
Pas forcément. Chaque niveau d’historique multiplie les pièges : rétention qui ne tourne pas, hardlinks perdus à la copie suivante. Pour des données déjà versionnées ailleurs, un miroir unique sur le NAS plus des dumps de bases sur quelques jours glissants peut suffire. Le bon niveau dépend de ce qu’on veut pouvoir restaurer, et à quelle date.

Partager cet article :

Article précédent
Banc LLM : un seul passage varie de ±12 points
Article suivant
Assistant LLM : la détection d’urgence sans le modèle