diff options
Diffstat (limited to 'Documentation/filesystems/fuse.txt')
-rw-r--r-- | Documentation/filesystems/fuse.txt | 40 |
1 files changed, 6 insertions, 34 deletions
diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt index 33f74310d16..e7747774ceb 100644 --- a/Documentation/filesystems/fuse.txt +++ b/Documentation/filesystems/fuse.txt | |||
@@ -304,25 +304,7 @@ Scenario 1 - Simple deadlock | |||
304 | | | for "file"] | 304 | | | for "file"] |
305 | | | *DEADLOCK* | 305 | | | *DEADLOCK* |
306 | 306 | ||
307 | The solution for this is to allow requests to be interrupted while | 307 | The solution for this is to allow the filesystem to be aborted. |
308 | they are in userspace: | ||
309 | |||
310 | | [interrupted by signal] | | ||
311 | | <fuse_unlink() | | ||
312 | | [release semaphore] | [semaphore acquired] | ||
313 | | <sys_unlink() | | ||
314 | | | >fuse_unlink() | ||
315 | | | [queue req on fc->pending] | ||
316 | | | [wake up fc->waitq] | ||
317 | | | [sleep on req->waitq] | ||
318 | |||
319 | If the filesystem daemon was single threaded, this will stop here, | ||
320 | since there's no other thread to dequeue and execute the request. | ||
321 | In this case the solution is to kill the FUSE daemon as well. If | ||
322 | there are multiple serving threads, you just have to kill them as | ||
323 | long as any remain. | ||
324 | |||
325 | Moral: a filesystem which deadlocks, can soon find itself dead. | ||
326 | 308 | ||
327 | Scenario 2 - Tricky deadlock | 309 | Scenario 2 - Tricky deadlock |
328 | ---------------------------- | 310 | ---------------------------- |
@@ -355,24 +337,14 @@ but is caused by a pagefault. | |||
355 | | | [lock page] | 337 | | | [lock page] |
356 | | | * DEADLOCK * | 338 | | | * DEADLOCK * |
357 | 339 | ||
358 | Solution is again to let the the request be interrupted (not | 340 | Solution is basically the same as above. |
359 | elaborated further). | ||
360 | 341 | ||
361 | An additional problem is that while the write buffer is being | 342 | An additional problem is that while the write buffer is being |
362 | copied to the request, the request must not be interrupted. This | 343 | copied to the request, the request must not be interrupted. This |
363 | is because the destination address of the copy may not be valid | 344 | is because the destination address of the copy may not be valid |
364 | after the request is interrupted. | 345 | after the request is interrupted. |
365 | 346 | ||
366 | This is solved with doing the copy atomically, and allowing | 347 | This is solved with doing the copy atomically, and allowing abort |
367 | interruption while the page(s) belonging to the write buffer are | 348 | while the page(s) belonging to the write buffer are faulted with |
368 | faulted with get_user_pages(). The 'req->locked' flag indicates | 349 | get_user_pages(). The 'req->locked' flag indicates when the copy is |
369 | when the copy is taking place, and interruption is delayed until | 350 | taking place, and abort is delayed until this flag is unset. |
370 | this flag is unset. | ||
371 | |||
372 | Scenario 3 - Tricky deadlock with asynchronous read | ||
373 | --------------------------------------------------- | ||
374 | |||
375 | The same situation as above, except thread-1 will wait on page lock | ||
376 | and hence it will be uninterruptible as well. The solution is to | ||
377 | abort the connection with forced umount (if mount is attached) or | ||
378 | through the abort attribute in sysfs. | ||