fuse - Συσκευή Filesystem in Userspace (FUSE)
ΣΥΝΤΑΞΗ
#include <linux/fuse.h>
ΠΕΡΙΓΡΑΦΗ
Αυτή η συσκευή είναι η κύρια διεπαφή μεταξύ του οδηγού συστήματος αρχείων FUSE και μιας διαδικασίας χώρου χρήστη που επιθυμεί να παρέχει το σύστημα αρχείων (αναφέρεται στην υπόλοιπη ενότητα αυτού του εγχειριδίου ως το δαίμονα του συστήματος αρχείων). Αυτή η σελίδα εγχειριδίου προορίζεται για όσους ενδιαφέρονται να κατανοήσουν τη διεπαφή πυρήνα. Όσοι εφαρμόζουν ένα σύστημα αρχείων FUSE, ενδέχεται να επιθυμούν να χρησιμοποιήσουν μια βιβλιοθήκη χώρου χρήστη, όπως η libfuse, η οποία αφαιρεί την διεπαφή χαμηλού επιπέδου.
Στον πυρήνα του, το FUSE είναι ένα απλό πρωτόκολλο πελάτη-διακομιστή, στο οποίο ο πυρήνας Linux είναι ο πελάτης και το δαίμονα είναι ο διακομιστής. Αφού αποκτηθεί ένας περιγραφέας αρχείου για αυτήν τη συσκευή, το δαίμονα μπορεί να διαβάσει (read(2)) αιτήματα από αυτόν τον περιγραφέα αρχείου και αναμένεται να γράψει (write(2)) τις απαντήσεις του. Είναι σημαντικό να σημειωθεί ότι ένας περιγραφέας αρχείου συνδέεται με ένα μοναδικό σύστημα αρχείων FUSE. Συγκεκριμένα, το άνοιγμα ενός δεύτερου αντιγράφου αυτής της συσκευής δεν θα επιτρέψει την πρόσβαση σε πόρους που δημιουργήθηκαν μέσω του πρώτου περιγραφέα αρχείου (και αντίστροφα).
Το βασικό πρωτόκολλο
Κάθε μήνυμα που διαβάζεται από το δαίμονα ξεκινά με μια κεφαλίδα που περιγράφεται από την ακόλουθη δομή:
struct fuse_in_header {
uint32_t len; /* Συνολικό μέγεθος των δεδομένων,
συμπεριλαμβανομένης αυτής της κεφαλίδας */
uint32_t opcode; /* Ο τύπος της λειτουργίας (δείτε παρακάτω) */
uint64_t unique; /* Ένας μοναδικός αναγνωριστικός για αυτό το αίτημα */
uint64_t nodeid; /* Αναγνωριστικό του αντικειμένου του συστήματος αρχείων
στο οποίο γίνεται η λειτουργία */
uint32_t uid; /* UID της διαδικασίας που υποβάλλει το αίτημα */
uint32_t gid; /* GID της διαδικασίας που υποβάλλει το αίτημα */
uint32_t pid; /* PID της διαδικασίας που υποβάλλει το αίτημα */
uint32_t padding;
};
Η κεφαλίδα ακολουθείται από ένα τμήμα δεδομένων μεταβλητού μεγέθους (το οποίο μπορεί να είναι κενό) ειδικό για την αιτούμενη λειτουργία (η αιτούμενη λειτουργία υποδεικνύεται από το opcode).
Το δαίμονα θα πρέπει στη συνέχεια να επεξεργαστεί το αίτημα και -εάν είναι απαραίτητο- να στείλει μια απάντηση, εκτελώντας μια λειτουργία εγγραφής (write(2)) στον περιγραφέα αρχείου. Όλες οι απαντήσεις πρέπει να ξεκινούν με την ακόλουθη κεφαλίδα:
struct fuse_out_header {
uint32_t len; /* Συνολικό μέγεθος των δεδομένων που γράφονται
στον περιγραφέα αρχείου */
int32_t error; /* Οποιοδήποτε σφάλμα που προέκυψε (0 εάν δεν υπάρχει) */
uint64_t unique; /* Η τιμή από το αντίστοιχο αίτημα */
};
Αυτή η κεφαλίδα ακολουθείται επίσης από (πιθανώς κενά) δεδομένα μεταβλητού μεγέθους, ανάλογα με το αίτημα που εκτελέστηκε. Ωστόσο, εάν η απάντηση είναι μια απάντηση σφάλματος (δηλαδή, το σφάλμα έχει οριστεί), τότε δεν πρέπει να σταλεί κανένα περαιτέρω τμήμα δεδομένων, ανεξάρτητα από το αίτημα.
Ανταλλαγμένα μηνύματα
Αυτή η ενότητα θα πρέπει να περιέχει τεκμηρίωση για κάθε μήνυμα στο πρωτόκολλο. Αυτή η σελίδα εγχειριδίου είναι επί του παρόντος ελλιπής, επομένως δεν είναι τεκμηριωμένα όλα τα μηνύματα. Για κάθε μήνυμα, πρώτα δίνεται η δομή που αποστέλλεται από τον πυρήνα, ακολουθούμενη από μια περιγραφή των σημασιολογικών στοιχείων του μηνύματος.
FUSE_INIT
struct fuse_init_in {
uint32_t major;
uint32_t minor;
uint32_t max_readahead; /* Από το πρωτόκολλο v7.6 */
uint32_t flags; /* Από το πρωτόκολλο v7.6 */
};
Αυτό είναι το πρώτο αίτημα που αποστέλλεται από τον πυρήνα στο daemon. Χρησιμοποιείται για τη διαπραγμάτευση της έκδοσης του πρωτοκόλλου και άλλων παραμέτρων του συστήματος αρχείων. Σημειώστε ότι η έκδοση του πρωτοκόλλου μπορεί να επηρεάσει τη διάταξη οποιασδήποτε δομής στο πρωτόκολλο (συμπεριλαμβανομένης αυτής της δομής). Επομένως, το daemon πρέπει να θυμάται τη διαπραγματευμένη έκδοση και τις σημαίες για κάθε συνεδρία. Από τη στιγμή της συγγραφής αυτής της σελίδας εγχειριδίου, η υψηλότερη υποστηριζόμενη έκδοση του πρωτοκόλλου του πυρήνα είναι η 7.26.
Οι χρήστες θα πρέπει να γνωρίζουν ότι οι περιγραφές σε αυτήν τη σελίδα εγχειριδίου ενδέχεται να είναι ελλιπείς ή εσφαλμένες για παλαιότερες ή νεότερες εκδόσεις του πρωτοκόλλου.
Η απάντηση για αυτό το αίτημα έχει την ακόλουθη μορφή:
struct fuse_init_out {
uint32_t major;
uint32_t minor;
uint32_t max_readahead; /* Από το v7.6 */
uint32_t flags; /* Από το v7.6· ορισμένα bit σημαίας προστέθηκαν αργότερα */
uint16_t max_background; /* Από το v7.13 */
uint16_t congestion_threshold; /* Από το v7.13 */
uint32_t max_write; /* Από το v7.5 */
uint32_t time_gran; /* Από το v7.6 */
uint32_t unused[9];
};
Εάν η έκδοση major που υποστηρίζεται από τον πυρήνα είναι μεγαλύτερη από αυτή που υποστηρίζεται από το daemon, η απάντηση θα αποτελείται μόνο από το uint32_t major (ακολουθώντας τη συνήθη κεφαλίδα), υποδεικνύοντας την μεγαλύτερη έκδοση major που υποστηρίζεται από το daemon. Στη συνέχεια, ο πυρήνας θα εκδώσει ένα νέο αίτημα FUSE_INIT που συμμορφώνεται με την παλαιότερη έκδοση. Στην αντίθετη περίπτωση, το daemon θα πρέπει να υποχωρήσει αθόρυβα στην έκδοση major του πυρήνα.
Η διαπραγματευμένη έκδοση minor θεωρείται ότι είναι η ελάχιστη από τις εκδόσεις minor που παρέχονται από το daemon και τον πυρήνα, και και τα δύο μέρη θα πρέπει να χρησιμοποιούν το πρωτόκολλο που αντιστοιχεί στην εν λόγω έκδοση minor.
FUSE_GETATTR
struct fuse_getattr_in {
uint32_t getattr_flags;
uint32_t dummy;
uint64_t fh; /* Ορίζεται μόνο εάν
(getattr_flags & FUSE_GETATTR_FH)
};
Η ζητούμενη λειτουργία είναι να υπολογιστούν τα χαρακτηριστικά που θα επιστραφούν από το [stat]({filename}../../stat)(2) και παρόμοιες λειτουργίες για το δεδομένο αντικείμενο του συστήματος αρχείων. Το αντικείμενο για το οποίο πρέπει να υπολογιστούν τα χαρακτηριστικά υποδεικνύεται είτε από το header->nodeid είτε, εάν έχει οριστεί η σημαία FUSE_GETATTR_FH, από τον χειριστή αρχείου fh. Η τελευταία περίπτωση λειτουργίας είναι ανάλογη με το fstat(2).
Για λόγους απόδοσης, αυτά τα χαρακτηριστικά μπορούν να αποθηκευτούν στην μνήμη cache του πυρήνα για μια καθορισμένη διάρκεια. Ενώ δεν έχει λήξει ο χρόνος λήξης της μνήμης cache, τα χαρακτηριστικά θα εξυπηρετούνται από τη μνήμη cache και δεν θα προκαλούν επιπλέον αιτήματα FUSE_GETATTR.
Τα υπολογισμένα χαρακτηριστικά και το ζητούμενο χρονικό όριο προσωρινής αποθήκευσης θα πρέπει στη συνέχεια να επιστραφούν στην ακόλουθη δομή:
struct fuse_attr_out {
/* Διάρκεια προσωρινής αποθήκευσης χαρακτηριστικών (δευτερόλεπτα + νανοδευτερόλεπτα) */
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;
};
FUSE_ACCESS
struct fuse_access_in {
uint32_t mask;
uint32_t padding;
};
Εάν δεν χρησιμοποιείται η επιλογή προσάρτησης default_permissions, αυτό το αίτημα μπορεί να χρησιμοποιηθεί για έλεγχο δικαιωμάτων. Δεν αναμένονται δεδομένα απάντησης, αλλά σφάλματα μπορούν να υποδεικνύονται όπως συνήθως, ορίζοντας το πεδίο σφάλματος στην κεφαλίδα απάντησης (ιδιαίτερα, σφάλματα άρνησης πρόσβασης μπορούν να υποδεικνύονται με την επιστροφή του -EACCES).
FUSE_OPEN
FUSE_OPENDIR
struct fuse_open_in {
uint32_t flags; /* Οι σημαίες που περάστηκαν στη συνάρτηση open(2) */
uint32_t unused;
};
Η αιτούμενη λειτουργία είναι η άνοιγμα του κόμβου που υποδεικνύεται από header->nodeid. Η ακριβής σημασιολογία του τι σημαίνει αυτό θα εξαρτηθεί από το σύστημα αρχείων που υλοποιείται. Ωστόσο, τουλάχιστον, το σύστημα αρχείων θα πρέπει να επικυρώνει ότι τα αιτούμενα flag είναι έγκυρα για το υποδεικνυόμενο πόρο και, στη συνέχεια, να στείλει μια απάντηση με την ακόλουθη μορφή:
struct fuse_open_out {
uint64_t fh;
uint32_t open_flags;
uint32_t padding;
};
Το πεδίο fh είναι ένας αδιαφανής αναγνωριστικός που θα χρησιμοποιηθεί από τον πυρήνα για να αναφέρεται σε αυτόν τον πόρο. Το πεδίο open_flags είναι μια μάσκα bit οποιουδήποτε αριθμού σημαίων που υποδεικνύουν ιδιότητες αυτού του περιγραφέα αρχείου προς τον πυρήνα:
FOPEN_DIRECT_IO Παράκαμψη της προσωρινής μνήμης σελίδων για αυτό το ανοιχτό αρχείο.
FOPEN_KEEP_CACHE Μην ακυρώνετε την προσωρινή μνήμη δεδομένων κατά το άνοιγμα.
FOPEN_NONSEEKABLE Το αρχείο δεν είναι αναζητήσιμο.
FUSE_READ
FUSE_READDIR
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;
};
Η αιτούμενη ενέργεια είναι η ανάγνωση έως και size byte του αρχείου ή του καταλόγου, ξεκινώντας από την θέση offset. Τα byte θα πρέπει να επιστρέφονται απευθείας μετά την συνήθη κεφαλίδα απάντησης.
FUSE_INTERRUPT
struct fuse_interrupt_in {
uint64_t unique;
};
Η αιτούμενη ενέργεια είναι η ακύρωση της εκκρεμούς λειτουργίας που υποδεικνύεται από το unique. Αυτό το αίτημα δεν απαιτεί απάντηση. Ωστόσο, η λήψη αυτού του μηνύματος δεν ακυρώνει από μόνη της την υποδεικνυόμενη λειτουργία. Ο πυρήνας θα εξακολουθεί να αναμένει μια απάντηση στην εν λόγω λειτουργία (π.χ., ένα σφάλμα EINTR ή μια σύντομη ανάγνωση). Το πολύ ένα αίτημα FUSE_INTERRUPT θα εκδοθεί για μια δεδομένη λειτουργία. Μετά την έκδοση της εν λόγω λειτουργίας, ο πυρήνας θα περιμένει χωρίς διακοπή για την ολοκλήρωση της υποδεικνυόμενης αίτησης.
FUSE_LOOKUP
Αμέσως μετά την κεφαλίδα υπάρχει ένα όνομα αρχείου που πρέπει να αναζητηθεί στον κατάλογο που υποδεικνύεται από το header->nodeid. Η αναμενόμενη απάντηση έχει την ακόλουθη μορφή:
struct fuse_entry_out {
uint64_t nodeid; /* Αναγνωριστικό inode */
uint64_t generation; /* Γενιά inode */
uint64_t entry_valid;
uint64_t attr_valid;
uint32_t entry_valid_nsec;
uint32_t attr_valid_nsec;
struct fuse_attr attr;
};
Ο συνδυασμός των nodeid και generation πρέπει να είναι μοναδικός για όλη τη διάρκεια ζωής του συστήματος αρχείων.
Η ερμηνεία των χρονικών ορίων και του attr είναι όπως για το FUSE_GETATTR.
FUSE_FLUSH
struct fuse_flush_in {
uint64_t fh;
uint32_t unused;
uint32_t padding;
uint64_t lock_owner;
};
Η ζητούμενη ενέργεια είναι η εκκαθάριση τυχόν εκκρεμών αλλαγών στο συγκεκριμένο file handle. Δεν αναμένονται δεδομένα απάντησης. Ωστόσο, πρέπει να εκδοθεί ένα άδειο μήνυμα απάντησης μόλις ολοκληρωθεί η λειτουργία εκκαθάρισης.
FUSE_RELEASE
FUSE_RELEASEDIR
struct fuse_release_in {
uint64_t fh;
uint32_t flags;
uint32_t release_flags;
uint64_t lock_owner;
};
Αυτές είναι οι αντίστροφες λειτουργίες του FUSE_OPEN και FUSE_OPENDIR, αντίστοιχα. Το daemon μπορεί πλέον να απελευθερώσει τυχόν πόρους που σχετίζονται με το file handle fh, καθώς ο πυρήνας δεν θα το αναφέρεται πλέον. Δεν υπάρχουν δεδομένα απάντησης που σχετίζονται με αυτό το αίτημα, αλλά πρέπει να εκδοθεί μια απάντηση μόλις επεξεργαστεί πλήρως το αίτημα.
FUSE_STATFS
Αυτή η λειτουργία υλοποιεί το statfs(2) για αυτό το σύστημα αρχείων. Δεν υπάρχουν δεδομένα εισόδου που σχετίζονται με αυτό το αίτημα. Τα αναμενόμενα δεδομένα απάντησης έχουν την ακόλουθη δομή:
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;
};
Για την ερμηνεία αυτών των πεδίων, δείτε το statfs(2).
ΣΦΑΛΜΑΤΑ
E2BIG Επιστρέφεται από τις λειτουργίες read(2) όταν το αίτημα του πυρήνα είναι πολύ μεγάλο για το παρεχόμενο buffer και το αίτημα ήταν FUSE_SETXATTR.
EINVAL Επιστρέφεται από το write(2) εάν η επικύρωση της απάντησης αποτύχει. Δεν θα εντοπιστούν όλα τα λάθη στις απαντήσεις μέσω αυτής της επικύρωσης. Ωστόσο, τα βασικά λάθη, όπως οι σύντομες απαντήσεις ή μια εσφαλμένη μοναδική τιμή, εντοπίζονται.
EIO Επιστρέφεται από τις λειτουργίες read(2) όταν το αίτημα του πυρήνα είναι πολύ μεγάλο για το παρεχόμενο buffer.
Σημείωση: Υπάρχουν διάφοροι τρόποι με τους οποίους η εσφαλμένη χρήση αυτών των διεπαφών μπορεί να προκαλέσει αποτυχία των λειτουργιών στα αρχεία και τους καταλόγους του παρεχόμενου συστήματος αρχείων με σφάλμα EIO. Μεταξύ των πιθανών εσφαλμένων χρήσεων είναι:
η αλλαγή του mode & S_IFMT για ένα inode που έχει προηγουμένως αναφερθεί στον πυρήνα. ή
η παροχή απαντήσεων στον πυρήνα που είναι μικρότερες από αυτές που περίμενε ο πυρήνας.
ENODEV Επιστρέφεται από τις λειτουργίες read(2) και write(2) εάν το σύστημα αρχείων FUSE έχει αποσυνδεθεί.
EPERM Επιστρέφεται από λειτουργίες σε μια περιγραφή αρχείου /dev/fuse που δεν έχει τοποθετηθεί.
ΠΡΟΤΥΠΑ
Linux.
ΣΗΜΕΙΩΣΕΙΣ
Τα ακόλουθα μηνύματα δεν είναι ακόμη τεκμηριωμένα σε αυτήν τη σελίδα εγχειριδίου:
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)