/** Default max number of pages that can be used in a single read request */ #define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32
/** Bias for fi->writectr, meaning new writepages must not be sent */ #define FUSE_NOWRITE INT_MIN
/** Maximum length of a filename, not including terminating null */
/* maximum, small enough for FUSE_MIN_READ_BUFFER*/ #define FUSE_NAME_LOW_MAX 1024 /* maximum, but needs a request buffer > FUSE_MIN_READ_BUFFER */ #define FUSE_NAME_MAX (PATH_MAX - 1)
/** Number of dentries for each connection in the control filesystem */ #define FUSE_CTL_NUM_DENTRIES 5
/* Frequency (in seconds) of request timeout checks, if opted into */ #define FUSE_TIMEOUT_TIMER_FREQ 15
/** Frequency (in jiffies) of request timeout checks, if opted into */ externconstunsignedlong fuse_timeout_timer_freq;
/** Maximum of max_pages received in init_out */ externunsignedint fuse_max_pages_limit; /* * Default timeout (in seconds) for the server to reply to a request * before the connection is aborted, if no timeout was specified on mount.
*/ externunsignedint fuse_default_req_timeout; /* * Max timeout (in seconds) for the server to reply to a request before * the connection is aborted.
*/ externunsignedint fuse_max_req_timeout;
/** List of active connections */ externstruct list_head fuse_conn_list;
/** Global mutex protecting fuse_conn_list and the control filesystem */ externstruct mutex fuse_mutex;
union fuse_file_args { /* Used during open() */ struct fuse_open_out open_outarg; /* Used during release() */ struct fuse_release_args release_args;
};
/** * Request flags * * FR_ISREPLY: set if the request has reply * FR_FORCE: force sending of the request even if interrupted * FR_BACKGROUND: request is sent in the background * FR_WAITING: request is counted as "waiting" * FR_ABORTED: the request was aborted * FR_INTERRUPTED: the request has been interrupted * FR_LOCKED: data is being copied to/from the request * FR_PENDING: request is not yet in userspace * FR_SENT: request is in userspace, waiting for an answer * FR_FINISHED: request is finished * FR_PRIVATE: request is on private list * FR_ASYNC: request is asynchronous * FR_URING: request is handled through fuse-io-uring
*/ enum fuse_req_flag {
FR_ISREPLY,
FR_FORCE,
FR_BACKGROUND,
FR_WAITING,
FR_ABORTED,
FR_INTERRUPTED,
FR_LOCKED,
FR_PENDING,
FR_SENT,
FR_FINISHED,
FR_PRIVATE,
FR_ASYNC,
FR_URING,
};
/** * A request to the client * * .waitq.lock protects the following fields: * - FR_ABORTED * - FR_LOCKED (may also be modified under fc->lock, tested under both)
*/ struct fuse_req { /** This can be on either pending processing or io lists in
fuse_conn */ struct list_head list;
/** Entry on the interrupts list */ struct list_head intr_entry;
/** Used to wake up the task waiting for completion of request*/
wait_queue_head_t waitq;
#if IS_ENABLED(CONFIG_VIRTIO_FS) /** virtio-fs's physically contiguous buffer for in and out args */ void *argbuf; #endif
/** fuse_mount this request belongs to */ struct fuse_mount *fm;
#ifdef CONFIG_FUSE_IO_URING void *ring_entry; void *ring_queue; #endif /** When (in jiffies) the request was created */ unsignedlong create_time;
};
struct fuse_iqueue;
/** * Input queue callbacks * * Input queue signalling is device-specific. For example, the /dev/fuse file * uses fiq->waitq and fasync to wake processes that are waiting on queue * readiness. These callbacks allow other device types to respond to input * queue activity.
*/ struct fuse_iqueue_ops { /** * Send one forget
*/ void (*send_forget)(struct fuse_iqueue *fiq, struct fuse_forget_link *link);
/* DAX device, may be NULL */ struct dax_device *dax_dev;
/* fuse_dev pointer to fill in, should contain NULL on entry */ void **fudptr;
};
struct fuse_sync_bucket { /* count is a possible scalability bottleneck */
atomic_t count;
wait_queue_head_t waitq; struct rcu_head rcu;
};
/** * A Fuse connection. * * This structure is created, when the root filesystem is mounted, and * is destroyed, when the client device is closed and the last * fuse_mount is destroyed.
*/ struct fuse_conn { /** Lock protecting accessess to members of this structure */
spinlock_t lock;
/** Refcount */
refcount_t count;
/** Number of fuse_dev's */
atomic_t dev_count;
/** Current epoch for up-to-date dentries */
atomic_t epoch;
struct rcu_head rcu;
/** The user id for this mount */
kuid_t user_id;
/** The group id for this mount */
kgid_t group_id;
/** The pid namespace for this mount */ struct pid_namespace *pid_ns;
/** The user namespace for this mount */ struct user_namespace *user_ns;
/** Maximum read size */ unsigned max_read;
/** Maximum write size */ unsigned max_write;
/** Maximum number of pages that can be used in a single request */ unsignedint max_pages;
/** Constrain ->max_pages to this value during feature negotiation */ unsignedint max_pages_limit;
/** Input queue */ struct fuse_iqueue iq;
/** The next unique kernel file handle */
atomic64_t khctr;
/** rbtree of fuse_files waiting for poll events indexed by ph */ struct rb_root polled_files;
/** Maximum number of outstanding background requests */ unsigned max_background;
/** Number of background requests at which congestion starts */ unsigned congestion_threshold;
/** Number of requests currently in the background */ unsigned num_background;
/** Number of background requests currently queued for userspace */ unsigned active_background;
/** The list of background requests set aside for later queuing */ struct list_head bg_queue;
/** Flag indicating that INIT reply has been received. Allocating
* any fuse request will be suspended until the flag is set */ int initialized;
/** Flag indicating if connection is blocked. This will be the case before the INIT reply is received, and if there
are too many outstading backgrounds requests */ int blocked;
/** waitq for blocked connection */
wait_queue_head_t blocked_waitq;
/** Connection established, cleared on umount, connection
abort and device release */ unsigned connected;
/** Connection aborted via sysfs */ bool aborted;
/** Connection failed (version mismatch). Cannot race with setting other bitfields since it is only set once in INIT
reply, before any other request, and never cleared */ unsigned conn_error:1;
/** Connection successful. Only set in INIT */ unsigned conn_init:1;
/** Do readahead asynchronously? Only set in INIT */ unsigned async_read:1;
/** Return an unique read error after abort. Only set in INIT */ unsigned abort_err:1;
/** Do not send separate SETATTR request before open(O_TRUNC) */ unsigned atomic_o_trunc:1;
/** Filesystem supports NFS exporting. Only set in INIT */ unsigned export_support:1;
/** write-back cache policy (default is write-through) */ unsigned writeback_cache:1;
/** allow parallel lookups and readdir (default is serialized) */ unsigned parallel_dirops:1;
/** cache READLINK responses in page cache */ unsigned cache_symlinks:1;
/* show legacy mount options */ unsignedint legacy_opts_show:1;
/* * fs kills suid/sgid/cap on write/chown/trunc. suid is killed on * write/trunc only if caller did not have CAP_FSETID. sgid is killed * on write/truncate only if caller did not have CAP_FSETID as well as * file has group execute permission.
*/ unsigned handle_killpriv_v2:1;
/* * The following bitfields are only for optimization purposes * and hence races in setting them will not cause malfunction
*/
/** Is open/release not implemented by fs? */ unsigned no_open:1;
/** Is opendir/releasedir not implemented by fs? */ unsigned no_opendir:1;
/** Is fsync not implemented by fs? */ unsigned no_fsync:1;
/** Is fsyncdir not implemented by fs? */ unsigned no_fsyncdir:1;
/** Is flush not implemented by fs? */ unsigned no_flush:1;
/** Is setxattr not implemented by fs? */ unsigned no_setxattr:1;
/** Does file server support extended setxattr */ unsigned setxattr_ext:1;
/** Is getxattr not implemented by fs? */ unsigned no_getxattr:1;
/** Is listxattr not implemented by fs? */ unsigned no_listxattr:1;
/** Is removexattr not implemented by fs? */ unsigned no_removexattr:1;
/** Are posix file locking primitives not implemented by fs? */ unsigned no_lock:1;
/** Is access not implemented by fs? */ unsigned no_access:1;
/** Is create not implemented by fs? */ unsigned no_create:1;
/** Is interrupt not implemented by fs? */ unsigned no_interrupt:1;
/** Is bmap not implemented by fs? */ unsigned no_bmap:1;
/** Is poll not implemented by fs? */ unsigned no_poll:1;
/** Do multi-page cached writes */ unsigned big_writes:1;
/** Don't apply umask to creation modes */ unsigned dont_mask:1;
/** Are BSD file locking primitives not implemented by fs? */ unsigned no_flock:1;
/** Is fallocate not implemented by fs? */ unsigned no_fallocate:1;
/** Is rename with flags implemented by fs? */ unsigned no_rename2:1;
/** Use enhanced/automatic page cache invalidation. */ unsigned auto_inval_data:1;
/** Filesystem is fully responsible for page cache invalidation. */ unsigned explicit_inval_data:1;
/** Does the filesystem support readdirplus? */ unsigned do_readdirplus:1;
/** Does the filesystem want adaptive readdirplus? */ unsigned readdirplus_auto:1;
/** Does the filesystem support asynchronous direct-IO submission? */ unsigned async_dio:1;
/** Is lseek not implemented by fs? */ unsigned no_lseek:1;
/** Does the filesystem support posix acls? */ unsigned posix_acl:1;
/** Check permissions based on the file mode or not? */ unsigned default_permissions:1;
/** Allow other than the mounter user to access the filesystem ? */ unsigned allow_other:1;
/** Does the filesystem support copy_file_range? */ unsigned no_copy_file_range:1;
/* Send DESTROY request */ unsignedint destroy:1;
/* Delete dentries that have gone stale */ unsignedint delete_stale:1;
/** Do not create entry in fusectl fs */ unsignedint no_control:1;
/** Do not allow MNT_FORCE umount */ unsignedint no_force_umount:1;
/* Auto-mount submounts announced by the server */ unsignedint auto_submounts:1;
/* Propagate syncfs() to server */ unsignedint sync_fs:1;
/* Initialize security xattrs when creating a new inode */ unsignedint init_security:1;
/* Add supplementary group info when creating a new inode */ unsignedint create_supp_group:1;
/* Does the filesystem support per inode DAX? */ unsignedint inode_dax:1;
/* Is tmpfile not implemented by fs? */ unsignedint no_tmpfile:1;
/* Relax restrictions to allow shared mmap in FOPEN_DIRECT_IO mode */ unsignedint direct_io_allow_mmap:1;
/* Is statx not implemented by fs? */ unsignedint no_statx:1;
/** Passthrough support for read/write IO */ unsignedint passthrough:1;
/* Use pages instead of pointer for kernel I/O */ unsignedint use_pages_for_kvec_io:1;
/* Is link not implemented by fs? */ unsignedint no_link:1;
/* Use io_uring for communication */ unsignedint io_uring;
/** Maximum stack depth for passthrough backing files */ int max_stack_depth;
/** The number of requests waiting for completion */
atomic_t num_waiting;
/** Negotiated minor version */ unsigned minor;
/** Entry on the fuse_conn_list */ struct list_head entry;
/** Device ID from the root super block */
dev_t dev;
/** Key for lock owner ID scrambling */
u32 scramble_key[4];
/** Version counter for attribute changes */
atomic64_t attr_version;
/** Version counter for evict inode */
atomic64_t evict_ctr;
/* maximum file name length */
u32 name_max;
/** Called on final put */ void (*release)(struct fuse_conn *);
/** * Read/write semaphore to hold when accessing the sb of any * fuse_mount belonging to this connection
*/ struct rw_semaphore killsb;
/** List of device instances belonging to this connection */ struct list_head devices;
/** Only used if the connection opts into request timeouts */ struct { /* Worker for checking if any requests have timed out */ struct delayed_work work;
/* Request timeout (in jiffies). 0 = no timeout */ unsignedint req_timeout;
} timeout;
/* * This is a workaround until fuse uses iomap for reads. * For fuseblk servers, this represents the blocksize passed in at * mount time and for regular fuse servers, this is equivalent to * inode->i_blkbits.
*/
u8 blkbits;
};
/* * Represents a mounted filesystem, potentially a submount. * * This object allows sharing a fuse_conn between separate mounts to * allow submounts with dedicated superblocks and thus separate device * IDs.
*/ struct fuse_mount { /* Underlying (potentially shared) connection to the FUSE server */ struct fuse_conn *fc;
/* * Super block for this connection (fc->killsb must be held when * accessing this).
*/ struct super_block *sb;
/* * Empty header for FUSE opcodes without specific header needs. * Used as a placeholder in args->in_args[0] for consistency * across all FUSE operations, simplifying request handling.
*/ struct fuse_zero_header {};
for (i = index; i < index + nr_folios; i++)
descs[i].length = PAGE_SIZE - descs[i].offset;
}
staticinlinevoid fuse_sync_bucket_dec(struct fuse_sync_bucket *bucket)
{ /* Need RCU protection to prevent use after free after the decrement */
rcu_read_lock(); if (atomic_dec_and_test(&bucket->count))
wake_up(&bucket->waitq);
rcu_read_unlock();
}
/** * Fill in superblock and initialize fuse connection * @sb: partially-initialized superblock to fill in * @ctx: mount context
*/ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx);
/* * Remove the mount from the connection * * Returns whether this was the last mount
*/ bool fuse_mount_remove(struct fuse_mount *fm);
/* * Setup context ops for submounts
*/ int fuse_init_fs_context_submount(struct fs_context *fsc);
/* * Shut down the connection (possibly sending DESTROY request).
*/ void fuse_conn_destroy(struct fuse_mount *fm);
/* Drop the connection and free the fuse mount */ void fuse_mount_destroy(struct fuse_mount *fm);
/** * Add connection to control filesystem
*/ int fuse_ctl_add_conn(struct fuse_conn *fc);
/** * Remove connection from control filesystem
*/ void fuse_ctl_remove_conn(struct fuse_conn *fc);
/** * Is file type valid?
*/ int fuse_valid_type(int m);
bool fuse_invalid_attr(struct fuse_attr *attr);
/** * Is current process allowed to perform filesystem operation?
*/ bool fuse_allow_current_process(struct fuse_conn *fc);
/** * Scan all fuse_mounts belonging to fc to find the first where * ilookup5() returns a result. Return that result and the * respective fuse_mount in *fm (unless fm is NULL). * * The caller must hold fc->killsb.
*/ struct inode *fuse_ilookup(struct fuse_conn *fc, u64 nodeid, struct fuse_mount **fm);
/** * File-system tells the kernel to invalidate cache for the given node id.
*/ int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid,
loff_t offset, loff_t len);
/** * File-system tells the kernel to invalidate parent attributes and * the dentry matching parent/name. * * If the child_nodeid is non-zero and: * - matches the inode number for the dentry matching parent/name, * - is not a mount point * - is a file or oan empty directory * then the dentry is unhashed (d_delete()).
*/ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
u64 child_nodeid, struct qstr *name, u32 flags);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.