162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci FUSE: Filesystem in Userspace 362306a36Sopenharmony_ci Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci This program can be distributed under the terms of the GNU GPL. 662306a36Sopenharmony_ci See the file COPYING. 762306a36Sopenharmony_ci*/ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef _FS_FUSE_I_H 1062306a36Sopenharmony_ci#define _FS_FUSE_I_H 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#ifndef pr_fmt 1362306a36Sopenharmony_ci# define pr_fmt(fmt) "fuse: " fmt 1462306a36Sopenharmony_ci#endif 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <linux/fuse.h> 1762306a36Sopenharmony_ci#include <linux/fs.h> 1862306a36Sopenharmony_ci#include <linux/mount.h> 1962306a36Sopenharmony_ci#include <linux/wait.h> 2062306a36Sopenharmony_ci#include <linux/list.h> 2162306a36Sopenharmony_ci#include <linux/spinlock.h> 2262306a36Sopenharmony_ci#include <linux/mm.h> 2362306a36Sopenharmony_ci#include <linux/backing-dev.h> 2462306a36Sopenharmony_ci#include <linux/mutex.h> 2562306a36Sopenharmony_ci#include <linux/rwsem.h> 2662306a36Sopenharmony_ci#include <linux/rbtree.h> 2762306a36Sopenharmony_ci#include <linux/poll.h> 2862306a36Sopenharmony_ci#include <linux/workqueue.h> 2962306a36Sopenharmony_ci#include <linux/kref.h> 3062306a36Sopenharmony_ci#include <linux/xattr.h> 3162306a36Sopenharmony_ci#include <linux/pid_namespace.h> 3262306a36Sopenharmony_ci#include <linux/refcount.h> 3362306a36Sopenharmony_ci#include <linux/user_namespace.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/** Default max number of pages that can be used in a single read request */ 3662306a36Sopenharmony_ci#define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/** Maximum of max_pages received in init_out */ 3962306a36Sopenharmony_ci#define FUSE_MAX_MAX_PAGES 256 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/** Bias for fi->writectr, meaning new writepages must not be sent */ 4262306a36Sopenharmony_ci#define FUSE_NOWRITE INT_MIN 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/** It could be as large as PATH_MAX, but would that have any uses? */ 4562306a36Sopenharmony_ci#define FUSE_NAME_MAX 1024 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/** Number of dentries for each connection in the control filesystem */ 4862306a36Sopenharmony_ci#define FUSE_CTL_NUM_DENTRIES 5 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/** List of active connections */ 5162306a36Sopenharmony_ciextern struct list_head fuse_conn_list; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/** Global mutex protecting fuse_conn_list and the control filesystem */ 5462306a36Sopenharmony_ciextern struct mutex fuse_mutex; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/** Module parameters */ 5762306a36Sopenharmony_ciextern unsigned max_user_bgreq; 5862306a36Sopenharmony_ciextern unsigned max_user_congthresh; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* One forget request */ 6162306a36Sopenharmony_cistruct fuse_forget_link { 6262306a36Sopenharmony_ci struct fuse_forget_one forget_one; 6362306a36Sopenharmony_ci struct fuse_forget_link *next; 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* Submount lookup tracking */ 6762306a36Sopenharmony_cistruct fuse_submount_lookup { 6862306a36Sopenharmony_ci /** Refcount */ 6962306a36Sopenharmony_ci refcount_t count; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /** Unique ID, which identifies the inode between userspace 7262306a36Sopenharmony_ci * and kernel */ 7362306a36Sopenharmony_ci u64 nodeid; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /** The request used for sending the FORGET message */ 7662306a36Sopenharmony_ci struct fuse_forget_link *forget; 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/** FUSE inode */ 8062306a36Sopenharmony_cistruct fuse_inode { 8162306a36Sopenharmony_ci /** Inode data */ 8262306a36Sopenharmony_ci struct inode inode; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci /** Unique ID, which identifies the inode between userspace 8562306a36Sopenharmony_ci * and kernel */ 8662306a36Sopenharmony_ci u64 nodeid; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /** Number of lookups on this inode */ 8962306a36Sopenharmony_ci u64 nlookup; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /** The request used for sending the FORGET message */ 9262306a36Sopenharmony_ci struct fuse_forget_link *forget; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /** Time in jiffies until the file attributes are valid */ 9562306a36Sopenharmony_ci u64 i_time; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* Which attributes are invalid */ 9862306a36Sopenharmony_ci u32 inval_mask; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /** The sticky bit in inode->i_mode may have been removed, so 10162306a36Sopenharmony_ci preserve the original mode */ 10262306a36Sopenharmony_ci umode_t orig_i_mode; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Cache birthtime */ 10562306a36Sopenharmony_ci struct timespec64 i_btime; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /** 64 bit inode number */ 10862306a36Sopenharmony_ci u64 orig_ino; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /** Version of last attribute change */ 11162306a36Sopenharmony_ci u64 attr_version; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci union { 11462306a36Sopenharmony_ci /* Write related fields (regular file only) */ 11562306a36Sopenharmony_ci struct { 11662306a36Sopenharmony_ci /* Files usable in writepage. Protected by fi->lock */ 11762306a36Sopenharmony_ci struct list_head write_files; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* Writepages pending on truncate or fsync */ 12062306a36Sopenharmony_ci struct list_head queued_writes; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci /* Number of sent writes, a negative bias 12362306a36Sopenharmony_ci * (FUSE_NOWRITE) means more writes are blocked */ 12462306a36Sopenharmony_ci int writectr; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* Waitq for writepage completion */ 12762306a36Sopenharmony_ci wait_queue_head_t page_waitq; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* List of writepage requestst (pending or sent) */ 13062306a36Sopenharmony_ci struct rb_root writepages; 13162306a36Sopenharmony_ci }; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* readdir cache (directory only) */ 13462306a36Sopenharmony_ci struct { 13562306a36Sopenharmony_ci /* true if fully cached */ 13662306a36Sopenharmony_ci bool cached; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* size of cache */ 13962306a36Sopenharmony_ci loff_t size; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* position at end of cache (position of next entry) */ 14262306a36Sopenharmony_ci loff_t pos; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci /* version of the cache */ 14562306a36Sopenharmony_ci u64 version; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* modification time of directory when cache was 14862306a36Sopenharmony_ci * started */ 14962306a36Sopenharmony_ci struct timespec64 mtime; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* iversion of directory when cache was started */ 15262306a36Sopenharmony_ci u64 iversion; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci /* protects above fields */ 15562306a36Sopenharmony_ci spinlock_t lock; 15662306a36Sopenharmony_ci } rdc; 15762306a36Sopenharmony_ci }; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /** Miscellaneous bits describing inode state */ 16062306a36Sopenharmony_ci unsigned long state; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /** Lock for serializing lookup and readdir for back compatibility*/ 16362306a36Sopenharmony_ci struct mutex mutex; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /** Lock to protect write related fields */ 16662306a36Sopenharmony_ci spinlock_t lock; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#ifdef CONFIG_FUSE_DAX 16962306a36Sopenharmony_ci /* 17062306a36Sopenharmony_ci * Dax specific inode data 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_ci struct fuse_inode_dax *dax; 17362306a36Sopenharmony_ci#endif 17462306a36Sopenharmony_ci /** Submount specific lookup tracking */ 17562306a36Sopenharmony_ci struct fuse_submount_lookup *submount_lookup; 17662306a36Sopenharmony_ci}; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/** FUSE inode state bits */ 17962306a36Sopenharmony_cienum { 18062306a36Sopenharmony_ci /** Advise readdirplus */ 18162306a36Sopenharmony_ci FUSE_I_ADVISE_RDPLUS, 18262306a36Sopenharmony_ci /** Initialized with readdirplus */ 18362306a36Sopenharmony_ci FUSE_I_INIT_RDPLUS, 18462306a36Sopenharmony_ci /** An operation changing file size is in progress */ 18562306a36Sopenharmony_ci FUSE_I_SIZE_UNSTABLE, 18662306a36Sopenharmony_ci /* Bad inode */ 18762306a36Sopenharmony_ci FUSE_I_BAD, 18862306a36Sopenharmony_ci /* Has btime */ 18962306a36Sopenharmony_ci FUSE_I_BTIME, 19062306a36Sopenharmony_ci}; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistruct fuse_conn; 19362306a36Sopenharmony_cistruct fuse_mount; 19462306a36Sopenharmony_cistruct fuse_release_args; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci/** FUSE specific file data */ 19762306a36Sopenharmony_cistruct fuse_file { 19862306a36Sopenharmony_ci /** Fuse connection for this file */ 19962306a36Sopenharmony_ci struct fuse_mount *fm; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* Argument space reserved for release */ 20262306a36Sopenharmony_ci struct fuse_release_args *release_args; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /** Kernel file handle guaranteed to be unique */ 20562306a36Sopenharmony_ci u64 kh; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /** File handle used by userspace */ 20862306a36Sopenharmony_ci u64 fh; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci /** Node id of this file */ 21162306a36Sopenharmony_ci u64 nodeid; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /** Refcount */ 21462306a36Sopenharmony_ci refcount_t count; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /** FOPEN_* flags returned by open */ 21762306a36Sopenharmony_ci u32 open_flags; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci /** Entry on inode's write_files list */ 22062306a36Sopenharmony_ci struct list_head write_entry; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* Readdir related */ 22362306a36Sopenharmony_ci struct { 22462306a36Sopenharmony_ci /* 22562306a36Sopenharmony_ci * Protects below fields against (crazy) parallel readdir on 22662306a36Sopenharmony_ci * same open file. Uncontended in the normal case. 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_ci struct mutex lock; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci /* Dir stream position */ 23162306a36Sopenharmony_ci loff_t pos; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* Offset in cache */ 23462306a36Sopenharmony_ci loff_t cache_off; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* Version of cache we are reading */ 23762306a36Sopenharmony_ci u64 version; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci } readdir; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci /** RB node to be linked on fuse_conn->polled_files */ 24262306a36Sopenharmony_ci struct rb_node polled_node; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /** Wait queue head for poll */ 24562306a36Sopenharmony_ci wait_queue_head_t poll_wait; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /** Has flock been performed on this file? */ 24862306a36Sopenharmony_ci bool flock:1; 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci/** One input argument of a request */ 25262306a36Sopenharmony_cistruct fuse_in_arg { 25362306a36Sopenharmony_ci unsigned size; 25462306a36Sopenharmony_ci const void *value; 25562306a36Sopenharmony_ci}; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci/** One output argument of a request */ 25862306a36Sopenharmony_cistruct fuse_arg { 25962306a36Sopenharmony_ci unsigned size; 26062306a36Sopenharmony_ci void *value; 26162306a36Sopenharmony_ci}; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci/** FUSE page descriptor */ 26462306a36Sopenharmony_cistruct fuse_page_desc { 26562306a36Sopenharmony_ci unsigned int length; 26662306a36Sopenharmony_ci unsigned int offset; 26762306a36Sopenharmony_ci}; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistruct fuse_args { 27062306a36Sopenharmony_ci uint64_t nodeid; 27162306a36Sopenharmony_ci uint32_t opcode; 27262306a36Sopenharmony_ci uint8_t in_numargs; 27362306a36Sopenharmony_ci uint8_t out_numargs; 27462306a36Sopenharmony_ci uint8_t ext_idx; 27562306a36Sopenharmony_ci bool force:1; 27662306a36Sopenharmony_ci bool noreply:1; 27762306a36Sopenharmony_ci bool nocreds:1; 27862306a36Sopenharmony_ci bool in_pages:1; 27962306a36Sopenharmony_ci bool out_pages:1; 28062306a36Sopenharmony_ci bool user_pages:1; 28162306a36Sopenharmony_ci bool out_argvar:1; 28262306a36Sopenharmony_ci bool page_zeroing:1; 28362306a36Sopenharmony_ci bool page_replace:1; 28462306a36Sopenharmony_ci bool may_block:1; 28562306a36Sopenharmony_ci bool is_ext:1; 28662306a36Sopenharmony_ci struct fuse_in_arg in_args[3]; 28762306a36Sopenharmony_ci struct fuse_arg out_args[2]; 28862306a36Sopenharmony_ci void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error); 28962306a36Sopenharmony_ci}; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistruct fuse_args_pages { 29262306a36Sopenharmony_ci struct fuse_args args; 29362306a36Sopenharmony_ci struct page **pages; 29462306a36Sopenharmony_ci struct fuse_page_desc *descs; 29562306a36Sopenharmony_ci unsigned int num_pages; 29662306a36Sopenharmony_ci}; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci#define FUSE_ARGS(args) struct fuse_args args = {} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci/** The request IO state (for asynchronous processing) */ 30162306a36Sopenharmony_cistruct fuse_io_priv { 30262306a36Sopenharmony_ci struct kref refcnt; 30362306a36Sopenharmony_ci int async; 30462306a36Sopenharmony_ci spinlock_t lock; 30562306a36Sopenharmony_ci unsigned reqs; 30662306a36Sopenharmony_ci ssize_t bytes; 30762306a36Sopenharmony_ci size_t size; 30862306a36Sopenharmony_ci __u64 offset; 30962306a36Sopenharmony_ci bool write; 31062306a36Sopenharmony_ci bool should_dirty; 31162306a36Sopenharmony_ci int err; 31262306a36Sopenharmony_ci struct kiocb *iocb; 31362306a36Sopenharmony_ci struct completion *done; 31462306a36Sopenharmony_ci bool blocking; 31562306a36Sopenharmony_ci}; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci#define FUSE_IO_PRIV_SYNC(i) \ 31862306a36Sopenharmony_ci{ \ 31962306a36Sopenharmony_ci .refcnt = KREF_INIT(1), \ 32062306a36Sopenharmony_ci .async = 0, \ 32162306a36Sopenharmony_ci .iocb = i, \ 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci/** 32562306a36Sopenharmony_ci * Request flags 32662306a36Sopenharmony_ci * 32762306a36Sopenharmony_ci * FR_ISREPLY: set if the request has reply 32862306a36Sopenharmony_ci * FR_FORCE: force sending of the request even if interrupted 32962306a36Sopenharmony_ci * FR_BACKGROUND: request is sent in the background 33062306a36Sopenharmony_ci * FR_WAITING: request is counted as "waiting" 33162306a36Sopenharmony_ci * FR_ABORTED: the request was aborted 33262306a36Sopenharmony_ci * FR_INTERRUPTED: the request has been interrupted 33362306a36Sopenharmony_ci * FR_LOCKED: data is being copied to/from the request 33462306a36Sopenharmony_ci * FR_PENDING: request is not yet in userspace 33562306a36Sopenharmony_ci * FR_SENT: request is in userspace, waiting for an answer 33662306a36Sopenharmony_ci * FR_FINISHED: request is finished 33762306a36Sopenharmony_ci * FR_PRIVATE: request is on private list 33862306a36Sopenharmony_ci * FR_ASYNC: request is asynchronous 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_cienum fuse_req_flag { 34162306a36Sopenharmony_ci FR_ISREPLY, 34262306a36Sopenharmony_ci FR_FORCE, 34362306a36Sopenharmony_ci FR_BACKGROUND, 34462306a36Sopenharmony_ci FR_WAITING, 34562306a36Sopenharmony_ci FR_ABORTED, 34662306a36Sopenharmony_ci FR_INTERRUPTED, 34762306a36Sopenharmony_ci FR_LOCKED, 34862306a36Sopenharmony_ci FR_PENDING, 34962306a36Sopenharmony_ci FR_SENT, 35062306a36Sopenharmony_ci FR_FINISHED, 35162306a36Sopenharmony_ci FR_PRIVATE, 35262306a36Sopenharmony_ci FR_ASYNC, 35362306a36Sopenharmony_ci}; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci/** 35662306a36Sopenharmony_ci * A request to the client 35762306a36Sopenharmony_ci * 35862306a36Sopenharmony_ci * .waitq.lock protects the following fields: 35962306a36Sopenharmony_ci * - FR_ABORTED 36062306a36Sopenharmony_ci * - FR_LOCKED (may also be modified under fc->lock, tested under both) 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_cistruct fuse_req { 36362306a36Sopenharmony_ci /** This can be on either pending processing or io lists in 36462306a36Sopenharmony_ci fuse_conn */ 36562306a36Sopenharmony_ci struct list_head list; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci /** Entry on the interrupts list */ 36862306a36Sopenharmony_ci struct list_head intr_entry; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci /* Input/output arguments */ 37162306a36Sopenharmony_ci struct fuse_args *args; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /** refcount */ 37462306a36Sopenharmony_ci refcount_t count; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci /* Request flags, updated with test/set/clear_bit() */ 37762306a36Sopenharmony_ci unsigned long flags; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci /* The request input header */ 38062306a36Sopenharmony_ci struct { 38162306a36Sopenharmony_ci struct fuse_in_header h; 38262306a36Sopenharmony_ci } in; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci /* The request output header */ 38562306a36Sopenharmony_ci struct { 38662306a36Sopenharmony_ci struct fuse_out_header h; 38762306a36Sopenharmony_ci } out; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci /** Used to wake up the task waiting for completion of request*/ 39062306a36Sopenharmony_ci wait_queue_head_t waitq; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_VIRTIO_FS) 39362306a36Sopenharmony_ci /** virtio-fs's physically contiguous buffer for in and out args */ 39462306a36Sopenharmony_ci void *argbuf; 39562306a36Sopenharmony_ci#endif 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci /** fuse_mount this request belongs to */ 39862306a36Sopenharmony_ci struct fuse_mount *fm; 39962306a36Sopenharmony_ci}; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistruct fuse_iqueue; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci/** 40462306a36Sopenharmony_ci * Input queue callbacks 40562306a36Sopenharmony_ci * 40662306a36Sopenharmony_ci * Input queue signalling is device-specific. For example, the /dev/fuse file 40762306a36Sopenharmony_ci * uses fiq->waitq and fasync to wake processes that are waiting on queue 40862306a36Sopenharmony_ci * readiness. These callbacks allow other device types to respond to input 40962306a36Sopenharmony_ci * queue activity. 41062306a36Sopenharmony_ci */ 41162306a36Sopenharmony_cistruct fuse_iqueue_ops { 41262306a36Sopenharmony_ci /** 41362306a36Sopenharmony_ci * Signal that a forget has been queued 41462306a36Sopenharmony_ci */ 41562306a36Sopenharmony_ci void (*wake_forget_and_unlock)(struct fuse_iqueue *fiq) 41662306a36Sopenharmony_ci __releases(fiq->lock); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci /** 41962306a36Sopenharmony_ci * Signal that an INTERRUPT request has been queued 42062306a36Sopenharmony_ci */ 42162306a36Sopenharmony_ci void (*wake_interrupt_and_unlock)(struct fuse_iqueue *fiq) 42262306a36Sopenharmony_ci __releases(fiq->lock); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /** 42562306a36Sopenharmony_ci * Signal that a request has been queued 42662306a36Sopenharmony_ci */ 42762306a36Sopenharmony_ci void (*wake_pending_and_unlock)(struct fuse_iqueue *fiq) 42862306a36Sopenharmony_ci __releases(fiq->lock); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci /** 43162306a36Sopenharmony_ci * Clean up when fuse_iqueue is destroyed 43262306a36Sopenharmony_ci */ 43362306a36Sopenharmony_ci void (*release)(struct fuse_iqueue *fiq); 43462306a36Sopenharmony_ci}; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci/** /dev/fuse input queue operations */ 43762306a36Sopenharmony_ciextern const struct fuse_iqueue_ops fuse_dev_fiq_ops; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistruct fuse_iqueue { 44062306a36Sopenharmony_ci /** Connection established */ 44162306a36Sopenharmony_ci unsigned connected; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci /** Lock protecting accesses to members of this structure */ 44462306a36Sopenharmony_ci spinlock_t lock; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci /** Readers of the connection are waiting on this */ 44762306a36Sopenharmony_ci wait_queue_head_t waitq; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /** The next unique request id */ 45062306a36Sopenharmony_ci u64 reqctr; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci /** The list of pending requests */ 45362306a36Sopenharmony_ci struct list_head pending; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /** Pending interrupts */ 45662306a36Sopenharmony_ci struct list_head interrupts; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci /** Queue of pending forgets */ 45962306a36Sopenharmony_ci struct fuse_forget_link forget_list_head; 46062306a36Sopenharmony_ci struct fuse_forget_link *forget_list_tail; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci /** Batching of FORGET requests (positive indicates FORGET batch) */ 46362306a36Sopenharmony_ci int forget_batch; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci /** O_ASYNC requests */ 46662306a36Sopenharmony_ci struct fasync_struct *fasync; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci /** Device-specific callbacks */ 46962306a36Sopenharmony_ci const struct fuse_iqueue_ops *ops; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci /** Device-specific state */ 47262306a36Sopenharmony_ci void *priv; 47362306a36Sopenharmony_ci}; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci#define FUSE_PQ_HASH_BITS 8 47662306a36Sopenharmony_ci#define FUSE_PQ_HASH_SIZE (1 << FUSE_PQ_HASH_BITS) 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistruct fuse_pqueue { 47962306a36Sopenharmony_ci /** Connection established */ 48062306a36Sopenharmony_ci unsigned connected; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci /** Lock protecting accessess to members of this structure */ 48362306a36Sopenharmony_ci spinlock_t lock; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci /** Hash table of requests being processed */ 48662306a36Sopenharmony_ci struct list_head *processing; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci /** The list of requests under I/O */ 48962306a36Sopenharmony_ci struct list_head io; 49062306a36Sopenharmony_ci}; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci/** 49362306a36Sopenharmony_ci * Fuse device instance 49462306a36Sopenharmony_ci */ 49562306a36Sopenharmony_cistruct fuse_dev { 49662306a36Sopenharmony_ci /** Fuse connection for this device */ 49762306a36Sopenharmony_ci struct fuse_conn *fc; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci /** Processing queue */ 50062306a36Sopenharmony_ci struct fuse_pqueue pq; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /** list entry on fc->devices */ 50362306a36Sopenharmony_ci struct list_head entry; 50462306a36Sopenharmony_ci}; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cienum fuse_dax_mode { 50762306a36Sopenharmony_ci FUSE_DAX_INODE_DEFAULT, /* default */ 50862306a36Sopenharmony_ci FUSE_DAX_ALWAYS, /* "-o dax=always" */ 50962306a36Sopenharmony_ci FUSE_DAX_NEVER, /* "-o dax=never" */ 51062306a36Sopenharmony_ci FUSE_DAX_INODE_USER, /* "-o dax=inode" */ 51162306a36Sopenharmony_ci}; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic inline bool fuse_is_inode_dax_mode(enum fuse_dax_mode mode) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci return mode == FUSE_DAX_INODE_DEFAULT || mode == FUSE_DAX_INODE_USER; 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistruct fuse_fs_context { 51962306a36Sopenharmony_ci int fd; 52062306a36Sopenharmony_ci struct file *file; 52162306a36Sopenharmony_ci unsigned int rootmode; 52262306a36Sopenharmony_ci kuid_t user_id; 52362306a36Sopenharmony_ci kgid_t group_id; 52462306a36Sopenharmony_ci bool is_bdev:1; 52562306a36Sopenharmony_ci bool fd_present:1; 52662306a36Sopenharmony_ci bool rootmode_present:1; 52762306a36Sopenharmony_ci bool user_id_present:1; 52862306a36Sopenharmony_ci bool group_id_present:1; 52962306a36Sopenharmony_ci bool default_permissions:1; 53062306a36Sopenharmony_ci bool allow_other:1; 53162306a36Sopenharmony_ci bool destroy:1; 53262306a36Sopenharmony_ci bool no_control:1; 53362306a36Sopenharmony_ci bool no_force_umount:1; 53462306a36Sopenharmony_ci bool legacy_opts_show:1; 53562306a36Sopenharmony_ci enum fuse_dax_mode dax_mode; 53662306a36Sopenharmony_ci unsigned int max_read; 53762306a36Sopenharmony_ci unsigned int blksize; 53862306a36Sopenharmony_ci const char *subtype; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci /* DAX device, may be NULL */ 54162306a36Sopenharmony_ci struct dax_device *dax_dev; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci /* fuse_dev pointer to fill in, should contain NULL on entry */ 54462306a36Sopenharmony_ci void **fudptr; 54562306a36Sopenharmony_ci}; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_cistruct fuse_sync_bucket { 54862306a36Sopenharmony_ci /* count is a possible scalability bottleneck */ 54962306a36Sopenharmony_ci atomic_t count; 55062306a36Sopenharmony_ci wait_queue_head_t waitq; 55162306a36Sopenharmony_ci struct rcu_head rcu; 55262306a36Sopenharmony_ci}; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci/** 55562306a36Sopenharmony_ci * A Fuse connection. 55662306a36Sopenharmony_ci * 55762306a36Sopenharmony_ci * This structure is created, when the root filesystem is mounted, and 55862306a36Sopenharmony_ci * is destroyed, when the client device is closed and the last 55962306a36Sopenharmony_ci * fuse_mount is destroyed. 56062306a36Sopenharmony_ci */ 56162306a36Sopenharmony_cistruct fuse_conn { 56262306a36Sopenharmony_ci /** Lock protecting accessess to members of this structure */ 56362306a36Sopenharmony_ci spinlock_t lock; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci /** Refcount */ 56662306a36Sopenharmony_ci refcount_t count; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci /** Number of fuse_dev's */ 56962306a36Sopenharmony_ci atomic_t dev_count; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci struct rcu_head rcu; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci /** The user id for this mount */ 57462306a36Sopenharmony_ci kuid_t user_id; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci /** The group id for this mount */ 57762306a36Sopenharmony_ci kgid_t group_id; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci /** The pid namespace for this mount */ 58062306a36Sopenharmony_ci struct pid_namespace *pid_ns; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci /** The user namespace for this mount */ 58362306a36Sopenharmony_ci struct user_namespace *user_ns; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci /** Maximum read size */ 58662306a36Sopenharmony_ci unsigned max_read; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci /** Maximum write size */ 58962306a36Sopenharmony_ci unsigned max_write; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci /** Maximum number of pages that can be used in a single request */ 59262306a36Sopenharmony_ci unsigned int max_pages; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci /** Constrain ->max_pages to this value during feature negotiation */ 59562306a36Sopenharmony_ci unsigned int max_pages_limit; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci /** Input queue */ 59862306a36Sopenharmony_ci struct fuse_iqueue iq; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci /** The next unique kernel file handle */ 60162306a36Sopenharmony_ci atomic64_t khctr; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /** rbtree of fuse_files waiting for poll events indexed by ph */ 60462306a36Sopenharmony_ci struct rb_root polled_files; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /** Maximum number of outstanding background requests */ 60762306a36Sopenharmony_ci unsigned max_background; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci /** Number of background requests at which congestion starts */ 61062306a36Sopenharmony_ci unsigned congestion_threshold; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci /** Number of requests currently in the background */ 61362306a36Sopenharmony_ci unsigned num_background; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci /** Number of background requests currently queued for userspace */ 61662306a36Sopenharmony_ci unsigned active_background; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci /** The list of background requests set aside for later queuing */ 61962306a36Sopenharmony_ci struct list_head bg_queue; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci /** Protects: max_background, congestion_threshold, num_background, 62262306a36Sopenharmony_ci * active_background, bg_queue, blocked */ 62362306a36Sopenharmony_ci spinlock_t bg_lock; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci /** Flag indicating that INIT reply has been received. Allocating 62662306a36Sopenharmony_ci * any fuse request will be suspended until the flag is set */ 62762306a36Sopenharmony_ci int initialized; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci /** Flag indicating if connection is blocked. This will be 63062306a36Sopenharmony_ci the case before the INIT reply is received, and if there 63162306a36Sopenharmony_ci are too many outstading backgrounds requests */ 63262306a36Sopenharmony_ci int blocked; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /** waitq for blocked connection */ 63562306a36Sopenharmony_ci wait_queue_head_t blocked_waitq; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci /** Connection established, cleared on umount, connection 63862306a36Sopenharmony_ci abort and device release */ 63962306a36Sopenharmony_ci unsigned connected; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci /** Connection aborted via sysfs */ 64262306a36Sopenharmony_ci bool aborted; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /** Connection failed (version mismatch). Cannot race with 64562306a36Sopenharmony_ci setting other bitfields since it is only set once in INIT 64662306a36Sopenharmony_ci reply, before any other request, and never cleared */ 64762306a36Sopenharmony_ci unsigned conn_error:1; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci /** Connection successful. Only set in INIT */ 65062306a36Sopenharmony_ci unsigned conn_init:1; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci /** Do readahead asynchronously? Only set in INIT */ 65362306a36Sopenharmony_ci unsigned async_read:1; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci /** Return an unique read error after abort. Only set in INIT */ 65662306a36Sopenharmony_ci unsigned abort_err:1; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci /** Do not send separate SETATTR request before open(O_TRUNC) */ 65962306a36Sopenharmony_ci unsigned atomic_o_trunc:1; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci /** Filesystem supports NFS exporting. Only set in INIT */ 66262306a36Sopenharmony_ci unsigned export_support:1; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci /** write-back cache policy (default is write-through) */ 66562306a36Sopenharmony_ci unsigned writeback_cache:1; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci /** allow parallel lookups and readdir (default is serialized) */ 66862306a36Sopenharmony_ci unsigned parallel_dirops:1; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci /** handle fs handles killing suid/sgid/cap on write/chown/trunc */ 67162306a36Sopenharmony_ci unsigned handle_killpriv:1; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci /** cache READLINK responses in page cache */ 67462306a36Sopenharmony_ci unsigned cache_symlinks:1; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci /* show legacy mount options */ 67762306a36Sopenharmony_ci unsigned int legacy_opts_show:1; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci /* 68062306a36Sopenharmony_ci * fs kills suid/sgid/cap on write/chown/trunc. suid is killed on 68162306a36Sopenharmony_ci * write/trunc only if caller did not have CAP_FSETID. sgid is killed 68262306a36Sopenharmony_ci * on write/truncate only if caller did not have CAP_FSETID as well as 68362306a36Sopenharmony_ci * file has group execute permission. 68462306a36Sopenharmony_ci */ 68562306a36Sopenharmony_ci unsigned handle_killpriv_v2:1; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci /* 68862306a36Sopenharmony_ci * The following bitfields are only for optimization purposes 68962306a36Sopenharmony_ci * and hence races in setting them will not cause malfunction 69062306a36Sopenharmony_ci */ 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci /** Is open/release not implemented by fs? */ 69362306a36Sopenharmony_ci unsigned no_open:1; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /** Is opendir/releasedir not implemented by fs? */ 69662306a36Sopenharmony_ci unsigned no_opendir:1; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci /** Is fsync not implemented by fs? */ 69962306a36Sopenharmony_ci unsigned no_fsync:1; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci /** Is fsyncdir not implemented by fs? */ 70262306a36Sopenharmony_ci unsigned no_fsyncdir:1; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /** Is flush not implemented by fs? */ 70562306a36Sopenharmony_ci unsigned no_flush:1; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci /** Is setxattr not implemented by fs? */ 70862306a36Sopenharmony_ci unsigned no_setxattr:1; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci /** Does file server support extended setxattr */ 71162306a36Sopenharmony_ci unsigned setxattr_ext:1; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci /** Is getxattr not implemented by fs? */ 71462306a36Sopenharmony_ci unsigned no_getxattr:1; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci /** Is listxattr not implemented by fs? */ 71762306a36Sopenharmony_ci unsigned no_listxattr:1; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /** Is removexattr not implemented by fs? */ 72062306a36Sopenharmony_ci unsigned no_removexattr:1; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci /** Are posix file locking primitives not implemented by fs? */ 72362306a36Sopenharmony_ci unsigned no_lock:1; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci /** Is access not implemented by fs? */ 72662306a36Sopenharmony_ci unsigned no_access:1; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci /** Is create not implemented by fs? */ 72962306a36Sopenharmony_ci unsigned no_create:1; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci /** Is interrupt not implemented by fs? */ 73262306a36Sopenharmony_ci unsigned no_interrupt:1; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci /** Is bmap not implemented by fs? */ 73562306a36Sopenharmony_ci unsigned no_bmap:1; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci /** Is poll not implemented by fs? */ 73862306a36Sopenharmony_ci unsigned no_poll:1; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci /** Do multi-page cached writes */ 74162306a36Sopenharmony_ci unsigned big_writes:1; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci /** Don't apply umask to creation modes */ 74462306a36Sopenharmony_ci unsigned dont_mask:1; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci /** Are BSD file locking primitives not implemented by fs? */ 74762306a36Sopenharmony_ci unsigned no_flock:1; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci /** Is fallocate not implemented by fs? */ 75062306a36Sopenharmony_ci unsigned no_fallocate:1; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci /** Is rename with flags implemented by fs? */ 75362306a36Sopenharmony_ci unsigned no_rename2:1; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci /** Use enhanced/automatic page cache invalidation. */ 75662306a36Sopenharmony_ci unsigned auto_inval_data:1; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci /** Filesystem is fully responsible for page cache invalidation. */ 75962306a36Sopenharmony_ci unsigned explicit_inval_data:1; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci /** Does the filesystem support readdirplus? */ 76262306a36Sopenharmony_ci unsigned do_readdirplus:1; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci /** Does the filesystem want adaptive readdirplus? */ 76562306a36Sopenharmony_ci unsigned readdirplus_auto:1; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci /** Does the filesystem support asynchronous direct-IO submission? */ 76862306a36Sopenharmony_ci unsigned async_dio:1; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci /** Is lseek not implemented by fs? */ 77162306a36Sopenharmony_ci unsigned no_lseek:1; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci /** Does the filesystem support posix acls? */ 77462306a36Sopenharmony_ci unsigned posix_acl:1; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci /** Check permissions based on the file mode or not? */ 77762306a36Sopenharmony_ci unsigned default_permissions:1; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci /** Allow other than the mounter user to access the filesystem ? */ 78062306a36Sopenharmony_ci unsigned allow_other:1; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci /** Does the filesystem support copy_file_range? */ 78362306a36Sopenharmony_ci unsigned no_copy_file_range:1; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci /* Send DESTROY request */ 78662306a36Sopenharmony_ci unsigned int destroy:1; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci /* Delete dentries that have gone stale */ 78962306a36Sopenharmony_ci unsigned int delete_stale:1; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci /** Do not create entry in fusectl fs */ 79262306a36Sopenharmony_ci unsigned int no_control:1; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci /** Do not allow MNT_FORCE umount */ 79562306a36Sopenharmony_ci unsigned int no_force_umount:1; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci /* Auto-mount submounts announced by the server */ 79862306a36Sopenharmony_ci unsigned int auto_submounts:1; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci /* Propagate syncfs() to server */ 80162306a36Sopenharmony_ci unsigned int sync_fs:1; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci /* Initialize security xattrs when creating a new inode */ 80462306a36Sopenharmony_ci unsigned int init_security:1; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci /* Add supplementary group info when creating a new inode */ 80762306a36Sopenharmony_ci unsigned int create_supp_group:1; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci /* Does the filesystem support per inode DAX? */ 81062306a36Sopenharmony_ci unsigned int inode_dax:1; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci /* Is tmpfile not implemented by fs? */ 81362306a36Sopenharmony_ci unsigned int no_tmpfile:1; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci /* Relax restrictions to allow shared mmap in FOPEN_DIRECT_IO mode */ 81662306a36Sopenharmony_ci unsigned int direct_io_allow_mmap:1; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci /* Is statx not implemented by fs? */ 81962306a36Sopenharmony_ci unsigned int no_statx:1; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci /** The number of requests waiting for completion */ 82262306a36Sopenharmony_ci atomic_t num_waiting; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci /** Negotiated minor version */ 82562306a36Sopenharmony_ci unsigned minor; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci /** Entry on the fuse_mount_list */ 82862306a36Sopenharmony_ci struct list_head entry; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci /** Device ID from the root super block */ 83162306a36Sopenharmony_ci dev_t dev; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci /** Dentries in the control filesystem */ 83462306a36Sopenharmony_ci struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES]; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci /** number of dentries used in the above array */ 83762306a36Sopenharmony_ci int ctl_ndents; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci /** Key for lock owner ID scrambling */ 84062306a36Sopenharmony_ci u32 scramble_key[4]; 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci /** Version counter for attribute changes */ 84362306a36Sopenharmony_ci atomic64_t attr_version; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci /** Called on final put */ 84662306a36Sopenharmony_ci void (*release)(struct fuse_conn *); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci /** 84962306a36Sopenharmony_ci * Read/write semaphore to hold when accessing the sb of any 85062306a36Sopenharmony_ci * fuse_mount belonging to this connection 85162306a36Sopenharmony_ci */ 85262306a36Sopenharmony_ci struct rw_semaphore killsb; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci /** List of device instances belonging to this connection */ 85562306a36Sopenharmony_ci struct list_head devices; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci#ifdef CONFIG_FUSE_DAX 85862306a36Sopenharmony_ci /* Dax mode */ 85962306a36Sopenharmony_ci enum fuse_dax_mode dax_mode; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* Dax specific conn data, non-NULL if DAX is enabled */ 86262306a36Sopenharmony_ci struct fuse_conn_dax *dax; 86362306a36Sopenharmony_ci#endif 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci /** List of filesystems using this connection */ 86662306a36Sopenharmony_ci struct list_head mounts; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci /* New writepages go into this bucket */ 86962306a36Sopenharmony_ci struct fuse_sync_bucket __rcu *curr_bucket; 87062306a36Sopenharmony_ci}; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci/* 87362306a36Sopenharmony_ci * Represents a mounted filesystem, potentially a submount. 87462306a36Sopenharmony_ci * 87562306a36Sopenharmony_ci * This object allows sharing a fuse_conn between separate mounts to 87662306a36Sopenharmony_ci * allow submounts with dedicated superblocks and thus separate device 87762306a36Sopenharmony_ci * IDs. 87862306a36Sopenharmony_ci */ 87962306a36Sopenharmony_cistruct fuse_mount { 88062306a36Sopenharmony_ci /* Underlying (potentially shared) connection to the FUSE server */ 88162306a36Sopenharmony_ci struct fuse_conn *fc; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci /* 88462306a36Sopenharmony_ci * Super block for this connection (fc->killsb must be held when 88562306a36Sopenharmony_ci * accessing this). 88662306a36Sopenharmony_ci */ 88762306a36Sopenharmony_ci struct super_block *sb; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci /* Entry on fc->mounts */ 89062306a36Sopenharmony_ci struct list_head fc_entry; 89162306a36Sopenharmony_ci}; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_cistatic inline struct fuse_mount *get_fuse_mount_super(struct super_block *sb) 89462306a36Sopenharmony_ci{ 89562306a36Sopenharmony_ci return sb->s_fs_info; 89662306a36Sopenharmony_ci} 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_cistatic inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) 89962306a36Sopenharmony_ci{ 90062306a36Sopenharmony_ci return get_fuse_mount_super(sb)->fc; 90162306a36Sopenharmony_ci} 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_cistatic inline struct fuse_mount *get_fuse_mount(struct inode *inode) 90462306a36Sopenharmony_ci{ 90562306a36Sopenharmony_ci return get_fuse_mount_super(inode->i_sb); 90662306a36Sopenharmony_ci} 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_cistatic inline struct fuse_conn *get_fuse_conn(struct inode *inode) 90962306a36Sopenharmony_ci{ 91062306a36Sopenharmony_ci return get_fuse_mount_super(inode->i_sb)->fc; 91162306a36Sopenharmony_ci} 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_cistatic inline struct fuse_inode *get_fuse_inode(struct inode *inode) 91462306a36Sopenharmony_ci{ 91562306a36Sopenharmony_ci return container_of(inode, struct fuse_inode, inode); 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_cistatic inline u64 get_node_id(struct inode *inode) 91962306a36Sopenharmony_ci{ 92062306a36Sopenharmony_ci return get_fuse_inode(inode)->nodeid; 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_cistatic inline int invalid_nodeid(u64 nodeid) 92462306a36Sopenharmony_ci{ 92562306a36Sopenharmony_ci return !nodeid || nodeid == FUSE_ROOT_ID; 92662306a36Sopenharmony_ci} 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_cistatic inline u64 fuse_get_attr_version(struct fuse_conn *fc) 92962306a36Sopenharmony_ci{ 93062306a36Sopenharmony_ci return atomic64_read(&fc->attr_version); 93162306a36Sopenharmony_ci} 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_cistatic inline bool fuse_stale_inode(const struct inode *inode, int generation, 93462306a36Sopenharmony_ci struct fuse_attr *attr) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci return inode->i_generation != generation || 93762306a36Sopenharmony_ci inode_wrong_type(inode, attr->mode); 93862306a36Sopenharmony_ci} 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_cistatic inline void fuse_make_bad(struct inode *inode) 94162306a36Sopenharmony_ci{ 94262306a36Sopenharmony_ci set_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state); 94362306a36Sopenharmony_ci} 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_cistatic inline bool fuse_is_bad(struct inode *inode) 94662306a36Sopenharmony_ci{ 94762306a36Sopenharmony_ci return unlikely(test_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state)); 94862306a36Sopenharmony_ci} 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_cistatic inline struct page **fuse_pages_alloc(unsigned int npages, gfp_t flags, 95162306a36Sopenharmony_ci struct fuse_page_desc **desc) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci struct page **pages; 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci pages = kzalloc(npages * (sizeof(struct page *) + 95662306a36Sopenharmony_ci sizeof(struct fuse_page_desc)), flags); 95762306a36Sopenharmony_ci *desc = (void *) (pages + npages); 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci return pages; 96062306a36Sopenharmony_ci} 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_cistatic inline void fuse_page_descs_length_init(struct fuse_page_desc *descs, 96362306a36Sopenharmony_ci unsigned int index, 96462306a36Sopenharmony_ci unsigned int nr_pages) 96562306a36Sopenharmony_ci{ 96662306a36Sopenharmony_ci int i; 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci for (i = index; i < index + nr_pages; i++) 96962306a36Sopenharmony_ci descs[i].length = PAGE_SIZE - descs[i].offset; 97062306a36Sopenharmony_ci} 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_cistatic inline void fuse_sync_bucket_dec(struct fuse_sync_bucket *bucket) 97362306a36Sopenharmony_ci{ 97462306a36Sopenharmony_ci /* Need RCU protection to prevent use after free after the decrement */ 97562306a36Sopenharmony_ci rcu_read_lock(); 97662306a36Sopenharmony_ci if (atomic_dec_and_test(&bucket->count)) 97762306a36Sopenharmony_ci wake_up(&bucket->waitq); 97862306a36Sopenharmony_ci rcu_read_unlock(); 97962306a36Sopenharmony_ci} 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci/** Device operations */ 98262306a36Sopenharmony_ciextern const struct file_operations fuse_dev_operations; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ciextern const struct dentry_operations fuse_dentry_operations; 98562306a36Sopenharmony_ciextern const struct dentry_operations fuse_root_dentry_operations; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci/** 98862306a36Sopenharmony_ci * Get a filled in inode 98962306a36Sopenharmony_ci */ 99062306a36Sopenharmony_cistruct inode *fuse_iget(struct super_block *sb, u64 nodeid, 99162306a36Sopenharmony_ci int generation, struct fuse_attr *attr, 99262306a36Sopenharmony_ci u64 attr_valid, u64 attr_version); 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ciint fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, 99562306a36Sopenharmony_ci struct fuse_entry_out *outarg, struct inode **inode); 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci/** 99862306a36Sopenharmony_ci * Send FORGET command 99962306a36Sopenharmony_ci */ 100062306a36Sopenharmony_civoid fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget, 100162306a36Sopenharmony_ci u64 nodeid, u64 nlookup); 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_cistruct fuse_forget_link *fuse_alloc_forget(void); 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_cistruct fuse_forget_link *fuse_dequeue_forget(struct fuse_iqueue *fiq, 100662306a36Sopenharmony_ci unsigned int max, 100762306a36Sopenharmony_ci unsigned int *countp); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci/* 101062306a36Sopenharmony_ci * Initialize READ or READDIR request 101162306a36Sopenharmony_ci */ 101262306a36Sopenharmony_cistruct fuse_io_args { 101362306a36Sopenharmony_ci union { 101462306a36Sopenharmony_ci struct { 101562306a36Sopenharmony_ci struct fuse_read_in in; 101662306a36Sopenharmony_ci u64 attr_ver; 101762306a36Sopenharmony_ci } read; 101862306a36Sopenharmony_ci struct { 101962306a36Sopenharmony_ci struct fuse_write_in in; 102062306a36Sopenharmony_ci struct fuse_write_out out; 102162306a36Sopenharmony_ci bool page_locked; 102262306a36Sopenharmony_ci } write; 102362306a36Sopenharmony_ci }; 102462306a36Sopenharmony_ci struct fuse_args_pages ap; 102562306a36Sopenharmony_ci struct fuse_io_priv *io; 102662306a36Sopenharmony_ci struct fuse_file *ff; 102762306a36Sopenharmony_ci}; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_civoid fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos, 103062306a36Sopenharmony_ci size_t count, int opcode); 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci/** 103462306a36Sopenharmony_ci * Send OPEN or OPENDIR request 103562306a36Sopenharmony_ci */ 103662306a36Sopenharmony_ciint fuse_open_common(struct inode *inode, struct file *file, bool isdir); 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_cistruct fuse_file *fuse_file_alloc(struct fuse_mount *fm); 103962306a36Sopenharmony_civoid fuse_file_free(struct fuse_file *ff); 104062306a36Sopenharmony_civoid fuse_finish_open(struct inode *inode, struct file *file); 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_civoid fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff, 104362306a36Sopenharmony_ci unsigned int flags); 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci/** 104662306a36Sopenharmony_ci * Send RELEASE or RELEASEDIR request 104762306a36Sopenharmony_ci */ 104862306a36Sopenharmony_civoid fuse_release_common(struct file *file, bool isdir); 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci/** 105162306a36Sopenharmony_ci * Send FSYNC or FSYNCDIR request 105262306a36Sopenharmony_ci */ 105362306a36Sopenharmony_ciint fuse_fsync_common(struct file *file, loff_t start, loff_t end, 105462306a36Sopenharmony_ci int datasync, int opcode); 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci/** 105762306a36Sopenharmony_ci * Notify poll wakeup 105862306a36Sopenharmony_ci */ 105962306a36Sopenharmony_ciint fuse_notify_poll_wakeup(struct fuse_conn *fc, 106062306a36Sopenharmony_ci struct fuse_notify_poll_wakeup_out *outarg); 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci/** 106362306a36Sopenharmony_ci * Initialize file operations on a regular file 106462306a36Sopenharmony_ci */ 106562306a36Sopenharmony_civoid fuse_init_file_inode(struct inode *inode, unsigned int flags); 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci/** 106862306a36Sopenharmony_ci * Initialize inode operations on regular files and special files 106962306a36Sopenharmony_ci */ 107062306a36Sopenharmony_civoid fuse_init_common(struct inode *inode); 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci/** 107362306a36Sopenharmony_ci * Initialize inode and file operations on a directory 107462306a36Sopenharmony_ci */ 107562306a36Sopenharmony_civoid fuse_init_dir(struct inode *inode); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci/** 107862306a36Sopenharmony_ci * Initialize inode operations on a symlink 107962306a36Sopenharmony_ci */ 108062306a36Sopenharmony_civoid fuse_init_symlink(struct inode *inode); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci/** 108362306a36Sopenharmony_ci * Change attributes of an inode 108462306a36Sopenharmony_ci */ 108562306a36Sopenharmony_civoid fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, 108662306a36Sopenharmony_ci struct fuse_statx *sx, 108762306a36Sopenharmony_ci u64 attr_valid, u64 attr_version); 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_civoid fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, 109062306a36Sopenharmony_ci struct fuse_statx *sx, 109162306a36Sopenharmony_ci u64 attr_valid, u32 cache_mask); 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ciu32 fuse_get_cache_mask(struct inode *inode); 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci/** 109662306a36Sopenharmony_ci * Initialize the client device 109762306a36Sopenharmony_ci */ 109862306a36Sopenharmony_ciint fuse_dev_init(void); 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci/** 110162306a36Sopenharmony_ci * Cleanup the client device 110262306a36Sopenharmony_ci */ 110362306a36Sopenharmony_civoid fuse_dev_cleanup(void); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ciint fuse_ctl_init(void); 110662306a36Sopenharmony_civoid __exit fuse_ctl_cleanup(void); 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci/** 110962306a36Sopenharmony_ci * Simple request sending that does request allocation and freeing 111062306a36Sopenharmony_ci */ 111162306a36Sopenharmony_cissize_t fuse_simple_request(struct fuse_mount *fm, struct fuse_args *args); 111262306a36Sopenharmony_ciint fuse_simple_background(struct fuse_mount *fm, struct fuse_args *args, 111362306a36Sopenharmony_ci gfp_t gfp_flags); 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci/** 111662306a36Sopenharmony_ci * End a finished request 111762306a36Sopenharmony_ci */ 111862306a36Sopenharmony_civoid fuse_request_end(struct fuse_req *req); 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci/* Abort all requests */ 112162306a36Sopenharmony_civoid fuse_abort_conn(struct fuse_conn *fc); 112262306a36Sopenharmony_civoid fuse_wait_aborted(struct fuse_conn *fc); 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci/** 112562306a36Sopenharmony_ci * Invalidate inode attributes 112662306a36Sopenharmony_ci */ 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci/* Attributes possibly changed on data modification */ 112962306a36Sopenharmony_ci#define FUSE_STATX_MODIFY (STATX_MTIME | STATX_CTIME | STATX_BLOCKS) 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci/* Attributes possibly changed on data and/or size modification */ 113262306a36Sopenharmony_ci#define FUSE_STATX_MODSIZE (FUSE_STATX_MODIFY | STATX_SIZE) 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_civoid fuse_invalidate_attr(struct inode *inode); 113562306a36Sopenharmony_civoid fuse_invalidate_attr_mask(struct inode *inode, u32 mask); 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_civoid fuse_invalidate_entry_cache(struct dentry *entry); 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_civoid fuse_invalidate_atime(struct inode *inode); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ciu64 fuse_time_to_jiffies(u64 sec, u32 nsec); 114262306a36Sopenharmony_ci#define ATTR_TIMEOUT(o) \ 114362306a36Sopenharmony_ci fuse_time_to_jiffies((o)->attr_valid, (o)->attr_valid_nsec) 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_civoid fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci/** 114862306a36Sopenharmony_ci * Acquire reference to fuse_conn 114962306a36Sopenharmony_ci */ 115062306a36Sopenharmony_cistruct fuse_conn *fuse_conn_get(struct fuse_conn *fc); 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci/** 115362306a36Sopenharmony_ci * Initialize fuse_conn 115462306a36Sopenharmony_ci */ 115562306a36Sopenharmony_civoid fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, 115662306a36Sopenharmony_ci struct user_namespace *user_ns, 115762306a36Sopenharmony_ci const struct fuse_iqueue_ops *fiq_ops, void *fiq_priv); 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci/** 116062306a36Sopenharmony_ci * Release reference to fuse_conn 116162306a36Sopenharmony_ci */ 116262306a36Sopenharmony_civoid fuse_conn_put(struct fuse_conn *fc); 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_cistruct fuse_dev *fuse_dev_alloc_install(struct fuse_conn *fc); 116562306a36Sopenharmony_cistruct fuse_dev *fuse_dev_alloc(void); 116662306a36Sopenharmony_civoid fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc); 116762306a36Sopenharmony_civoid fuse_dev_free(struct fuse_dev *fud); 116862306a36Sopenharmony_civoid fuse_send_init(struct fuse_mount *fm); 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci/** 117162306a36Sopenharmony_ci * Fill in superblock and initialize fuse connection 117262306a36Sopenharmony_ci * @sb: partially-initialized superblock to fill in 117362306a36Sopenharmony_ci * @ctx: mount context 117462306a36Sopenharmony_ci */ 117562306a36Sopenharmony_ciint fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx); 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci/* 117862306a36Sopenharmony_ci * Remove the mount from the connection 117962306a36Sopenharmony_ci * 118062306a36Sopenharmony_ci * Returns whether this was the last mount 118162306a36Sopenharmony_ci */ 118262306a36Sopenharmony_cibool fuse_mount_remove(struct fuse_mount *fm); 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci/* 118562306a36Sopenharmony_ci * Setup context ops for submounts 118662306a36Sopenharmony_ci */ 118762306a36Sopenharmony_ciint fuse_init_fs_context_submount(struct fs_context *fsc); 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci/* 119062306a36Sopenharmony_ci * Shut down the connection (possibly sending DESTROY request). 119162306a36Sopenharmony_ci */ 119262306a36Sopenharmony_civoid fuse_conn_destroy(struct fuse_mount *fm); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci/* Drop the connection and free the fuse mount */ 119562306a36Sopenharmony_civoid fuse_mount_destroy(struct fuse_mount *fm); 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci/** 119862306a36Sopenharmony_ci * Add connection to control filesystem 119962306a36Sopenharmony_ci */ 120062306a36Sopenharmony_ciint fuse_ctl_add_conn(struct fuse_conn *fc); 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci/** 120362306a36Sopenharmony_ci * Remove connection from control filesystem 120462306a36Sopenharmony_ci */ 120562306a36Sopenharmony_civoid fuse_ctl_remove_conn(struct fuse_conn *fc); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci/** 120862306a36Sopenharmony_ci * Is file type valid? 120962306a36Sopenharmony_ci */ 121062306a36Sopenharmony_ciint fuse_valid_type(int m); 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_cibool fuse_invalid_attr(struct fuse_attr *attr); 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci/** 121562306a36Sopenharmony_ci * Is current process allowed to perform filesystem operation? 121662306a36Sopenharmony_ci */ 121762306a36Sopenharmony_cibool fuse_allow_current_process(struct fuse_conn *fc); 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ciu64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_civoid fuse_flush_time_update(struct inode *inode); 122262306a36Sopenharmony_civoid fuse_update_ctime(struct inode *inode); 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ciint fuse_update_attributes(struct inode *inode, struct file *file, u32 mask); 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_civoid fuse_flush_writepages(struct inode *inode); 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_civoid fuse_set_nowrite(struct inode *inode); 122962306a36Sopenharmony_civoid fuse_release_nowrite(struct inode *inode); 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci/** 123262306a36Sopenharmony_ci * Scan all fuse_mounts belonging to fc to find the first where 123362306a36Sopenharmony_ci * ilookup5() returns a result. Return that result and the 123462306a36Sopenharmony_ci * respective fuse_mount in *fm (unless fm is NULL). 123562306a36Sopenharmony_ci * 123662306a36Sopenharmony_ci * The caller must hold fc->killsb. 123762306a36Sopenharmony_ci */ 123862306a36Sopenharmony_cistruct inode *fuse_ilookup(struct fuse_conn *fc, u64 nodeid, 123962306a36Sopenharmony_ci struct fuse_mount **fm); 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci/** 124262306a36Sopenharmony_ci * File-system tells the kernel to invalidate cache for the given node id. 124362306a36Sopenharmony_ci */ 124462306a36Sopenharmony_ciint fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid, 124562306a36Sopenharmony_ci loff_t offset, loff_t len); 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci/** 124862306a36Sopenharmony_ci * File-system tells the kernel to invalidate parent attributes and 124962306a36Sopenharmony_ci * the dentry matching parent/name. 125062306a36Sopenharmony_ci * 125162306a36Sopenharmony_ci * If the child_nodeid is non-zero and: 125262306a36Sopenharmony_ci * - matches the inode number for the dentry matching parent/name, 125362306a36Sopenharmony_ci * - is not a mount point 125462306a36Sopenharmony_ci * - is a file or oan empty directory 125562306a36Sopenharmony_ci * then the dentry is unhashed (d_delete()). 125662306a36Sopenharmony_ci */ 125762306a36Sopenharmony_ciint fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid, 125862306a36Sopenharmony_ci u64 child_nodeid, struct qstr *name, u32 flags); 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ciint fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, 126162306a36Sopenharmony_ci bool isdir); 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci/** 126462306a36Sopenharmony_ci * fuse_direct_io() flags 126562306a36Sopenharmony_ci */ 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci/** If set, it is WRITE; otherwise - READ */ 126862306a36Sopenharmony_ci#define FUSE_DIO_WRITE (1 << 0) 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci/** CUSE pass fuse_direct_io() a file which f_mapping->host is not from FUSE */ 127162306a36Sopenharmony_ci#define FUSE_DIO_CUSE (1 << 1) 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_cissize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, 127462306a36Sopenharmony_ci loff_t *ppos, int flags); 127562306a36Sopenharmony_cilong fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, 127662306a36Sopenharmony_ci unsigned int flags); 127762306a36Sopenharmony_cilong fuse_ioctl_common(struct file *file, unsigned int cmd, 127862306a36Sopenharmony_ci unsigned long arg, unsigned int flags); 127962306a36Sopenharmony_ci__poll_t fuse_file_poll(struct file *file, poll_table *wait); 128062306a36Sopenharmony_ciint fuse_dev_release(struct inode *inode, struct file *file); 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_cibool fuse_write_update_attr(struct inode *inode, loff_t pos, ssize_t written); 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ciint fuse_flush_times(struct inode *inode, struct fuse_file *ff); 128562306a36Sopenharmony_ciint fuse_write_inode(struct inode *inode, struct writeback_control *wbc); 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ciint fuse_do_setattr(struct dentry *dentry, struct iattr *attr, 128862306a36Sopenharmony_ci struct file *file); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_civoid fuse_set_initialized(struct fuse_conn *fc); 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_civoid fuse_unlock_inode(struct inode *inode, bool locked); 129362306a36Sopenharmony_cibool fuse_lock_inode(struct inode *inode); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ciint fuse_setxattr(struct inode *inode, const char *name, const void *value, 129662306a36Sopenharmony_ci size_t size, int flags, unsigned int extra_flags); 129762306a36Sopenharmony_cissize_t fuse_getxattr(struct inode *inode, const char *name, void *value, 129862306a36Sopenharmony_ci size_t size); 129962306a36Sopenharmony_cissize_t fuse_listxattr(struct dentry *entry, char *list, size_t size); 130062306a36Sopenharmony_ciint fuse_removexattr(struct inode *inode, const char *name); 130162306a36Sopenharmony_ciextern const struct xattr_handler *fuse_xattr_handlers[]; 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_cistruct posix_acl; 130462306a36Sopenharmony_cistruct posix_acl *fuse_get_inode_acl(struct inode *inode, int type, bool rcu); 130562306a36Sopenharmony_cistruct posix_acl *fuse_get_acl(struct mnt_idmap *idmap, 130662306a36Sopenharmony_ci struct dentry *dentry, int type); 130762306a36Sopenharmony_ciint fuse_set_acl(struct mnt_idmap *, struct dentry *dentry, 130862306a36Sopenharmony_ci struct posix_acl *acl, int type); 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci/* readdir.c */ 131162306a36Sopenharmony_ciint fuse_readdir(struct file *file, struct dir_context *ctx); 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci/** 131462306a36Sopenharmony_ci * Return the number of bytes in an arguments list 131562306a36Sopenharmony_ci */ 131662306a36Sopenharmony_ciunsigned int fuse_len_args(unsigned int numargs, struct fuse_arg *args); 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci/** 131962306a36Sopenharmony_ci * Get the next unique ID for a request 132062306a36Sopenharmony_ci */ 132162306a36Sopenharmony_ciu64 fuse_get_unique(struct fuse_iqueue *fiq); 132262306a36Sopenharmony_civoid fuse_free_conn(struct fuse_conn *fc); 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci/* dax.c */ 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci#define FUSE_IS_DAX(inode) (IS_ENABLED(CONFIG_FUSE_DAX) && IS_DAX(inode)) 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_cissize_t fuse_dax_read_iter(struct kiocb *iocb, struct iov_iter *to); 132962306a36Sopenharmony_cissize_t fuse_dax_write_iter(struct kiocb *iocb, struct iov_iter *from); 133062306a36Sopenharmony_ciint fuse_dax_mmap(struct file *file, struct vm_area_struct *vma); 133162306a36Sopenharmony_ciint fuse_dax_break_layouts(struct inode *inode, u64 dmap_start, u64 dmap_end); 133262306a36Sopenharmony_ciint fuse_dax_conn_alloc(struct fuse_conn *fc, enum fuse_dax_mode mode, 133362306a36Sopenharmony_ci struct dax_device *dax_dev); 133462306a36Sopenharmony_civoid fuse_dax_conn_free(struct fuse_conn *fc); 133562306a36Sopenharmony_cibool fuse_dax_inode_alloc(struct super_block *sb, struct fuse_inode *fi); 133662306a36Sopenharmony_civoid fuse_dax_inode_init(struct inode *inode, unsigned int flags); 133762306a36Sopenharmony_civoid fuse_dax_inode_cleanup(struct inode *inode); 133862306a36Sopenharmony_civoid fuse_dax_dontcache(struct inode *inode, unsigned int flags); 133962306a36Sopenharmony_cibool fuse_dax_check_alignment(struct fuse_conn *fc, unsigned int map_alignment); 134062306a36Sopenharmony_civoid fuse_dax_cancel_work(struct fuse_conn *fc); 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci/* ioctl.c */ 134362306a36Sopenharmony_cilong fuse_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 134462306a36Sopenharmony_cilong fuse_file_compat_ioctl(struct file *file, unsigned int cmd, 134562306a36Sopenharmony_ci unsigned long arg); 134662306a36Sopenharmony_ciint fuse_fileattr_get(struct dentry *dentry, struct fileattr *fa); 134762306a36Sopenharmony_ciint fuse_fileattr_set(struct mnt_idmap *idmap, 134862306a36Sopenharmony_ci struct dentry *dentry, struct fileattr *fa); 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci/* file.c */ 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_cistruct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid, 135362306a36Sopenharmony_ci unsigned int open_flags, bool isdir); 135462306a36Sopenharmony_civoid fuse_file_release(struct inode *inode, struct fuse_file *ff, 135562306a36Sopenharmony_ci unsigned int open_flags, fl_owner_t id, bool isdir); 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci#endif /* _FS_FUSE_I_H */ 1358