aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTahsin Erdogan <tahsin@google.com>2017-01-12 15:04:04 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-26 02:24:38 -0500
commit0181b3603681d03e5753079cef8b17d2905faee5 (patch)
tree197f5584af18a5143e86437abdfe7179f111dec9 /fs
parentbb82fb48df8cab8f902052ce03f6d51b9b8f1bcd (diff)
fuse: clear FR_PENDING flag when moving requests out of pending queue
commit a8a86d78d673b1c99fe9b0064739fde9e9774184 upstream. fuse_abort_conn() moves requests from pending list to a temporary list before canceling them. This operation races with request_wait_answer() which also tries to remove the request after it gets a fatal signal. It checks FR_PENDING flag to determine whether the request is still in the pending list. Make fuse_abort_conn() clear FR_PENDING flag so that request_wait_answer() does not remove the request from temporary list. This bug causes an Oops when trying to delete an already deleted list entry in end_requests(). Fixes: ee314a870e40 ("fuse: abort: no fc->lock needed for request ending") Signed-off-by: Tahsin Erdogan <tahsin@google.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dev.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 70ea57c7b6bb..4e06a27ed7f8 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2025,7 +2025,6 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head)
2025 struct fuse_req *req; 2025 struct fuse_req *req;
2026 req = list_entry(head->next, struct fuse_req, list); 2026 req = list_entry(head->next, struct fuse_req, list);
2027 req->out.h.error = -ECONNABORTED; 2027 req->out.h.error = -ECONNABORTED;
2028 clear_bit(FR_PENDING, &req->flags);
2029 clear_bit(FR_SENT, &req->flags); 2028 clear_bit(FR_SENT, &req->flags);
2030 list_del_init(&req->list); 2029 list_del_init(&req->list);
2031 request_end(fc, req); 2030 request_end(fc, req);
@@ -2103,6 +2102,8 @@ void fuse_abort_conn(struct fuse_conn *fc)
2103 spin_lock(&fiq->waitq.lock); 2102 spin_lock(&fiq->waitq.lock);
2104 fiq->connected = 0; 2103 fiq->connected = 0;
2105 list_splice_init(&fiq->pending, &to_end2); 2104 list_splice_init(&fiq->pending, &to_end2);
2105 list_for_each_entry(req, &to_end2, list)
2106 clear_bit(FR_PENDING, &req->flags);
2106 while (forget_pending(fiq)) 2107 while (forget_pending(fiq))
2107 kfree(dequeue_forget(fiq, 1, NULL)); 2108 kfree(dequeue_forget(fiq, 1, NULL));
2108 wake_up_all_locked(&fiq->waitq); 2109 wake_up_all_locked(&fiq->waitq);