diff options
Diffstat (limited to 'fs/fuse/fuse_i.h')
-rw-r--r-- | fs/fuse/fuse_i.h | 106 |
1 files changed, 69 insertions, 37 deletions
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 0ea5301f86be..46cf933aa3bf 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -21,6 +21,9 @@ | |||
21 | /** If more requests are outstanding, then the operation will block */ | 21 | /** If more requests are outstanding, then the operation will block */ |
22 | #define FUSE_MAX_OUTSTANDING 10 | 22 | #define FUSE_MAX_OUTSTANDING 10 |
23 | 23 | ||
24 | /** It could be as large as PATH_MAX, but would that have any uses? */ | ||
25 | #define FUSE_NAME_MAX 1024 | ||
26 | |||
24 | /** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem | 27 | /** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem |
25 | module will check permissions based on the file mode. Otherwise no | 28 | module will check permissions based on the file mode. Otherwise no |
26 | permission checking is done in the kernel */ | 29 | permission checking is done in the kernel */ |
@@ -91,6 +94,11 @@ struct fuse_out { | |||
91 | /** Header returned from userspace */ | 94 | /** Header returned from userspace */ |
92 | struct fuse_out_header h; | 95 | struct fuse_out_header h; |
93 | 96 | ||
97 | /* | ||
98 | * The following bitfields are not changed during the request | ||
99 | * processing | ||
100 | */ | ||
101 | |||
94 | /** Last argument is variable length (can be shorter than | 102 | /** Last argument is variable length (can be shorter than |
95 | arg->size) */ | 103 | arg->size) */ |
96 | unsigned argvar:1; | 104 | unsigned argvar:1; |
@@ -108,15 +116,23 @@ struct fuse_out { | |||
108 | struct fuse_arg args[3]; | 116 | struct fuse_arg args[3]; |
109 | }; | 117 | }; |
110 | 118 | ||
111 | struct fuse_req; | 119 | /** The request state */ |
120 | enum fuse_req_state { | ||
121 | FUSE_REQ_INIT = 0, | ||
122 | FUSE_REQ_PENDING, | ||
123 | FUSE_REQ_READING, | ||
124 | FUSE_REQ_SENT, | ||
125 | FUSE_REQ_FINISHED | ||
126 | }; | ||
127 | |||
112 | struct fuse_conn; | 128 | struct fuse_conn; |
113 | 129 | ||
114 | /** | 130 | /** |
115 | * A request to the client | 131 | * A request to the client |
116 | */ | 132 | */ |
117 | struct fuse_req { | 133 | struct fuse_req { |
118 | /** This can be on either unused_list, pending or processing | 134 | /** This can be on either unused_list, pending processing or |
119 | lists in fuse_conn */ | 135 | io lists in fuse_conn */ |
120 | struct list_head list; | 136 | struct list_head list; |
121 | 137 | ||
122 | /** Entry on the background list */ | 138 | /** Entry on the background list */ |
@@ -125,6 +141,12 @@ struct fuse_req { | |||
125 | /** refcount */ | 141 | /** refcount */ |
126 | atomic_t count; | 142 | atomic_t count; |
127 | 143 | ||
144 | /* | ||
145 | * The following bitfields are either set once before the | ||
146 | * request is queued or setting/clearing them is protected by | ||
147 | * fuse_lock | ||
148 | */ | ||
149 | |||
128 | /** True if the request has reply */ | 150 | /** True if the request has reply */ |
129 | unsigned isreply:1; | 151 | unsigned isreply:1; |
130 | 152 | ||
@@ -140,11 +162,8 @@ struct fuse_req { | |||
140 | /** Data is being copied to/from the request */ | 162 | /** Data is being copied to/from the request */ |
141 | unsigned locked:1; | 163 | unsigned locked:1; |
142 | 164 | ||
143 | /** Request has been sent to userspace */ | 165 | /** State of the request */ |
144 | unsigned sent:1; | 166 | enum fuse_req_state state; |
145 | |||
146 | /** The request is finished */ | ||
147 | unsigned finished:1; | ||
148 | 167 | ||
149 | /** The request input */ | 168 | /** The request input */ |
150 | struct fuse_in in; | 169 | struct fuse_in in; |
@@ -159,7 +178,9 @@ struct fuse_req { | |||
159 | union { | 178 | union { |
160 | struct fuse_forget_in forget_in; | 179 | struct fuse_forget_in forget_in; |
161 | struct fuse_release_in release_in; | 180 | struct fuse_release_in release_in; |
162 | struct fuse_init_in_out init_in_out; | 181 | struct fuse_init_in init_in; |
182 | struct fuse_init_out init_out; | ||
183 | struct fuse_read_in read_in; | ||
163 | } misc; | 184 | } misc; |
164 | 185 | ||
165 | /** page vector */ | 186 | /** page vector */ |
@@ -179,6 +200,9 @@ struct fuse_req { | |||
179 | 200 | ||
180 | /** File used in the request (or NULL) */ | 201 | /** File used in the request (or NULL) */ |
181 | struct file *file; | 202 | struct file *file; |
203 | |||
204 | /** Request completion callback */ | ||
205 | void (*end)(struct fuse_conn *, struct fuse_req *); | ||
182 | }; | 206 | }; |
183 | 207 | ||
184 | /** | 208 | /** |
@@ -189,9 +213,6 @@ struct fuse_req { | |||
189 | * unmounted. | 213 | * unmounted. |
190 | */ | 214 | */ |
191 | struct fuse_conn { | 215 | struct fuse_conn { |
192 | /** Reference count */ | ||
193 | int count; | ||
194 | |||
195 | /** The user id for this mount */ | 216 | /** The user id for this mount */ |
196 | uid_t user_id; | 217 | uid_t user_id; |
197 | 218 | ||
@@ -216,6 +237,9 @@ struct fuse_conn { | |||
216 | /** The list of requests being processed */ | 237 | /** The list of requests being processed */ |
217 | struct list_head processing; | 238 | struct list_head processing; |
218 | 239 | ||
240 | /** The list of requests under I/O */ | ||
241 | struct list_head io; | ||
242 | |||
219 | /** Requests put in the background (RELEASE or any other | 243 | /** Requests put in the background (RELEASE or any other |
220 | interrupted request) */ | 244 | interrupted request) */ |
221 | struct list_head background; | 245 | struct list_head background; |
@@ -237,14 +261,22 @@ struct fuse_conn { | |||
237 | u64 reqctr; | 261 | u64 reqctr; |
238 | 262 | ||
239 | /** Mount is active */ | 263 | /** Mount is active */ |
240 | unsigned mounted : 1; | 264 | unsigned mounted; |
241 | 265 | ||
242 | /** Connection established */ | 266 | /** Connection established, cleared on umount, connection |
243 | unsigned connected : 1; | 267 | abort and device release */ |
268 | unsigned connected; | ||
244 | 269 | ||
245 | /** Connection failed (version mismatch) */ | 270 | /** Connection failed (version mismatch). Cannot race with |
271 | setting other bitfields since it is only set once in INIT | ||
272 | reply, before any other request, and never cleared */ | ||
246 | unsigned conn_error : 1; | 273 | unsigned conn_error : 1; |
247 | 274 | ||
275 | /* | ||
276 | * The following bitfields are only for optimization purposes | ||
277 | * and hence races in setting them will not cause malfunction | ||
278 | */ | ||
279 | |||
248 | /** Is fsync not implemented by fs? */ | 280 | /** Is fsync not implemented by fs? */ |
249 | unsigned no_fsync : 1; | 281 | unsigned no_fsync : 1; |
250 | 282 | ||
@@ -272,18 +304,22 @@ struct fuse_conn { | |||
272 | /** Is create not implemented by fs? */ | 304 | /** Is create not implemented by fs? */ |
273 | unsigned no_create : 1; | 305 | unsigned no_create : 1; |
274 | 306 | ||
307 | /** The number of requests waiting for completion */ | ||
308 | atomic_t num_waiting; | ||
309 | |||
310 | /** Negotiated minor version */ | ||
311 | unsigned minor; | ||
312 | |||
275 | /** Backing dev info */ | 313 | /** Backing dev info */ |
276 | struct backing_dev_info bdi; | 314 | struct backing_dev_info bdi; |
277 | }; | ||
278 | 315 | ||
279 | static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb) | 316 | /** kobject */ |
280 | { | 317 | struct kobject kobj; |
281 | return (struct fuse_conn **) &sb->s_fs_info; | 318 | }; |
282 | } | ||
283 | 319 | ||
284 | static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) | 320 | static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) |
285 | { | 321 | { |
286 | return *get_fuse_conn_super_p(sb); | 322 | return sb->s_fs_info; |
287 | } | 323 | } |
288 | 324 | ||
289 | static inline struct fuse_conn *get_fuse_conn(struct inode *inode) | 325 | static inline struct fuse_conn *get_fuse_conn(struct inode *inode) |
@@ -291,6 +327,11 @@ static inline struct fuse_conn *get_fuse_conn(struct inode *inode) | |||
291 | return get_fuse_conn_super(inode->i_sb); | 327 | return get_fuse_conn_super(inode->i_sb); |
292 | } | 328 | } |
293 | 329 | ||
330 | static inline struct fuse_conn *get_fuse_conn_kobj(struct kobject *obj) | ||
331 | { | ||
332 | return container_of(obj, struct fuse_conn, kobj); | ||
333 | } | ||
334 | |||
294 | static inline struct fuse_inode *get_fuse_inode(struct inode *inode) | 335 | static inline struct fuse_inode *get_fuse_inode(struct inode *inode) |
295 | { | 336 | { |
296 | return container_of(inode, struct fuse_inode, inode); | 337 | return container_of(inode, struct fuse_inode, inode); |
@@ -332,11 +373,10 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, | |||
332 | unsigned long nodeid, u64 nlookup); | 373 | unsigned long nodeid, u64 nlookup); |
333 | 374 | ||
334 | /** | 375 | /** |
335 | * Send READ or READDIR request | 376 | * Initialize READ or READDIR request |
336 | */ | 377 | */ |
337 | size_t fuse_send_read_common(struct fuse_req *req, struct file *file, | 378 | void fuse_read_fill(struct fuse_req *req, struct file *file, |
338 | struct inode *inode, loff_t pos, size_t count, | 379 | struct inode *inode, loff_t pos, size_t count, int opcode); |
339 | int isdir); | ||
340 | 380 | ||
341 | /** | 381 | /** |
342 | * Send OPEN or OPENDIR request | 382 | * Send OPEN or OPENDIR request |
@@ -391,12 +431,6 @@ void fuse_init_symlink(struct inode *inode); | |||
391 | void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr); | 431 | void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr); |
392 | 432 | ||
393 | /** | 433 | /** |
394 | * Check if the connection can be released, and if yes, then free the | ||
395 | * connection structure | ||
396 | */ | ||
397 | void fuse_release_conn(struct fuse_conn *fc); | ||
398 | |||
399 | /** | ||
400 | * Initialize the client device | 434 | * Initialize the client device |
401 | */ | 435 | */ |
402 | int fuse_dev_init(void); | 436 | int fuse_dev_init(void); |
@@ -452,6 +486,9 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req); | |||
452 | */ | 486 | */ |
453 | void fuse_release_background(struct fuse_req *req); | 487 | void fuse_release_background(struct fuse_req *req); |
454 | 488 | ||
489 | /* Abort all requests */ | ||
490 | void fuse_abort_conn(struct fuse_conn *fc); | ||
491 | |||
455 | /** | 492 | /** |
456 | * Get the attributes of a file | 493 | * Get the attributes of a file |
457 | */ | 494 | */ |
@@ -461,8 +498,3 @@ int fuse_do_getattr(struct inode *inode); | |||
461 | * Invalidate inode attributes | 498 | * Invalidate inode attributes |
462 | */ | 499 | */ |
463 | void fuse_invalidate_attr(struct inode *inode); | 500 | void fuse_invalidate_attr(struct inode *inode); |
464 | |||
465 | /** | ||
466 | * Send the INIT message | ||
467 | */ | ||
468 | void fuse_send_init(struct fuse_conn *fc); | ||