fuse(4) Device Drivers Manual fuse(4)

fuse — périphérique FUSE (Filesystem in Userspace)

#include <linux/fuse.h>

Ce périphérique est l’interface principale entre le pilote du système de fichiers FUSE et un processus en espace utilisateur voulant fournir le système de fichiers (référé dans le reste de cette page de manuel comme démon du système de fichiers). Cette page de manuel est destinée à ceux qui veulent comprendre l’interface du noyau elle-même. Ceux mettant en œuvre un système de fichiers FUSE peuvent utiliser une bibliothèque en espace utilisateur telle que libfuse qui permet de faire abstraction de l’interface de bas niveau.

En substance, FUSE est un protocole client-serveur simple, dans lequel le noyau Linux est le client et le démon le serveur. Après l’obtention d’un descripteur de fichier pour ce périphérique, le démon peut lire (read(2)) les requêtes de ce descripteur de fichier et est présumé écrire (write(2)) en retour les réponses. Il est important de noter que ce descripteur de fichier est associé à un système de fichiers FUSE unique. En particulier, l’ouverture d’une seconde copie de ce périphérique ne permet pas l’accès aux ressources crées à travers le premier descripteur de fichier (et vice versa).

Chaque message lu par le démon commence par un en-tête décrit par la structure suivante :


struct fuse_in_header {
    uint32_t len;       /* Taille totale des données,
                           incluant cet en-tête */
    uint32_t opcode;    /* Le type d’opération (voir ci-après) */
    uint64_t unique;    /* Un identifiant unique pour cette requête */
    uint64_t nodeid;    /* ID de l’objet de système de fichiers
                           qui est manipulé */
    uint32_t uid;       /* UID du processus requérant */
    uint32_t gid;       /* GID du processus requérant */
    uint32_t pid;       /* PID du processus requérant */
    uint32_t padding;
};

L’en-tête est suivi d’une partie de données de taille variable (pouvant être vide) spécifique à l’opération demandée (l’opération demandée est indiquée par opcode).

Le démon doit alors traiter la requête et, si applicable, envoyer une réponse (presque toutes les opérations demandent une réponse — si ce n’est le cas, cela est documenté ci-après) en réalisant un write(2) pour le descripteur de fichier. Toutes les réponses doivent débuter par l’en-tête suivant :


struct fuse_out_header {
    uint32_t len;       /* Taille totale des données écrites
                           sur le descripteur de fichier */
    int32_t  error;     /* Toute erreur produite (0 si aucune) */
    uint64_t unique;    /* La valeur de la requête correspondante */
};

Cet en-tête est aussi suivi par des données (potentiellement absentes) de taille variable dépendant de la requête exécutée. Cependant, si la réponse est une réponse d’erreur (c’est-à-dire, error est définie), alors plus aucunes données de charge utile ne seront envoyées, indépendamment de la requête.

Cette section devrait contenir la documentation de chacun des messages du protocole. Cette page de manuel est actuellement incomplète, aussi tous les messages ne sont pas documentés. Pour chaque message, la structure envoyée par le noyau est fournie en premier, suivie par une description des sémantiques du message.


struct fuse_init_in {
    uint32_t major;
    uint32_t minor;
    uint32_t max_readahead; /* Depuis la version 7.6 du protocole */
    uint32_t flags;         /* Depuis la version 7.6 du protocole */
};

C’est la première requête envoyée par le noyau au démon. Elle est utilisée pour négocier la version de protocole et les autres paramètres de système de fichiers. Il est à remarquer que la version de protocole peut affecter la disposition de n’importe quelle structure dans le protocole (y compris celle-ci). Le démon doit par conséquent se souvenir de la version négociée et des drapeaux de chaque session. Au moment de l’écriture de cette page de manuel, la version de protocole la plus récente prise en charge par le noyau est la version 7.26.
Les utilisateurs doivent faire attention à ce que les descriptions dans cette page de manuel peuvent être incorrectes ou incomplètes pour les versions de protocole plus anciennes ou plus récentes.
La réponse à cette requête est du format suivant :

struct fuse_init_out {
    uint32_t major;
    uint32_t minor;
    uint32_t max_readahead;   /* Depuis la version 7.6 */
    uint32_t flags;           /* Depuis la version 7.6 ; quelques bits
                                 de drapeaux ont été ajoutés après */
    uint16_t max_background;  /* Depuis la version 7.13 */
    uint16_t congestion_threshold;  /* Depuis la version 7.13 */
    uint32_t max_write;       /* Depuis la version 7.5 */
    uint32_t time_gran;       /* Depuis la version 7.6 */
    uint32_t unused[9];
};

Si la version majeure prise en charge par le noyau est supérieure à celle prise en charge par le démon, la réponse sera constituée de seulement uint32_t major (suivi par l’en-tête habituel), indiquant la version majeure la plus élevée prise en charge par le démon. Le noyau produira alors une nouvelle requête FUSE_INIT se conformant à l’ancienne version. Dans le cas contraire, le démon reviendra silencieusement à la version majeure du noyau.
La version mineure négociée est considérée comme la version mineure minimale fournie par le démon et le noyau, et les deux parties doivent utiliser le protocole correspondant pour ladite version mineure.

struct fuse_getattr_in {
    uint32_t getattr_flags;
    uint32_t dummy;
    uint64_t fh;      /* Défini seulement si
                         (getattr_flags & FUSE_GETATTR_FH)
};

L’opération requise est de déterminer les attributs que stat(2) doit renvoyer et les opérations similaires pour l’objet indiqué de système de fichiers. L’objet pour lequel les attributs doivent être déterminés est indiqué soit par header->nodeid ou, si le drapeau FUSE_GETATTR_FH est défini, par le gestionnaire de fichier fh. Le dernier cas d’opération est analogue à fstat(2).
Pour des raisons de performance, ces attributs peuvent être mis en cache dans le noyau pendant une durée indiquée. Tant que la temporisation du cache n'est pas dépassée, les attributs seront servis à partir du cache et ne provoqueront pas de requêtes FUSE_GETATTR supplémentaires.
Les attributs calculés et la temporisation de cache demandée doivent alors être renvoyés dans la structure suivante :

struct fuse_attr_out {
    /* Temporisation de cache d’attributs (secondes + nanosecondes) */
    uint64_t attr_valid;
    uint32_t attr_valid_nsec;
    uint32_t dummy;
    struct fuse_attr {
        uint64_t ino;
        uint64_t size;
        uint64_t blocks;
        uint64_t atime;
        uint64_t mtime;
        uint64_t ctime;
        uint32_t atimensec;
        uint32_t mtimensec;
        uint32_t ctimensec;
        uint32_t mode;
        uint32_t nlink;
        uint32_t uid;
        uint32_t gid;
        uint32_t rdev;
        uint32_t blksize;
        uint32_t padding;
    } attr;
};


struct fuse_access_in {
    uint32_t mask;
    uint32_t padding;
};

Si l’option default_permissions de montage n’est pas utilisée, cette requête peut être utilisée pour la vérification des permissions. Aucunes données de réponse ne sont attendues, mais les erreurs peuvent être indiquées comme d’habitude en réglant le champ error dans l’en-tête de réponse (en particulier, les erreurs de refus d’accès peuvent être indiquées en renvoyant -EACCES).

struct fuse_open_in {
    uint32_t flags;     /* Les drapeaux qui étaient passés
                           à open(2) */
    uint32_t unused;
};

L’opération demandée est d’ouvrir le nœud indiqué par header->nodeid. Les sémantiques exactes de ce que cela signifie dépendent du système de fichiers mis en œuvre. Cependant, à tout le moins, le système de fichiers doit valider que les drapeaux demandés sont valables pour la ressource indiquée et alors envoyer une réponse de format suivant :

struct fuse_open_out {
    uint64_t fh;
    uint32_t open_flags;
    uint32_t padding;
};

Le champ fh est un identifiant opaque que le noyau utilise pour référer à cette ressource. Le champ open_flags est un masque de bits de n’importe quel nombre de drapeaux qui indiquent les propriétés de ce gestionnaire de fichier au noyau :
Contournement de ce cache de pages pour ce fichier ouvert.
Ne pas invalider le cache de données lors de l’ouverture.
Ce fichier ne peut être parcouru.

struct fuse_read_in {
    uint64_t fh;
    uint64_t offset;
    uint32_t size;
    uint32_t read_flags;
    uint64_t lock_owner;
    uint32_t flags;
    uint32_t padding;
};

L’action demandée est de lire jusqu’à size d’octets du fichier ou du répertoire, en commençant à offset. Les octets sont renvoyés directement en suivant l’en-tête de réponse habituel.

struct fuse_interrupt_in {
    uint64_t unique;
};

L’action demandée est d’annuler l’opération en attente indiquée par unique. Cette requête ne demande aucune réponse. Cependant, la réception de ce message n’annule pas par lui-même l’opération indiquée. Le noyau attendra toujours une réponse à ladite opération (par exemple, une erreur EINTR ou une lecture courte). Au plus une requête FUSE_INTERRUPT sera faite pour une opération donnée. Après l’émission de ladite opération, le noyau attendra de façon ininterrompue pour l’achèvement de la requête indiquée.
Directement à la suite de l’en-tête est un nom de fichier à rechercher dans le répertoire indiqué par header->nodeid. La réponse attendue est de la forme :

struct fuse_entry_out {
    uint64_t nodeid;            /* Id d’inœud */
    uint64_t generation;        /* Génération d’inœud */
    uint64_t entry_valid;
    uint64_t attr_valid;
    uint32_t entry_valid_nsec;
    uint32_t attr_valid_nsec;
    struct fuse_attr attr;
};

La combinaison de nodeid et generation doit être unique pour toute la durée de vie du système de fichiers.
L’interprétation des temporisations et de attr est comme pour FUSE_GETATTR.

struct fuse_flush_in {
    uint64_t fh;
    uint32_t unused;
    uint32_t padding;
    uint64_t lock_owner;
};

L’action demandée est de vider toute modification en attente dans le gestionnaire de fichiers indiqué. Aucune donnée de réponse n’est attendue. Cependant, un message de réponse vide doit toujours être émis une fois que l’opération de vidage est terminée.

struct fuse_release_in {
    uint64_t fh;
    uint32_t flags;
    uint32_t release_flags;
    uint64_t lock_owner;
};

Ce sont les opposés de FUSE_OPEN et FUSE_OPENDIR respectivement. Le démon peut désormais libérer toute ressource associée avec le gestionnaire de fichier fh, car le noyau ne se référera plus à celui-ci. Il n’y a aucune donnée de réponse associée à la requête, mais une réponse doit toujours être fournie une fois que la requête a été complètement traitée.
L’opération met en œuvre statfs(2) pour ce système de fichiers. Il n’y a aucune donnée d’entrée associée à cette requête. Les données de réponse attendues ont la structure suivante :

struct fuse_kstatfs {
    uint64_t blocks;
    uint64_t bfree;
    uint64_t bavail;
    uint64_t files;
    uint64_t ffree;
    uint32_t bsize;
    uint32_t namelen;
    uint32_t frsize;
    uint32_t padding;
    uint32_t spare[6];
};
struct fuse_statfs_out {
    struct fuse_kstatfs st;
};

Pour l’interprétation de ces champs, consulter statfs(2).

Renvoyé par les opérations read(2) quand la requête du noyau est trop grande pour le tampon fourni et que la requête était FUSE_SETXATTR.
Renvoyé par write(2) si la validation de la réponse échoue. Toutes les erreurs dans les réponses ne seront pas capturées par cette validation. Cependant les fautes basiques, telles que les réponses courtes ou une valeur unique incorrecte, sont détectées.
Renvoyé par les opérations read(2) quand la requête du noyau est trop grande pour le tampon fourni.
Remarque : il existe diverses façons par lesquelles l’utilisation incorrecte de ces interfaces peut faire que les opérations sur les fichiers et les répertoires indiqués du système de fichiers échouent avec EIO. Parmi les utilisations incorrectes possibles :
  • la modification de mode & S_IFMT pour un inœud ayant été rapportée auparavant au noyau ;
  • la fourniture de réponses au noyau plus courtes que ce que le noyau attendait.
Renvoyé par read(2) et write(2) si le système de fichiers FUSE a été démonté.
Renvoyé par les opérations sur un descripteur de fichier /dev/fuse n’ayant pas été monté.

Linux.

Les messages suivants ne sont pas encore documentés dans cette page de manuel :


FUSE_BATCH_FORGET
FUSE_BMAP
FUSE_CREATE
FUSE_DESTROY
FUSE_FALLOCATE
FUSE_FORGET
FUSE_FSYNC
FUSE_FSYNCDIR
FUSE_GETLK
FUSE_GETXATTR
FUSE_IOCTL
FUSE_LINK
FUSE_LISTXATTR
FUSE_LSEEK
FUSE_MKDIR
FUSE_MKNOD
FUSE_NOTIFY_REPLY
FUSE_POLL
FUSE_READDIRPLUS
FUSE_READLINK
FUSE_REMOVEXATTR
FUSE_RENAME
FUSE_RENAME2
FUSE_RMDIR
FUSE_SETATTR
FUSE_SETLK
FUSE_SETLKW
FUSE_SYMLINK
FUSE_UNLINK
FUSE_WRITE

fusermount(1), mount.fuse(8)

La traduction française de cette page de manuel a été créée par Christophe Blaess https://www.blaess.fr/christophe/, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Paul Guillonneau <guillonneau.jeanpaul@free.fr>

Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.

31 octobre 2023 Pages du manuel de Linux 6.06