aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/dev.c')
-rw-r--r--fs/fuse/dev.c71
1 files changed, 67 insertions, 4 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index c72e44b58d09..60c222517ccd 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -260,11 +260,13 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
260 wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED); 260 wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED);
261 restore_sigs(&oldset); 261 restore_sigs(&oldset);
262 spin_lock(&fuse_lock); 262 spin_lock(&fuse_lock);
263 if (req->state == FUSE_REQ_FINISHED) 263 if (req->state == FUSE_REQ_FINISHED && !req->interrupted)
264 return; 264 return;
265 265
266 req->out.h.error = -EINTR; 266 if (!req->interrupted) {
267 req->interrupted = 1; 267 req->out.h.error = -EINTR;
268 req->interrupted = 1;
269 }
268 if (req->locked) { 270 if (req->locked) {
269 /* This is uninterruptible sleep, because data is 271 /* This is uninterruptible sleep, because data is
270 being copied to/from the buffers of req. During 272 being copied to/from the buffers of req. During
@@ -770,6 +772,10 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
770 goto err_finish; 772 goto err_finish;
771 773
772 spin_lock(&fuse_lock); 774 spin_lock(&fuse_lock);
775 err = -ENOENT;
776 if (!fc->connected)
777 goto err_unlock;
778
773 req = request_find(fc, oh.unique); 779 req = request_find(fc, oh.unique);
774 err = -EINVAL; 780 err = -EINVAL;
775 if (!req) 781 if (!req)
@@ -836,7 +842,11 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
836 return mask; 842 return mask;
837} 843}
838 844
839/* Abort all requests on the given list (pending or processing) */ 845/*
846 * Abort all requests on the given list (pending or processing)
847 *
848 * This function releases and reacquires fuse_lock
849 */
840static void end_requests(struct fuse_conn *fc, struct list_head *head) 850static void end_requests(struct fuse_conn *fc, struct list_head *head)
841{ 851{
842 while (!list_empty(head)) { 852 while (!list_empty(head)) {
@@ -848,6 +858,59 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head)
848 } 858 }
849} 859}
850 860
861/*
862 * Abort requests under I/O
863 *
864 * The requests are set to interrupted and finished, and the request
865 * waiter is woken up. This will make request_wait_answer() wait
866 * until the request is unlocked and then return.
867 */
868static void end_io_requests(struct fuse_conn *fc)
869{
870 while (!list_empty(&fc->io)) {
871 struct fuse_req *req;
872 req = list_entry(fc->io.next, struct fuse_req, list);
873 req->interrupted = 1;
874 req->out.h.error = -ECONNABORTED;
875 req->state = FUSE_REQ_FINISHED;
876 list_del_init(&req->list);
877 wake_up(&req->waitq);
878 }
879}
880
881/*
882 * Abort all requests.
883 *
884 * Emergency exit in case of a malicious or accidental deadlock, or
885 * just a hung filesystem.
886 *
887 * The same effect is usually achievable through killing the
888 * filesystem daemon and all users of the filesystem. The exception
889 * is the combination of an asynchronous request and the tricky
890 * deadlock (see Documentation/filesystems/fuse.txt).
891 *
892 * During the aborting, progression of requests from the pending and
893 * processing lists onto the io list, and progression of new requests
894 * onto the pending list is prevented by req->connected being false.
895 *
896 * Progression of requests under I/O to the processing list is
897 * prevented by the req->interrupted flag being true for these
898 * requests. For this reason requests on the io list must be aborted
899 * first.
900 */
901void fuse_abort_conn(struct fuse_conn *fc)
902{
903 spin_lock(&fuse_lock);
904 if (fc->connected) {
905 fc->connected = 0;
906 end_io_requests(fc);
907 end_requests(fc, &fc->pending);
908 end_requests(fc, &fc->processing);
909 wake_up_all(&fc->waitq);
910 }
911 spin_unlock(&fuse_lock);
912}
913
851static int fuse_dev_release(struct inode *inode, struct file *file) 914static int fuse_dev_release(struct inode *inode, struct file *file)
852{ 915{
853 struct fuse_conn *fc; 916 struct fuse_conn *fc;