diff options
Diffstat (limited to 'fs/fuse/fuse_i.h')
-rw-r--r-- | fs/fuse/fuse_i.h | 135 |
1 files changed, 91 insertions, 44 deletions
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 0474202cb5dc..0dbf96621841 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -8,12 +8,13 @@ | |||
8 | 8 | ||
9 | #include <linux/fuse.h> | 9 | #include <linux/fuse.h> |
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include <linux/mount.h> | ||
11 | #include <linux/wait.h> | 12 | #include <linux/wait.h> |
12 | #include <linux/list.h> | 13 | #include <linux/list.h> |
13 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
14 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
15 | #include <linux/backing-dev.h> | 16 | #include <linux/backing-dev.h> |
16 | #include <asm/semaphore.h> | 17 | #include <linux/mutex.h> |
17 | 18 | ||
18 | /** Max number of pages that can be used in a single read request */ | 19 | /** Max number of pages that can be used in a single read request */ |
19 | #define FUSE_MAX_PAGES_PER_REQ 32 | 20 | #define FUSE_MAX_PAGES_PER_REQ 32 |
@@ -24,6 +25,9 @@ | |||
24 | /** It could be as large as PATH_MAX, but would that have any uses? */ | 25 | /** It could be as large as PATH_MAX, but would that have any uses? */ |
25 | #define FUSE_NAME_MAX 1024 | 26 | #define FUSE_NAME_MAX 1024 |
26 | 27 | ||
28 | /** Number of dentries for each connection in the control filesystem */ | ||
29 | #define FUSE_CTL_NUM_DENTRIES 3 | ||
30 | |||
27 | /** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem | 31 | /** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem |
28 | module will check permissions based on the file mode. Otherwise no | 32 | module will check permissions based on the file mode. Otherwise no |
29 | permission checking is done in the kernel */ | 33 | permission checking is done in the kernel */ |
@@ -33,6 +37,11 @@ | |||
33 | doing the mount will be allowed to access the filesystem */ | 37 | doing the mount will be allowed to access the filesystem */ |
34 | #define FUSE_ALLOW_OTHER (1 << 1) | 38 | #define FUSE_ALLOW_OTHER (1 << 1) |
35 | 39 | ||
40 | /** List of active connections */ | ||
41 | extern struct list_head fuse_conn_list; | ||
42 | |||
43 | /** Global mutex protecting fuse_conn_list and the control filesystem */ | ||
44 | extern struct mutex fuse_mutex; | ||
36 | 45 | ||
37 | /** FUSE inode */ | 46 | /** FUSE inode */ |
38 | struct fuse_inode { | 47 | struct fuse_inode { |
@@ -56,7 +65,7 @@ struct fuse_inode { | |||
56 | /** FUSE specific file data */ | 65 | /** FUSE specific file data */ |
57 | struct fuse_file { | 66 | struct fuse_file { |
58 | /** Request reserved for flush and release */ | 67 | /** Request reserved for flush and release */ |
59 | struct fuse_req *release_req; | 68 | struct fuse_req *reserved_req; |
60 | 69 | ||
61 | /** File handle used by userspace */ | 70 | /** File handle used by userspace */ |
62 | u64 fh; | 71 | u64 fh; |
@@ -122,6 +131,7 @@ enum fuse_req_state { | |||
122 | FUSE_REQ_PENDING, | 131 | FUSE_REQ_PENDING, |
123 | FUSE_REQ_READING, | 132 | FUSE_REQ_READING, |
124 | FUSE_REQ_SENT, | 133 | FUSE_REQ_SENT, |
134 | FUSE_REQ_WRITING, | ||
125 | FUSE_REQ_FINISHED | 135 | FUSE_REQ_FINISHED |
126 | }; | 136 | }; |
127 | 137 | ||
@@ -135,12 +145,15 @@ struct fuse_req { | |||
135 | fuse_conn */ | 145 | fuse_conn */ |
136 | struct list_head list; | 146 | struct list_head list; |
137 | 147 | ||
138 | /** Entry on the background list */ | 148 | /** Entry on the interrupts list */ |
139 | struct list_head bg_entry; | 149 | struct list_head intr_entry; |
140 | 150 | ||
141 | /** refcount */ | 151 | /** refcount */ |
142 | atomic_t count; | 152 | atomic_t count; |
143 | 153 | ||
154 | /** Unique ID for the interrupt request */ | ||
155 | u64 intr_unique; | ||
156 | |||
144 | /* | 157 | /* |
145 | * The following bitfields are either set once before the | 158 | * The following bitfields are either set once before the |
146 | * request is queued or setting/clearing them is protected by | 159 | * request is queued or setting/clearing them is protected by |
@@ -150,12 +163,18 @@ struct fuse_req { | |||
150 | /** True if the request has reply */ | 163 | /** True if the request has reply */ |
151 | unsigned isreply:1; | 164 | unsigned isreply:1; |
152 | 165 | ||
153 | /** The request was interrupted */ | 166 | /** Force sending of the request even if interrupted */ |
154 | unsigned interrupted:1; | 167 | unsigned force:1; |
168 | |||
169 | /** The request was aborted */ | ||
170 | unsigned aborted:1; | ||
155 | 171 | ||
156 | /** Request is sent in the background */ | 172 | /** Request is sent in the background */ |
157 | unsigned background:1; | 173 | unsigned background:1; |
158 | 174 | ||
175 | /** The request has been interrupted */ | ||
176 | unsigned interrupted:1; | ||
177 | |||
159 | /** Data is being copied to/from the request */ | 178 | /** Data is being copied to/from the request */ |
160 | unsigned locked:1; | 179 | unsigned locked:1; |
161 | 180 | ||
@@ -181,6 +200,7 @@ struct fuse_req { | |||
181 | struct fuse_init_in init_in; | 200 | struct fuse_init_in init_in; |
182 | struct fuse_init_out init_out; | 201 | struct fuse_init_out init_out; |
183 | struct fuse_read_in read_in; | 202 | struct fuse_read_in read_in; |
203 | struct fuse_lk_in lk_in; | ||
184 | } misc; | 204 | } misc; |
185 | 205 | ||
186 | /** page vector */ | 206 | /** page vector */ |
@@ -192,17 +212,20 @@ struct fuse_req { | |||
192 | /** offset of data on first page */ | 212 | /** offset of data on first page */ |
193 | unsigned page_offset; | 213 | unsigned page_offset; |
194 | 214 | ||
195 | /** Inode used in the request */ | ||
196 | struct inode *inode; | ||
197 | |||
198 | /** Second inode used in the request (or NULL) */ | ||
199 | struct inode *inode2; | ||
200 | |||
201 | /** File used in the request (or NULL) */ | 215 | /** File used in the request (or NULL) */ |
202 | struct file *file; | 216 | struct file *file; |
203 | 217 | ||
218 | /** vfsmount used in release */ | ||
219 | struct vfsmount *vfsmount; | ||
220 | |||
221 | /** dentry used in release */ | ||
222 | struct dentry *dentry; | ||
223 | |||
204 | /** Request completion callback */ | 224 | /** Request completion callback */ |
205 | void (*end)(struct fuse_conn *, struct fuse_req *); | 225 | void (*end)(struct fuse_conn *, struct fuse_req *); |
226 | |||
227 | /** Request is stolen from fuse_file->reserved_req */ | ||
228 | struct file *stolen_file; | ||
206 | }; | 229 | }; |
207 | 230 | ||
208 | /** | 231 | /** |
@@ -216,6 +239,9 @@ struct fuse_conn { | |||
216 | /** Lock protecting accessess to members of this structure */ | 239 | /** Lock protecting accessess to members of this structure */ |
217 | spinlock_t lock; | 240 | spinlock_t lock; |
218 | 241 | ||
242 | /** Refcount */ | ||
243 | atomic_t count; | ||
244 | |||
219 | /** The user id for this mount */ | 245 | /** The user id for this mount */ |
220 | uid_t user_id; | 246 | uid_t user_id; |
221 | 247 | ||
@@ -243,13 +269,12 @@ struct fuse_conn { | |||
243 | /** The list of requests under I/O */ | 269 | /** The list of requests under I/O */ |
244 | struct list_head io; | 270 | struct list_head io; |
245 | 271 | ||
246 | /** Requests put in the background (RELEASE or any other | ||
247 | interrupted request) */ | ||
248 | struct list_head background; | ||
249 | |||
250 | /** Number of requests currently in the background */ | 272 | /** Number of requests currently in the background */ |
251 | unsigned num_background; | 273 | unsigned num_background; |
252 | 274 | ||
275 | /** Pending interrupts */ | ||
276 | struct list_head interrupts; | ||
277 | |||
253 | /** Flag indicating if connection is blocked. This will be | 278 | /** Flag indicating if connection is blocked. This will be |
254 | the case before the INIT reply is received, and if there | 279 | the case before the INIT reply is received, and if there |
255 | are too many outstading backgrounds requests */ | 280 | are too many outstading backgrounds requests */ |
@@ -258,15 +283,9 @@ struct fuse_conn { | |||
258 | /** waitq for blocked connection */ | 283 | /** waitq for blocked connection */ |
259 | wait_queue_head_t blocked_waitq; | 284 | wait_queue_head_t blocked_waitq; |
260 | 285 | ||
261 | /** RW semaphore for exclusion with fuse_put_super() */ | ||
262 | struct rw_semaphore sbput_sem; | ||
263 | |||
264 | /** The next unique request id */ | 286 | /** The next unique request id */ |
265 | u64 reqctr; | 287 | u64 reqctr; |
266 | 288 | ||
267 | /** Mount is active */ | ||
268 | unsigned mounted; | ||
269 | |||
270 | /** Connection established, cleared on umount, connection | 289 | /** Connection established, cleared on umount, connection |
271 | abort and device release */ | 290 | abort and device release */ |
272 | unsigned connected; | 291 | unsigned connected; |
@@ -305,12 +324,18 @@ struct fuse_conn { | |||
305 | /** Is removexattr not implemented by fs? */ | 324 | /** Is removexattr not implemented by fs? */ |
306 | unsigned no_removexattr : 1; | 325 | unsigned no_removexattr : 1; |
307 | 326 | ||
327 | /** Are file locking primitives not implemented by fs? */ | ||
328 | unsigned no_lock : 1; | ||
329 | |||
308 | /** Is access not implemented by fs? */ | 330 | /** Is access not implemented by fs? */ |
309 | unsigned no_access : 1; | 331 | unsigned no_access : 1; |
310 | 332 | ||
311 | /** Is create not implemented by fs? */ | 333 | /** Is create not implemented by fs? */ |
312 | unsigned no_create : 1; | 334 | unsigned no_create : 1; |
313 | 335 | ||
336 | /** Is interrupt not implemented by fs? */ | ||
337 | unsigned no_interrupt : 1; | ||
338 | |||
314 | /** The number of requests waiting for completion */ | 339 | /** The number of requests waiting for completion */ |
315 | atomic_t num_waiting; | 340 | atomic_t num_waiting; |
316 | 341 | ||
@@ -320,11 +345,23 @@ struct fuse_conn { | |||
320 | /** Backing dev info */ | 345 | /** Backing dev info */ |
321 | struct backing_dev_info bdi; | 346 | struct backing_dev_info bdi; |
322 | 347 | ||
323 | /** kobject */ | 348 | /** Entry on the fuse_conn_list */ |
324 | struct kobject kobj; | 349 | struct list_head entry; |
350 | |||
351 | /** Unique ID */ | ||
352 | u64 id; | ||
353 | |||
354 | /** Dentries in the control filesystem */ | ||
355 | struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES]; | ||
356 | |||
357 | /** number of dentries used in the above array */ | ||
358 | int ctl_ndents; | ||
325 | 359 | ||
326 | /** O_ASYNC requests */ | 360 | /** O_ASYNC requests */ |
327 | struct fasync_struct *fasync; | 361 | struct fasync_struct *fasync; |
362 | |||
363 | /** Key for lock owner ID scrambling */ | ||
364 | u32 scramble_key[4]; | ||
328 | }; | 365 | }; |
329 | 366 | ||
330 | static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) | 367 | static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) |
@@ -337,11 +374,6 @@ static inline struct fuse_conn *get_fuse_conn(struct inode *inode) | |||
337 | return get_fuse_conn_super(inode->i_sb); | 374 | return get_fuse_conn_super(inode->i_sb); |
338 | } | 375 | } |
339 | 376 | ||
340 | static inline struct fuse_conn *get_fuse_conn_kobj(struct kobject *obj) | ||
341 | { | ||
342 | return container_of(obj, struct fuse_conn, kobj); | ||
343 | } | ||
344 | |||
345 | static inline struct fuse_inode *get_fuse_inode(struct inode *inode) | 377 | static inline struct fuse_inode *get_fuse_inode(struct inode *inode) |
346 | { | 378 | { |
347 | return container_of(inode, struct fuse_inode, inode); | 379 | return container_of(inode, struct fuse_inode, inode); |
@@ -383,12 +415,9 @@ void fuse_file_free(struct fuse_file *ff); | |||
383 | void fuse_finish_open(struct inode *inode, struct file *file, | 415 | void fuse_finish_open(struct inode *inode, struct file *file, |
384 | struct fuse_file *ff, struct fuse_open_out *outarg); | 416 | struct fuse_file *ff, struct fuse_open_out *outarg); |
385 | 417 | ||
386 | /** | 418 | /** */ |
387 | * Send a RELEASE request | 419 | struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, |
388 | */ | 420 | int opcode); |
389 | void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, | ||
390 | u64 nodeid, struct inode *inode, int flags, int isdir); | ||
391 | |||
392 | /** | 421 | /** |
393 | * Send RELEASE or RELEASEDIR request | 422 | * Send RELEASE or RELEASEDIR request |
394 | */ | 423 | */ |
@@ -435,6 +464,9 @@ int fuse_dev_init(void); | |||
435 | */ | 464 | */ |
436 | void fuse_dev_cleanup(void); | 465 | void fuse_dev_cleanup(void); |
437 | 466 | ||
467 | int fuse_ctl_init(void); | ||
468 | void fuse_ctl_cleanup(void); | ||
469 | |||
438 | /** | 470 | /** |
439 | * Allocate a request | 471 | * Allocate a request |
440 | */ | 472 | */ |
@@ -446,14 +478,14 @@ struct fuse_req *fuse_request_alloc(void); | |||
446 | void fuse_request_free(struct fuse_req *req); | 478 | void fuse_request_free(struct fuse_req *req); |
447 | 479 | ||
448 | /** | 480 | /** |
449 | * Reinitialize a request, the preallocated flag is left unmodified | 481 | * Get a request, may fail with -ENOMEM |
450 | */ | 482 | */ |
451 | void fuse_reset_request(struct fuse_req *req); | 483 | struct fuse_req *fuse_get_req(struct fuse_conn *fc); |
452 | 484 | ||
453 | /** | 485 | /** |
454 | * Reserve a preallocated request | 486 | * Gets a requests for a file operation, always succeeds |
455 | */ | 487 | */ |
456 | struct fuse_req *fuse_get_req(struct fuse_conn *fc); | 488 | struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file); |
457 | 489 | ||
458 | /** | 490 | /** |
459 | * Decrement reference count of a request. If count goes to zero free | 491 | * Decrement reference count of a request. If count goes to zero free |
@@ -476,11 +508,6 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req); | |||
476 | */ | 508 | */ |
477 | void request_send_background(struct fuse_conn *fc, struct fuse_req *req); | 509 | void request_send_background(struct fuse_conn *fc, struct fuse_req *req); |
478 | 510 | ||
479 | /** | ||
480 | * Release inodes and file associated with background request | ||
481 | */ | ||
482 | void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req); | ||
483 | |||
484 | /* Abort all requests */ | 511 | /* Abort all requests */ |
485 | void fuse_abort_conn(struct fuse_conn *fc); | 512 | void fuse_abort_conn(struct fuse_conn *fc); |
486 | 513 | ||
@@ -493,3 +520,23 @@ int fuse_do_getattr(struct inode *inode); | |||
493 | * Invalidate inode attributes | 520 | * Invalidate inode attributes |
494 | */ | 521 | */ |
495 | void fuse_invalidate_attr(struct inode *inode); | 522 | void fuse_invalidate_attr(struct inode *inode); |
523 | |||
524 | /** | ||
525 | * Acquire reference to fuse_conn | ||
526 | */ | ||
527 | struct fuse_conn *fuse_conn_get(struct fuse_conn *fc); | ||
528 | |||
529 | /** | ||
530 | * Release reference to fuse_conn | ||
531 | */ | ||
532 | void fuse_conn_put(struct fuse_conn *fc); | ||
533 | |||
534 | /** | ||
535 | * Add connection to control filesystem | ||
536 | */ | ||
537 | int fuse_ctl_add_conn(struct fuse_conn *fc); | ||
538 | |||
539 | /** | ||
540 | * Remove connection from control filesystem | ||
541 | */ | ||
542 | void fuse_ctl_remove_conn(struct fuse_conn *fc); | ||