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