diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2006-01-16 17:52:24 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2006-01-16 17:52:24 +0000 |
commit | 15af1b81cfcc81b9f25d4155d191c071e35dabac (patch) | |
tree | 986a6b45528509e7f28b08c9c13bbf7cee566f8b /kernel/fuse_i.h | |
parent | 75bb0deaf170b5aa1894de324139196310509ccc (diff) | |
download | libfuse-15af1b81cfcc81b9f25d4155d191c071e35dabac.tar.gz |
fix
Diffstat (limited to 'kernel/fuse_i.h')
-rw-r--r-- | kernel/fuse_i.h | 115 |
1 files changed, 78 insertions, 37 deletions
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index 84e17dc..b68b9e3 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -55,6 +55,7 @@ # endif # define new_decode_dev(x) (x) # define new_encode_dev(x) (x) +# define s_fs_info u.generic_sbp #endif /* KERNEL_2_6 */ #endif /* FUSE_MAINLINE */ #include <linux/fs.h> @@ -86,6 +87,22 @@ static inline void set_page_dirty_lock(struct page *page) set_page_dirty(page); unlock_page(page); } + +struct kobject { + atomic_t count; + void (*release) (struct kobject *); +}; + +static inline void kobject_get(struct kobject *kobj) +{ + atomic_inc(&kobj->count); +} + +static inline void kobject_put(struct kobject *kobj) +{ + if (atomic_dec_and_test(&kobj->count)) + kobj->release(kobj); +} #endif /** Max number of pages that can be used in a single read request */ #define FUSE_MAX_PAGES_PER_REQ 32 @@ -171,6 +188,11 @@ 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; @@ -188,12 +210,23 @@ struct fuse_out { 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_FINISHED +}; + +struct fuse_conn; + /** * A request to the client */ struct fuse_req { - /** This can be on either unused_list, pending or processing - lists in fuse_conn */ + /** This can be on either unused_list, pending processing or + io lists in fuse_conn */ struct list_head list; /** Entry on the background list */ @@ -202,6 +235,12 @@ struct fuse_req { /** refcount */ atomic_t count; + /* + * The following bitfields are either set once before the + * request is queued or setting/clearing them is protected by + * fuse_lock + */ + /** True if the request has reply */ unsigned isreply:1; @@ -217,11 +256,8 @@ struct fuse_req { /** Data is being copied to/from the request */ unsigned locked:1; - /** Request has been sent to userspace */ - unsigned sent:1; - - /** The request is finished */ - unsigned finished:1; + /** State of the request */ + enum fuse_req_state state; /** The request input */ struct fuse_in in; @@ -238,6 +274,7 @@ struct fuse_req { struct fuse_release_in release_in; struct fuse_init_in init_in; struct fuse_init_out init_out; + struct fuse_read_in read_in; } misc; /** page vector */ @@ -257,6 +294,9 @@ struct fuse_req { /** File used in the request (or NULL) */ struct file *file; + + /** Request completion callback */ + void (*end)(struct fuse_conn *, struct fuse_req *); }; /** @@ -267,9 +307,6 @@ struct fuse_req { * unmounted. */ struct fuse_conn { - /** Reference count */ - int count; - /** The user id for this mount */ uid_t user_id; @@ -294,6 +331,9 @@ struct fuse_conn { /** The list of requests being processed */ struct list_head processing; + /** The list of requests under I/O */ + struct list_head io; + /** Requests put in the background (RELEASE or any other interrupted request) */ struct list_head background; @@ -317,12 +357,20 @@ struct fuse_conn { /** Mount is active */ unsigned mounted; - /** Connection established */ + /** Connection established, cleared on umount, connection + abort and device release */ unsigned connected; - /** Connection failed (version mismatch) */ + /** 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; + /* + * 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; @@ -350,6 +398,9 @@ struct fuse_conn { /** Is create not implemented by fs? */ unsigned no_create : 1; + /** The number of requests waiting for completion */ + atomic_t num_waiting; + /** Negotiated minor version */ unsigned minor; @@ -357,20 +408,14 @@ struct fuse_conn { /** Backing dev info */ struct backing_dev_info bdi; #endif -}; -static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb) -{ -#ifdef KERNEL_2_6 - return (struct fuse_conn **) &sb->s_fs_info; -#else - return (struct fuse_conn **) &sb->u.generic_sbp; -#endif -} + /** kobject */ + struct kobject kobj; +}; static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) { - return *get_fuse_conn_super_p(sb); + return sb->s_fs_info; } static inline struct fuse_conn *get_fuse_conn(struct inode *inode) @@ -378,6 +423,11 @@ static inline struct fuse_conn *get_fuse_conn(struct inode *inode) return get_fuse_conn_super(inode->i_sb); } +static inline struct fuse_conn *get_fuse_conn_kobj(struct kobject *obj) +{ + return container_of(obj, struct fuse_conn, kobj); +} + static inline struct fuse_inode *get_fuse_inode(struct inode *inode) { return container_of(inode, struct fuse_inode, inode); @@ -419,11 +469,10 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, unsigned long nodeid, u64 nlookup); /** - * Send READ or READDIR request + * Initialize READ or READDIR request */ -size_t fuse_send_read_common(struct fuse_req *req, struct file *file, - struct inode *inode, loff_t pos, size_t count, - int isdir); +void fuse_read_fill(struct fuse_req *req, struct file *file, + struct inode *inode, loff_t pos, size_t count, int opcode); /** * Send OPEN or OPENDIR request @@ -478,12 +527,6 @@ void fuse_init_symlink(struct inode *inode); void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr); /** - * Check if the connection can be released, and if yes, then free the - * connection structure - */ -void fuse_release_conn(struct fuse_conn *fc); - -/** * Initialize the client device */ int fuse_dev_init(void); @@ -539,6 +582,9 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req); */ void fuse_release_background(struct fuse_req *req); +/* Abort all requests */ +void fuse_abort_conn(struct fuse_conn *fc); + /** * Get the attributes of a file */ @@ -548,8 +594,3 @@ int fuse_do_getattr(struct inode *inode); * Invalidate inode attributes */ void fuse_invalidate_attr(struct inode *inode); - -/** - * Send the INIT message - */ -void fuse_send_init(struct fuse_conn *fc); |