Résumé

  • La RFC 1094 explique qu’un serveur NFS sans état ne peut pas maintenir le cas où un processus garde ouvert un fichier dont l’entrée de répertoire a été supprimée.
  • Son palliatif est côté client : renommer l’entrée au moment de la suppression, puis la retirer quand l’ouverture locale prend fin. Le RFC décrit une possibilité, pas une procédure universelle de nettoyage après incident.

Le processus tenait encore le fichier

Supposons qu’un programme ouvre un rapport, en lise une partie et continue son travail. Une autre action supprime le nom du rapport dans le répertoire. Sur certains systèmes de fichiers locaux, cette suppression n’annule pas immédiatement la référence déjà détenue par le processus : le nom n’est plus visible, mais le fichier reste accessible jusqu’à la fermeture.

Avec un fichier distant, cette distinction traverse deux machines. L’application voit un arbre monté dans son système. Le serveur reçoit, lui, des procédures séparées. Il doit pourtant savoir si la disparition de l’entrée autorise la récupération du contenu ou si un client en a encore besoin.

La RFC 1094, publiée en mars 1989 pour NFS version 2, ne transforme pas cette habitude locale en garantie du protocole. Elle nomme le problème : un serveur sans état ne peut reproduire l’ouverture d’un fichier qui demeure utilisable après la suppression de son nom. La solution évoquée est de renommer le fichier au moment de la suppression, puis d’effacer ce nouveau nom à la fermeture.

Le point historique est la frontière de responsabilité. Le client sait qu’un processus conserve une ouverture locale. Le serveur, sans procédure distante d’ouverture, ne reçoit pas cette information.

Le protocole envoyait des opérations, pas une durée d’ouverture

L’interface NFSv2 comprend notamment LOOKUP, READ, WRITE, CREATE, REMOVE et RENAME. REMOVE vise un nom dans un répertoire. La liste ne comporte pas de procédure OPEN ou CLOSE qui enregistrerait côté serveur le début, puis la fin de la dernière ouverture d’un client.

Le client utilise bien un file handle attribué par le serveur pour certaines opérations. Mais ce handle désigne un objet au niveau du protocole ; il ne prouve pas qu’un processus local a appelé open() ni qu’il conserve encore cette référence. Le client peut traduire une ouverture applicative dans son propre noyau et son implémentation NFS sans créer un état d’ouverture correspondant sur le serveur.

Ainsi, le serveur peut recevoir la suppression d’un nom sans connaître l’engagement encore détenu par un processus distant. La RFC ne prétend pas que l’émulation est impossible : elle précise que le serveur stateless ne peut la fournir seul. Le côté client, qui connaît l’ouverture, doit relier les deux états.

Renommer faisait attendre la suppression

Le palliatif proposé change l’ordre. Au lieu de retirer tout de suite l’entrée, le client la renomme temporairement. L’application ne voit plus son ancien nom ; le client se souvient que le nouveau doit être supprimé quand l’ouverture se termine. Le serveur garde ainsi une entrée qu’il sait représenter pendant que le client préserve le comportement attendu par le processus.

Ce mécanisme déplace le moment de la suppression réelle. Le répertoire peut ne plus exposer le nom d’origine alors que le stockage reste occupé. La fonction qui semble être un seul unlink devient une séquence entre deux acteurs : retrait visible maintenant, nettoyage distant plus tard.

La RFC 1094 ne fixe ni la forme du nom temporaire, ni la résolution d’une collision, ni le comportement si le client redémarre avant la fermeture. Elle ne définit pas non plus comment plusieurs clients doivent interpréter l’entrée intermédiaire. C’est une astuce de compatibilité proposée, pas un contrat complet de transaction ou de reprise.

Il serait donc abusif d’en déduire que tous les clients NFS de l’époque la mettaient en œuvre ou qu’un fichier était toujours nettoyé sans erreur. Il faut une preuve propre à l’implémentation pour décrire ce qu’un produit faisait réellement.

« Sans état » ne voulait pas dire sans données

La RFC voulait éviter que le serveur doive garder un état de protocole pour chacun de ses clients. Après une panne ou une interruption réseau, le client pouvait recommencer des opérations plutôt que reconstruire une session d’ouvertures. Les données, les attributs et les entrées de répertoire conservaient évidemment leur propre état sur le système de fichiers.

La durée d’une ouverture locale ne s’insérait pas aisément dans ce modèle. NFS rendait des opérations de fichiers accessibles à distance, sans pour autant transporter chaque convention d’un noyau local. Le verrouillage de fichiers et d’enregistrements se trouvait également hors du protocole décrit par la RFC 1094 et relevait de services séparés.

Les versions ultérieures ont fait un autre choix. NFSv3 conserve une interface d’opérations sans OPEN ni CLOSE distants ; RFC 7530, qui décrit NFSv4, comprend ces opérations et des stateids. Ce changement n’atteste pas une migration générale ni une sémantique identique dans tous les systèmes. Il montre que l’on peut intégrer l’état d’ouverture au protocole quand on accepte la coordination supplémentaire.

Une garantie de compatibilité a un responsable

Le serveur contrôle le répertoire exporté et exécute REMOVE. Le système du client connaît les processus et leurs références ouvertes. Tant que le serveur ne reçoit pas d’information sur ces ouvertures, il ne peut pas décider seul à quel moment supprimer un fichier sans trahir le comportement local. La proposition de la RFC relie les deux surfaces par un renommage et un retrait différé.

Cette adaptation suppose un nom temporaire, un suivi local et une règle de nettoyage. Une application qui dépend de l’accès après suppression doit donc vérifier que son couple client-serveur conserve bien ce comportement. L’administrateur serveur peut, de son côté, devoir comprendre pourquoi une entrée subsiste après la disparition de son nom visible. Le RFC ne fournit pas une politique opérationnelle détaillée à ces acteurs.

La limite ne condamne pas le choix de NFSv2. Le protocole privilégiait un serveur simple et indiquait où une convention locale pouvait demander davantage. Ce choix distribuait le coût : simplicité du serveur, travail supplémentaire du client, et tests du couple réellement utilisé par l’application.

Sources et limites

Ces textes établissent des interfaces et des choix de conception. Ils ne mesurent ni la diffusion de l’astuce de renommage, ni le nettoyage d’un client précis après un redémarrage, ni la fréquence du problème.