/** FUSE inode */
struct fuse_inode {
/** Inode data */
struct inode inode;
/** Unique ID, which identifies the inode between userspace
* and kernel */
u64 nodeid;
/** Number of lookups on this inode */
u64 nlookup;
/** The request used for sending the FORGET message */
struct fuse_req *forget_req;
/** Time in jiffies until the file attributes are valid */
u64 i_time;
};
/** FUSE specific file data */
struct fuse_file {
/** Request reserved for flush and release */
struct fuse_req *reserved_req;
/** File handle used by userspace */
u64 fh;
};
/** One input argument of a request */
struct fuse_in_arg {
unsigned size;
const void *value;
};
/** The request input */
struct fuse_in {
/** The request header */
struct fuse_in_header h;
/** True if the data for the last argument is in req->pages */
unsigned argpages:1;
/** Number of arguments */
unsigned numargs;
/** Array of arguments */
struct fuse_in_arg args[3];
};
/** One output argument of a request */
struct fuse_arg {
unsigned size;
void *value;
};
/** The request output */
struct fuse_out {
/** Header returned from userspace */
struct fuse_out_header h;
/*
* The following bitfields are not changed during the request
* processing
*/
/** Last argument is variable length (can be shorter than
arg->size) */
unsigned argvar:1;
/** Last argument is a list of pages to copy data to */
unsigned argpages:1;
/** Zero partially or not copied pages */
unsigned page_zeroing:1;
/** Number or arguments */
unsigned numargs;
/** Array of arguments */
struct fuse_arg args[3];
};
/** The request state */
enum fuse_req_state {
FUSE_REQ_INIT = 0,
FUSE_REQ_PENDING,
FUSE_REQ_READING,
FUSE_REQ_SENT,
FUSE_REQ_WRITING,
FUSE_REQ_FINISHED
};
struct fuse_conn;
/**
* A request to the client
*/
struct fuse_req {
/** This can be on either pending processing or io lists in
fuse_conn */
struct list_head list;
/** Entry on the interrupts list */
struct list_head intr_entry;
/** refcount */
atomic_t count;
/** Unique ID for the interrupt request */
u64 intr_unique;
/*
* The following bitfields are either set once before the
* request is queued or setting/clearing them is protected by
* fuse_conn->lock
*/
/** True if the request has reply */
unsigned isreply:1;
/** Force sending of the request even if interrupted */
unsigned force:1;
/** The request was aborted */
unsigned aborted:1;
/** Request is sent in the background */
unsigned background:1;
/** The request has been interrupted */
unsigned interrupted:1;
/** Data is being copied to/from the request */
unsigned locked:1;
/** Request is counted as "waiting" */
unsigned waiting:1;
/** State of the request */
enum fuse_req_state state;
/** The request input */
struct fuse_in in;
/** The request output */
struct fuse_out out;
/** Used to wake up the task waiting for completion of request*/
wait_queue_head_t waitq;
/** Data for asynchronous requests */
union {
struct fuse_forget_in forget_in;
struct fuse_release_in release_in;
struct fuse_init_in init_in;
struct fuse_init_out init_out;
struct fuse_read_in read_in;
struct fuse_lk_in lk_in;
} misc;
/** page vector */
struct page *pages[FUSE_MAX_PAGES_PER_REQ];
/** number of pages in vector */
unsigned num_pages;
/** offset of data on first page */
unsigned page_offset;
/** File used in the request (or NULL) */
struct file *file;
/** vfsmount used in release */
struct vfsmount *vfsmount;
/** dentry used in release */
struct dentry *dentry;
/** Request completion callback */
void (*end)(struct fuse_conn *, struct fuse_req *);
/** Request is stolen from fuse_file->reserved_req */
struct file *stolen_file;
};
/**
* A Fuse connection.
*
* This structure is created, when the filesystem is mounted, and is
* destroyed, when the client device is closed and the filesystem is
* unmounted.
*/
struct fuse_conn {
/** Lock protecting accessess to members of this structure */
spinlock_t lock;
/** Mutex protecting against directory alias creation */
struct mutex inst_mutex;
/** Refcount */
atomic_t count;
/** The user id for this mount */
uid_t user_id;
/** The group id for this mount */
gid_t group_id;
/** The fuse mount flags for this mount */
unsigned flags;
/** Maximum read size */
unsigned max_read;
/** Maximum write size */
unsigned max_write;
/** Readers of the connection are waiting on this */
wait_queue_head_t waitq;
/** The list of pending requests */
struct list_head pending;
/** The list of requests being processed */
struct list_head processing;
/** The list of requests under I/O */
struct list_head io;
/** Number of requests currently in the background */
unsigned num_background;
/** Pending interrupts */
struct list_head interrupts;
/** Flag indicating if connection is blocked. This will be
the case before the INIT reply is received, and if there
are too many outstading backgrounds requests */
int blocked;
/** waitq for blocked connection */
wait_queue_head_t blocked_waitq;
/** waitq for reserved requests */
wait_queue_head_t reserved_req_waitq;
/** The next unique request id */
u64 reqctr;
/** Connection established, cleared on umount, connection
abort and device release */
unsigned connected;
/** Connection failed (version mismatch). Cannot race with
setting other bitfields since it is only set once in INIT
reply, before any other request, and never cleared */
unsigned conn_error : 1;
/** Connection successful. Only set in INIT */
unsigned conn_init : 1;
/** Do readpages asynchronously? Only set in INIT */
unsigned async_read : 1;
/*
* The following bitfields are only for optimization purposes
* and hence races in setting them will not cause malfunction
*/
/** Is fsync not implemented by fs? */
unsigned no_fsync : 1;
/** Is fsyncdir not implemented by fs? */
unsigned no_fsyncdir : 1;
/** Is flush not implemented by fs? */
unsigned no_flush : 1;
/** Is setxattr not implemented by fs? */
unsigned no_setxattr : 1;
/** Is getxattr not implemented by fs? */
unsigned no_getxattr : 1;
/** Is listxattr not implemented by fs? */
unsigned no_listxattr : 1;
/** Is removexattr not implemented by fs? */
unsigned no_removexattr : 1;
/** Are file locking primitives not implemented by fs? */
unsigned no_lock : 1;
/** Is access not implemented by fs? */
unsigned no_access : 1;
/** Is create not implemented by fs? */
unsigned no_create : 1;
/** Is interrupt not implemented by fs? */
unsigned no_interrupt : 1;
/** Is bmap not implemented by fs? */
unsigned no_bmap : 1;
/** The number of requests waiting for completion */
atomic_t num_waiting;
/** Negotiated minor version */
unsigned minor;
/** Backing dev info */
struct backing_dev_info bdi;
/** Entry on the fuse_conn_list */
struct list_head entry;
/** Unique ID */
u64 id;
/** Dentries in the control filesystem */
struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES];
/** number of dentries used in the above array */
int ctl_ndents;
/** O_ASYNC requests */
struct fasync_struct *fasync;
/** Key for lock owner ID scrambling */
u32 scramble_key[4];
/** Reserved request for the DESTROY message */
struct fuse_req *destroy_req;
};
|